Help with expansion content (General How To)?

Hey all…

I’m wondering how to handle expansion content?

What I need to do is fairly simple. Just the addition of new assets & some xml config files.

I sense the word AssetPack is about to be mentioned. And this sounds good! However, here be a scenario… can someone give me a general rundown on how this works?

Scenario:

  1. Game is installed on an Android device.
  2. I decide to push out content additions that don’t require any change to the code.
    ** An .xml config file
    ** Some j3o(s)
    ** A few images
    ** etc

How does one know the AssetPack exists?
I assume that it is pushed to the apk specific directory?
Does this require scanning the folder for additional jars?
Do you set up the package name the same as your game and it automatically is available through the registered assets location?
Do you have to register a new location for each?

I’m a bit more than confused about this atm. Any and all help is very appreciated!

P.S. I used Android as an example… if you are familiar with how to do this on desktop… that would do!

while technically not a solution. whats wrong with just distributing an entire repackaged game with the new content? Unless your game is gigabytes big i dont think most people will know the difference or appreciate your hard work to provide a more efficient upgrading system.

When I’m thinking about this topic these pages help me get back on track:

JNLP update tutorial

JNLP update syntax

These tutorials are for the Java JNLP method of distribution. But what they explain is exactly the same concept to be used on android.

1 Like
@icamefromspace said: while technically not a solution. whats wrong with just distributing an entire repackaged game with the new content? Unless your game is gigabytes big i dont think most people will know the difference or appreciate your hard work to provide a more efficient upgrading system.

In app purchases (free or not) would kinda stop this, unfortunately.

I took the game I wrote for the contest and enabled android deployment… and seeing as the entire thing is written using tonegodGUI (not the 2D framework… just the GUI components) it all worked perfectly (yes, this surprised me).

The only thing I had to update was the size of the texture for that building.

Soooo… I did a quick rewrite to allow the entire scene to be loaded from an xml definition file so I could add new scenes from a level selector… config the subscreens, game time, HUD, etc… then it dawned on me, that I could could add new content at any time if I could just find out how I would handle looking for the additional asset jars.

Google Play Store gives you the option of pushing out add-on content, but I’m not sure what would be the best way handle this internal to the app. I’d like to set it up to allow downloads from the app store through an internal store interface to the app.

@Pixelapp said: When I'm thinking about this topic these pages help me get back on track:

JNLP update tutorial

JNLP update syntax

These tutorials are for the Java JNLP method of distribution. But what they explain is exactly the same concept to be used on android.

Thanks… will look through this info… most appreciated.

You can separate your assets.jar using the build.xml, say you’d make a folder “update_content” in the assets folder and jar that separately. Then you’d only have to distribute that jar file. I actually planned to add separating jar files and making different “deployment targets” with different content for the same file names (e.g. XML GUI files and materials for different platforms) and/or additional content (for updates and extensions) to the SDK. But I don’t know if this will happen before SDK projects move to gradle or not.

2 Likes

[java]
main.getAssetManager().registerLocator(“test.zip”, ZipLocator.class);
Document doc = main.getAssetManager().loadAsset(new AssetKey<Document>(“test.xml”));
[/java]

Worked just fine…

Can just search the root directory or data/data/package.name/ for zip files I guess.

Anyone know of any issues I should be aware of when using the above as a potential solution?

I wonder if this is the time for the first mention of a plugin I’ve been working on separating from my game. I wanted to be able to have new user created assets uploaded to the game server at any time, and for those assets to be available to everyone else immediately. This also allows the game itself to be tiny, assets are loaded as they are needed the first time. Subsequent runs will used the local cached copy.

To achieve this, I now have a bunch of extensions to the JME3 asset system that :-

  • Will download these assets from an HTTP server, and cache them locallly.
  • Does freshness checks on assets in the local cache.
  • Can use an index file to provide MUCH faster freshness checks and the ability to search filenames
  • Encryption (you must provide your own way of hiding the key - i.e. the hard part). Assets are stored encrypted on the server and in the local cache, but provided to JME decrypted.
  • Encryption and caching is all done on-the-fly, no temporary files.

