I have run into an implementation problem I would like to see ideas about.
Basically, for those who do not know, I have many "Mod Handler" objects I use for reading the content (usually items, blocks, and configs) of other mods. All of these work off the Java strategy known as "reflection", where fields and methods (variables and functions in most languages) are fetched from a class object by their names (and the class itself is also found by its name).
The problem lies here:
This system of course relies on the mods' code remaining unchanged. If, for example, Forestry renames its "Recipe" class to "CentrifugeRecipe", Class.forName("forestry.factory.gadgets.MachineCentrifuge$Recipe") will return null and the whole handler fails. Similarly, if MagicCrops restructures and renames half its fields, the item fetching there fails.
Now, traditionally what I have done is only support the most recent version. This mostly worked, but it meant that those not updating the other mod saw the compatibility break.
So I switched to a version-based system, where it intelligently loads the correct handler for the version. This worked, except:
The way these classes were created was as a singleton, i.e. only one instance was created, and that instance was fetched with a static getInstance() method. From there I could call whatever code I needed. However, this method, being static, was a property of the class. Therefore, if, for example, I want to load the OreBerry bush handler, I call OreBerryHandler.getInstance().bushID or whatever I need. The problem is, with multiple versions, that getInstance() only returns for the class I directly referenced. To dynamically load, I would need to use the same version checking metrics as the initialization does, and then have a massive and mess if-elseif-else system to differentiate.
Now, I could write a registry of sorts that intelligently returns the correct handler object....except:
They are not identical between versions. Some items get added, removed, or renamed, and as such methods, fields, and similar might be renamed, added, or removed. So, for example, the MagicCrops handler's old version has a "dropID" field for the experience drop. That field was removed for the new version, as that item was removed in the new MagicCrops.
I am on the verge of giving up on the whole version support system.