Multi-game support in one app

I’ll explain a bit what I’m trying to achieve, and then I have some questions in case others have come across this and have some advice.

I have an application that contains multiple games that can be selected by the player. The applications has resources that are always loaded (common resources). Once the player clicks on one of the games, the resources for that game are loaded (along with initialization of the specific code to that game).

The player can then exit that game, and go back to the game selection screen (which is a separate scene object), and then can select another game to play.

More game resource bundles can be downloaded and added to the app, so they don’t actually exist within the initial bundle that is downloaded from the app stores. The code for the games already exists inside the application, so there is no dynamically loaded executable code or scripts (since they’re not allowed by app store policies).

The way I have it working at the moment is that the player can download the app (say from Google Play, the APK), and it installs. Once the player loads the application, it downloads several extra resource ZIP files from a host where the games exist. Those ZIP files are copied to a writable folder, and extracted. That path is then added to the search path in Cocos2d-x by FileUtils::getInstance()->addSearchPath(path).

Now, there doesn’t seem to be a way to remove that path from the list, so it’s always there, and I’m worried that resources for different games will clash because of this issue.

Also, there doesn’t seem to be a built in way to unload specific resources (since there is no concept of resource group etc). I think I’ve managed to find a way around this by manually tracking all the resources that are added, and then unloading them myself, but I’m not yet sure if it’s 100% effective (meaning resources still in memory when they shouldn’t be).

Now, my questions:

  1. Is there a valid technical reason why a method does not exist for removing a path from the list of search paths? If there isn’t a reason, then I can add one myself without troubling the Cocos2d-x devs.

  2. Is there any 100% effective way to unload only certain resources (like loading resources with some kind of ID or tag, be it integer or otherwise, and only unloading those with that tag).

  3. Is there ANY way to use ZIP files directly without having to extract the contents? Basically the same way APKs are handled by Android, where the APK is accessed like a filesystem.

Any information or suggestions would be appreciated.

EDIT:
Possible solution to (1) is to use setSearchPaths instead of addSearchPath. setSearchPaths nukes the current file path cache along with all the set paths, and overwrites them with the new list. This will do the job fine for my app. One thing to note though, I just realised addSearchPath doesn’t check for duplicates, so you can end up with multiple of the same entry in the lists by using it.

I’m well aware of that, which is why I wrote this in my original post:
“The code for the games already exists inside the application, so there is no dynamically loaded executable code or scripts (since they’re not allowed by app store policies).”

What you posted is from the Apple website, yet are you aware of resource bundles for iOS?
In case you are not, here’s a link to explain it:
https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/On_Demand_Resources_Guide/index.html#//apple_ref/doc/uid/TP40015083-CH2-SW1

  1. search paths is a vector, can you just iterate over it and remove what you want?

  2. You can always removeFromParentAndCleanUp() by specifying a tag

  3. zip is already a dependency. Just look up the API and work with it if you wish. I don’t think we handle this in the engine to the best of my knowledge.

  1. I am aware that the search paths are stored in a vector, but my question was to do with there being a reason for not having a remove search path method; if there was a technical constraint for it not to be there. By your answer, I am to understand that there is no technical reason, and it simply just wasn’t a requirement. So, it’s all good, I’ll just remove the paths from the vector if needed.

  2. removeFromParentAndCleanUp() doesn’t seem to clear the texture data from what I can see, but I’ve found another way to ensure everything is cleared from memory on switching games, and it is working well at the moment. I first use removeSpriteFramesFromFile on all files I initially loaded into memory (I keep track of them in my own resource manager), then once that’s done, I call removeUnusedTextures(), which nukes all unused texture data.

  3. Yep I noticed the ZIP API related stuff in the cocos2d code, just wondered if there was a way to treat the ZIP internals as a filesystem, and it seems that there isn’t, so I’ll see what I can about writing a module to handle this requirement.

Thanks for your input slackmoehrle.

If the game is running on Android, an OBB file can be used. So the framework can handle out of the box ZIPs as a filesystem.