It is not QUITE ready for a proper release/announcement yet, but if you are interested I’d certainly like to hear opinions. Oh, I should say I have no idea how well this will work on Android. I currently extend DesktopAssetManager (presumably thats a problem), but that could be changed.

You can find the code and a more complete description here, and the associated Ant task here.

RR

2 Likes
@rockfire said: I wonder if this is the time for the first mention of a plugin I've been working on separating from my game. I wanted to be able to have new user created assets uploaded to the game server at any time, and for those assets to be available to everyone else immediately. This also allows the game itself to be tiny, assets are loaded as they are needed the first time. Subsequent runs will used the local cached copy.

To achieve this, I now have a bunch of extensions to the JME3 asset system that :-

  • Will download these assets from an HTTP server, and cache them locallly.
  • Does freshness checks on assets in the local cache.
  • Can use an index file to provide MUCH faster freshness checks and the ability to search filenames
  • Encryption (you must provide your own way of hiding the key - i.e. the hard part). Assets are stored encrypted on the server and in the local cache, but provided to JME decrypted.
  • Encryption and caching is all done on-the-fly, no temporary files.

It is not QUITE ready for a proper release/announcement yet, but if you are interested I’d certainly like to hear opinions. Oh, I should say I have no idea how well this will work on Android. I currently extend DesktopAssetManager (presumably thats a problem), but that could be changed.

You can find the code and a more complete description here, and the associated Ant task here.

RR

I’m really looking forward to this!

My mini-solution for small Android games was this: (Please let me know where I am not doing things correctly as this was trial and error without a clear idea of what I needed to do):

[java]
public void loadExpansions() {
List<String> zipFiles = new ArrayList();

// Apparently it doesn't matter if the file exists... it just gets the root directory of the running
// app + the bogus file name
File rootFile = new File("t.zip");
// Likely, there is a way to just get the root directory, but I didn't see it... so I parse it
String rootPath = rootFile.getAbsolutePath().substring(
	0,
	rootFile.getAbsolutePath().lastIndexOf(File.separator)+1
);

// Get a directory list &amp; store all zip file names
File dir = new File(rootPath);
for (String file : dir.list()) {
	if (file.indexOf(".zip") != -1) {
		File tFile = new File(file);
		String tPath = tFile.getPath();
		zipFiles.add(tPath);
	}
}

// I also tried registering &amp; unregistering the Locator so I could use the same file names,
// but unregisterLocator doesn't seem to work.
if (!zipFiles.isEmpty()) {
	int index = 1;
	for (String zip : zipFiles) {
		main.getAssetManager().registerLocator(zip, ZipLocator.class);
		String filename = zip.substring(0,zip.lastIndexOf("."));
		filename += "_config.xml";
		parseScenes(filename, zip);
		System.out.println("Parsed " + index + " expansion pack(s): " + zip);
		index++;
	}
}

}
[/java]

1 Like

Cont…

Long story short, the above allows me to load whole new scenes and game parameters for content added after the apk or app is deployed.

1 Like
@t0neg0d said: [java] main.getAssetManager().registerLocator("test.zip", ZipLocator.class); Document doc = main.getAssetManager().loadAsset(new AssetKey<Document>("test.xml")); [/java]

Worked just fine…

Can just search the root directory or data/data/package.name/ for zip files I guess.

Anyone know of any issues I should be aware of when using the above as a potential solution?

You don’t know the execution path of you app in advance so you might fail to find the zip file, also it won’t work on iOS and Android.

I load nearly my whole game on the fly.

Any class implementing Autoload will be loaded, the dependencies are injected and they are initialized.
Don’t know if that works on android but it works nicely on the pc where you have a lib folder

