Clicker Cookie's modding system is hand-down one of the most unique ones out there.
Mods are entirely loaded at runtime, meaning special care has to be taken in order for the saving/loading system to accommodate saving/loading mods that might literally just not be there but still be in the save. This is functionality that at the moment I still deem as important, but is also extremely painful to develop for, and I sincerely wish often that it didn't have to be this way.
Besides developer experience, there is obviously a problem in terms of user experience with this solution, most notable that users do not know what mods they have used on their save. We could, theoretically, warn the users with a popup telling them "these namespaces are not registered in the ModHandler but are in your save", but I don't accept this as a solution. Baring the fact that not all mods will have any save data at all, users will still have to keep note of the URL for every mod they use... worse a folder on their desktop with .js files for them all. Oof.
Unfortunately, excluding nuclear solutions such as adding a title menu that allows you to add mods before loading your save (although this is a genuinely really interesting idea), this is a very difficult situation to work around. We have two primary mod distribution methods: URL and File. Now, if we were to send a GET request to the site that hosts a mod file in between ClickerCookie registration and Game.PROTOTYPE.init() (henceforth "mod-loading time") and load the mod from there, such a task would be trivial. This is a genuinely really good way to load a mod automatically at the right time in initialization. This is simply not the case for files. We cannot arbitrarily access mod files on the users PCs. They have to be given to us. There are two solutions for this:
- We can present a popup to the user during this critical mod-loading time and ask them to load a mod with X namespace and give them a file picker dialog (probably give them an "Ignore" button too). This is not very user friendly and is kinda a band-aid solution.
- We can literally cache an entire mod's code into
IndexedDB. This is easily the most user-friendly but also the most difficult implementation to develop.
Even still, there are problems with the File distribution method in general, most notably updating the mod. URL is easy because it will always be up-to-date, it's fetched from the source each time. With files, anything is anything. I propose that, so users can easily tell when a mod is out of date, we should probably add a version property to ModMetadata. This should be shown in the mods list (#61) so that users could go to the mod distribution platform, see 1.9.0, note that they are on 1.7.5, and know to update. I am also not against mod developers adding their own automatic update checker, perhaps even to the point of implementing such as solution into existing abstractions to make this simpler.
Okay. We have some solutions for how we can save mods. This is good. New problem (or old depending on how long you've been in the modding scene): removing mods.
I have long chosen to opt for saying "to remove mods refresh the page" because removing a mod at runtime is truly an impossible feat for DX. Unfortunately, we have lost this luxury. What to do?
Honestly, the best solution is the laziest. In the mod list add a remove button, and when this list is closed if any mods were removed then save and refresh the page automatically or give the user a popup saying the page must be refreshed. It's a somewhat boring solution but also happens to be the only feasible one.
Clicker Cookie's modding system is hand-down one of the most unique ones out there.
Mods are entirely loaded at runtime, meaning special care has to be taken in order for the saving/loading system to accommodate saving/loading mods that might literally just not be there but still be in the save. This is functionality that at the moment I still deem as important, but is also extremely painful to develop for, and I sincerely wish often that it didn't have to be this way.
Besides developer experience, there is obviously a problem in terms of user experience with this solution, most notable that users do not know what mods they have used on their save. We could, theoretically, warn the users with a popup telling them "these namespaces are not registered in the
ModHandlerbut are in your save", but I don't accept this as a solution. Baring the fact that not all mods will have any save data at all, users will still have to keep note of the URL for every mod they use... worse a folder on their desktop with.jsfiles for them all. Oof.Unfortunately, excluding nuclear solutions such as adding a title menu that allows you to add mods before loading your save (although this is a genuinely really interesting idea), this is a very difficult situation to work around. We have two primary mod distribution methods: URL and File. Now, if we were to send a GET request to the site that hosts a mod file in between
ClickerCookieregistration andGame.PROTOTYPE.init()(henceforth "mod-loading time") and load the mod from there, such a task would be trivial. This is a genuinely really good way to load a mod automatically at the right time in initialization. This is simply not the case for files. We cannot arbitrarily access mod files on the users PCs. They have to be given to us. There are two solutions for this:IndexedDB. This is easily the most user-friendly but also the most difficult implementation to develop.Even still, there are problems with the File distribution method in general, most notably updating the mod. URL is easy because it will always be up-to-date, it's fetched from the source each time. With files, anything is anything. I propose that, so users can easily tell when a mod is out of date, we should probably add a
versionproperty toModMetadata. This should be shown in the mods list (#61) so that users could go to the mod distribution platform, see 1.9.0, note that they are on 1.7.5, and know to update. I am also not against mod developers adding their own automatic update checker, perhaps even to the point of implementing such as solution into existing abstractions to make this simpler.Okay. We have some solutions for how we can save mods. This is good. New problem (or old depending on how long you've been in the modding scene): removing mods.
I have long chosen to opt for saying "to remove mods refresh the page" because removing a mod at runtime is truly an impossible feat for DX. Unfortunately, we have lost this luxury. What to do?
Honestly, the best solution is the laziest. In the mod list add a remove button, and when this list is closed if any mods were removed then save and refresh the page automatically or give the user a popup saying the page must be refreshed. It's a somewhat boring solution but also happens to be the only feasible one.