[SOLVED]Is it possible to load assets with the same extension with several asset loaders?

Actually I’m using 2 custom asset loaders for xml loading, but it isn’t working, the first loader loads its respective xml assets fine, and then the second try to load its respective xml assets, but it freezes the application. Basically what I’m doing is creating a asset loader for load my xml files, and I created a second one asset loader for load a xml file where the others xml files’ paths.



For example, this is one of the xml files:



aces-high.xml



[xml]

<?xml version=“1.0” encoding=“UTF-8”?>

<rhythmTrack soundId=“music#0” soundName=“Iron Maiden - Aces High” durationTime=“8000” difficulty=“Easy”>

<moveBars>

<moveBar moveTime=“1000”/>

<moveBar moveTime=“2000”/>

<moveBar moveTime=“3000”/>

<moveBar moveTime=“4000”/>

<moveBar moveTime=“5000”/>

<moveBar moveTime=“8000”/>

</moveBars>

</rhythmTrack>

[/xml]



And this is the xml where I map the xml files that I want to load:



rhythmTrackMapping.xml



[xml]

<?xml version=“1.0” encoding=“UTF-8”?>

<rhythmTrackMapping>

<mapping fileName=“Interface/RhythmTracks/aces-high.xml”/>

<mapping fileName=“Interface/RhythmTracks/aces-high.xml”/>

</rhythmTrackMapping>

[/xml]





And I’m registering them so:



[java]

assetManager.registerLoader(RhythmTrackLoader.class, “xml”);

assetManager.registerLoader(RhythmTrackMappingLoader.class, “xml”);

[/java]



P.S.: About the iron maiden’s music, it’s just for testing xD, I’ll put other musics of course :).

Normally that should work but why don’t you just rename the suffix of the files and use one?

Fixed the second xml above that wasn’t showed up, you can see that now.

About the suffix, what do u mean? As you can see the aces-high.xml, It isn’t the only one track, there are a lot of that, every track is a xml find. Did you get it?



EDIT: About the suffix, I got it, but it’s not the problem. I tested with only one, and it doesn’t work too.

EDIT2: Btw, I’ll do a testcase for that.

hmmmmmmm. I did a testcase for that, and it threw an exception, maybe I did something wrong. I’ll fix that.



[java]

java.lang.ClassCastException: rhythmgame.nifty.control.rhythmtrack.RhythmTrackMapping cannot be cast to rhythmgame.nifty.control.rhythmtrack.RhythmTrackData

at rhythmgame.nifty.control.rhythmtrack.loader.RhythmTrackKey.createClonedInstance(RhythmTrackKey.java:30)

at com.jme3.asset.DesktopAssetManager.loadAsset(DesktopAssetManager.java:300)

at rhythmgame.test.TestLoaders.simpleInitApp(TestLoaders.java:41)

at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:231)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:129)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:205)

at java.lang.Thread.run(Thread.java:662)

[/java]

About the error above, I’ve double checked the source code, and it looks fine, it looks like the asset loader system is having conflits with my loaders.

This is the testcase that I did that threw the exception above :



[java]

public class TestLoaders extends SimpleApplication {



public static void main(String[] args) {

new TestLoaders().start();

}



@Override

public void simpleInitApp() {

NiftyJmeDisplay display = new NiftyJmeDisplay(assetManager, inputManager, audioRenderer, viewPort);

Nifty nifty = display.getNifty();



assetManager.registerLoader(RhythmTrackLoader.class, “xml”);

assetManager.registerLoader(RhythmTrackMappingLoader.class, “xml”);



List<String> mappings = assetManager.loadAsset(new RhythmTrackMappingKey(“Interface/RhythmTracks/rhythmTrackMapping.xml”)).getFileNameMapping();



List<RhythmTrackData> datas = new ArrayList<RhythmTrackData>();



for (String map : mappings) {

datas.add(assetManager.loadAsset(new RhythmTrackKey(map)));

}



System.out.println("Datas " + datas);

}

}

[/java]



This is the RhythmTrackKey.java :



[java]

