Jump to content

Is it possible to develop backwards compatible mods?


Zeigfreid

Recommended Posts

I am learning to make mods.

 

Is it possible to develop a mod that is compatible with 1.7.10, using later versions of forge? I noticed that botania does not hardcode the minecraft version number into its gradle.build file, instead importing it from a config file. I haven't dug around in their git repo, so I'm not sure how this works, or to what end.

 

If so, are there some resources available for modders who are concerned with backwards compatibility?

 

I'm sure someone will ask so I'll just go ahead and explain: I have no particular attachment to any version of minecraft and, as a programmer, I would like to work using the latest versions of the tools available. However, I started wanting to write mods while playing around with Botania and Pam's Harvestcraft in "the 1.7.10 modpack". This is a server that some friends and I are playing on together, and I thought it would be cool to be able to add some simple blocks and items (proper tatami mats, for example).

 

Thank you!

Link to comment
Share on other sites

3 minutes ago, Zeigfreid said:

Is it possible to develop a mod that is compatible with 1.7.10

No this is impossible. In 1.8 a lot of things changed method names, models, etc. Its basically impossible for mods to be backwards compatible between minecraft versions like 1.10 to 1.11 but 1.11.0 to 1.11.1 would be possible.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

No, there is no mod compatibility at all between major Minecraft versions.

 