1 Like
@normen said: You don't know the execution path of you app in advance so you might fail to find the zip file, also it won't work on iOS and Android.

Hey you… this is currently working on Android. It resolves to /data/data/com.package.name/ which has auto read/write privileges. I have no way of testing this on iOS though. How would one go about resolving this for potential iOS differences?

EDIT: Speaking of which, the current SaveGame addition has a problem with how it is selecting the save folder for Android. Can’t remember what version this changed in, but user.home doesn’t resolve to above path (data/data/com/package.name) which is (I guess) where you are supposed to save/load game data to due to the auto privileges and lack of user access (unless the device has been rooted).

@zzuegg said: I load nearly my whole game on the fly.

Any class implementing Autoload will be loaded, the dependencies are injected and they are initialized.
Don’t know if that works on android but it works nicely on the pc where you have a lib folder

I’ll mess around with this and see if I can get it to work on Android. Thanks for the tip!

@t0neg0d said: Hey you... this is currently working on Android. It resolves to /data/data/com.package.name/ which has auto read/write privileges. I have no way of testing this on iOS though. How would one go about resolving this for potential iOS differences?

EDIT: Speaking of which, the current SaveGame addition has a problem with how it is selecting the save folder for Android. Can’t remember what version this changed in, but user.home doesn’t resolve to above path (data/data/com/package.name) which is (I guess) where you are supposed to save/load game data to due to the auto privileges and lack of user access (unless the device has been rooted).

Theres no file access at all on iOS, at least you can’t bring in files to the package, you can create settings files however. All assets have to be packaged in jar files and loaded via the classpath.

You are supposed to save your files somewhere else than the installation directory on Android (some kind of user settings folder), thats why it was changed. It doesn’t have anything to do with SaveGame really, its a general getWritableFolder() (or whatever) thingie in the JmeSystem. Can’t say if it works on Android or what folder exactly its supposed to return there though.

@normen said: Theres no file access at all on iOS, at least you can't bring in files to the package, you can create settings files however. All assets have to be packaged in jar files and loaded via the classpath.

You are supposed to save your files somewhere else than the installation directory on Android (some kind of user settings folder), thats why it was changed. It doesn’t have anything to do with SaveGame really, its a general getWritableFolder() (or whatever) thingie in the JmeSystem. Can’t say if it works on Android or what folder exactly its supposed to return there though.

Thanks for this info… I’m not writing data to this folder ever… I just needed to read extra files that are downloaded from the Play Store. So… how are people pushing out content updates for distributed apps on iOS (i.e. in-game purchases)?

@t0neg0d said: Thanks for this info... I'm not writing data to this folder ever... I just needed to read extra files that are downloaded from the Play Store. So... how are people pushing out content updates for distributed apps on iOS (i.e. in-game purchases)?

In-app purchases and updates are different things. Updates are always complete replacements of the app. In-game purchases don’t necessarily include data content that has to be downloaded. Since you have a normal iOS app you certainly can do everything file-wise that you can in a normal iOS app, the issue is more with how far the java environment can access this data. Theoretically you can prepare data packages, “tunnel” them though native code and use them in the java code in any case. Maybe the Java VM emulation even allows access to some folders in the private user space of the app, none of this has been wired up from our side though.

@normen said: In-app purchases and updates are different things. Updates are always complete replacements of the app. In-game purchases don't necessarily include data content that has to be downloaded. Since you have a normal iOS app you certainly can do everything file-wise that you can in a normal iOS app, the issue is more with how far the java environment can access this data. Theoretically you can prepare data packages, "tunnel" them though native code and use them in the java code in any case. Maybe the Java VM emulation even allows access to some folders in the private user space of the app, none of this has been wired up from our side though.

Perfect… thanks. Once I am able to, I’ll try and contribute as much as possible to “How to’s” for iOS deployment to help save on the # of questions you get. When I say contribute, I mean compile info together, etc.