public class RhythmTrackKey extends AssetKey<RhythmTrackData> {



public RhythmTrackKey() {

}



public RhythmTrackKey(String name) {

super(name);

}



@Override

public boolean useSmartCache() {

return true;

}



@Override

public Object createClonedInstance(Object asset) {

RhythmTrackData rhythmTrackData = (RhythmTrackData) asset;

return rhythmTrackData.clone();

}

}

[/java]



This is the RhythmTrackMappingKey.java :



[java]

public class RhythmTrackMappingKey extends AssetKey<RhythmTrackMapping> {



public RhythmTrackMappingKey() {

}



public RhythmTrackMappingKey(String name) {

super(name);

}



@Override

public boolean useSmartCache() {

return true;

}



@Override

public Object createClonedInstance(Object asset) {

RhythmTrackMapping obj = (RhythmTrackMapping) asset;

return obj.clone();

}

}

[/java]



and the xml files :



rhythmTrackMapping.xml



[xml]

<?xml version=“1.0” encoding=“UTF-8”?>

<rhythmTrackMapping>

<mapping fileName=“Interface/RhythmTracks/aces-high.xml”/>

<mapping fileName=“Interface/RhythmTracks/aces-high_1.xml”/>

</rhythmTrackMapping>



[/xml]



aces-high.xml :



[xml]

<?xml version=“1.0” encoding=“UTF-8”?>

<rhythmTrack soundId=“music#0” soundName=“Iron Maiden - Aces High” durationTime=“8000” difficulty=“Easy”>

<moveBars>

<moveBar moveTime=“1000”/>

<moveBar moveTime=“2000”/>

<moveBar moveTime=“3000”/>

<moveBar moveTime=“4000”/>

<moveBar moveTime=“5000”/>

<moveBar moveTime=“8000”/>

</moveBars>

</rhythmTrack>

[/xml]



aces-high_1.xml :



[xml]

<?xml version=“1.0” encoding=“UTF-8”?>

<rhythmTrack soundId=“music#0” soundName=“Iron Maiden - Aces High” durationTime=“8000” difficulty=“Easy”>

<moveBars>

<moveBar moveTime=“1000”/>

<moveBar moveTime=“2000”/>

<moveBar moveTime=“3000”/>

<moveBar moveTime=“4000”/>

<moveBar moveTime=“5000”/>

<moveBar moveTime=“8000”/>

</moveBars>

</rhythmTrack>

[/xml]



And the loaders source code looks fine, any ideas what that might be?



EDIT: and this is the clone method of the RhythmTrackData:



[java]

@Override

public RhythmTrackData clone() {

return new RhythmTrackData(highScore, bestScore, bestCombo, difficulty, soundId, soundName, durationTime, moveBars);

}

[/java]

Its a cast error, you probably have two variables mixed up or try to cast to a wrong type in the read/write methods.

No, as you can see above, there aren’t any read/write method at all, and the loaders’s load method look fine too :



RhythmTrackLoader.load()



[java]

public Object load(AssetInfo assetInfo) throws IOException {

try {

SAXParserFactory factory = SAXParserFactory.newInstance();

XMLReader xr = factory.newSAXParser().getXMLReader();



xr.setContentHandler(this);

xr.setErrorHandler(this);



InputStreamReader r = null;



try {

r = new InputStreamReader(assetInfo.openStream());

xr.parse(new InputSource®);

} finally {

if (r != null) {

r.close();

}

}



return rhythmTrack;

} catch (SAXException ex) {

throw new IOException(“Error while parsing RhythmTrackData”, ex);

} catch (ParserConfigurationException ex) {

throw new IOException(“Error while parsing RhythmTrackData”, ex);

}

}

[/java]



RhythmTrackMappingLoader.load()



[java]

public Object load(AssetInfo assetInfo) throws IOException {



try {

SAXParserFactory factory = SAXParserFactory.newInstance();

XMLReader xr = factory.newSAXParser().getXMLReader();



xr.setContentHandler(this);

xr.setErrorHandler(this);



InputStreamReader r = null;



try {

r = new InputStreamReader(assetInfo.openStream());

xr.parse(new InputSource®);

} finally {

if (r != null) {

r.close();

}

}



return rhythmTrackMapping;

} catch (SAXException ex) {

throw new IOException(“Error while parsing RhythmTrackMapping”, ex);

} catch (ParserConfigurationException ex) {

throw new IOException(“Error while parsing RhythmTrackMapping”, ex);

}

}