(Apart from odd cases like 1.9->1.0 which were mostly compatible - but don't count on that ever happening again).

 

Also worth noting that compatibility layers have been attempted in the past, most notably McJty's compatlayer - which worked pretty well between 1.10 and 1.11, but it's worth noting that he decided 1.12 was too different to be feasible to support and therefore gave up on it for 1.12.

Edited by desht
Link to comment
Share on other sites

5 minutes ago, Animefan8888 said:

No this is impossible. In 1.8 a lot of things changed method names, models, etc. Its basically impossible for mods to be backwards compatible between minecraft versions like 1.10 to 1.11 but 1.11.0 to 1.11.1 would be possible.

Well its actually 100% possibly if you're willing define backwards compatible as rewriting the mod for every version.

If your mod is very simple (just adds blocks & items etc.), you could also use/make a system (API) that handles all the registration & stuff while not externally changing from version to version (this still means you/someone else has to rewriting the mod for every version).

  • Like 1

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

OK right, if I make a wrapper to isolate my mod code from the forge APIs etc... that would achieve the result I desire.

 

What about things like the formats of the various json files? That's something I would not be able to encapsulate with a wrapper, if the formats have changed I would need to either... generate the json files from some common format, or write everything twice.

 

What would be a good guide to look at for porting from 1.7 to 1.8 ? (just to get a sense of the concerns involved)

 

What I will probably do is just learn 1.12.2, but I thank you, Cadiboo, for your advice! 

 

Quote

this still means you/someone else has to rewriting the mod for every version

It could mean that, but couldn't it also mean that you/someone just has to write a new wrapper for each supported forge version?

Edited by Zeigfreid
Link to comment
Share on other sites

12 minutes ago, Zeigfreid said:

What about things like the formats of the various json files? That's something I would not be able to encapsulate with a wrapper, if the formats have changed I would need to either... generate the json files from some common format, or write everything twice.

I did say "very simple mod", your wrapper could inject some autogenerated models (I'M NOT RECOMMENDING OR SUPPORTING OR ENCOURAGING OR ENDORSING DOING THAT!)

 

14 minutes ago, Zeigfreid said:

What would be a good guide to look at for porting from 1.7 to 1.8 ? (just to get a sense of the concerns involved)

Depends what your trying to port, I just ported a 1.7.10 rendering based mod to 1.12.2 (it took me almost a year to learn the stuff required, but the mod was pretty high level). If I remember correctly, aside from the rendering changes 1.7->1.8 wasn't that big of a change, so you could probably go straight from 1.7 to 1.12.2. The best guide is learn to mod in 1.12.2, then take that experience and use it to port the old mod.

 

17 minutes ago, Zeigfreid said:

It could mean that, but couldn't it also mean that you/someone just has to write a new wrapper for each supported forge version?

Forge code doesn't change too much except when a new version comes out (they save up forge changes for new MC versions), but yeah me/someone has to write a new wrapper for every supported forge version (which should be every forge version)

  • Like 1

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

I am actually kind of already porting a mod from 1.10 to 1.12 ^o^// I started working on this tutorial a few days ago, but I had downloaded the latest version of forge (1.12). This resulted in bugs involving the registry changes, which I had to fix, which promoted learning. Even though I now know that an updated version exists I'm going to do the rest of the 1.10 tutorial, porting it to 1.12 as I go. Adversity helps me learn!

 

Anyway, thanks again for your help! I'll be back with less annoying, more practical questions soon.

Link to comment
Share on other sites

1.10 -> 1.12 is relatively straightforward.  There will be some method name changes, which are generally fairly easy to work out using your IDE and examining the decompiled Minecraft source.  One big change is that null ItemStacks should never be used from 1.11 onwards, instead use ItemStack.EMPTY and ItemStack#isEmpty().  Missing null ItemStack usages is a common source of NPE's in ported mods, and they can be tricky to track down in some cases.  Other than that, recipe registration changed in 1.12 (recipes are now defined in JSON files for the most part, and while the old way can be made to work, it should be considered deprecated). And there are the registry changes, which it sounds like you're aware of.

 

Link to comment
Share on other sites

@Cadiboo @desht @Zeigfreid You are forgetting about obfuscation of Minecraft classes. In one version the Item class could be called a while in another it could be called b. You can't fix that by creating a wrapper.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

7 hours ago, Animefan8888 said:

@Cadiboo @desht @Zeigfreid You are forgetting about obfuscation of Minecraft classes. In one version the Item class could be called a while in another it could be called b. You can't fix that by creating a wrapper.

What I meant by a wrapper was an API built on top of Forge that handles all the registration, using an input system that doesn’t change per version. Why would you ever deal with unobfuscated Minecraft classes directly?

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

1 hour ago, Cadiboo said:

Why would you ever deal with unobfuscated Minecraft classes directly?

When your mod is compiled it doesnt just stay as extends Item or new ItemStack it is translated into the obfuscated names. Which is why using an IDEs built in compiler doesnt work, you have to use gradle.

VANILLA MINECRAFT CLASSES ARE THE BEST RESOURCES WHEN MODDING

I will be posting 1.15.2 modding tutorials on this channel. If you want to be notified of it do the normal YouTube stuff like subscribing, ect.

Forge and vanilla BlockState generator.

Link to comment
Share on other sites

2 hours ago, Animefan8888 said:

When your mod is compiled it doesnt just stay as extends Item or new ItemStack it is translated into the obfuscated names. Which is why using an IDEs built in compiler doesnt work, you have to use gradle.

Sorry, I thought this was related to the wrapper, obviously mods break between versions because of that

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

4 hours ago, Animefan8888 said:

When your mod is compiled it doesnt just stay as extends Item or new ItemStack it is translated into the obfuscated names. Which is why using an IDEs built in compiler doesnt work, you have to use gradle.

This is incorrect. Method and field names are reobfuscated from MCP to SRG names when you compile, but MCP and SRG class names are the same. Forge deobfuscates Minecraft from Notch to SRG names at runtime.

Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.

Link to comment
Share on other sites

The API approach mentioned above is logically sound, but practically it is more work than just doing the porting directly. Firstly, this all assumes that you will make  a fair number of mods to be worth considering such generalizing.

 

But if you do make lots of mods it is likely that each of your mods touches fairly different aspects of the game. Like one might add dimensions, another entities, another items and so forth. Sure there might be some cross-useful stuff, but generally modders end up making either a bunch of targeted mods or one comprehensive mod. So then making an abstraction layer beyond Forge itself doesn't make sense -- you'll be trying to generalize something that you only use a couple times and going through a number of hoops to accomplish even that.

 

I also struggled for a while trying to figure out the best way to support porting multiple mods, because frankly it is a lot of work. At one point I thought that even branching my code would be useful -- like start a mod in 1.7.10 then branch for each additional version up to 1.12.2 or whatever. However, I found that the code changes so much between versions that even that was a waste of time!

 

Honestly, with modding you have both the underlying Minecraft vanilla code as well as the Forge code both undergoing significant overhauls for each version. Heck even the upcoming 1.13 is going to be a huge rewrite!

 

The best thing in the end is just to organize your code in a useful and familiar way and then just put in the work for the porting.

 

One last tip: you need to pick your battles. For example, some things like Entities haven't really changed much through the various versions. But things like blocks have changed a lot with properties, blockstates, JSON models, and registry events all changing and now they are going to be "flattened"! So if you have a mod that focuses on Entities I would highly recommend trying to port it to as many versions as possible. But if you have a mod that focuses on Blocks I would recommend just concentrating on one or two suitable versions to support.

Edited by jabelar
  • Like 1

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

Actually I think we skipped the important thing, it’s pretty much no trouble to port a mod between versions if your code is easily readable and understandable. 

  • Like 1

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

20 hours ago, Animefan8888 said:

@Cadiboo @desht @Zeigfreid You are forgetting about obfuscation of Minecraft classes. In one version the Item class could be called a while in another it could be called b. You can't fix that by creating a wrapper.

And yet McJty's compatlayer allowed binary compatibility between mods for 1.10 and 1.11.  So it is possible, but probably more work than is worth it in the long run (as I mentioned, McJty dropped compatlayer for 1.12).

 

Best bet is just to keep your code as clean as possible, and put in the porting work when the time comes.  And pay attention to any PSA's & tutorials about what's changing ahead of time.

Link to comment
Share on other sites

13 hours ago, Animefan8888 said:

When your mod is compiled it doesnt just stay as extends Item or new ItemStack it is translated into the obfuscated names. Which is why using an IDEs built in compiler doesnt work, you have to use gradle.

Actually you may have a point, I think (I could be wrong) that 1.13 Forge is not going to do runtime deobfuscation so no more SRG names?

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

3 hours ago, desht said:

And yet McJty's compatlayer allowed binary compatibility between mods for 1.10 and 1.11.  So it is possible, but probably more work than is worth it in the long run (as I mentioned, McJty dropped compatlayer for 1.12).

 

Yes, it is definitely possible but as my long "essay" above notes it is rarely worth it. 1.10 to 1.11 was a rare transition with very little big things changing between them. Most versions are much more drastic.

 

But imagine going from a version before blockstates was introduced to afterwards -- you'd need to like replicate the whole system of one of the two approaches in order to make them compatible. Or imagine going from a version before capabilities to one afterwards, and so forth.

 

So like I said before -- you can do it but only if you "pick your battles". If your mod focuses on a specific thing like entities and that doesn't change much between versions then it might be worth a compatibility layer. 

Edited by jabelar
  • Like 2

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Link to comment
Share on other sites

1.7 > 1.12 i think is too much complex, but for 1.11 > 1.12 besides McJty, SquidDev did temporarialy a compat injection for ComputerCraft while dan200 didnt opened the source code.

You can talk with him on Computer Mods server (if you want i can send the inivitation link via DM).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Hello everyone, I'm making this post to seek help for my modded block, It's a special block called FrozenBlock supposed to take the place of an old block, then after a set amount of ticks, it's supposed to revert its Block State, Entity, data... to the old block like this :  The problem I have is that the system breaks when handling multi blocks (I tried some fix but none of them worked) :  The bug I have identified is that the function "setOldBlockFields" in the item's "setFrozenBlock" function gets called once for the 1st block of multiblock getting frozen (as it should), but gets called a second time BEFORE creating the first FrozenBlock with the data of the 1st block, hence giving the same data to the two FrozenBlock :   Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=head] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@73681674 BlockEntityData : id:"minecraft:bed",x:3,y:-60,z:-6} Old Block Fields set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=3, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} Frozen Block Entity set BlockState : Block{minecraft:black_bed}[facing=east,occupied=false,part=foot] BlockPos{x=2, y=-60, z=-6} BlockEntity : net.minecraft.world.level.block.entity.BedBlockEntity@6d1aa3da BlockEntityData : {id:"minecraft:bed",x:2,y:-60,z:-6} here is the code inside my custom "freeze" item :    @Override     public @NotNull InteractionResult useOn(@NotNull UseOnContext pContext) {         if (!pContext.getLevel().isClientSide() && pContext.getHand() == InteractionHand.MAIN_HAND) {             BlockPos blockPos = pContext.getClickedPos();             BlockPos secondBlockPos = getMultiblockPos(blockPos, pContext.getLevel().getBlockState(blockPos));             if (secondBlockPos != null) {                 createFrozenBlock(pContext, secondBlockPos);             }             createFrozenBlock(pContext, blockPos);             return InteractionResult.SUCCESS;         }         return super.useOn(pContext);     }     public static void createFrozenBlock(UseOnContext pContext, BlockPos blockPos) {         BlockState oldState = pContext.getLevel().getBlockState(blockPos);         BlockEntity oldBlockEntity = oldState.hasBlockEntity() ? pContext.getLevel().getBlockEntity(blockPos) : null;         CompoundTag oldBlockEntityData = oldState.hasBlockEntity() ? oldBlockEntity.serializeNBT() : null;         if (oldBlockEntity != null) {             pContext.getLevel().removeBlockEntity(blockPos);         }         BlockState FrozenBlock = setFrozenBlock(oldState, oldBlockEntity, oldBlockEntityData);         pContext.getLevel().setBlockAndUpdate(blockPos, FrozenBlock);     }     public static BlockState setFrozenBlock(BlockState blockState, @Nullable BlockEntity blockEntity, @Nullable CompoundTag blockEntityData) {         BlockState FrozenBlock = BlockRegister.FROZEN_BLOCK.get().defaultBlockState();         ((FrozenBlock) FrozenBlock.getBlock()).setOldBlockFields(blockState, blockEntity, blockEntityData);         return FrozenBlock;     }  
    • It is an issue with quark - update it to this build: https://www.curseforge.com/minecraft/mc-mods/quark/files/3642325
    • Remove Instant Massive Structures Mod from your server     Add new crash-reports with sites like https://paste.ee/  
    • Update your drivers: https://www.amd.com/en/support/graphics/amd-radeon-r9-series/amd-radeon-r9-200-series/amd-radeon-r9-280x
  • Topics

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.