Yep, I know about the OBB file, and it’s great for standard apps that are over 100MB, but in my case it doesn’t fit the requirement. There is a limit of 2 OBB files, both up to 2GB in size. For my requirement, the actual game resource bundles are less than 35MB each, and more games can be added as time goes by, so I don’t want the user to download a massive file every time a new game is released. If any of the games require new code, then a new APK has to be released, but if they are just re-skins of existing game types, then there isn’t a need for a new APK.

Apple has a great way of handling this with their On Demand Resource support, and I really wish Google would have gone down the same path and provided something similar to Apple’s implementation.

Anyhow, for my purposes, Android will require me to host the resource bundles, but for iOS it’ll be Apple that hosts them. Just trying to design a generic interface to serve both cases at the moment.

For anyone curious about the type of app, it’s a casino slots app with multiple slot games in it, and while it’s working well at the moment, there have been times that I’ve had to fight against the game engine just to get relatively simple things done. I really hope the C++ Cocos2d-x engine doesn’t get neglected moving forward, since it’s not a bad game engine to use.

Google has the same feature. It’s just released in beta: https://developer.android.com/guide/app-bundle/configure#dynamic_feature_modules

I just read through the details, and unfortunately it’s not quite the same as Apple’s implementation. It’s nice that it actually allows code in those dynamic modules, but the issue is that they must be built and uploaded at the same time as the base APK, at least from my understanding of the process. The Google servers handle the signing and splitting of the APK into the feature modules once entire bundle is uploaded. There doesn’t seem to be a way to upload new modules on their own.

It’s a useful feature for those who’s apps actually would benefit from using it, but won’t work in my case. :frowning:

But you said, the game code will be in the main APK. So you need a full bundle upload everytime you create a new game, but the user will only download the assets for games, which are used. The dynamic feature is 100% of what you requested, imho.

If i’m wrong, I don’t understand your game setup. What will be in the initial APK (binary?, assets?) and what will the use download later (only assets?).

The main app will have all the code and common resources. The app contains generic code for different types of games.

The downloadable bundles are for different games, and will have resources only (graphics/sound/configuration assets), no code. These resource bundles contain a game type identifier, so the main code knows which type of game to use in order to display these resources.

Now, focusing on Android for the moment, there is absolutely no point in updating the APK if there are no code changes. In my setup, new game bundles can be released at any time, without requiring the base code to change in the APK.

If I were to use the Google dynamic feature modules, I would have to upload a whole new APK every time I want to simply add a new game resource bundle, which means users would have to download/update their application from the Play Store. That is precisely what I don’t want the users to have to go through every time a new game resource bundle is available.

The only time the APK should be updated is if there is a new type of game that isn’t currently catered for within the application which requires new code.

So, once again, using the dynamic feature modules requires the entire APK to be uploaded every time there is any change to anything related to the app, even the assets. The link you posted explains exactly what the purpose of this feature is, and unfortunately it has nothing to do with what my requirements are. It’s meant as a way to reduce data downloaded by users for applications that exist in full on the Play Store, so the app retrieves only the parts the user needs.

I see. Your APK is just like scummVM and your games are the game data, you can attach to it.

You’re right. This feature isn’t support by the PlayStore. And I can’t believe that Apple allow devs to update content of their apps without a new review process. This will be unusual for Apple. But okay, I can’t check this.

Your assets need a “meta file” where the app can find any available games and after that the game can downloaded on demand. If I need such a feature for my game, I would create a Firebase project. The meta data will be in the Realtime Database or Cloud Firestore and the assets (as zip) would be in the Storage. This way the iOS can also benefit from it. - But this is the solution I would prefer, because I don’t want to configure a server by myself and I don’t know if this will be also your way of doing it.

I’m not 100% certain that Apple actually allows using content that they have not yet reviewed, but they do force you to have that content available on their own server unless it’s an enterprise application (where you can host on your own server). Perhaps they force you to host it on the Apple servers for that specific purpose (they can review it at any time), who knows. I haven’t got around yet to implementing the iOS platform specific code yet, so I’ll find out eventually.

