It has been years and years and years since i first started playing Minecraft and the BIGGEST problem i have for it is waiting, after every update, for my favorite mods to be updated. Sometimes they just get abandoned.
It is infuriating and frustrating. Minecraft needs to implement better support so that mods don't break so easily when there is an update or so that updating a mod doesn't take so much time.
Seriously, i don't know how Minecraft has come so far without mod support which i am fairly certain was supposed to be an upcoming feature for the past 4 years.
It has been years and years and years since i first started playing Minecraft and the BIGGEST problem i have for it is waiting, after every update, for my favorite mods to be updated. Sometimes they just get abandoned.
It is infuriating and frustrating. Minecraft needs to implement better support so that mods don't break so easily when there is an update or so that updating a mod doesn't take so much time.
Seriously, i don't know how Minecraft has come so far without mod support which i am fairly certain was supposed to be an upcoming feature for the past 4 years.
Isn't that simple.
To explain why, I firstly need to explain why updates break things in the first place. Typically an application will have an official API, an API is basically a set of functions, classes and interfaces / templates separate from the actual program that other programs have access to. An API is typically used to communicate between some code and a parent application whilst introducing abstraction. Rather than directly adding something to a list, you tell the API that you want to add something to the list and the API adds it to the list, that way if the developers of the program change some code your mod / addon, on paper, isn't affected since the API on your end should remain the same.
The problem with Minecraft modding is Minecraft does not have an API like this. Rather than going to a set of separate classes and functions, you're sitting directly on top of the very code Mojang writes, and therefore that code you're using is subject to change. This is what breaks mods. If you want to set a block in the world, you call "World#setBlock(BlockPos pos, Block block)", it's not necessarily that exactly but that's roughly the function you call. Now, under 1.7.10 it was "World#setBlock(int x, int y, int z, Block block)", and under 1.6.4 it was "World#setBlock(int x, int y, int z, int blockID)". This method has changed over updates, so if you're developing a mod for 1.6.4 and someone tries to run it on 1.7.10, "World#setBlock(int , int y, int z, int blockID)" doesn't exist as it is now "World#setBlock(int x, int y, int z, Block block)", hence the game crashes. And 1.8 is even worse as you're attempting to call "World#setBlock(int x, int y, int z, Block block)", but it's now "World#setBlock(BlockPos pos, Block block)". This is part of the reason why updates break mods.
Now, to prevent this what should happen is you should have an API in the middle, so mod -> API -> game. Usually the API will have a function in place, virtually the same, that acts as an intermediary so if the function changes the API is still the same. So an API would say have "WorldManager.setBlockAt(int x, int y, int z, BlockInstance block)". BlockInstance is a virtual object which essentially maps to some other value, so BlockInstance.stone could map out to 1 for 1.6.4 or Blocks.block for 1.7.10, but it will always be BlockInstance.stone for your mod so nothing changes. And "int x, int y, int z" could easily be wrapped into a BlockPos in the API's code, so "int x, int y, int z" never changes, hence this function will never crash your game. Expand this to every function, and you have a cross-version-compatible API, on paper anyways. Mojang could change "setBlock(...)" to something completely different, in which case the API has to change and therefore your mod has to change, meaning the update broke your mod. However.
Doing this limits what mods can do. If you only ever give mods access to the API, mods can only do what the API allows, so what if a mod wants to do something the API doesn't allow it to? One of three things. One, the author simply drops whatever they want to do because it cannot be done cleanly. Two, the author looks to a third-party unofficial API that exposes whatever the author needs. Or three, the author uses some native API to access things they normally shouldn't have access to, such as Java's Reflection API which allows any Java code to essentially reference any object even if the object isn't in the classpath (so a mod, say Buildcraft, can reference a class in Thaumcraft without actually needing to have Thaumcraft as a dependency, in theory anyways). We typically do option two or three, two being we outsource specific things to third-party APIs and three being we take things into our own hands.
Forge satisfies most of our modding needs, and hence is the third-party API actually allowing us to mod the game cleanly, but in the cases that it doesn't allow us to do what we want to do, we either use another API (say if we want power but don't want to write out own system, we use the RF API), or we use bytecode injection to directly modify the game's code in a way that Forge is sort of okay with.
The second reason why updates break mods is because of something called obfuscation. Obfuscation basically is a security process used by developers to slow down modders from modifying and potentially cracking software. Obfuscation pretty much takes every object and gives it a random name unique within the set of given object types, so each function in the game has a different and random name, just like every class does, but where two functions belonging to the same class cannot share the same name, and two classes cannot share the same name, a function and a class can. Hopefully that was easy to understand, let me provide an example...
Say we have a class called "Human", a second class called "Parent" and a third class called "Child". "Human" has the function "Human#say(String whatToSay)", "Child" has the function "Child#pester(String whatIWant)" and "Parent" has the function "Parent#punish(String whatToPunishFor, int punishmentTime)". Both "Parent" and "Child" extend "Human", so they also have the "say(...)" function. The "pester(...)" and "punish(...)" functions just call "say(...)", which "say(...)" prints "whatToSay". "pester(...)" prints out "No, you're not having <whatIWant>!", and "punish(...)" prints out "BUT I WANT <whatToPunishFor>!!!". Take the code:
</div>
<div>Parent parent = new Parent();
Child child = new Child();
Child.pester("candy"); // Basically 'say("BUT I WANT candy!!!")'
Parent.punish("candy", 5); // Basically 'say("No, you're not having candy!")'</div>
<div>
Remember that Child and Parent both extend Human, so both can call "say(...)". Also recall that "pester(...)" and "punish(...)" print out what's explained above. So the code above can be broken down into basically creating a parent and a child, then the child asking / pestering for candy, and the parent denying the request / punishing the child for 5 minutes. Easy? Now let's obfuscate it... "Parent", "Child" and "Human" are now "gqu", "hwo" and "ghw" respectively, "Parent#punish(String whatToPunishFor, int punishmentTime)" is now "gqu#ghw(String phi, int fig)", "Child#pester(String whatIWant)" is now "hwo#iaf(String ogi)" and "Human#say(String whatToSay)" is now "ghw#paf(String igi)". Now let's check the code again...
</div>
<div>gqu tqs = new gqu();
hwo oho = new hwo();
oho.iaf("candy"); // Basically 'paf("BUT I WANT candy!!!")'
tgs.ghw("candy", 5); // Basically 'paf("No, you're not having candy!")'</div>
<div>
Forgetting the code we saw earlier, harder to read now huh? What may have taken maybe a couple hours scouring the source of a single file to see what something does could take weeks, months even looking over every single related file and class to see what this one class does. For a company wanting to protect their product, this is invaluable. Minecraft is put under the same process, open up one of the .jar files for any version and you'll see thousands of randomly named .class files, if you grab a JVM bytecode decompiler like JD-GUI, you'll see everything is pretty much named similarly.
Before making mods, some very patient people map out each random name to an SRG name, so "uqg" could be "func_41848_a", whilst "qqt" could be "class_14040_c". These, whilst still quite hard to read, make distinction between things much easier. "gqu" the class is different to "gqu" the function, as "gqu" the class is now "class_19491_b" whilst "gqu" the function is now "func_14919_a". Then, some SRG names are converted to readable names, so "func_11401_d" could be "setBlock", but "func_11401_c" remains the same.
The problem is obfuscation is shuffled between versions, one version "gqu" could be "World", the next it could be "ItemStack", meaning any mods intended for the former will crash the game with the latter. For a cross-version-compatible API you'd either need to remove obfuscation within mods, which has the same problems as before, or remove obfuscation altogether, which compromises security.
Rollback Post to RevisionRollBack
Author of the Clarity, Serenity, Sapphire & Halcyon shader packs for Minecraft: Java Edition.
Even with an official modding API, mods for 1.7 would most likely not work in 1.8 (due to the rendering overhaul), and mods in 1.8 would most likely not work in 1.9 (due to the dual-wielding and loot tables). Other games are relatively static, so mods are likely to function between versions, but Minecraft has some massive change every version. Sometimes it has a massive change in a sub-version.
They have said they will - there may or may not be an official modding api called "Workbench API".
The API has been in the works for several major releases, and promised several more major releases ago. At this point they do not officially support modding.
Rollback Post to RevisionRollBack
Author of the Clarity, Serenity, Sapphire & Halcyon shader packs for Minecraft: Java Edition.
It has been years and years and years since i first started playing Minecraft and the BIGGEST problem i have for it is waiting, after every update, for my favorite mods to be updated. Sometimes they just get abandoned.
It is infuriating and frustrating. Minecraft needs to implement better support so that mods don't break so easily when there is an update or so that updating a mod doesn't take so much time.
Seriously, i don't know how Minecraft has come so far without mod support which i am fairly certain was supposed to be an upcoming feature for the past 4 years.
bum
Isn't that simple.
To explain why, I firstly need to explain why updates break things in the first place. Typically an application will have an official API, an API is basically a set of functions, classes and interfaces / templates separate from the actual program that other programs have access to. An API is typically used to communicate between some code and a parent application whilst introducing abstraction. Rather than directly adding something to a list, you tell the API that you want to add something to the list and the API adds it to the list, that way if the developers of the program change some code your mod / addon, on paper, isn't affected since the API on your end should remain the same.
The problem with Minecraft modding is Minecraft does not have an API like this. Rather than going to a set of separate classes and functions, you're sitting directly on top of the very code Mojang writes, and therefore that code you're using is subject to change. This is what breaks mods. If you want to set a block in the world, you call "World#setBlock(BlockPos pos, Block block)", it's not necessarily that exactly but that's roughly the function you call. Now, under 1.7.10 it was "World#setBlock(int x, int y, int z, Block block)", and under 1.6.4 it was "World#setBlock(int x, int y, int z, int blockID)". This method has changed over updates, so if you're developing a mod for 1.6.4 and someone tries to run it on 1.7.10, "World#setBlock(int , int y, int z, int blockID)" doesn't exist as it is now "World#setBlock(int x, int y, int z, Block block)", hence the game crashes. And 1.8 is even worse as you're attempting to call "World#setBlock(int x, int y, int z, Block block)", but it's now "World#setBlock(BlockPos pos, Block block)". This is part of the reason why updates break mods.
Now, to prevent this what should happen is you should have an API in the middle, so mod -> API -> game. Usually the API will have a function in place, virtually the same, that acts as an intermediary so if the function changes the API is still the same. So an API would say have "WorldManager.setBlockAt(int x, int y, int z, BlockInstance block)". BlockInstance is a virtual object which essentially maps to some other value, so BlockInstance.stone could map out to 1 for 1.6.4 or Blocks.block for 1.7.10, but it will always be BlockInstance.stone for your mod so nothing changes. And "int x, int y, int z" could easily be wrapped into a BlockPos in the API's code, so "int x, int y, int z" never changes, hence this function will never crash your game. Expand this to every function, and you have a cross-version-compatible API, on paper anyways. Mojang could change "setBlock(...)" to something completely different, in which case the API has to change and therefore your mod has to change, meaning the update broke your mod. However.
Doing this limits what mods can do. If you only ever give mods access to the API, mods can only do what the API allows, so what if a mod wants to do something the API doesn't allow it to? One of three things. One, the author simply drops whatever they want to do because it cannot be done cleanly. Two, the author looks to a third-party unofficial API that exposes whatever the author needs. Or three, the author uses some native API to access things they normally shouldn't have access to, such as Java's Reflection API which allows any Java code to essentially reference any object even if the object isn't in the classpath (so a mod, say Buildcraft, can reference a class in Thaumcraft without actually needing to have Thaumcraft as a dependency, in theory anyways). We typically do option two or three, two being we outsource specific things to third-party APIs and three being we take things into our own hands.
Forge satisfies most of our modding needs, and hence is the third-party API actually allowing us to mod the game cleanly, but in the cases that it doesn't allow us to do what we want to do, we either use another API (say if we want power but don't want to write out own system, we use the RF API), or we use bytecode injection to directly modify the game's code in a way that Forge is sort of okay with.
The second reason why updates break mods is because of something called obfuscation. Obfuscation basically is a security process used by developers to slow down modders from modifying and potentially cracking software. Obfuscation pretty much takes every object and gives it a random name unique within the set of given object types, so each function in the game has a different and random name, just like every class does, but where two functions belonging to the same class cannot share the same name, and two classes cannot share the same name, a function and a class can. Hopefully that was easy to understand, let me provide an example...
Say we have a class called "Human", a second class called "Parent" and a third class called "Child". "Human" has the function "Human#say(String whatToSay)", "Child" has the function "Child#pester(String whatIWant)" and "Parent" has the function "Parent#punish(String whatToPunishFor, int punishmentTime)". Both "Parent" and "Child" extend "Human", so they also have the "say(...)" function. The "pester(...)" and "punish(...)" functions just call "say(...)", which "say(...)" prints "whatToSay". "pester(...)" prints out "No, you're not having <whatIWant>!", and "punish(...)" prints out "BUT I WANT <whatToPunishFor>!!!". Take the code:
Remember that Child and Parent both extend Human, so both can call "say(...)". Also recall that "pester(...)" and "punish(...)" print out what's explained above. So the code above can be broken down into basically creating a parent and a child, then the child asking / pestering for candy, and the parent denying the request / punishing the child for 5 minutes. Easy? Now let's obfuscate it... "Parent", "Child" and "Human" are now "gqu", "hwo" and "ghw" respectively, "Parent#punish(String whatToPunishFor, int punishmentTime)" is now "gqu#ghw(String phi, int fig)", "Child#pester(String whatIWant)" is now "hwo#iaf(String ogi)" and "Human#say(String whatToSay)" is now "ghw#paf(String igi)". Now let's check the code again...
Forgetting the code we saw earlier, harder to read now huh? What may have taken maybe a couple hours scouring the source of a single file to see what something does could take weeks, months even looking over every single related file and class to see what this one class does. For a company wanting to protect their product, this is invaluable. Minecraft is put under the same process, open up one of the .jar files for any version and you'll see thousands of randomly named .class files, if you grab a JVM bytecode decompiler like JD-GUI, you'll see everything is pretty much named similarly.
Before making mods, some very patient people map out each random name to an SRG name, so "uqg" could be "func_41848_a", whilst "qqt" could be "class_14040_c". These, whilst still quite hard to read, make distinction between things much easier. "gqu" the class is different to "gqu" the function, as "gqu" the class is now "class_19491_b" whilst "gqu" the function is now "func_14919_a". Then, some SRG names are converted to readable names, so "func_11401_d" could be "setBlock", but "func_11401_c" remains the same.
The problem is obfuscation is shuffled between versions, one version "gqu" could be "World", the next it could be "ItemStack", meaning any mods intended for the former will crash the game with the latter. For a cross-version-compatible API you'd either need to remove obfuscation within mods, which has the same problems as before, or remove obfuscation altogether, which compromises security.
Author of the Clarity, Serenity, Sapphire & Halcyon shader packs for Minecraft: Java Edition.
My Github page.
The entire Minecraft shader development community now has its own Discord server! Feel free to join and chat with all the developers!
Even with an official modding API, mods for 1.7 would most likely not work in 1.8 (due to the rendering overhaul), and mods in 1.8 would most likely not work in 1.9 (due to the dual-wielding and loot tables). Other games are relatively static, so mods are likely to function between versions, but Minecraft has some massive change every version. Sometimes it has a massive change in a sub-version.
System.out.err("Nope");
No support
Since Mojang does not officially support modding.
They have said they will - there may or may not be an official modding api called "Workbench API".
The API has been in the works for several major releases, and promised several more major releases ago. At this point they do not officially support modding.
Author of the Clarity, Serenity, Sapphire & Halcyon shader packs for Minecraft: Java Edition.
My Github page.
The entire Minecraft shader development community now has its own Discord server! Feel free to join and chat with all the developers!