[/java]

Yes ^^

java.lang.ClassCastException: rhythmgame.nifty.control.rhythmtrack.RhythmTrackMapping cannot be cast to rhythmgame.nifty.control.rhythmtrack.RhythmTrackData
at rhythmgame.nifty.control.rhythmtrack.loader.RhythmTrackKey.createClonedInstance(RhythmTrackKey.java:30)
@normen said:
Yes ^^


No

@glaucomardano said:
This is the RhythmTrackKey.java :

[java]
public class RhythmTrackKey extends AssetKey&lt;RhythmTrackData&gt; {

public RhythmTrackKey() {
}

public RhythmTrackKey(String name) {
super(name);
}

@Override
public boolean useSmartCache() {
return true;
}

@Override
public Object createClonedInstance(Object asset) {
RhythmTrackData rhythmTrackData = (RhythmTrackData) asset;
return rhythmTrackData.clone();
}
}
[/java]


The asset loader system is passing the object asset param as a RhythmTrackMapping object, but it should be a RhythmTrackData object, as I said before, it looks like the asset loder system is confusing my loders.

You are generally not adhering to the coding standards if this is supposed to be a jME3 importer, look at for example the NeoTexture loaders for a simple example. Also, you can only register one importer per suffix, but you register both loaders for the xml ending. As you asked in the beginning, yes you’d have to set up multiple AssetManagers for this (JmeSystem.getAssetManager())

Sorry, what do you mean about suffix in this context?

Also, I updated my jmp and I’ve reported a possible bug, :



[java]

java.lang.ClassNotFoundException: com.jme3.scene.plugins.blender.BlenderModelLoader

at java.net.URLClassLoader$1.run(URLClassLoader.java:202)

at java.security.AccessController.doPrivileged(Native Method)

at java.net.URLClassLoader.findClass(URLClassLoader.java:190)

at java.lang.ClassLoader.loadClass(ClassLoader.java:306)

at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)

at java.lang.ClassLoader.loadClass(ClassLoader.java:247)

at java.lang.Class.forName0(Native Method)

at java.lang.Class.forName(Class.java:169)

at com.jme3.asset.DesktopAssetManager.registerLoader(DesktopAssetManager.java:135)

at com.jme3.asset.AssetConfig.loadText(AssetConfig.java:74)

at com.jme3.asset.DesktopAssetManager.<init>(DesktopAssetManager.java:88)

at com.jme3.system.JmeDesktopSystem.newAssetManager(JmeDesktopSystem.java:62)

at com.jme3.system.JmeSystem.newAssetManager(JmeSystem.java:87)

at com.jme3.app.Application.initAssetManager(Application.java:171)

at com.jme3.app.Application.initialize(Application.java:499)

at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:204)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:129)

at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:205)

at java.lang.Thread.run(Thread.java:662)

[/java]



And the application code is empty.

The blender importer is a separate library now, if you do not use the default “jme3-libraries” you have to select the jme3-libraries-blender plugin if you want to load blender files directly.

Well, I create a new freshly basic game template and when I run that, the exception above is thrown, the basic game template doesn’t load any .blend files… if I add the jme3-libralies-blender jar to project’s the classpath, it solves the problem. But should be that exception thrown always the jme3-libralies-blender jar isn’t added to the project’s classpath?

Well, you’re not supposed to load .blend files in the game anyway. Solution is simple.

1 Like

Hehe, thanks!

And about the class cast exception, I get rid of that by just removing the createClonedInstance() overridding from my asset keys forever, once I won’t clone my xml assets U.u. I was a simple solution :P.

As you asked in the beginning, yes you’d have to set up multiple AssetManagers for this (JmeSystem.getAssetManager())


Thanks, it was the solution! SOLVED!