diff --git a/README.md b/README.md index 9b67c19..54c2e7a 100644 --- a/README.md +++ b/README.md @@ -1,74 +1,114 @@ # Discombobulator A java preprocessor gradle plugin for Minecraft mod development. -This project seeks to improve the [ReplayMod preprocessor](https://github.com/ReplayMod/preprocessor) by Johni0702 in several ways +Allows you to develop for multiple Minecraft versions at the same time via statements in the comments -## Comparison -### Syntax -The ReplayMod preprocessor uses the following syntax: +This project seeks to improve the [ReplayMod preprocessor](https://github.com/ReplayMod/preprocessor) by Johni0702 in several ways. + +## Basic workflow +When developing, you can add preprocessor statements into your code via comments, which will comment in/out the code depending on the Minecraft version. + +A typical project may look like this: +``` +workspace +├── 1.19 +│ ├── src # 1.19 project source +│ └── build.gradle # 1.19 specific gradle config +├── MC1.21.11 +│ ├── src # 1.21.11 project source +│ └── build.gradle # 1.21.11 specific gradle config +├── src # Base project source +├── build.gradle # Discombobulator gradle config +├── common.gradle # Common build.gradle for all versions +└── settings.gradle +``` +The `Base project source` will contain the unified code for all Minecraft versions and will be committed to version control. + +In the `build.gradle` you can add your versions and the order in which they appear: +```gradle +discombobulator { + versions = [ + "1.21.11":"MC1.21.11" // If the subfolder is named differently than the version + "1.19":"", + ] +} +``` + +When running the `preprocessBase` task, the entire "Base project source" is copied to the subprojects, but with comments enabled/disabled depending on the code. + +When coding, run the `preprocessWatch` task, which watches for changes in your code. If a change occurs in a file, that file is then copied back to the base source and also to all other Minecraft versions. It's best to *not* run the task in your IDE but rather in a seperate terminal. Gradle usually locks down the IDE when running a gradle task and stops the IDE from updating the files correctly. A seperate terminal instance fixes that. + +If you ever forget to run the watch command, you can use `1.19:preprocessVersion` to preprocess the entire subprojects into all other versions. +## Syntax +### Version blocks +To enable/disable code in certain Minecraft versions, add preprocessor statements like this: ```java - //#if MC>=11200 - // This is the block for MC >= 1.12.0 + //# 1.21.11 + // This is the block for MC >= 1.21.11 category.addDetail(name, callable::call); - //#else - //$$ // This is the block for MC < 1.12.0 - //$$ category.setDetail(name, callable::call); - //#endif + //# 1.19 + // This is the block for MC >= 1.19 + category.setDetail(name, callable::call); + //# end ``` -While the syntax is powerful, in practice, a lot of it is simply unnecessary and bothersome to write. -We noticed how we *always* use the "greater equals" syntax paired with else. -Furthermore, we dislike the version numbering that was chosen (11200), as it does not support snapshots versions -and when reading it, you always need a second untangle the version in your head, especially with 12001, 11202 or 12101 +* The operator used is always the `greater or equal`-operator. +* The order does not matter +* The amount of spaces before and after the `#` does not matter, only a space and a version needs to be in the comment +* It always has to end with a `//# end` +#### Default keyword +Instead of a version, you can add `//# def` and it is basically the `else`-operator. Moreover, `def` will always resolve to the *lowest* version set in the build.gradle, in the example above it's 1.19. -Hence we simplified the syntax by making it the default operator: +So ideally, our example should look like this: ```java - //# 1.12 - // This is the block for MC >= 1.12.0 + //# 1.21.11 + // This is the block for MC >= 1.21.11 category.addDetail(name, callable::call); //# def - //$$ // This is the block for MC < 1.12.0 - //$$ category.setDetail(name, callable::call); + // This is the block for MC >= 1.19 + category.setDetail(name, callable::call); //# end ``` -With `# def` being the default lowest version -### Nesting -```java - //#if MC>=10904 - public CPacketResourcePackStatus makeStatusPacket(String hash, Action action) { - //#if MC>=11002 - return new CPacketResourcePackStatus(action); - //#else - //$$ return new CPacketResourcePackStatus(hash, action); - //#endif - } - //#else - //$$ public C19PacketResourcePackStatus makeStatusPacket(String hash, Action action) { - //$$ return new C19PacketResourcePackStatus(hash, action); - //$$ } - //#endif -``` -Nesting is also supported by adding # to the version: +This has the advantage, that if you ever want to downgrade your version, like 1.18 or lower, it will immediately work. + +#### Nesting +You can have preprocessor statements within preprocessor statements. However, to aid visibility, an additional `#` is added for each nesting level. ```java //# 1.9.4 + // Greater or equal than 1.9.4 public CPacketResourcePackStatus makeStatusPacket(String hash, Action action) { //## 1.10.2 + // Greater or equal than 1.10.4 return new CPacketResourcePackStatus(action); //## def - //$$ return new CPacketResourcePackStatus(hash, action); + // Only 1.9.4 + return new CPacketResourcePackStatus(hash, action); //## end } //# def - //$$ public C19PacketResourcePackStatus makeStatusPacket(String hash, Action action) { - //$$ return new C19PacketResourcePackStatus(hash, action); - //$$ } + // Below 1.9.4 + public C19PacketResourcePackStatus makeStatusPacket(String hash, Action action) { + return new C19PacketResourcePackStatus(hash, action); + } + //# end +``` +* A nested `## def` will resolve to the version of the parent block, in this case 1.9.4 +* You can add as many nesting levels as you like (or at least until the stack overflows, they are processed recursively) +* A nested block *has to* end with a `## end` +* The order once again does not matter, even in nested blocks + +#### Less than +Using a `less than`-operator is not common, but can still be achieved with `greater or equal`-operators +``` + //# 1.21.11 + //# def + // Enabled in versions below 1.21.11 + category.setDetail(name, callable::call); //# end ``` -With `## def` being the version of the parent block, in this case 1.9.4 ### Patterns -The ReplayMod patterns are quite involved, requiring an annotation and a [class](https://github.com/ReplayMod/ReplayMod/blob/193e51b3c2023e1d8382384aedebb9f046a82436/src/main/java/com/replaymod/core/versions/Patterns.java). -While that may be superior, we opted to apply patterns on a line by line basis: +Adding a pattern in an inline comment will make a simple search and replace in that line ```java System.out.println(mc.window); // @GetWindow; @@ -78,7 +118,7 @@ Multiple patterns being applied like so: Minecraft.getMinecraft().setWindow(mc.window); // @GetWindow,GetMinecraft; ``` and all of them being registered in the build.gradle -```groovy +```gradle discombobulator { patterns = [ GetWindow: [ @@ -91,14 +131,53 @@ discombobulator { ] } ``` -### Workflow -When editing code in ReplayMod, you can only edit and run one mod version at a time, -slowing things down considerably. +## Config +```gradle +plugins { + id 'discombobulator' version "${discombobulator_version}" +} -With Discombobulator, all versions are open at the same time -and you can edit the code in one version, which then gets copied to every other version after saving. +discombobulator { -The main src folder is updated as well, which then gets committed via git. No more "switching to the newest version" for committing! + // *Required* + // The versions in descending order. Lowest (e.g. 1.14.4) will be //# def + versions = [ + "26.1":"", + "1.21.11":"", + "1.20.6":"", + "1.19.4":"", + "1.18.2":"", + "1.17.1":"", + "1.16.5":"", + "1.16.1":"", + "1.15.2":"", + "1.14.4":"" + ] + // Uses the versions above, operates like version blocks with the greater or equal operator + patterns = [ + GetWindow: [ + "def": "mc.window", + "1.15.2": "mc.getWindow()" + ], + GetMinecraft: [ + //etc... + ] + ] + + // If true, inverts the version list, makes the default operator less or equal + // and sets the default to the highest version. + // You can technically simply invert the `versions` config above, but ehh... + inverted = false + + // Overwrites the default line feed to either "\n\r" or "\n" + // Can also be set by setting the system property "line.separator=\n" + defaultLineFeed = "\n" + + // Excludes file formats from being preprocessed, but still be copied to the folder + // Uses a org.apache.commons.io.filefilter.WildcardFileFilter to check + ignoredFileFormats = ["*.png"] +} +``` ## Setup -More can be found via the [Discombobulator-Template](https://github.com/MinecraftTAS/Discombobulator-Template) \ No newline at end of file +It's recommended to use the [Discombobulator-Template](https://github.com/MinecraftTAS/Discombobulator-Template) \ No newline at end of file