Regarding the game discovery (or “meta file” as you called it), I’ve actually got that process running. It does involve my own server code. The entire ecosystem consists of the mobile client and a server (multiple Web API running on .NET Core), along with several databases (for different purposes) on the server tracking player accounts, game logic and game data etc. No game decisions are handled in the game client besides displaying the games, which stops the possibility of any form of cheating. The list of available games (including remote download location etc) is sent to the client app on every time it is started, so it always has a new list of what games are available.

It actually works pretty well at the moment, and while I could have chosen any other game engine for the mobile client, Cocos2d-x was a decent fit at the time I started this project. The bonus is that in order for anyone to steal certain game code, they’d need to go to a great deal of effort to reverse the binaries, which is usually enough of a deterrent not to bother doing so (unfortunately it’s happened to me before with C#/Unity releases).

So you have an own server right now? So why do you need the hosting of you assets at Apple/Google? I think your current setup will be good, because others do this as well. Even big mobile game publisher (looking at EA) are hosting the assets on their own servers. Everything you have in control is good.

Apple won’t allow it. Everything must be hosted on their own server.

As for Google, it’s precisely what I’m doing. The only thing the Google Play Store will have is the APK. The ZIP files with the games will all be hosted on my own server.

Right now I’m just designing a common interface so my app just uses that without worrying about the platform specific implementation. In a perfect world they’d make everything standard, but yeah, that’s just wishful thinking. :stuck_out_tongue:

This isn’t quite right. Every news magazine app hosts the content not at Apple. So why do they disallow it for games?

And Apple will never follow standards, because they can’t control it this way. Just think of the adapter hell on Apple devices.

Here’s the Apple info:

https://developer.apple.com/library/content/documentation/FileManagement/Conceptual/On_Demand_Resources_Guide/IntrotoHostingODR.html#//apple_ref/doc/uid/TP40015083-CH17-SW1

It’s in the first paragraph on that page.

There is a difference between dynamic content to display (like news feeds + photos for a magazine/newsreader, which can be sourced from anywhere) and assets that belong to the app (items which are specifically referenced in the application, which must be hosted on the Apple server). It seems that they do make that distinction.

I checked our app portfolio and we do have at least one app (not news feed or newspaper), which is loading the texts to display from our own servers. So we don’t have to update the app, if we want to change visible texts to the user. This also includes graphics. - The app is a telephony provider app, where the users can see there monthly uses traffic etc.

So I believe you can also host the game assets on your own server.

On-Demand resources are resource types that your app has direct references to (like resource tags, names etc). These kinds of resources must be hosted on the Apple servers, as per their policy and restrictions.

The text and graphics you are talking about is dynamic content which is purely displayed, same concept as web page content. This kind of content does not need to be hosted on Apple servers, since there are no hard-coded references in the application to the objects within that content.

I would love it if you were right and we could host app-referenced content on our own server, but after digging deeper into all of the Apple info, unfortunately that just isn’t what Apple allows.

But you said, your game logic is still in the compiled binary, so you only want to host the assets somewhere else. I don’t get the main difference between our apps and your game.

The game logic is in the binary, correct, and that game logic references specific resources. Since it has direct references to the resources, those resources must either be included within the initial bundle downloaded from the App Store, or hosted on Apple’s servers as ‘On-Demand Resources’. I’m not just stating this for the sake of it, this is what is explicitly stated in the Apple documentation that I linked in an earlier post.

The way your application works as you described it, and if I understand correctly, has no direct references to resources, and all it is literally doing is downloading data to be displayed. The content of that data does not affect the operation of your application.

In my case, I’ll be following the Apple guidelines to the word, because the way my app works requires that I make it work exactly as they describe.

Anyhow, it feels like we’re going around in circles. I have nothing further to add regarding this, and as I stated earlier, I really wish you were right about hosting resources on another server for the specific way my app works, but unfortunately that is not the case when it comes to iOS.