-
Notifications
You must be signed in to change notification settings - Fork 19
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Supporting multiple versions of Minecraft #99
Comments
Looking back at the process from updating GDMC-HTTP from Minecraft 1.19 to 1.20, it doesn't seem possible to support multiple versions of Minecraft simultaneously in the same distribution. The jar files are compiled for a specific Minecraft-Forge version. Having said that, I don't think there is anything fundamentally different between the APIs of these versions of Minecraft that would prevent me from back-porting the features I've created for GDMC-HTTP 1.4 (Minecraft 1.20) to Minecraft 1.19. The code relies a lot on code that's internal to Minecraft, so writing a wrapper so I could compile two versions simultaneously isn't trivial. Still, I do know that other mod developers have done this. They often even support very different mod frameworks such as Fabric + Forge at the same time using wrappers for either and a core of shared code. To keep it simple I could start with creating a branch from my current 1.20 version and start back-porting all the features I've created to Minecraft 1.19. The user will still need to install a specific version for their version of Minecraft, which I will likely indicate by suffxing the files with the Minecraft version (eg. On the topic of the NBT method: I do believe that working with the NBT format should be encouraged. It's a universal format that can contain both blocks and entities. And has the |
Thanks for reading that wall of text ;). Having separate GDMC-HTTP jars with the same API but for different Minecraft versions is exactly what I had in mind for "Cause 1 on the GDMC-HTTP side"! If that's maintainable, I think it would be the best solution. You will get more and more jars in each release, though. Also, don't worry, there's no need to hurry with this. The GDMC competition uses a set version anyway, and if the GDMC-HTTP API remains backwards compatible, multiple-Minecraft-support will even work retroactively! What do you mean with "the NBT method" and "the NBT format"? For blocks, I don't intend to discourage using NBT data (it's just one of the three components, along with ID/name and states). There's no The potential new endpoint you describe sounds very interesting! If you can let Minecraft itself do all the conversions, then that would greatly help with "Cause 2" as well. Can Minecraft convert in both directions (new->old and old->new)? |
I've started to see if and how I could back port the currently latest version of GDMC-HTTP (1.4.4-1.20.2) to work with Minecraft 1.19.2 such that there is complete feature parity no matter the Minecraft version. I'm happy to report this was relatively painless and from some initial testing it looks it behaves the same as 1.4.4 as well, including the huge performance boost introduced with version 1.4.0. I think I will be able to release a 1.5.0 update soon. This will be especially useful going forward when we want to include future Minecraft versions like the upcoming 1.21. Sorry for the confusion. I didn't explain what I meant with the "NBT method" very well. What I'm basically saying it that sending and receiving (S)NBT-formatted structure files via the When you're working with an older Minecraft version it cannot convert data to a version newer than it, so there are limitations. |
This sounds very good! If
That is unfortunate. That means this wouldn't work for the "new generator, old Minecraft" scenario. But it's better than nothing. |
Update from my side: with update v1.4.6 GDMC-HTTP now has full support for both 1.19.2 and 1.20.2 versions of game! |
Fantastic! Then I can go look into the GDPC side (cause 2). The changes will certainly be breaking, so this will be slated for 8.0, probably after this year's competition. I've been given permission by the developers of Amulet Core to use it in GDPC for Minecraft data conversion, which will help greatly. It will however come with some usage limitations for GDPC, since GDPC will then inherit the usage limitations from Amulet (Core)'s proprietary license: it can't be used commercially and can't be used in a system that competes with Amulet. I feel like these limitations are worth the benefit, however: Amulet's data conversion system is well-maintained, and, due to its use in Amulet, very well-tested. The design I currently have in mind is as follows:
|
The problem
There is a significant limitation (perhaps even design flaw) in GDPC: it cannot support multiple versions of Minecraft simultaneously. Or, differently said, new features in the library cannot be used when writing a generator for an older version of Minecraft, and older versions of the library (and thus old generators) cannot be used with newer versions of Minecraft.
There are two causes of this limitation:
Cause 1: GDPC depends on a minimum version of GDMC-HTTP, which has the same fundamental limitation: Each version of GDMC-HTTP only supports one specific version of Minecraft, with neither backwards nor forwards compatibility.
Cause 2: GDPC interacts with "Minecraft data" (blocks, entities, items) in a few places (see e.g. #98). I attempted to limit this as much as possible, but couldn't fully eliminate it. Currently, I believe these places are:
signData
/placeSign
,bookData
, etc.).WorldSlice
constructor.In an ideal world, it would be possible to write a generator using the latest version of GDPC and apply it to any out of a range of supported Minecraft version, and to take an old generator and to apply even to newer Minecraft versions, but the limitations above prevent this.
Why cause 1 must be solved first
I believe that adressing the minecraft data interactions (cause 2) is not useful, or has very limited use, before either GDMC-HTTP becomes backwards compatible with Minecraft versions or GDPC becomes backwards compatible with GDMC-HTTP versions. Abstractly, the reason is as follows: if GDPC inherently supports Minecraft versions X through Y, but requires GDMC-HTTP version >= Z, and GDMC-HTTP version Z requires Minecraft version Y, then by transivitiy, GDPC still only supports Minecraft version Y. There is no use to supporting Minecraft versions that are not supported by the minimum required version of GDMC-HTTP.
For a concrete example, consider issue #98. Issue #98 is about the sign helper functions like
placeSign
. The NBT data format for signs changed in Minecraft 1.20. If these functions would be updated to the >=1.20 format, they would no longer support <1.20 (cause 2). In #98, it is suggested to change the sign helper functions to check the version of Minecraft that is currently in use (this is not quite trivial, as I will explain under "Solving cause 2", but not impossible), and change their behavior depending on it. In principle, this is a good idea. However, consider the following. GDMC-HTTP 1.4.0 requires Minecraft 1.20.2, and later versions of GDMC-HTTP thus far have only supported later versions of Minecraft. So, if we want to implement features in GDPC that require functionality from GDMC-HTTP 1.4.0 (such as the improvedwithinBuildArea
support), GDPC will have to require GDMC-HTTP 1.4.0, and thus, by transitivity, Minecraft 1.20.2. So the behavior switch in the sign helpers would become useless.Solving cause 1
Cause 1 can be solved from either the GDMC-HTTP side or the GDPC side.
The GDMC-HTTP side
To solve cause 1 on the GDMC-HTTP side, GDMC-HTTP needs to become backwards compatible with regards to Minecraft. GDPC could then simply depend on the latest version of GDMC-HTTP. One way to do this might be for there to be versions of the mod for a range of Minecraft versions instead of just one: "GDMC-HTTP 1.4.0 for Minecraft 1.20.2", "GDMC-HTTP 1.4.0 for Minecraft 1.19.2", etc. By solving this on the GDMC-HTTP side, everyone who uses GDMC-HTTP would benefit, not just those who use GDPC.
I do not know how possible this is or how much work it would take. @Niels-NTG, I would like to hear your input on this!
The GDPC side
To solve cause 1 on the GDPC side, GDPC needs to become backwards compatible with regards to GDMC-HTTP. It might be possible to do this: we could introduce an abstract class
Interface
, and add multiple implementations such asGDMC_HTTP_1_3_3_Interface
,GDMC_HTTP_1_4_0_Interface
, etc. This would even allow things likeAmuletInterface
, so it may be beneficial regardless. All features that require interface support (such as build area enforcement) would then move to these concrete interface classes, with some classes not supporting all features and perhaps logging warnings when this is the case. However, I am not entirely sure if all interface-dependent features can be so easily grouped together.Solving cause 2
Once cause 1 is solved, we can consider solving cause 2. To reiterate, I believe the places where GDPC interacts with Minecraft data are:
signData
/placeSign
,bookData
, etc.).WorldSlice
constructor.WorldSlice
First of all,
WorldSlice
. This one might be the most problematic, since it essentially parses Minecraft's entire world format. I think the best way to make this Minecraft version-independent is to completely get rid of theGET /chunks
call and instead rely on higher-level GDMC-HTTP calls. GDMC-HTTP now supports getting 3D regions of blocks and biomes, and there is now a/heightmaps
endpoint, so this could very well be possible. If we don't switch to higher-level calls, there is no way to get around maintaining multiple implementations of theWorldSlice
parser for various versions of Minecraft.Blocks, entities and items
The other two parts, rotating/flipping blocks and NBT helpers, are fairly similar. They both deal with blocks, entities or items.
In #98, it was suggested to make a NBT helper check the active Minecraft version and switch on it. This approach could in principle be used by all NBT helpers and block transform functions. However, it has a few disadvantages:
Editor
instance now will, which will cause problems with cyclic imports and will certainly cause breaking changes in a lot of places.signData
.I think the ideal place to do version-conversions for Minecraft data is right before sending to or after receiving from GDMC-HTTP. This way, you capture all occurences of Minecraft data that needs to be converted, without requiring breaking changes anywhere else.
It seems that Amulet learned from the mistakes of MCEdit, because Amulet Core has a really clever solution to the version-conversion-problem in the form of PyMCTranslate. It uses a "universal format" for blocks (and I believe entities and items as well) which should not be directly used and can therefore be changed without breaking compatibility. When you read or write a block, you specify the Minecraft version you want to work in, and PyMCTranslate translates between that version and the universal format. And while I'm not sure about this, I believe this architecture even enables support for future Minecraft versions, since you could update
PyMCTranslate
without updating the rest of Amulet Core.I think it would be possible to utilize PyMCTranslate in GDPC by using it to convert to or from the current Minecraft version right before interacting with GDMC-HTTP. The only problem is that I'm unsure if this is allowed by its license, specificially its non-conpetition restriction. GDPC with GDMC-HTTP might fall under "competition" as described there. But if we could use it, this seems like it would be an ideal solution.
Summary
To support multiple versions of Minecraft with the same version of GDPC, the following is needed:
WorldSlice
.The text was updated successfully, but these errors were encountered: