├── gradle ├── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties └── libs.versions.toml ├── settings.gradle.kts ├── src └── main │ └── java │ └── org │ └── cloudburstmc │ └── blockstateupdater │ ├── BlockStateUpdater.java │ ├── BlockStateUpdater_1_10_0.java │ ├── BlockStateUpdater_1_17_40.java │ ├── BlockStateUpdater_1_21_110.java │ ├── BlockStateUpdater_1_15_0.java │ ├── BlockStateUpdater_1_19_20.java │ ├── BlockStateUpdater_1_17_30.java │ ├── BlockStateUpdater_1_12_0.java │ ├── BlockStateUpdater_1_16_210.java │ ├── BlockStateUpdater_1_21_40.java │ ├── BlockStateUpdater_1_20_40.java │ ├── BlockStateUpdater_1_20_60.java │ ├── BlockStateUpdater_1_19_70.java │ ├── BlockStateUpdater_1_19_80.java │ ├── BlockStateUpdater_1_18_10.java │ ├── BlockStateUpdater_1_20_50.java │ ├── BlockStateUpdater_1_19_0.java │ ├── BlockStateUpdater_1_18_30.java │ ├── util │ ├── TagUtils.java │ ├── OrderedUpdater.java │ └── tagupdater │ │ ├── CompoundTagEditHelper.java │ │ ├── CompoundTagUpdaterContext.java │ │ └── CompoundTagUpdater.java │ ├── BlockStateUpdater_1_20_70.java │ ├── BlockStateUpdater_1_14_0.java │ ├── BlockStateUpdater_1_20_10.java │ ├── BlockStateUpdaters.java │ ├── BlockStateUpdater_1_20_80.java │ ├── BlockStateUpdaterBase.java │ ├── BlockStateUpdater_1_21_20.java │ ├── BlockStateUpdater_1_21_60.java │ ├── BlockStateUpdater_1_21_0.java │ ├── BlockStateUpdater_1_13_0.java │ ├── BlockStateUpdater_1_21_30.java │ ├── BlockStateUpdater_1_20_30.java │ ├── BlockStateUpdater_1_20_0.java │ ├── BlockStateUpdater_1_16_0.java │ └── BlockStateUpdater_1_21_10.java ├── .github └── workflows │ ├── deploy-release.yml │ ├── deploy-snapshot.yml │ └── deploy.yml ├── README.md ├── gradlew.bat ├── .gitignore ├── LICENSE └── gradlew /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CloudburstMC/BlockStateUpdater/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "block-state-updater" 2 | 3 | plugins { 4 | id("org.gradle.toolchains.foojay-resolver-convention") version ("0.4.0") 5 | } 6 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip 4 | networkTimeout=10000 5 | zipStoreBase=GRADLE_USER_HOME 6 | zipStorePath=wrapper/dists 7 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public interface BlockStateUpdater { 6 | 7 | void registerUpdaters(CompoundTagUpdaterContext context); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /gradle/libs.versions.toml: -------------------------------------------------------------------------------- 1 | [versions] 2 | junit = "5.9.2" 3 | 4 | [libraries] 5 | 6 | jackson-databind = { group = "com.fasterxml.jackson.core", name = "jackson-databind", version = "2.14.2" } 7 | lombok = { group = "org.projectlombok", name = "lombok", version = "1.18.26" } 8 | nbt = { group = "org.cloudburstmc", name = "nbt", version = "3.0.3.Final" } 9 | junit-jupiter-api = { group = "org.junit.jupiter", name = "junit-jupiter-api", version.ref = "junit" } 10 | junit-jupiter-engine = { group = "org.junit.jupiter", name = "junit-jupiter-engine", version.ref = "junit" } 11 | -------------------------------------------------------------------------------- /.github/workflows/deploy-release.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Release 2 | on: 3 | push: 4 | tags: 5 | - '*' 6 | 7 | jobs: 8 | deploy: 9 | uses: CloudburstMC/BlockStateUpdater/.github/workflows/deploy.yml@master 10 | with: 11 | deploy-url: "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/" 12 | secrets: 13 | DEPLOY_USERNAME: ${{ secrets.OSSRH_USERNAME }} 14 | DEPLOY_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} 15 | PGP_SECRET: ${{ secrets.MAVEN_CENTRAL_SECRET }} 16 | PGP_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_PASSPHRASE }} 17 | -------------------------------------------------------------------------------- /.github/workflows/deploy-snapshot.yml: -------------------------------------------------------------------------------- 1 | name: Deploy Snapshot 2 | on: 3 | push: 4 | branches: 5 | - 'master' 6 | 7 | jobs: 8 | deploy: 9 | uses: CloudburstMC/BlockStateUpdater/.github/workflows/deploy.yml@master 10 | with: 11 | deploy-url: "https://repo.opencollab.dev/maven-snapshots/" 12 | secrets: 13 | DEPLOY_USERNAME: ${{ secrets.OPENCOLLAB_USERNAME }} 14 | DEPLOY_PASSWORD: ${{ secrets.OPENCOLLAB_PASSWORD }} 15 | PGP_SECRET: ${{ secrets.MAVEN_CENTRAL_SECRET }} 16 | PGP_PASSPHRASE: ${{ secrets.MAVEN_CENTRAL_PASSPHRASE }} 17 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_10_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import lombok.AccessLevel; 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 8 | public class BlockStateUpdater_1_10_0 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_10_0(); 11 | 12 | @Override 13 | public void registerUpdaters(CompoundTagUpdaterContext context) { 14 | // TODO: mapped types. (I'm not sure if these are needed) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_17_40.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_17_40 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_17_40(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext context) { 11 | context.addUpdater(1, 16, 210, true) // Palette version wasn't bumped so far 12 | .match("name", "minecraft:sculk_catalyst") 13 | .visit("states") 14 | .tryAdd("bloom", (byte) 0); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_21_110.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_21_110 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_21_110(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 11 | ctx.addUpdater(1, 21, 110).match("name", "minecraft:chain") 12 | .edit("name", helper -> helper.replaceWith("name", "minecraft:iron_chain")); 13 | 14 | ctx.addUpdater(1, 21, 110) 15 | .match("name", "minecraft:lightning_rod") 16 | .visit("states") 17 | .tryAdd("powered_bit", (byte) 0); 18 | 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BlockStateUpdater 2 | 3 | Extracted block state mappings from the Minecraft: Bedrock Edition used to update versioned NBT tags found in LevelDB 4 | worlds to the latest version. 5 | 6 | ### Usage 7 | 8 | Updating legacy meta values to block states 9 | 10 | ```java 11 | NbtMap updatedTag = BlockStateUpdaters.updateBlockState(NbtMap.builder() 12 | .putString("name","minecraft:stone") 13 | .putShort("val",(short)1) 14 | .build(),0); 15 | ``` 16 | 17 | ### Maven 18 | 19 | ```xml 20 | 21 | 22 | 23 | nukkitx-repo-release 24 | https://repo.nukkitx.com/maven-releases/ 25 | 26 | 27 | 28 | 29 | 30 | org.cloudburstmc 31 | block-state-updater 32 | 1.19.80-SNAPSHOT 33 | 34 | 35 | ``` -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_15_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import lombok.AccessLevel; 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 8 | public class BlockStateUpdater_1_15_0 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_15_0(); 11 | 12 | @Override 13 | public void registerUpdaters(CompoundTagUpdaterContext context) { 14 | context.addUpdater(1, 15, 0) 15 | .match("name", "minecraft:kelp") 16 | .visit("states") 17 | .edit("age", helper -> { 18 | int age = (int) helper.getTag(); 19 | helper.replaceWith("kelp_age", age); 20 | }); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_19_20.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_19_20 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_19_20(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext context) { 11 | this.addProperty(context, "minecraft:muddy_mangrove_roots", "pillar_axis", "y"); 12 | } 13 | 14 | private void addProperty(CompoundTagUpdaterContext context, String identifier, String propertyName, Object value) { 15 | context.addUpdater(1, 18, 10, true) // Here we go again Mojang 16 | .match("name", identifier) 17 | .visit("states") 18 | .tryAdd(propertyName, value); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_17_30.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_17_30 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_17_30(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext context) { 11 | this.updateItemFrame("minecraft:frame", context); 12 | this.updateItemFrame("minecraft:glow_frame", context); 13 | } 14 | 15 | private void updateItemFrame(String name, CompoundTagUpdaterContext context) { 16 | context.addUpdater(1, 16, 210, true) // Palette version wasn't bumped so far 17 | .match("name", name) 18 | .visit("states") 19 | .tryAdd("item_frame_photo_bit", (byte) 0); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_12_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import lombok.AccessLevel; 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 8 | public class BlockStateUpdater_1_12_0 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_12_0(); 11 | 12 | @Override 13 | public void registerUpdaters(CompoundTagUpdaterContext context) { 14 | context.addUpdater(1, 12, 0) 15 | .match("name", "minecraft:coral_fan") 16 | .visit("states") 17 | .rename("direction", "coral_fan_direction"); 18 | 19 | context.addUpdater(1, 12, 0) 20 | .match("name", "minecraft:coral_fan_dead") 21 | .visit("states") 22 | .rename("direction", "coral_fan_direction"); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_16_210.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import lombok.AccessLevel; 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 8 | public class BlockStateUpdater_1_16_210 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_16_210(); 11 | 12 | private static void registerUpdater(CompoundTagUpdaterContext context, String name) { 13 | context.addUpdater(1, 16, 210) 14 | .match("name", name) 15 | .visit("states") 16 | .remove("deprecated"); 17 | } 18 | 19 | @Override 20 | public void registerUpdaters(CompoundTagUpdaterContext context) { 21 | registerUpdater(context, "minecraft:stripped_crimson_stem"); 22 | registerUpdater(context, "minecraft:stripped_warped_stem"); 23 | registerUpdater(context, "minecraft:stripped_crimson_hyphae"); 24 | registerUpdater(context, "minecraft:stripped_warped_hyphae"); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_call: 3 | inputs: 4 | deploy-url: 5 | description: 'The maven repository to deploy to' 6 | required: true 7 | type: string 8 | secrets: 9 | DEPLOY_USERNAME: 10 | required: true 11 | DEPLOY_PASSWORD: 12 | required: true 13 | PGP_SECRET: 14 | required: true 15 | PGP_PASSPHRASE: 16 | required: true 17 | 18 | jobs: 19 | publish: 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/checkout@v3 23 | - uses: actions/setup-java@v3 24 | with: 25 | distribution: 'temurin' 26 | java-version: '8' 27 | - name: Validate Gradle Wrapper 28 | uses: gradle/wrapper-validation-action@v1 29 | - name: Build 30 | uses: gradle/gradle-build-action@v2 31 | with: 32 | gradle-version: wrapper 33 | arguments: "publish" 34 | env: 35 | MAVEN_DEPLOY_USERNAME: ${{ secrets.DEPLOY_USERNAME }} 36 | MAVEN_DEPLOY_PASSWORD: ${{ secrets.DEPLOY_PASSWORD }} 37 | PGP_SECRET: ${{ secrets.PGP_SECRET }} 38 | PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} 39 | MAVEN_DEPLOY_URL: ${{ inputs.deploy-url }} 40 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_21_40.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_21_40 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_21_40(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 11 | // Skull blocks was now split into individual blocks 12 | // however, skull type was determined by block entity or item data, and we do not have that information here 13 | ctx.addUpdater(1, 21, 40) 14 | .match("name", "minecraft:skull") 15 | .edit("name", helper -> { 16 | helper.replaceWith("name", "minecraft:skeleton_skull"); 17 | }); 18 | 19 | 20 | // these are not vanilla updaters 21 | // but use this one to bump the version to 18163713 as that's what vanilla does 22 | ctx.addUpdater(1, 21, 40) 23 | .match("name", "minecraft:cherry_wood") 24 | .visit("states") 25 | .remove("stripped_bit"); 26 | 27 | ctx.addUpdater(1, 21, 40, false, false) 28 | .match("name", "minecraft:mangrove_wood") 29 | .visit("states") 30 | .remove("stripped_bit"); 31 | 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_40.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.OrderedUpdater; 4 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 5 | 6 | import static org.cloudburstmc.blockstateupdater.util.OrderedUpdater.*; 7 | 8 | public class BlockStateUpdater_1_20_40 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_40(); 11 | 12 | @Override 13 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 14 | this.addDirectionUpdater(ctx, "minecraft:chest", FACING_TO_CARDINAL); 15 | this.addDirectionUpdater(ctx, "minecraft:ender_chest", FACING_TO_CARDINAL); 16 | this.addDirectionUpdater(ctx, "minecraft:stonecutter_block", FACING_TO_CARDINAL); 17 | this.addDirectionUpdater(ctx, "minecraft:trapped_chest", FACING_TO_CARDINAL); 18 | } 19 | 20 | private void addDirectionUpdater(CompoundTagUpdaterContext ctx, String identifier, OrderedUpdater updater) { 21 | ctx.addUpdater(1, 20, 40) 22 | .match("name", identifier) 23 | .visit("states") 24 | .edit(updater.getOldProperty(), helper -> { 25 | int value = (int) helper.getTag(); 26 | helper.replaceWith(updater.getNewProperty(), updater.translate(value)); 27 | }); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_60.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_20_60 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_60(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 11 | ctx.addUpdater(1, 20, 60) 12 | .match("name", "minecraft:hard_stained_glass") 13 | .visit("states") 14 | .edit("color", helper -> { 15 | String color = (String) helper.getTag(); 16 | if (color.equals("silver")) { 17 | color = "light_gray"; 18 | } 19 | helper.getRootTag().put("name", "minecraft:hard_" + color + "_stained_glass"); 20 | }) 21 | .remove("color"); 22 | 23 | ctx.addUpdater(1, 20, 60) 24 | .match("name", "minecraft:hard_stained_glass_pane") 25 | .visit("states") 26 | .edit("color", helper -> { 27 | String color = (String) helper.getTag(); 28 | if (color.equals("silver")) { 29 | color = "light_gray"; 30 | } 31 | helper.getRootTag().put("name", "minecraft:hard_" + color + "_stained_glass_pane"); 32 | }) 33 | .remove("color"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_19_70.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_19_70 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_19_70(); 8 | 9 | public static final String[] COLORS = { 10 | "magenta", 11 | "pink", 12 | "green", 13 | "lime", 14 | "yellow", 15 | "black", 16 | "light_blue", 17 | "brown", 18 | "cyan", 19 | "orange", 20 | "red", 21 | "gray", 22 | "white", 23 | "blue", 24 | "purple", 25 | "silver" 26 | }; 27 | 28 | @Override 29 | public void registerUpdaters(CompoundTagUpdaterContext context) { 30 | for (String color : COLORS) { 31 | this.addColorUpdater(context, color); 32 | } 33 | } 34 | 35 | private void addColorUpdater(CompoundTagUpdaterContext context, String color) { 36 | context.addUpdater(1, 19, 70) 37 | .match("name", "minecraft:wool") 38 | .visit("states") 39 | .match("color", color) 40 | .edit("color", helper -> { 41 | if (color.equals("silver")) { 42 | helper.getRootTag().put("name", "minecraft:light_gray_wool"); 43 | } else { 44 | helper.getRootTag().put("name", "minecraft:" + color + "_wool"); 45 | } 46 | }) 47 | .remove("color"); 48 | 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_19_80.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_19_80 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_19_80(); 8 | 9 | private static final String[] WOOD = { 10 | "birch", 11 | "oak", 12 | "jungle", 13 | "spruce", 14 | "acacia", 15 | "dark_oak" 16 | }; 17 | 18 | @Override 19 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 20 | // It could be done the more clever way, but Mojang added 12 updaters, and so we do. 21 | for (int i = 0; i < WOOD.length; i++) { 22 | String type = WOOD[i]; 23 | this.addTypeUpdater(ctx, "minecraft:fence", "wood_type", type, "minecraft:" + type + "_fence"); 24 | if (i < 4) { 25 | this.addTypeUpdater(ctx, "minecraft:log", "old_log_type", type, "minecraft:" + type + "_log"); 26 | } else { 27 | this.addTypeUpdater(ctx, "minecraft:log2", "new_log_type", type, "minecraft:" + type + "_log"); 28 | } 29 | } 30 | } 31 | 32 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, String type, String newIdentifier) { 33 | context.addUpdater(1, 19, 80) 34 | .match("name", identifier) 35 | .visit("states") 36 | .match(typeState, type) 37 | .edit(typeState, helper -> helper.getRootTag().put("name", newIdentifier)) 38 | .remove(typeState); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_18_10.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_18_10 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_18_10(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext context) { 11 | context.addUpdater(1, 18, 10) 12 | .match("name", "minecraft:skull") 13 | .visit("states") 14 | .remove("no_drop_bit"); 15 | 16 | 17 | context.addUpdater(1, 18, 10) 18 | .match("name", "minecraft:glow_lichen") 19 | .visit("states") 20 | .tryEdit("multi_face_direction_bits", helper -> { 21 | int bits = (int) helper.getTag(); 22 | boolean north = (bits & (1 << 2)) != 0; 23 | boolean south = (bits & (1 << 3)) != 0; 24 | boolean west = (bits & (1 << 4)) != 0; 25 | if (north) { 26 | bits |= 1 << 4; 27 | } else { 28 | bits &= ~(1 << 4); 29 | } 30 | if (south) { 31 | bits |= 1 << 2; 32 | } else { 33 | bits &= ~(1 << 2); 34 | } 35 | if (west) { 36 | bits |= 1 << 3; 37 | } else { 38 | bits &= ~(1 << 3); 39 | } 40 | helper.replaceWith("multi_face_direction_bits", bits); 41 | }); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_50.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_20_50 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_50(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 11 | ctx.addUpdater(1, 20, 50) 12 | .match("name", "minecraft:planks") 13 | .visit("states") 14 | .edit("wood_type", helper -> { 15 | String type = (String) helper.getTag(); 16 | helper.getRootTag().put("name", "minecraft:" + type + "_planks"); 17 | }) 18 | .remove("wood_type"); 19 | 20 | ctx.addUpdater(1, 20, 50) 21 | .match("name", "minecraft:stone") 22 | .visit("states") 23 | .edit("stone_type", helper -> { 24 | String type = (String) helper.getTag(); 25 | switch (type) { 26 | case "andesite_smooth": 27 | type = "polished_andesite"; 28 | break; 29 | case "diorite_smooth": 30 | type = "polished_diorite"; 31 | break; 32 | case "granite_smooth": 33 | type = "polished_granite"; 34 | break; 35 | } 36 | helper.getRootTag().put("name", "minecraft:" + type); 37 | }) 38 | .remove("stone_type"); 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_19_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_19_0 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_19_0(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext context) { 11 | this.renameIdentifier(context, "minecraft:stone_slab", "minecraft:stone_block_slab"); 12 | this.renameIdentifier(context, "minecraft:stone_slab2", "minecraft:stone_block_slab2"); 13 | this.renameIdentifier(context, "minecraft:stone_slab3", "minecraft:stone_block_slab3"); 14 | this.renameIdentifier(context, "minecraft:stone_slab4", "minecraft:stone_block_slab4"); 15 | this.renameIdentifier(context, "minecraft:double_stone_slab", "minecraft:double_stone_block_slab"); 16 | this.renameIdentifier(context, "minecraft:double_stone_slab2", "minecraft:double_stone_block_slab2"); 17 | this.renameIdentifier(context, "minecraft:double_stone_slab3", "minecraft:double_stone_block_slab3"); 18 | this.renameIdentifier(context, "minecraft:double_stone_slab4", "minecraft:double_stone_block_slab4"); 19 | 20 | this.addProperty(context, "minecraft:sculk_shrieker", "can_summon", (byte) 0); 21 | 22 | } 23 | 24 | private void renameIdentifier(CompoundTagUpdaterContext context, String from, String to) { 25 | context.addUpdater(1, 18, 10, true) // Here we go again Mojang 26 | .match("name", from) 27 | .edit("name", helper -> helper.replaceWith("name", to)); 28 | } 29 | 30 | private void addProperty(CompoundTagUpdaterContext context, String identifier, String propertyName, Object value) { 31 | context.addUpdater(1, 18, 10, true) // Here we go again Mojang 32 | .match("name", identifier) 33 | .visit("states") 34 | .tryAdd(propertyName, value); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_18_30.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | public class BlockStateUpdater_1_18_30 implements BlockStateUpdater { 6 | 7 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_18_30(); 8 | 9 | @Override 10 | public void registerUpdaters(CompoundTagUpdaterContext context) { 11 | this.renameIdentifier(context, "minecraft:concretePowder", "minecraft:concrete_powder"); 12 | this.renameIdentifier(context, "minecraft:frog_egg", "minecraft:frog_spawn"); 13 | this.renameIdentifier(context, "minecraft:invisibleBedrock", "minecraft:invisible_bedrock"); 14 | this.renameIdentifier(context, "minecraft:movingBlock", "minecraft:moving_block"); 15 | this.renameIdentifier(context, "minecraft:pistonArmCollision", "minecraft:piston_arm_collision"); 16 | this.renameIdentifier(context, "minecraft:seaLantern", "minecraft:sea_lantern"); 17 | this.renameIdentifier(context, "minecraft:stickyPistonArmCollision", "minecraft:sticky_piston_arm_collision"); 18 | this.renameIdentifier(context, "minecraft:tripWire", "minecraft:trip_wire"); 19 | 20 | this.addPillarAxis(context, "minecraft:ochre_froglight"); 21 | this.addPillarAxis(context, "minecraft:pearlescent_froglight"); 22 | this.addPillarAxis(context, "minecraft:verdant_froglight"); 23 | } 24 | 25 | private void renameIdentifier(CompoundTagUpdaterContext context, String from, String to) { 26 | context.addUpdater(1, 18, 10, true) // Here we go again Mojang 27 | .match("name", from) 28 | .edit("name", helper -> helper.replaceWith("name", to)); 29 | } 30 | 31 | private void addPillarAxis(CompoundTagUpdaterContext context, String from) { 32 | context.addUpdater(1, 18, 10, true) // Here we go again Mojang 33 | .match("name", from) 34 | .visit("states") 35 | .tryAdd("pillar_axis", "y"); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/util/TagUtils.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater.util; 2 | 3 | import org.cloudburstmc.nbt.NbtList; 4 | import org.cloudburstmc.nbt.NbtMap; 5 | import org.cloudburstmc.nbt.NbtMapBuilder; 6 | import org.cloudburstmc.nbt.NbtType; 7 | 8 | import java.util.ArrayList; 9 | import java.util.LinkedHashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | public class TagUtils { 14 | 15 | public static Object toMutable(Object immutable) { 16 | if (immutable instanceof NbtMap) { 17 | NbtMap map = (NbtMap) immutable; 18 | Map mutable = new LinkedHashMap<>(); 19 | for (Map.Entry entry : map.entrySet()) { 20 | mutable.put(entry.getKey(), toMutable(entry.getValue())); 21 | } 22 | return mutable; 23 | } else if (immutable instanceof NbtList) { 24 | List list = new ArrayList<>(); 25 | for (Object value : (List) immutable) { 26 | list.add(toMutable(value)); 27 | } 28 | return list; 29 | } 30 | return immutable; 31 | } 32 | 33 | public static Object toImmutable(Object mutable) { 34 | if (mutable instanceof Map) { 35 | Map map = (Map) mutable; 36 | NbtMapBuilder immutable = NbtMap.builder(); 37 | for (Map.Entry entry : map.entrySet()) { 38 | immutable.put(entry.getKey(), toImmutable(entry.getValue())); 39 | } 40 | return immutable.build(); 41 | } else if (mutable instanceof List) { 42 | List list = new ArrayList<>(); 43 | NbtType type = NbtType.END; 44 | for (Object value : (List) mutable) { 45 | if (type == NbtType.END) { 46 | type = NbtType.byClass(value.getClass()); 47 | } 48 | list.add(toImmutable(value)); 49 | } 50 | return new NbtList(type, list); 51 | } 52 | return mutable; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_70.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | import java.util.Map; 6 | import java.util.function.Function; 7 | 8 | public class BlockStateUpdater_1_20_70 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_70(); 11 | 12 | @Override 13 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 14 | this.addTypeUpdater(ctx, "minecraft:double_wooden_slab", "wood_type", type -> "minecraft:" + type + "_double_slab"); 15 | this.addTypeUpdater(ctx, "minecraft:leaves", "old_leaf_type", type -> "minecraft:" + type + "_leaves"); 16 | this.addTypeUpdater(ctx, "minecraft:leaves2", "new_leaf_type", type -> "minecraft:" + type + "_leaves"); 17 | this.addTypeUpdater(ctx, "minecraft:wooden_slab", "wood_type", type -> "minecraft:" + type + "_slab"); 18 | 19 | ctx.addUpdater(1, 20, 70) 20 | .match("name", "minecraft:wood") 21 | .edit("states", helper -> { 22 | Map states = helper.getCompoundTag(); 23 | Object bit = states.remove("stripped_bit"); 24 | boolean toggles = bit instanceof Byte && (byte) bit == 1 || bit instanceof Boolean && (boolean) bit; 25 | 26 | String type = (String) states.remove("wood_type"); 27 | helper.getRootTag().put("name", toggles ? "minecraft:stripped_" + type + "_wood" : "minecraft:" + type + "_wood"); 28 | }); 29 | 30 | // Vanilla does not use updater for this block for some reason 31 | ctx.addUpdater(1, 20, 70, false, false) 32 | .match("name", "minecraft:grass") 33 | .edit("name", helper -> helper.replaceWith("name", "minecraft:grass_block")); 34 | } 35 | 36 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, Function rename) { 37 | context.addUpdater(1, 20, 70) 38 | .match("name", identifier) 39 | .visit("states") 40 | .edit(typeState, helper -> helper.getRootTag().put("name", rename.apply((String) helper.getTag()))) 41 | .remove(typeState); 42 | 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/util/OrderedUpdater.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater.util; 2 | 3 | import lombok.Getter; 4 | 5 | /** 6 | * Stores updates from ints to Strings. 7 | */ 8 | public class OrderedUpdater { 9 | 10 | public static final OrderedUpdater FACING_TO_BLOCK = new OrderedUpdater( 11 | "facing_direction", "minecraft:block_face", 12 | "down", "up", "north", "south", "west", "east"); 13 | 14 | public static final OrderedUpdater FACING_TO_CARDINAL = new OrderedUpdater( 15 | "facing_direction", "minecraft:cardinal_direction", 2, 16 | "north", "south", "west", "east"); 17 | 18 | public static final OrderedUpdater DIRECTION_TO_CARDINAL = new OrderedUpdater( 19 | "direction", "minecraft:cardinal_direction", 20 | "south", "west", "north", "east"); 21 | 22 | @Getter 23 | private final String oldProperty; 24 | @Getter 25 | private final String newProperty; 26 | 27 | private final String[] order; 28 | private final int offset; 29 | 30 | /** 31 | * {@link #OrderedUpdater(String, String, int, String...)} with an offset of 0 (old values start at 0) 32 | */ 33 | public OrderedUpdater(String oldProperty, String newProperty, String... order) { 34 | this(oldProperty, newProperty, 0, order); 35 | } 36 | 37 | /** 38 | * Creates an OrderedUpdater whose values are provided by the ordered array. 39 | * 40 | * @param oldProperty the old state property 41 | * @param newProperty the new state property 42 | * @param offset the difference between a value's old integer type and the value's index in the array. 43 | * If the first element has an old value of n, then the offset is n. 44 | * @param order an array of ordered values 45 | */ 46 | public OrderedUpdater(String oldProperty, String newProperty, int offset, String... order) { 47 | if (order.length < 1) { 48 | throw new IllegalArgumentException("empty order array"); 49 | } 50 | this.oldProperty = oldProperty; 51 | this.newProperty = newProperty; 52 | this.offset = offset; 53 | this.order = order; 54 | } 55 | 56 | public String translate(int value) { 57 | int index = value - offset; 58 | if (index < 0 || index >= order.length) { 59 | index = 0; 60 | } 61 | return order[index]; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/util/tagupdater/CompoundTagEditHelper.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater.util.tagupdater; 2 | 3 | import java.util.ArrayDeque; 4 | import java.util.Deque; 5 | import java.util.Map; 6 | 7 | import static java.util.Objects.requireNonNull; 8 | 9 | @SuppressWarnings("unchecked") 10 | public class CompoundTagEditHelper { 11 | private final Deque parentTag = new ArrayDeque<>(); 12 | private final Deque tagName = new ArrayDeque<>(); 13 | private Map rootTag; 14 | private Object tag; 15 | 16 | public CompoundTagEditHelper(Map tag) { 17 | this.rootTag = tag; 18 | this.tag = tag; 19 | } 20 | 21 | public Map getRootTag() { 22 | return rootTag; 23 | } 24 | 25 | public Map getCompoundTag() { 26 | return (Map) tag; 27 | } 28 | 29 | public Object getTag() { 30 | return tag; 31 | } 32 | 33 | public Map getParent() { 34 | if (!this.parentTag.isEmpty()) { 35 | Object tag = this.parentTag.peekLast(); 36 | if (tag instanceof Map) { 37 | return (Map) tag; 38 | } 39 | } 40 | return null; 41 | } 42 | 43 | public boolean canPopChild() { 44 | return !this.parentTag.isEmpty(); 45 | } 46 | 47 | public void popChild() { 48 | if (!this.parentTag.isEmpty()) { 49 | this.tag = this.parentTag.pollLast(); 50 | this.tagName.pollLast(); 51 | } 52 | } 53 | 54 | public void pushChild(String name) { 55 | requireNonNull(name, "name"); 56 | if (!(tag instanceof Map)) throw new IllegalStateException("Tag is not of Compound type"); 57 | this.parentTag.addLast(this.tag); 58 | this.tagName.addLast(name); 59 | this.tag = ((Map) this.tag).get(name); 60 | } 61 | 62 | public void replaceWith(String name, Object newTag) { 63 | this.tag = newTag; 64 | if (this.parentTag.isEmpty()) { 65 | this.rootTag = ((Map) tag); 66 | return; 67 | } 68 | Object tag = this.parentTag.getLast(); 69 | if (tag instanceof Map) { 70 | Map map = (Map) tag; 71 | map.remove(this.tagName.pollLast()); 72 | map.put(name, newTag); 73 | this.tagName.offerLast(name); 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_14_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import lombok.AccessLevel; 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 8 | public class BlockStateUpdater_1_14_0 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_14_0(); 11 | 12 | private static void addRailUpdater(String name, CompoundTagUpdaterContext context) { 13 | context.addUpdater(1, 14, 0) 14 | .match("name", name) 15 | .visit("states") 16 | .edit("rail_direction", helper -> { 17 | int direction = (int) helper.getTag(); 18 | if (direction > 5) direction = 0; 19 | helper.replaceWith("rail_direction", direction); 20 | }); 21 | } 22 | 23 | public static void addMaxStateUpdater(String name, String state, int maxValue, CompoundTagUpdaterContext context) { 24 | context.addUpdater(1, 14, 0) 25 | .match("name", name) 26 | .visit("states") 27 | .edit(state, helper -> { 28 | int value = (int) helper.getTag(); 29 | if (value > maxValue) value = maxValue; 30 | helper.replaceWith(state, value); 31 | }); 32 | } 33 | 34 | private static int convertWeirdoDirectionToFacing(int weirdoDirection) { 35 | switch (weirdoDirection) { 36 | case 0: 37 | return 5; 38 | case 1: 39 | return 4; 40 | case 2: 41 | return 3; 42 | case 3: 43 | default: 44 | return 2; 45 | } 46 | } 47 | 48 | @Override 49 | public void registerUpdaters(CompoundTagUpdaterContext context) { 50 | context.addUpdater(1, 14, 0) 51 | .match("name", "minecraft:frame") 52 | .visit("states") 53 | .edit("weirdo_direction", helper -> { 54 | int tag = (int) helper.getTag(); 55 | int newDirection = convertWeirdoDirectionToFacing(tag); 56 | helper.replaceWith("facing_direction", newDirection); 57 | }); 58 | 59 | addRailUpdater("minecraft:golden_rail", context); 60 | addRailUpdater("minecraft:detector_rail", context); 61 | addRailUpdater("minecraft:activator_rail", context); 62 | 63 | addMaxStateUpdater("minecraft:rail", "rail_direction", 9, context); 64 | addMaxStateUpdater("minecraft:cake", "bite_counter", 6, context); 65 | addMaxStateUpdater("minecraft:chorus_flower", "age", 5, context); 66 | addMaxStateUpdater("minecraft:cocoa", "age", 2, context); 67 | addMaxStateUpdater("minecraft:composter", "composter_fill_level", 8, context); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_10.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.OrderedUpdater; 4 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 5 | 6 | public class BlockStateUpdater_1_20_10 implements BlockStateUpdater { 7 | 8 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_10(); 9 | 10 | public static final String[] COLORS = { 11 | "magenta", 12 | "pink", 13 | "green", 14 | "lime", 15 | "yellow", 16 | "black", 17 | "light_blue", 18 | "brown", 19 | "cyan", 20 | "orange", 21 | "red", 22 | "gray", 23 | "white", 24 | "blue", 25 | "purple", 26 | "silver" 27 | }; 28 | 29 | /** 30 | * Literally the only block as of 1.20.30 that uses "minecraft:facing_direction"... 31 | * Seems equivalent to "minecraft:block_face" 32 | */ 33 | public static final OrderedUpdater OBSERVER_DIRECTIONS = new OrderedUpdater( 34 | "facing_direction", "minecraft:facing_direction", 35 | "down", "up", "north", "south", "west", "east"); 36 | 37 | @Override 38 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 39 | for (String color : COLORS) { 40 | if (color.equals("silver")) { 41 | this.addTypeUpdater(ctx, "minecraft:concrete", "color", color, "minecraft:light_gray_concrete"); 42 | this.addTypeUpdater(ctx, "minecraft:shulker_box", "color", color, "minecraft:light_gray_shulker_box"); 43 | } else { 44 | this.addTypeUpdater(ctx, "minecraft:concrete", "color", color, "minecraft:" + color + "_concrete"); 45 | this.addTypeUpdater(ctx, "minecraft:shulker_box", "color", color, "minecraft:" + color + "_shulker_box"); 46 | } 47 | } 48 | 49 | this.addFacingDirectionUpdater(ctx, "minecraft:observer"); 50 | } 51 | 52 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, String type, String newIdentifier) { 53 | context.addUpdater(1, 20, 10) 54 | .match("name", identifier) 55 | .visit("states") 56 | .match(typeState, type) 57 | .edit(typeState, helper -> helper.getRootTag().put("name", newIdentifier)) 58 | .remove(typeState); 59 | 60 | } 61 | 62 | private void addFacingDirectionUpdater(CompoundTagUpdaterContext ctx, String identifier) { 63 | ctx.addUpdater(1, 20, 10) 64 | .match("name", identifier) 65 | .visit("states") 66 | .edit(OBSERVER_DIRECTIONS.getOldProperty(), helper -> { 67 | int value = (int) helper.getTag(); 68 | helper.replaceWith(OBSERVER_DIRECTIONS.getNewProperty(), OBSERVER_DIRECTIONS.translate(value)); // Don't ask me why namespace is in vanilla state 69 | }); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%"=="" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%"=="" set DIRNAME=. 29 | @rem This is normally unused 30 | set APP_BASE_NAME=%~n0 31 | set APP_HOME=%DIRNAME% 32 | 33 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 34 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 35 | 36 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 37 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 38 | 39 | @rem Find java.exe 40 | if defined JAVA_HOME goto findJavaFromJavaHome 41 | 42 | set JAVA_EXE=java.exe 43 | %JAVA_EXE% -version >NUL 2>&1 44 | if %ERRORLEVEL% equ 0 goto execute 45 | 46 | echo. 47 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 48 | echo. 49 | echo Please set the JAVA_HOME variable in your environment to match the 50 | echo location of your Java installation. 51 | 52 | goto fail 53 | 54 | :findJavaFromJavaHome 55 | set JAVA_HOME=%JAVA_HOME:"=% 56 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 57 | 58 | if exist "%JAVA_EXE%" goto execute 59 | 60 | echo. 61 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 62 | echo. 63 | echo Please set the JAVA_HOME variable in your environment to match the 64 | echo location of your Java installation. 65 | 66 | goto fail 67 | 68 | :execute 69 | @rem Setup the command line 70 | 71 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 72 | 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if %ERRORLEVEL% equ 0 goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | set EXIT_CODE=%ERRORLEVEL% 85 | if %EXIT_CODE% equ 0 set EXIT_CODE=1 86 | if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% 87 | exit /b %EXIT_CODE% 88 | 89 | :mainEnd 90 | if "%OS%"=="Windows_NT" endlocal 91 | 92 | :omega 93 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdaters.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import org.cloudburstmc.nbt.NbtMap; 5 | import lombok.experimental.UtilityClass; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | @UtilityClass 12 | public class BlockStateUpdaters { 13 | 14 | private static final CompoundTagUpdaterContext CONTEXT; 15 | private static final int LATEST_VERSION; 16 | 17 | static { 18 | List updaters = new ArrayList<>(); 19 | updaters.add(BlockStateUpdaterBase.INSTANCE); 20 | updaters.add(BlockStateUpdater_1_10_0.INSTANCE); 21 | updaters.add(BlockStateUpdater_1_12_0.INSTANCE); 22 | updaters.add(BlockStateUpdater_1_13_0.INSTANCE); 23 | updaters.add(BlockStateUpdater_1_14_0.INSTANCE); 24 | updaters.add(BlockStateUpdater_1_15_0.INSTANCE); 25 | updaters.add(BlockStateUpdater_1_16_0.INSTANCE); 26 | updaters.add(BlockStateUpdater_1_16_210.INSTANCE); 27 | updaters.add(BlockStateUpdater_1_17_30.INSTANCE); 28 | updaters.add(BlockStateUpdater_1_17_40.INSTANCE); 29 | updaters.add(BlockStateUpdater_1_18_10.INSTANCE); 30 | updaters.add(BlockStateUpdater_1_18_30.INSTANCE); 31 | updaters.add(BlockStateUpdater_1_19_0.INSTANCE); 32 | updaters.add(BlockStateUpdater_1_19_20.INSTANCE); 33 | updaters.add(BlockStateUpdater_1_19_70.INSTANCE); 34 | updaters.add(BlockStateUpdater_1_19_80.INSTANCE); 35 | updaters.add(BlockStateUpdater_1_20_0.INSTANCE); 36 | updaters.add(BlockStateUpdater_1_20_10.INSTANCE); 37 | updaters.add(BlockStateUpdater_1_20_30.INSTANCE); 38 | updaters.add(BlockStateUpdater_1_20_40.INSTANCE); 39 | updaters.add(BlockStateUpdater_1_20_50.INSTANCE); 40 | updaters.add(BlockStateUpdater_1_20_60.INSTANCE); 41 | updaters.add(BlockStateUpdater_1_20_70.INSTANCE); 42 | updaters.add(BlockStateUpdater_1_20_80.INSTANCE); 43 | updaters.add(BlockStateUpdater_1_21_0.INSTANCE); 44 | updaters.add(BlockStateUpdater_1_21_10.INSTANCE); 45 | updaters.add(BlockStateUpdater_1_21_20.INSTANCE); 46 | updaters.add(BlockStateUpdater_1_21_30.INSTANCE); 47 | updaters.add(BlockStateUpdater_1_21_40.INSTANCE); 48 | updaters.add(BlockStateUpdater_1_21_60.INSTANCE); 49 | updaters.add(BlockStateUpdater_1_21_110.INSTANCE); 50 | 51 | CompoundTagUpdaterContext context = new CompoundTagUpdaterContext(); 52 | updaters.forEach(updater -> updater.registerUpdaters(context)); 53 | CONTEXT = context; 54 | LATEST_VERSION = context.getLatestVersion(); 55 | } 56 | 57 | public static NbtMap updateBlockState(NbtMap tag, int version) { 58 | return CONTEXT.update(tag, version); 59 | } 60 | 61 | public static void serializeCommon(Map builder, String id) { 62 | builder.put("version", LATEST_VERSION); 63 | builder.put("name", id); 64 | } 65 | 66 | public static int getLatestVersion() { 67 | return LATEST_VERSION; 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_80.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | import java.util.function.Function; 6 | 7 | public class BlockStateUpdater_1_20_80 implements BlockStateUpdater { 8 | 9 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_80(); 10 | 11 | @Override 12 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 13 | this.addTypeUpdater(ctx, "minecraft:sapling", "sapling_type", type -> "minecraft:" + type + "_sapling"); 14 | this.addTypeUpdater(ctx, "minecraft:red_flower", "flower_type", type -> { 15 | switch (type) { 16 | case "tulip_orange": 17 | return "minecraft:orange_tulip"; 18 | case "tulip_pink": 19 | return "minecraft:pink_tulip"; 20 | case "tulip_white": 21 | return "minecraft:white_tulip"; 22 | case "oxeye": 23 | return "minecraft:oxeye_daisy"; 24 | case "orchid": 25 | return "minecraft:blue_orchid"; 26 | case "houstonia": 27 | return "minecraft:azure_bluet"; 28 | case "tulip_red": 29 | return "minecraft:red_tulip"; 30 | default: 31 | return "minecraft:" + type; 32 | } 33 | }); 34 | 35 | this.addTypeUpdater(ctx, "minecraft:coral_fan", "coral_color", type -> { 36 | switch (type) { 37 | case "blue": 38 | return "minecraft:tube_coral_fan"; 39 | case "pink": 40 | return "minecraft:brain_coral_fan"; 41 | case "purple": 42 | return "minecraft:bubble_coral_fan"; 43 | case "yellow": 44 | return "minecraft:horn_coral_fan"; 45 | case "red": 46 | default: 47 | return "minecraft:fire_coral_fan"; 48 | } 49 | }); 50 | 51 | this.addTypeUpdater(ctx, "minecraft:coral_fan_dead", "coral_color", type -> { 52 | switch (type) { 53 | case "blue": 54 | return "minecraft:dead_tube_coral_fan"; 55 | case "pink": 56 | return "minecraft:dead_brain_coral_fan"; 57 | case "purple": 58 | return "minecraft:dead_bubble_coral_fan"; 59 | case "yellow": 60 | return "minecraft:dead_horn_coral_fan"; 61 | case "red": 62 | default: 63 | return "minecraft:dead_fire_coral_fan"; 64 | } 65 | }); 66 | 67 | 68 | // This is not official updater, but they correctly removed sapling_type 69 | ctx.addUpdater(1, 20, 80, false, false) 70 | .match("name", "minecraft:bamboo_sapling") 71 | .visit("states") 72 | .remove("sapling_type"); 73 | } 74 | 75 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, Function rename) { 76 | context.addUpdater(1, 20, 80) 77 | .match("name", identifier) 78 | .visit("states") 79 | .edit(typeState, helper -> helper.getRootTag().put("name", rename.apply((String) helper.getTag()))) 80 | .remove(typeState); 81 | 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdaterBase.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import com.fasterxml.jackson.databind.JsonNode; 4 | import com.fasterxml.jackson.databind.ObjectMapper; 5 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 6 | import lombok.AccessLevel; 7 | import lombok.NoArgsConstructor; 8 | 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.HashMap; 12 | import java.util.Iterator; 13 | import java.util.LinkedHashMap; 14 | import java.util.Map; 15 | 16 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 17 | public class BlockStateUpdaterBase implements BlockStateUpdater { 18 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdaterBase(); 19 | 20 | public static final Map[]> LEGACY_BLOCK_DATA_MAP = new HashMap<>(); 21 | private static final ObjectMapper JSON_MAPPER = new ObjectMapper(); 22 | 23 | static { 24 | JsonNode node; 25 | try (InputStream stream = BlockStateUpdater.class.getClassLoader().getResourceAsStream("legacy_block_data_map.json")) { 26 | node = JSON_MAPPER.readTree(stream); 27 | } catch (IOException e) { 28 | throw new AssertionError("Error loading legacy block data map", e); 29 | } 30 | 31 | Iterator> iterator = node.fields(); 32 | while (iterator.hasNext()) { 33 | Map.Entry entry = iterator.next(); 34 | String name = entry.getKey(); 35 | JsonNode stateNodes = entry.getValue(); 36 | 37 | int size = stateNodes.size(); 38 | Map[] states = new Map[size]; 39 | for (int i = 0; i < size; i++) { 40 | states[i] = convertStateToCompound(stateNodes.get(i)); 41 | } 42 | 43 | LEGACY_BLOCK_DATA_MAP.put(name, states); 44 | } 45 | } 46 | 47 | private static Map convertStateToCompound(JsonNode node) { 48 | Map tag = new LinkedHashMap<>(); 49 | Iterator> iterator = node.fields(); 50 | while (iterator.hasNext()) { 51 | Map.Entry entry = iterator.next(); 52 | String name = entry.getKey(); 53 | JsonNode value = entry.getValue(); 54 | switch (value.getNodeType()) { 55 | case BOOLEAN: 56 | tag.put(name, value.booleanValue()); 57 | break; 58 | case NUMBER: 59 | tag.put(name, value.intValue()); 60 | break; 61 | case STRING: 62 | tag.put(name, value.textValue()); 63 | break; 64 | default: 65 | throw new UnsupportedOperationException("Invalid state type"); 66 | } 67 | } 68 | return tag; 69 | } 70 | 71 | @Override 72 | public void registerUpdaters(CompoundTagUpdaterContext context) { 73 | context.addUpdater(0, 0, 0) 74 | .regex("name", "minecraft:.+") 75 | .regex("val", "[0-9]+") 76 | .addCompound("states") 77 | .tryEdit("states", helper -> { 78 | Map tag = helper.getCompoundTag(); 79 | Map parent = helper.getParent(); 80 | String id = (String) parent.get("name"); 81 | short val = (short) parent.get("val"); 82 | Map[] statesArray = LEGACY_BLOCK_DATA_MAP.get(id); 83 | if (statesArray != null) { 84 | if (val >= statesArray.length) val = 0; 85 | tag.putAll(statesArray[val]); 86 | } 87 | }) 88 | .remove("val"); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/util/tagupdater/CompoundTagUpdaterContext.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater.util.tagupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.TagUtils; 4 | import org.cloudburstmc.nbt.NbtMap; 5 | import org.cloudburstmc.nbt.NbtMapBuilder; 6 | 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | import java.util.Map; 10 | 11 | public class CompoundTagUpdaterContext { 12 | 13 | private final List updaters = new ArrayList<>(); 14 | 15 | private static int mergeVersions(int baseVersion, int updaterVersion) { 16 | return updaterVersion | baseVersion; 17 | } 18 | 19 | private static int baseVersion(int version) { 20 | return version & 0xFFFFFF00; 21 | } 22 | 23 | public static int updaterVersion(int version) { 24 | return version & 0x000000FF; 25 | } 26 | 27 | public static int makeVersion(int major, int minor, int patch) { 28 | return (patch << 8) | (minor << 16) | (major << 24); 29 | } 30 | 31 | public CompoundTagUpdater.Builder addUpdater(int major, int minor, int patch) { 32 | return this.addUpdater(major, minor, patch, false); 33 | } 34 | 35 | public CompoundTagUpdater.Builder addUpdater(int major, int minor, int patch, boolean resetVersion) { 36 | return this.addUpdater(major, minor, patch, resetVersion, true); 37 | } 38 | 39 | public CompoundTagUpdater.Builder addUpdater(int major, int minor, int patch, boolean resetVersion, boolean bumpVersion) { 40 | int version = makeVersion(major, minor, patch); 41 | CompoundTagUpdater prevUpdater = this.getLatestUpdater(); 42 | 43 | int updaterVersion; 44 | if (resetVersion || prevUpdater == null || baseVersion(prevUpdater.getVersion()) != version) { 45 | updaterVersion = 0; 46 | } else { 47 | updaterVersion = updaterVersion(prevUpdater.getVersion()); 48 | if (bumpVersion) { 49 | updaterVersion++; 50 | } 51 | } 52 | version = mergeVersions(version, updaterVersion); 53 | 54 | CompoundTagUpdater updater = new CompoundTagUpdater(version); 55 | this.updaters.add(updater); 56 | this.updaters.sort(null); 57 | return updater.builder(); 58 | } 59 | 60 | public NbtMap update(NbtMap tag, int version) { 61 | Map updated = this.updateStates0(tag, version); 62 | 63 | if (updated == null && version != this.getLatestVersion()) { 64 | NbtMapBuilder builder = tag.toBuilder(); 65 | builder.putInt("version", this.getLatestVersion()); 66 | return builder.build(); 67 | } else if (updated == null) { 68 | return tag; 69 | } else { 70 | updated.put("version", this.getLatestVersion()); 71 | return (NbtMap) TagUtils.toImmutable(updated); 72 | } 73 | } 74 | 75 | public NbtMap updateStates(NbtMap tag, int version) { 76 | Map updated = this.updateStates0(tag, version); 77 | return updated == null ? tag : (NbtMap) TagUtils.toImmutable(updated); 78 | } 79 | 80 | private Map updateStates0(NbtMap tag, int version) { 81 | Map mutableTag = null; 82 | boolean updated = false; 83 | for (CompoundTagUpdater updater : updaters) { 84 | if (updater.getVersion() < version) { 85 | continue; 86 | } 87 | 88 | if (mutableTag == null) { 89 | mutableTag = (Map) TagUtils.toMutable(tag); 90 | } 91 | updated |= updater.update(mutableTag); 92 | } 93 | 94 | if (mutableTag == null || !updated) { 95 | return null; 96 | } 97 | return mutableTag; 98 | } 99 | 100 | private CompoundTagUpdater getLatestUpdater() { 101 | return this.updaters.isEmpty() ? null : this.updaters.get(this.updaters.size() - 1); 102 | } 103 | 104 | public int getLatestVersion() { 105 | CompoundTagUpdater updater = this.getLatestUpdater(); 106 | return updater == null ? 0 : updater.getVersion(); 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by https://www.toptal.com/developers/gitignore/api/java,gradle,intellij+all,windows,linux 2 | # Edit at https://www.toptal.com/developers/gitignore?templates=java,gradle,intellij+all,windows,linux 3 | 4 | ### Intellij+all ### 5 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 6 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 7 | 8 | # User-specific stuff 9 | .idea/**/workspace.xml 10 | .idea/**/tasks.xml 11 | .idea/**/usage.statistics.xml 12 | .idea/**/dictionaries 13 | .idea/**/shelf 14 | 15 | # AWS User-specific 16 | .idea/**/aws.xml 17 | 18 | # Generated files 19 | .idea/**/contentModel.xml 20 | 21 | # Sensitive or high-churn files 22 | .idea/**/dataSources/ 23 | .idea/**/dataSources.ids 24 | .idea/**/dataSources.local.xml 25 | .idea/**/sqlDataSources.xml 26 | .idea/**/dynamic.xml 27 | .idea/**/uiDesigner.xml 28 | .idea/**/dbnavigator.xml 29 | 30 | # Gradle 31 | .idea/**/gradle.xml 32 | .idea/**/libraries 33 | 34 | # Gradle and Maven with auto-import 35 | # When using Gradle or Maven with auto-import, you should exclude module files, 36 | # since they will be recreated, and may cause churn. Uncomment if using 37 | # auto-import. 38 | # .idea/artifacts 39 | # .idea/compiler.xml 40 | # .idea/jarRepositories.xml 41 | # .idea/modules.xml 42 | # .idea/*.iml 43 | # .idea/modules 44 | # *.iml 45 | # *.ipr 46 | 47 | # CMake 48 | cmake-build-*/ 49 | 50 | # Mongo Explorer plugin 51 | .idea/**/mongoSettings.xml 52 | 53 | # File-based project format 54 | *.iws 55 | 56 | # IntelliJ 57 | out/ 58 | 59 | # mpeltonen/sbt-idea plugin 60 | .idea_modules/ 61 | 62 | # JIRA plugin 63 | atlassian-ide-plugin.xml 64 | 65 | # Cursive Clojure plugin 66 | .idea/replstate.xml 67 | 68 | # SonarLint plugin 69 | .idea/sonarlint/ 70 | 71 | # Crashlytics plugin (for Android Studio and IntelliJ) 72 | com_crashlytics_export_strings.xml 73 | crashlytics.properties 74 | crashlytics-build.properties 75 | fabric.properties 76 | 77 | # Editor-based Rest Client 78 | .idea/httpRequests 79 | 80 | # Android studio 3.1+ serialized cache file 81 | .idea/caches/build_file_checksums.ser 82 | 83 | ### Intellij+all Patch ### 84 | # Ignore everything but code style settings and run configurations 85 | # that are supposed to be shared within teams. 86 | 87 | .idea/* 88 | .idea/ 89 | 90 | !.idea/codeStyles 91 | !.idea/runConfigurations 92 | 93 | ### Java ### 94 | # Compiled class file 95 | *.class 96 | 97 | # Log file 98 | *.log 99 | 100 | # BlueJ files 101 | *.ctxt 102 | 103 | # Mobile Tools for Java (J2ME) 104 | .mtj.tmp/ 105 | 106 | # Package Files # 107 | *.jar 108 | *.war 109 | *.nar 110 | *.ear 111 | *.zip 112 | *.tar.gz 113 | *.rar 114 | 115 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 116 | hs_err_pid* 117 | replay_pid* 118 | 119 | ### Linux ### 120 | *~ 121 | 122 | # temporary files which can be created if a process still has a handle open of a deleted file 123 | .fuse_hidden* 124 | 125 | # KDE directory preferences 126 | .directory 127 | 128 | # Linux trash folder which might appear on any partition or disk 129 | .Trash-* 130 | 131 | # .nfs files are created when an open file is removed but is still being accessed 132 | .nfs* 133 | 134 | ### Windows ### 135 | # Windows thumbnail cache files 136 | Thumbs.db 137 | Thumbs.db:encryptable 138 | ehthumbs.db 139 | ehthumbs_vista.db 140 | 141 | # Dump file 142 | *.stackdump 143 | 144 | # Folder config file 145 | [Dd]esktop.ini 146 | 147 | # Recycle Bin used on file shares 148 | $RECYCLE.BIN/ 149 | 150 | # Windows Installer files 151 | *.cab 152 | *.msi 153 | *.msix 154 | *.msm 155 | *.msp 156 | 157 | # Windows shortcuts 158 | *.lnk 159 | 160 | ### Gradle ### 161 | .gradle 162 | **/build/ 163 | !src/**/build/ 164 | 165 | # Ignore Gradle GUI config 166 | gradle-app.setting 167 | 168 | # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) 169 | !gradle-wrapper.jar 170 | 171 | # Avoid ignore Gradle wrappper properties 172 | !gradle-wrapper.properties 173 | 174 | # Cache of project 175 | .gradletasknamecache 176 | 177 | # Eclipse Gradle plugin generated files 178 | # Eclipse Core 179 | .project 180 | # JDT-specific (Eclipse Java Development Tools) 181 | .classpath 182 | 183 | ### Gradle Patch ### 184 | # Java heap dump 185 | *.hprof 186 | 187 | # End of https://www.toptal.com/developers/gitignore/api/java,gradle,intellij+all,windows,linux 188 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_21_20.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | import java.util.function.Function; 6 | 7 | public class BlockStateUpdater_1_21_20 implements BlockStateUpdater { 8 | 9 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_21_20(); 10 | 11 | @Override 12 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 13 | ctx.addUpdater(1, 21, 20) 14 | .match("name", "minecraft:light_block") 15 | .visit("states") 16 | .edit("block_light_level", helper -> helper.getRootTag().put("name", "minecraft:light_block_" + helper.getTag())) 17 | .remove("block_light_level"); 18 | 19 | 20 | this.addTypeUpdater(ctx, "minecraft:sandstone", "sand_stone_type", type -> { 21 | switch (type) { 22 | case "cut": 23 | return "minecraft:cut_sandstone"; 24 | case "heiroglyphs": 25 | return "minecraft:chiseled_sandstone"; 26 | case "smooth": 27 | return "minecraft:smooth_sandstone"; 28 | case "default": 29 | default: 30 | return "minecraft:sandstone"; 31 | } 32 | }); 33 | 34 | this.addTypeUpdater(ctx, "minecraft:quartz_block", "chisel_type", type -> { 35 | switch (type) { 36 | case "chiseled": 37 | return "minecraft:chiseled_quartz_block"; 38 | case "lines": 39 | return "minecraft:quartz_pillar"; 40 | case "smooth": 41 | return "minecraft:smooth_quartz"; 42 | case "default": 43 | default: 44 | return "minecraft:quartz_block"; 45 | } 46 | }); 47 | 48 | this.addTypeUpdater(ctx, "minecraft:red_sandstone", "sand_stone_type", type -> { 49 | switch (type) { 50 | case "cut": 51 | return "minecraft:cut_red_sandstone"; 52 | case "heiroglyphs": 53 | return "minecraft:chiseled_red_sandstone"; 54 | case "smooth": 55 | return "minecraft:smooth_red_sandstone"; 56 | case "default": 57 | default: 58 | return "minecraft:red_sandstone"; 59 | } 60 | }); 61 | 62 | this.addTypeUpdater(ctx, "minecraft:sand", "sand_type", type -> { 63 | switch (type) { 64 | case "red": 65 | return "minecraft:red_sand"; 66 | case "normal": 67 | default: 68 | return "minecraft:sand"; 69 | } 70 | }); 71 | 72 | this.addTypeUpdater(ctx, "minecraft:dirt", "dirt_type", type -> { 73 | switch (type) { 74 | case "coarse": 75 | return "minecraft:coarse_dirt"; 76 | case "normal": 77 | default: 78 | return "minecraft:dirt"; 79 | } 80 | }); 81 | 82 | this.addTypeUpdater(ctx, "minecraft:anvil", "damage", type -> { 83 | switch (type) { 84 | case "broken": 85 | return "minecraft:damaged_anvil"; 86 | case "slightly_damaged": 87 | return "minecraft:chipped_anvil"; 88 | case "very_damaged": 89 | return "minecraft:deprecated_anvil"; 90 | case "undamaged": 91 | default: 92 | return "minecraft:anvil"; 93 | } 94 | }); 95 | 96 | // Vanilla does not use updater for this block for some reason 97 | ctx.addUpdater(1, 21, 20, false, false) 98 | .match("name", "minecraft:yellow_flower") 99 | .edit("name", helper -> { 100 | helper.replaceWith("name", "minecraft:dandelion"); 101 | }); 102 | } 103 | 104 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, Function rename) { 105 | context.addUpdater(1, 21, 20) 106 | .match("name", identifier) 107 | .visit("states") 108 | .edit(typeState, helper -> helper.getRootTag().put("name", rename.apply((String) helper.getTag()))) 109 | .remove(typeState); 110 | 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_21_60.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.OrderedUpdater; 4 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 5 | 6 | import java.util.Map; 7 | 8 | import static org.cloudburstmc.blockstateupdater.util.OrderedUpdater.DIRECTION_TO_CARDINAL; 9 | 10 | public class BlockStateUpdater_1_21_60 implements BlockStateUpdater { 11 | 12 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_21_60(); 13 | 14 | @Override 15 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 16 | this.addDirectionUpdater(ctx, "minecraft:acacia_door", DIRECTION_TO_CARDINAL); 17 | this.addDirectionUpdater(ctx, "minecraft:acacia_fence_gate", DIRECTION_TO_CARDINAL); 18 | this.addDirectionUpdater(ctx, "minecraft:bamboo_door", DIRECTION_TO_CARDINAL); 19 | this.addDirectionUpdater(ctx, "minecraft:bamboo_fence_gate", DIRECTION_TO_CARDINAL); 20 | this.addDirectionUpdater(ctx, "minecraft:birch_door", DIRECTION_TO_CARDINAL); 21 | this.addDirectionUpdater(ctx, "minecraft:birch_fence_gate", DIRECTION_TO_CARDINAL); 22 | this.addDirectionUpdater(ctx, "minecraft:cherry_door", DIRECTION_TO_CARDINAL); 23 | this.addDirectionUpdater(ctx, "minecraft:cherry_fence_gate", DIRECTION_TO_CARDINAL); 24 | this.addDirectionUpdater(ctx, "minecraft:copper_door", DIRECTION_TO_CARDINAL); 25 | this.addDirectionUpdater(ctx, "minecraft:crimson_door", DIRECTION_TO_CARDINAL); 26 | this.addDirectionUpdater(ctx, "minecraft:crimson_fence_gate", DIRECTION_TO_CARDINAL); 27 | this.addDirectionUpdater(ctx, "minecraft:dark_oak_door", DIRECTION_TO_CARDINAL); 28 | this.addDirectionUpdater(ctx, "minecraft:dark_oak_fence_gate", DIRECTION_TO_CARDINAL); 29 | this.addDirectionUpdater(ctx, "minecraft:exposed_copper_door", DIRECTION_TO_CARDINAL); 30 | this.addDirectionUpdater(ctx, "minecraft:fence_gate", DIRECTION_TO_CARDINAL); 31 | this.addDirectionUpdater(ctx, "minecraft:iron_door", DIRECTION_TO_CARDINAL); 32 | this.addDirectionUpdater(ctx, "minecraft:jungle_door", DIRECTION_TO_CARDINAL); 33 | this.addDirectionUpdater(ctx, "minecraft:jungle_fence_gate", DIRECTION_TO_CARDINAL); 34 | this.addDirectionUpdater(ctx, "minecraft:mangrove_door", DIRECTION_TO_CARDINAL); 35 | this.addDirectionUpdater(ctx, "minecraft:mangrove_fence_gate", DIRECTION_TO_CARDINAL); 36 | this.addDirectionUpdater(ctx, "minecraft:oxidized_copper_door", DIRECTION_TO_CARDINAL); 37 | this.addDirectionUpdater(ctx, "minecraft:pale_oak_door", DIRECTION_TO_CARDINAL); 38 | this.addDirectionUpdater(ctx, "minecraft:pale_oak_fence_gate", DIRECTION_TO_CARDINAL); 39 | this.addDirectionUpdater(ctx, "minecraft:spruce_door", DIRECTION_TO_CARDINAL); 40 | this.addDirectionUpdater(ctx, "minecraft:spruce_fence_gate", DIRECTION_TO_CARDINAL); 41 | this.addDirectionUpdater(ctx, "minecraft:warped_door", DIRECTION_TO_CARDINAL); 42 | this.addDirectionUpdater(ctx, "minecraft:warped_fence_gate", DIRECTION_TO_CARDINAL); 43 | this.addDirectionUpdater(ctx, "minecraft:waxed_copper_door", DIRECTION_TO_CARDINAL); 44 | this.addDirectionUpdater(ctx, "minecraft:waxed_exposed_copper_door", DIRECTION_TO_CARDINAL); 45 | this.addDirectionUpdater(ctx, "minecraft:waxed_oxidized_copper_door", DIRECTION_TO_CARDINAL); 46 | this.addDirectionUpdater(ctx, "minecraft:waxed_weathered_copper_door", DIRECTION_TO_CARDINAL); 47 | this.addDirectionUpdater(ctx, "minecraft:weathered_copper_door", DIRECTION_TO_CARDINAL); 48 | this.addDirectionUpdater(ctx, "minecraft:wooden_door", DIRECTION_TO_CARDINAL); 49 | 50 | ctx.addUpdater(1, 21, 60) 51 | .match("name", "minecraft:creaking_heart") 52 | .visit("states") 53 | .tryEdit("active", helper -> { 54 | Object bit = helper.getTag(); 55 | boolean active = bit instanceof Byte && (byte) bit == 1 || bit instanceof Boolean && (boolean) bit; 56 | helper.replaceWith("creaking_heart_state", active ? "awake" : "uprooted"); 57 | }); 58 | 59 | } 60 | 61 | private void addDirectionUpdater(CompoundTagUpdaterContext ctx, String identifier, OrderedUpdater updater) { 62 | ctx.addUpdater(1, 21, 60) 63 | .match("name", identifier) 64 | .visit("states") 65 | .edit(updater.getOldProperty(), helper -> { 66 | int value = (int) helper.getTag(); 67 | helper.replaceWith(updater.getNewProperty(), updater.translate(value)); 68 | }); 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_21_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | import java.util.function.Function; 6 | 7 | public class BlockStateUpdater_1_21_0 implements BlockStateUpdater { 8 | 9 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_21_0(); 10 | 11 | @Override 12 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 13 | ctx.addUpdater(1, 21, 0) 14 | .match("name", "minecraft:coral_block") 15 | .edit("states", helper -> { 16 | String type = (String) helper.getCompoundTag().remove("coral_color"); 17 | Object bit = helper.getCompoundTag().remove("dead_bit"); 18 | boolean dead = bit instanceof Byte && (byte) bit == 1 || bit instanceof Boolean && (boolean) bit; 19 | 20 | String newName; 21 | switch (type) { 22 | case "blue": 23 | newName = "minecraft:" + (dead ? "dead_" : "") + "tube_coral_block"; 24 | break; 25 | case "pink": 26 | newName = "minecraft:" + (dead ? "dead_" : "") + "brain_coral_block"; 27 | break; 28 | case "purple": 29 | newName = "minecraft:" + (dead ? "dead_" : "") + "bubble_coral_block"; 30 | break; 31 | case "yellow": 32 | newName = "minecraft:" + (dead ? "dead_" : "") + "horn_coral_block"; 33 | break; 34 | case "red": 35 | default: 36 | newName = "minecraft:" + (dead ? "dead_" : "") + "fire_coral_block"; 37 | break; 38 | } 39 | helper.getRootTag().put("name", newName); 40 | }); 41 | 42 | this.addTypeUpdater(ctx, "minecraft:double_plant", "double_plant_type", type -> { 43 | switch (type) { 44 | case "syringa": 45 | return "minecraft:lilac"; 46 | case "grass": 47 | return "minecraft:tall_grass"; 48 | case "fern": 49 | return "minecraft:large_fern"; 50 | case "rose": 51 | return "minecraft:rose_bush"; 52 | case "paeonia": 53 | return "minecraft:peony"; 54 | case "sunflower": 55 | default: 56 | return "minecraft:sunflower"; 57 | } 58 | }); 59 | 60 | this.addTypeUpdater(ctx, "minecraft:stone_block_slab", "stone_slab_type", type -> { 61 | switch (type) { 62 | case "quartz": 63 | return "minecraft:quartz_slab"; 64 | case "wood": 65 | return "minecraft:petrified_oak_slab"; 66 | case "stone_brick": 67 | return "minecraft:stone_brick_slab"; 68 | case "brick": 69 | return "minecraft:brick_slab"; 70 | case "smooth_stone": 71 | return "minecraft:smooth_stone_slab"; 72 | case "sandstone": 73 | return "minecraft:sandstone_slab"; 74 | case "nether_brick": 75 | return "minecraft:nether_brick_slab"; 76 | case "cobblestone": 77 | default: 78 | return "minecraft:cobblestone_slab"; 79 | } 80 | }); 81 | 82 | this.addTypeUpdater(ctx, "minecraft:tallgrass", "tall_grass_type", type -> { 83 | switch (type) { 84 | case "fern": 85 | return "minecraft:fern"; 86 | case "default": 87 | default: 88 | return "minecraft:short_grass"; 89 | } 90 | }); 91 | 92 | // These are not official updaters 93 | 94 | ctx.addUpdater(1, 21, 0, false, false) 95 | .match("name", "minecraft:trial_spawner") 96 | .visit("states") 97 | .tryAdd("ominous", (byte) 0); 98 | 99 | ctx.addUpdater(1, 21, 0, false, false) 100 | .match("name", "minecraft:vault") 101 | .visit("states") 102 | .tryAdd("ominous", (byte) 0); 103 | } 104 | 105 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, Function rename) { 106 | context.addUpdater(1, 21, 0) 107 | .match("name", identifier) 108 | .visit("states") 109 | .edit(typeState, helper -> helper.getRootTag().put("name", rename.apply((String) helper.getTag()))) 110 | .remove(typeState); 111 | 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_13_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import lombok.AccessLevel; 5 | import lombok.NoArgsConstructor; 6 | 7 | @NoArgsConstructor(access = AccessLevel.PRIVATE) 8 | public class BlockStateUpdater_1_13_0 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_13_0(); 11 | 12 | private static final String[] LEVER_DIRECTIONS = 13 | {"down_east_west", "east", "west", "south", "north", "up_north_south", "up_east_west", "down_north_south"}; 14 | private static final String[] PILLAR_DIRECTION = {"y", "x", "z"}; 15 | 16 | private static void registerLogUpdater(String name, String replace, CompoundTagUpdaterContext context) { 17 | context.addUpdater(1, 13, 0) 18 | .match("name", name) 19 | .visit("states") 20 | .regex("direction", "[0-2]") 21 | .edit("direction", helper -> { 22 | int value = (int) helper.getTag(); 23 | helper.replaceWith("pillar_axis", PILLAR_DIRECTION[value % 3]); 24 | }); 25 | 26 | context.addUpdater(1, 13, 0) 27 | .match("name", name) 28 | .visit("states") 29 | .regex("direction", "[3]") 30 | .rename(replace, "wood_type") 31 | .edit("direction", helper -> { 32 | int value = (int) helper.getTag(); 33 | helper.replaceWith("pillar_axis", PILLAR_DIRECTION[value % 3]); 34 | }) 35 | .addByte("stripped_bit", (byte) 0) 36 | .popVisit() 37 | .edit("name", helper -> { 38 | helper.replaceWith("name", "minecraft:wood"); 39 | }); 40 | } 41 | 42 | private static void registerPillarUpdater(String name, CompoundTagUpdaterContext context) { 43 | context.addUpdater(1, 13, 0) 44 | .match("name", name) 45 | .visit("states") 46 | .edit("direction", helper -> { 47 | int value = (int) helper.getTag(); 48 | helper.replaceWith("pillar_axis", PILLAR_DIRECTION[value % 3]); 49 | }); 50 | 51 | context.addUpdater(1, 13, 0) 52 | .match("name", name) 53 | .visit("states") 54 | .tryAdd("pillar_axis", PILLAR_DIRECTION[0]); 55 | } 56 | 57 | @Override 58 | public void registerUpdaters(CompoundTagUpdaterContext context) { 59 | context.addUpdater(1, 13, 0) 60 | .match("name", "minecraft:lever") 61 | .visit("states") 62 | .edit("facing_direction", helper -> { 63 | int value = (int) helper.getTag(); 64 | helper.replaceWith("lever_direction", LEVER_DIRECTIONS[value]); 65 | }); 66 | 67 | registerLogUpdater("minecraft:log", "old_log_type", context); 68 | registerLogUpdater("minecraft:log2", "new_log_type", context); 69 | 70 | registerPillarUpdater("minecraft:log", context); 71 | registerPillarUpdater("minecraft:quartz_block", context); 72 | registerPillarUpdater("minecraft:log2", context); 73 | registerPillarUpdater("minecraft:purpur_block", context); 74 | registerPillarUpdater("minecraft:bone_block", context); 75 | registerPillarUpdater("minecraft:stripped_spruce_log", context); 76 | registerPillarUpdater("minecraft:stripped_birch_log", context); 77 | registerPillarUpdater("minecraft:stripped_jungle_log", context); 78 | registerPillarUpdater("minecraft:stripped_acacia_log", context); 79 | registerPillarUpdater("minecraft:stripped_dark_oak_log", context); 80 | registerPillarUpdater("minecraft:stripped_oak_log", context); 81 | registerPillarUpdater("minecraft:wood", context); 82 | registerPillarUpdater("minecraft:hay_block", context); 83 | 84 | context.addUpdater(1, 13, 0) 85 | .match("name", "minecraft:end_rod") 86 | .visit("states") 87 | .regex("facing_direction", "[^0-5]") 88 | .remove("facing_direction") 89 | .addInt("block_light_level", 14) 90 | .popVisit() 91 | .edit("name", helper -> helper.replaceWith("name", "minecraft:light_block")); 92 | 93 | context.addUpdater(1, 13, 0) 94 | .regex("name", "minecraft:.+") 95 | .visit("states") 96 | .edit("facing_direction", helper -> { 97 | int value = (int) helper.getTag(); 98 | if (value >= 6) { 99 | helper.replaceWith("facing_direction", 0); 100 | } 101 | }); 102 | 103 | context.addUpdater(1, 13, 0) 104 | .regex("name", "minecraft:.+") 105 | .visit("states") 106 | .edit("fill_level", helper -> { 107 | int value = (int) helper.getTag(); 108 | if (value >= 7) { 109 | helper.replaceWith("fill_level", 6); 110 | } 111 | }); 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_21_30.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | import java.util.Map; 6 | import java.util.function.Function; 7 | 8 | public class BlockStateUpdater_1_21_30 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_21_30(); 11 | 12 | @Override 13 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 14 | this.addTypeUpdater(ctx, "minecraft:chemistry_table", "chemistry_table_type", type -> "minecraft:" + type); 15 | 16 | this.addTypeUpdater(ctx, "minecraft:cobblestone_wall", "wall_block_type", type -> { 17 | switch (type) { 18 | case "prismarine": 19 | return "minecraft:prismarine_wall"; 20 | case "red_sandstone": 21 | return "minecraft:red_sandstone_wall"; 22 | case "mossy_stone_brick": 23 | return "minecraft:mossy_stone_brick_wall"; 24 | case "mossy_cobblestone": 25 | return "minecraft:mossy_cobblestone_wall"; 26 | case "sandstone": 27 | return "minecraft:sandstone_wall"; 28 | case "nether_brick": 29 | return "minecraft:nether_brick_wall"; 30 | case "granite": 31 | return "minecraft:granite_wall"; 32 | case "red_nether_brick": 33 | return "minecraft:red_nether_brick_wall"; 34 | case "stone_brick": 35 | return "minecraft:stone_brick_wall"; 36 | case "end_brick": 37 | return "minecraft:end_stone_brick_wall"; 38 | case "brick": 39 | return "minecraft:brick_wall"; 40 | case "andesite": 41 | return "minecraft:andesite_wall"; 42 | case "diorite": 43 | return "minecraft:diorite_wall"; 44 | case "cobblestone": 45 | default: 46 | return "minecraft:cobblestone_wall"; 47 | } 48 | }); 49 | 50 | ctx.addUpdater(1, 21, 30) 51 | .match("name", "minecraft:colored_torch_bp") 52 | .edit("states", helper -> { 53 | Map states = helper.getCompoundTag(); 54 | Object bit = states.remove("color_bit"); 55 | boolean toggled = bit instanceof Byte && (byte) bit == 1 || bit instanceof Boolean && (boolean) bit; 56 | helper.getRootTag().put("name", toggled ? "minecraft:colored_torch_purple" : "minecraft:colored_torch_blue"); 57 | }); 58 | 59 | ctx.addUpdater(1, 21, 30) 60 | .match("name", "minecraft:colored_torch_rg") 61 | .edit("states", helper -> { 62 | Map states = helper.getCompoundTag(); 63 | Object bit = states.remove("color_bit"); 64 | boolean toggled = bit instanceof Byte && (byte) bit == 1 || bit instanceof Boolean && (boolean) bit; 65 | helper.getRootTag().put("name", toggled ? "minecraft:colored_torch_red" : "minecraft:colored_torch_green"); 66 | }); 67 | 68 | this.addTypeUpdater(ctx, "minecraft:purpur_block", "chisel_type", type -> { 69 | switch (type) { 70 | case "lines": 71 | return "minecraft:purpur_pillar"; 72 | case "default": // chiseled, smooth were deprecated 73 | default: 74 | return "minecraft:purpur_block"; 75 | } 76 | }); 77 | 78 | this.addTypeUpdater(ctx, "minecraft:sponge", "sponge_type", type -> { 79 | switch (type) { 80 | case "wet": 81 | return "minecraft:wet_sponge"; 82 | case "dry": 83 | default: 84 | return "minecraft:sponge"; 85 | } 86 | }); 87 | 88 | this.addTypeUpdater(ctx, "minecraft:structure_void", "structure_void_type", type -> { 89 | return "minecraft:structure_void"; // air was removed 90 | }); 91 | 92 | ctx.addUpdater(1, 21, 30) 93 | .match("name", "minecraft:tnt") 94 | .edit("states", helper -> { 95 | Map states = helper.getCompoundTag(); 96 | Object allowUnderwater = states.remove("allow_underwater_bit"); 97 | boolean toggled = allowUnderwater instanceof Byte && (byte) allowUnderwater == 1 || allowUnderwater instanceof Boolean && (boolean) allowUnderwater; 98 | helper.getRootTag().put("name", toggled ? "minecraft:tnt" : "minecraft:underwater_tnt"); 99 | }); 100 | 101 | 102 | } 103 | 104 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, Function rename) { 105 | context.addUpdater(1, 21, 30) 106 | .match("name", identifier) 107 | .visit("states") 108 | .edit(typeState, helper -> helper.getRootTag().put("name", rename.apply((String) helper.getTag()))) 109 | .remove(typeState); 110 | 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_30.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.OrderedUpdater; 4 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 5 | 6 | import static org.cloudburstmc.blockstateupdater.util.OrderedUpdater.DIRECTION_TO_CARDINAL; 7 | import static org.cloudburstmc.blockstateupdater.util.OrderedUpdater.FACING_TO_BLOCK; 8 | import static org.cloudburstmc.blockstateupdater.util.OrderedUpdater.FACING_TO_CARDINAL; 9 | 10 | public class BlockStateUpdater_1_20_30 implements BlockStateUpdater { 11 | 12 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_30(); 13 | 14 | public static final String[] COLORS = { 15 | "magenta", 16 | "pink", 17 | "green", 18 | "lime", 19 | "yellow", 20 | "black", 21 | "light_blue", 22 | "brown", 23 | "cyan", 24 | "orange", 25 | "red", 26 | "gray", 27 | "white", 28 | "blue", 29 | "purple", 30 | "silver" 31 | }; 32 | 33 | @Override 34 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 35 | for (String color : COLORS) { 36 | if (color.equals("silver")) { 37 | this.addColorUpdater(ctx, "minecraft:stained_glass", color, "minecraft:light_gray_stained_glass"); 38 | this.addColorUpdater(ctx, "minecraft:stained_glass_pane", color, "minecraft:light_gray_stained_glass_pane"); 39 | this.addColorUpdater(ctx, "minecraft:concrete_powder", color, "minecraft:light_gray_concrete_powder"); 40 | this.addColorUpdater(ctx, "minecraft:stained_hardened_clay", color, "minecraft:light_gray_terracotta"); 41 | } else { 42 | this.addColorUpdater(ctx, "minecraft:stained_glass", color, "minecraft:" + color + "_stained_glass"); 43 | this.addColorUpdater(ctx, "minecraft:stained_glass_pane", color, "minecraft:" + color + "_stained_glass_pane"); 44 | this.addColorUpdater(ctx, "minecraft:concrete_powder", color, "minecraft:" + color + "_concrete_powder"); 45 | this.addColorUpdater(ctx, "minecraft:stained_hardened_clay", color, "minecraft:" + color + "_terracotta"); 46 | } 47 | } 48 | 49 | this.addDirectionUpdater(ctx, "minecraft:amethyst_cluster", FACING_TO_BLOCK); 50 | this.addDirectionUpdater(ctx, "minecraft:medium_amethyst_bud", FACING_TO_BLOCK); 51 | this.addDirectionUpdater(ctx, "minecraft:large_amethyst_bud", FACING_TO_BLOCK); 52 | this.addDirectionUpdater(ctx, "minecraft:small_amethyst_bud", FACING_TO_BLOCK); 53 | 54 | this.addDirectionUpdater(ctx, "minecraft:blast_furnace", FACING_TO_CARDINAL); 55 | this.addDirectionUpdater(ctx, "minecraft:furnace", FACING_TO_CARDINAL); 56 | this.addDirectionUpdater(ctx, "minecraft:lit_blast_furnace", FACING_TO_CARDINAL); 57 | this.addDirectionUpdater(ctx, "minecraft:lit_furnace", FACING_TO_CARDINAL); 58 | this.addDirectionUpdater(ctx, "minecraft:lit_smoker", FACING_TO_CARDINAL); 59 | this.addDirectionUpdater(ctx, "minecraft:smoker", FACING_TO_CARDINAL); 60 | 61 | this.addDirectionUpdater(ctx, "minecraft:anvil", DIRECTION_TO_CARDINAL); 62 | this.addDirectionUpdater(ctx, "minecraft:big_dripleaf", DIRECTION_TO_CARDINAL); 63 | this.addDirectionUpdater(ctx, "minecraft:calibrated_sculk_sensor", DIRECTION_TO_CARDINAL); 64 | this.addDirectionUpdater(ctx, "minecraft:campfire", DIRECTION_TO_CARDINAL); 65 | this.addDirectionUpdater(ctx, "minecraft:end_portal_frame", DIRECTION_TO_CARDINAL); 66 | this.addDirectionUpdater(ctx, "minecraft:lectern", DIRECTION_TO_CARDINAL); 67 | this.addDirectionUpdater(ctx, "minecraft:pink_petals", DIRECTION_TO_CARDINAL); 68 | this.addDirectionUpdater(ctx, "minecraft:powered_comparator", DIRECTION_TO_CARDINAL); 69 | this.addDirectionUpdater(ctx, "minecraft:powered_repeater", DIRECTION_TO_CARDINAL); 70 | this.addDirectionUpdater(ctx, "minecraft:small_dripleaf_block", DIRECTION_TO_CARDINAL); 71 | this.addDirectionUpdater(ctx, "minecraft:soul_campfire", DIRECTION_TO_CARDINAL); 72 | this.addDirectionUpdater(ctx, "minecraft:unpowered_comparator", DIRECTION_TO_CARDINAL); 73 | this.addDirectionUpdater(ctx, "minecraft:unpowered_repeater", DIRECTION_TO_CARDINAL); 74 | 75 | ctx.addUpdater(1, 20, 30) 76 | .regex("name", "minecraft:.+slab(?:[2-4])?\\b") 77 | .visit("states") 78 | .edit("top_slot_bit", helper -> { 79 | boolean value; 80 | if (helper.getTag() instanceof Byte) { 81 | value = (byte) helper.getTag() == 1; 82 | } else { 83 | value = (boolean) helper.getTag(); 84 | } 85 | 86 | if (value) { 87 | helper.replaceWith("minecraft:vertical_half", "top"); 88 | } else { 89 | helper.replaceWith("minecraft:vertical_half", "bottom"); 90 | } 91 | }); 92 | 93 | // TODO: Mojang added 51 updaters, I managed to do the same with less. Maybe I missed something? Need to check later. 94 | } 95 | 96 | private void addColorUpdater(CompoundTagUpdaterContext context, String identifier, String color, String newIdentifier) { 97 | context.addUpdater(1, 20, 30) 98 | .match("name", identifier) 99 | .visit("states") 100 | .match("color", color) 101 | .edit("color", helper -> helper.getRootTag().put("name", newIdentifier)) 102 | .remove("color"); 103 | } 104 | 105 | private void addDirectionUpdater(CompoundTagUpdaterContext ctx, String identifier, OrderedUpdater updater) { 106 | ctx.addUpdater(1, 20, 30) 107 | .match("name", identifier) 108 | .visit("states") 109 | .edit(updater.getOldProperty(), helper -> { 110 | int value = (int) helper.getTag(); 111 | helper.replaceWith(updater.getNewProperty(), updater.translate(value)); 112 | }); 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_20_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.OrderedUpdater; 4 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 5 | 6 | import java.util.Map; 7 | 8 | public class BlockStateUpdater_1_20_0 implements BlockStateUpdater { 9 | 10 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_20_0(); 11 | 12 | public static final String[] COLORS = { 13 | "magenta", 14 | "pink", 15 | "green", 16 | "lime", 17 | "yellow", 18 | "black", 19 | "light_blue", 20 | "brown", 21 | "cyan", 22 | "orange", 23 | "red", 24 | "gray", 25 | "white", 26 | "blue", 27 | "purple", 28 | "silver" 29 | }; 30 | 31 | @Override 32 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 33 | for (String color : COLORS) { 34 | if (color.equals("silver")) { 35 | this.addTypeUpdater(ctx, "minecraft:carpet", "color", color, "minecraft:light_gray_carpet"); 36 | } else { 37 | this.addTypeUpdater(ctx, "minecraft:carpet", "color", color, "minecraft:" + color + "_carpet"); 38 | } 39 | } 40 | 41 | this.addCoralUpdater(ctx, "red", "minecraft:fire_coral"); 42 | this.addCoralUpdater(ctx, "pink", "minecraft:brain_coral"); 43 | this.addCoralUpdater(ctx, "blue", "minecraft:tube_coral"); 44 | this.addCoralUpdater(ctx, "yellow", "minecraft:horn_coral"); 45 | this.addCoralUpdater(ctx, "purple", "minecraft:bubble_coral"); 46 | 47 | this.addDeadCoralUpdater(ctx, "red", "minecraft:dead_fire_coral"); 48 | this.addDeadCoralUpdater(ctx, "pink", "minecraft:dead_brain_coral"); 49 | this.addDeadCoralUpdater(ctx, "blue", "minecraft:dead_tube_coral"); 50 | this.addDeadCoralUpdater(ctx, "yellow", "minecraft:dead_horn_coral"); 51 | this.addDeadCoralUpdater(ctx, "purple", "minecraft:dead_bubble_coral"); 52 | 53 | ctx.addUpdater(1, 20, 0) 54 | .match("name", "minecraft:calibrated_sculk_sensor") 55 | .visit("states") 56 | .edit("powered_bit", helper -> { 57 | int value; 58 | if (helper.getTag() instanceof Byte) { 59 | value = (byte) helper.getTag(); 60 | } else { 61 | value = (int) helper.getTag(); 62 | } 63 | helper.replaceWith("sculk_sensor_phase", value); 64 | }); 65 | 66 | ctx.addUpdater(1, 20, 0) 67 | .match("name", "minecraft:sculk_sensor") 68 | .visit("states") 69 | .edit("powered_bit", helper -> { 70 | int value; 71 | if (helper.getTag() instanceof Byte) { 72 | value = (byte) helper.getTag(); 73 | } else { 74 | value = (int) helper.getTag(); 75 | } 76 | helper.replaceWith("sculk_sensor_phase", value); 77 | }); 78 | 79 | this.addPumpkinUpdater(ctx, "minecraft:carved_pumpkin"); 80 | this.addPumpkinUpdater(ctx, "minecraft:lit_pumpkin"); 81 | this.addPumpkinUpdater(ctx, "minecraft:pumpkin"); 82 | 83 | this.addCauldronUpdater(ctx, "water"); 84 | this.addCauldronUpdater(ctx, "lava"); 85 | this.addCauldronUpdater(ctx, "powder_snow"); 86 | } 87 | 88 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, String type, String newIdentifier) { 89 | context.addUpdater(1, 20, 0) 90 | .match("name", identifier) 91 | .visit("states") 92 | .match(typeState, type) 93 | .edit(typeState, helper -> helper.getRootTag().put("name", newIdentifier)) 94 | .remove(typeState); 95 | 96 | } 97 | 98 | private void addPumpkinUpdater(CompoundTagUpdaterContext ctx, String identifier) { 99 | OrderedUpdater updater = OrderedUpdater.DIRECTION_TO_CARDINAL; 100 | ctx.addUpdater(1, 20, 0) 101 | .match("name", identifier) 102 | .visit("states") 103 | .edit(updater.getOldProperty(), helper -> { 104 | int value = (int) helper.getTag(); 105 | helper.replaceWith(updater.getNewProperty(), updater.translate(value)); // Don't ask me why namespace is in vanilla state 106 | }); 107 | } 108 | 109 | private void addCauldronUpdater(CompoundTagUpdaterContext ctx, String type) { 110 | ctx.addUpdater(1, 20, 0) 111 | .match("name", "minecraft:lava_cauldron") 112 | .visit("states") 113 | .match("cauldron_liquid", type) 114 | .popVisit() 115 | .tryEdit("states", helper -> { 116 | Map states = helper.getCompoundTag(); 117 | states.put("cauldron_liquid", type); 118 | helper.getRootTag().put("name", "minecraft:cauldron"); 119 | }); 120 | } 121 | 122 | private void addCoralUpdater(CompoundTagUpdaterContext context, String type, String newIdentifier) { 123 | context.addUpdater(1, 20, 0) 124 | .match("name", "minecraft:coral") 125 | .visit("states") 126 | .match("coral_color", type) 127 | .match("dead_bit", "0") 128 | .edit("coral_color", helper -> helper.getRootTag().put("name", newIdentifier)) 129 | .remove("coral_color") 130 | .remove("dead_bit"); 131 | } 132 | 133 | private void addDeadCoralUpdater(CompoundTagUpdaterContext context, String type, String newIdentifier) { 134 | context.addUpdater(1, 20, 0) 135 | .match("name", "minecraft:coral") 136 | .visit("states") 137 | .match("coral_color", type) 138 | .match("dead_bit", "1") 139 | .edit("coral_color", helper -> helper.getRootTag().put("name", newIdentifier)) 140 | .remove("coral_color") 141 | .remove("dead_bit"); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_16_0.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | import lombok.AccessLevel; 5 | import lombok.RequiredArgsConstructor; 6 | 7 | import java.util.Map; 8 | 9 | @RequiredArgsConstructor(access = AccessLevel.PRIVATE) 10 | public class BlockStateUpdater_1_16_0 implements BlockStateUpdater { 11 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_16_0(); 12 | 13 | private static int convertFacingDirectionToDirection(int facingDirection) { 14 | switch (facingDirection) { 15 | case 2: 16 | return 2; 17 | case 3: 18 | default: 19 | return 0; 20 | case 4: 21 | return 1; 22 | case 5: 23 | return 3; 24 | } 25 | } 26 | 27 | @Override 28 | public void registerUpdaters(CompoundTagUpdaterContext context) { 29 | context.addUpdater(1, 16, 0) 30 | .match("name", "jigsaw") 31 | .visit("states") 32 | .tryAdd("rotation", 0); 33 | 34 | context.addUpdater(1, 16, 0) 35 | .match("name", "minecraft:blue_fire") 36 | .edit("name", helper -> { 37 | helper.replaceWith("name", "soul_fire"); 38 | }); 39 | 40 | context.addUpdater(1, 16, 0) 41 | .match("name", "minecraft:blue_nether_wart_block") 42 | .edit("name", helper -> { 43 | helper.replaceWith("name", "warped_wart_block"); 44 | }); 45 | 46 | context.addUpdater(1, 16, 0) 47 | .match("name", "minecraft:shroomlight_block") 48 | .edit("name", helper -> { 49 | helper.replaceWith("name", "minecraft:shroomlight"); 50 | }); 51 | 52 | context.addUpdater(1, 16, 0) 53 | .match("name", "minecraft:weeping_vines_block") 54 | .edit("name", helper -> { 55 | helper.replaceWith("name", "minecraft:weeping_vines"); 56 | }); 57 | 58 | context.addUpdater(1, 16, 0) 59 | .match("name", "minecraft:basalt_block") 60 | .edit("name", helper -> { 61 | helper.replaceWith("name", "minecraft:basalt"); 62 | }); 63 | 64 | context.addUpdater(1, 16, 0) 65 | .match("name", "minecraft:polished_basalt_block") 66 | .edit("name", helper -> { 67 | helper.replaceWith("name", "minecraft:polished_basalt"); 68 | }); 69 | 70 | context.addUpdater(1, 16, 0) 71 | .match("name", "minecraft:soul_soil_block") 72 | .edit("name", helper -> { 73 | helper.replaceWith("name", "minecraft:soul_soil"); 74 | }); 75 | 76 | context.addUpdater(1, 16, 0) 77 | .match("name", "minecraft:target_block") 78 | .edit("name", helper -> { 79 | helper.replaceWith("name", "minecraft:target"); 80 | }); 81 | 82 | context.addUpdater(1, 16, 0) 83 | .match("name", "minecraft:crimson_trap_door") 84 | .edit("name", helper -> { 85 | helper.replaceWith("name", "minecraft:crimsom_trapdoor"); 86 | }); 87 | 88 | context.addUpdater(1, 16, 0) 89 | .match("name", "minecraft:lodestone_block") 90 | .edit("name", helper -> { 91 | helper.replaceWith("name", "minecraft:lodestone"); 92 | }); 93 | 94 | context.addUpdater(1, 16, 0) 95 | .match("name", "minecraft:twisted_vines_block") 96 | .edit("name", helper -> { 97 | helper.replaceWith("name", "minecraft:twisted_vines"); 98 | }); 99 | 100 | // This is not a vanilla state updater. In vanilla 1.16, the invalid block state is updated when the chunk is 101 | // loaded in so it can generate the connection data however the state set below should never occur naturally. 102 | // Checking for this block state instead means we don't have to break our loading system in order to support it. 103 | this.addLegacyWallUpdater(context, "minecraft:.+_wall"); 104 | this.addLegacyWallUpdater(context, "minecraft:border_block"); 105 | 106 | this.addWallUpdater(context, "minecraft:blackstone_wall"); 107 | this.addWallUpdater(context, "minecraft:polished_blackstone_brick_wall"); 108 | this.addWallUpdater(context, "minecraft:polished_blackstone_wall"); 109 | 110 | this.addBeeHiveUpdater(context, "minecraft:beehive"); 111 | this.addBeeHiveUpdater(context, "minecraft:bee_nest"); 112 | 113 | this.addRequiredValueUpdater(context, "minecraft:pumpkin_stem", "facing_direction", 0); 114 | this.addRequiredValueUpdater(context, "minecraft:melon_stem", "facing_direction", 0); 115 | } 116 | 117 | private void addLegacyWallUpdater(CompoundTagUpdaterContext context, String name) { 118 | context.addUpdater(1, 16, 0) 119 | .regex("name", name) 120 | .tryEdit("states", helper -> { 121 | Map states = helper.getCompoundTag(); 122 | states.put("wall_post_bit", (byte) 0); 123 | states.put("wall_connection_type_north", "none"); 124 | states.put("wall_connection_type_east", "none"); 125 | states.put("wall_connection_type_south", "none"); 126 | states.put("wall_connection_type_west", "none"); 127 | }); 128 | } 129 | 130 | private void addWallUpdater(CompoundTagUpdaterContext context, String name) { 131 | context.addUpdater(1, 16, 0) 132 | .match("name", name) 133 | .visit("states") 134 | .remove("wall_block_type"); 135 | } 136 | 137 | private void addBeeHiveUpdater(CompoundTagUpdaterContext context, String name) { 138 | context.addUpdater(1, 16, 0) 139 | .match("name", name) 140 | .visit("states") 141 | .edit("facing_direction", helper -> { 142 | int facingDirection = (int) helper.getTag(); 143 | helper.replaceWith("direction", convertFacingDirectionToDirection(facingDirection)); 144 | }); 145 | } 146 | 147 | private void addRequiredValueUpdater(CompoundTagUpdaterContext contex, String name, String state, Object value) { 148 | contex.addUpdater(1, 16, 0) 149 | .match("name", name) 150 | .visit("states") 151 | .tryAdd(state, value); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU LESSER GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | 9 | This version of the GNU Lesser General Public License incorporates 10 | the terms and conditions of version 3 of the GNU General Public 11 | License, supplemented by the additional permissions listed below. 12 | 13 | 0. Additional Definitions. 14 | 15 | As used herein, "this License" refers to version 3 of the GNU Lesser 16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU 17 | General Public License. 18 | 19 | "The Library" refers to a covered work governed by this License, 20 | other than an Application or a Combined Work as defined below. 21 | 22 | An "Application" is any work that makes use of an interface provided 23 | by the Library, but which is not otherwise based on the Library. 24 | Defining a subclass of a class defined by the Library is deemed a mode 25 | of using an interface provided by the Library. 26 | 27 | A "Combined Work" is a work produced by combining or linking an 28 | Application with the Library. The particular version of the Library 29 | with which the Combined Work was made is also called the "Linked 30 | Version". 31 | 32 | The "Minimal Corresponding Source" for a Combined Work means the 33 | Corresponding Source for the Combined Work, excluding any source code 34 | for portions of the Combined Work that, considered in isolation, are 35 | based on the Application, and not on the Linked Version. 36 | 37 | The "Corresponding Application Code" for a Combined Work means the 38 | object code and/or source code for the Application, including any data 39 | and utility programs needed for reproducing the Combined Work from the 40 | Application, but excluding the System Libraries of the Combined Work. 41 | 42 | 1. Exception to Section 3 of the GNU GPL. 43 | 44 | You may convey a covered work under sections 3 and 4 of this License 45 | without being bound by section 3 of the GNU GPL. 46 | 47 | 2. Conveying Modified Versions. 48 | 49 | If you modify a copy of the Library, and, in your modifications, a 50 | facility refers to a function or data to be supplied by an Application 51 | that uses the facility (other than as an argument passed when the 52 | facility is invoked), then you may convey a copy of the modified 53 | version: 54 | 55 | a) under this License, provided that you make a good faith effort to 56 | ensure that, in the event an Application does not supply the 57 | function or data, the facility still operates, and performs 58 | whatever part of its purpose remains meaningful, or 59 | 60 | b) under the GNU GPL, with none of the additional permissions of 61 | this License applicable to that copy. 62 | 63 | 3. Object Code Incorporating Material from Library Header Files. 64 | 65 | The object code form of an Application may incorporate material from 66 | a header file that is part of the Library. You may convey such object 67 | code under terms of your choice, provided that, if the incorporated 68 | material is not limited to numerical parameters, data structure 69 | layouts and accessors, or small macros, inline functions and templates 70 | (ten or fewer lines in length), you do both of the following: 71 | 72 | a) Give prominent notice with each copy of the object code that the 73 | Library is used in it and that the Library and its use are 74 | covered by this License. 75 | 76 | b) Accompany the object code with a copy of the GNU GPL and this license 77 | document. 78 | 79 | 4. Combined Works. 80 | 81 | You may convey a Combined Work under terms of your choice that, 82 | taken together, effectively do not restrict modification of the 83 | portions of the Library contained in the Combined Work and reverse 84 | engineering for debugging such modifications, if you also do each of 85 | the following: 86 | 87 | a) Give prominent notice with each copy of the Combined Work that 88 | the Library is used in it and that the Library and its use are 89 | covered by this License. 90 | 91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license 92 | document. 93 | 94 | c) For a Combined Work that displays copyright notices during 95 | execution, include the copyright notice for the Library among 96 | these notices, as well as a reference directing the user to the 97 | copies of the GNU GPL and this license document. 98 | 99 | d) Do one of the following: 100 | 101 | 0) Convey the Minimal Corresponding Source under the terms of this 102 | License, and the Corresponding Application Code in a form 103 | suitable for, and under terms that permit, the user to 104 | recombine or relink the Application with a modified version of 105 | the Linked Version to produce a modified Combined Work, in the 106 | manner specified by section 6 of the GNU GPL for conveying 107 | Corresponding Source. 108 | 109 | 1) Use a suitable shared library mechanism for linking with the 110 | Library. A suitable mechanism is one that (a) uses at run time 111 | a copy of the Library already present on the user's computer 112 | system, and (b) will operate properly with a modified version 113 | of the Library that is interface-compatible with the Linked 114 | Version. 115 | 116 | e) Provide Installation Information, but only if you would otherwise 117 | be required to provide such information under section 6 of the 118 | GNU GPL, and only to the extent that such information is 119 | necessary to install and execute a modified version of the 120 | Combined Work produced by recombining or relinking the 121 | Application with a modified version of the Linked Version. (If 122 | you use option 4d0, the Installation Information must accompany 123 | the Minimal Corresponding Source and Corresponding Application 124 | Code. If you use option 4d1, you must provide the Installation 125 | Information in the manner specified by section 6 of the GNU GPL 126 | for conveying Corresponding Source.) 127 | 128 | 5. Combined Libraries. 129 | 130 | You may place library facilities that are a work based on the 131 | Library side by side in a single library together with other library 132 | facilities that are not Applications and are not covered by this 133 | License, and convey such a combined library under terms of your 134 | choice, if you do both of the following: 135 | 136 | a) Accompany the combined library with a copy of the same work based 137 | on the Library, uncombined with any other library facilities, 138 | conveyed under the terms of this License. 139 | 140 | b) Give prominent notice with the combined library that part of it 141 | is a work based on the Library, and explaining where to find the 142 | accompanying uncombined form of the same work. 143 | 144 | 6. Revised Versions of the GNU Lesser General Public License. 145 | 146 | The Free Software Foundation may publish revised and/or new versions 147 | of the GNU Lesser General Public License from time to time. Such new 148 | versions will be similar in spirit to the present version, but may 149 | differ in detail to address new problems or concerns. 150 | 151 | Each version is given a distinguishing version number. If the 152 | Library as you received it specifies that a certain numbered version 153 | of the GNU Lesser General Public License "or any later version" 154 | applies to it, you have the option of following the terms and 155 | conditions either of that published version or of any later version 156 | published by the Free Software Foundation. If the Library as you 157 | received it does not specify a version number of the GNU Lesser 158 | General Public License, you may choose any version of the GNU Lesser 159 | General Public License ever published by the Free Software Foundation. 160 | 161 | If the Library as you received it specifies that a proxy can decide 162 | whether future versions of the GNU Lesser General Public License shall 163 | apply, that proxy's public statement of acceptance of any version is 164 | permanent authorization for you to choose that version for the 165 | Library. -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/util/tagupdater/CompoundTagUpdater.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater.util.tagupdater; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedHashMap; 5 | import java.util.List; 6 | import java.util.Map; 7 | import java.util.function.Consumer; 8 | import java.util.function.Predicate; 9 | import java.util.regex.Pattern; 10 | 11 | public class CompoundTagUpdater implements Comparable { 12 | 13 | private static final Predicate COMPOUND_FILTER = helper -> helper.getTag() instanceof Map; 14 | 15 | private final Builder builder = new Builder(); 16 | private final List> filters = new ArrayList<>(); 17 | private final List> updaters = new ArrayList<>(); 18 | private final int version; 19 | 20 | public CompoundTagUpdater(int version) { 21 | this.version = version; 22 | } 23 | 24 | private static String getTagValue(Object tag) { 25 | if (tag == null) { 26 | return "END"; 27 | } else if (tag instanceof Byte || tag instanceof Short || tag instanceof Integer || tag instanceof Long || 28 | tag instanceof Float || tag instanceof Double) { 29 | return String.valueOf(tag); 30 | } else if (tag instanceof String) { 31 | return (String) tag; 32 | } else if (tag instanceof Boolean) { 33 | return tag == Boolean.TRUE ? "1" : "0"; 34 | } 35 | throw new IllegalArgumentException("Invalid tag " + tag.getClass().getSimpleName()); 36 | } 37 | 38 | public int getVersion() { 39 | return version; 40 | } 41 | 42 | public boolean update(Map tag) { 43 | CompoundTagEditHelper filterHelper = new CompoundTagEditHelper(tag); 44 | for (Predicate filter : this.filters) { 45 | if (!filter.test(filterHelper)) { 46 | return false; 47 | } 48 | } 49 | 50 | CompoundTagEditHelper updaterHelper = new CompoundTagEditHelper(tag); 51 | for (Consumer updater : this.updaters) { 52 | updater.accept(updaterHelper); 53 | } 54 | return true; 55 | } 56 | 57 | Builder builder() { 58 | return builder; 59 | } 60 | 61 | @Override 62 | public int compareTo(CompoundTagUpdater o) { 63 | return Integer.compare(this.version, o.version); 64 | } 65 | 66 | private static class TagNamePredicate implements Predicate { 67 | private final String name; 68 | 69 | private TagNamePredicate(String name) { 70 | this.name = name; 71 | } 72 | 73 | @Override 74 | public boolean test(CompoundTagEditHelper helper) { 75 | Object tag = helper.getTag(); 76 | return tag instanceof Map && ((Map) tag).containsKey(name); 77 | } 78 | } 79 | 80 | private static class TryAddPredicate implements Predicate { 81 | private final String name; 82 | 83 | private TryAddPredicate(String name) { 84 | this.name = name; 85 | } 86 | 87 | @Override 88 | public boolean test(CompoundTagEditHelper helper) { 89 | Object tag = helper.getTag(); 90 | return tag instanceof Map && !((Map) tag).containsKey(name); 91 | } 92 | } 93 | 94 | public class Builder { 95 | 96 | public Builder addByte(String name, byte value) { 97 | CompoundTagUpdater.this.filters.add(COMPOUND_FILTER); 98 | CompoundTagUpdater.this.updaters.add(helper -> helper.getCompoundTag().put(name, value)); 99 | return this; 100 | } 101 | 102 | public Builder tryAdd(String name, Object value) { 103 | CompoundTagUpdater.this.filters.add(new TryAddPredicate(name)); 104 | CompoundTagUpdater.this.updaters.add(helper -> helper.getCompoundTag().put(name, value)); 105 | return this; 106 | } 107 | 108 | public Builder addInt(String name, int value) { 109 | CompoundTagUpdater.this.filters.add(COMPOUND_FILTER); 110 | CompoundTagUpdater.this.updaters.add(helper -> helper.getCompoundTag().put(name, value)); 111 | return this; 112 | } 113 | 114 | public Builder addCompound(String name) { 115 | CompoundTagUpdater.this.filters.add(COMPOUND_FILTER); 116 | CompoundTagUpdater.this.updaters.add(helper -> helper.getCompoundTag().put(name, new LinkedHashMap<>())); 117 | return this; 118 | } 119 | 120 | public Builder edit(String name, Consumer function) { 121 | CompoundTagUpdater.this.filters.add(new TagNamePredicate(name)); 122 | CompoundTagUpdater.this.updaters.add(helper -> helper.pushChild(name)); 123 | CompoundTagUpdater.this.updaters.add(function); 124 | CompoundTagUpdater.this.updaters.add(CompoundTagEditHelper::popChild); 125 | return this; 126 | } 127 | 128 | public Builder regex(String name, String regex) { 129 | return this.match(name, regex, true); 130 | } 131 | 132 | public Builder match(String name, String match) { 133 | return this.match(name, match, false); 134 | } 135 | 136 | public Builder match(String name, String match, boolean regex) { 137 | Pattern pattern = regex ? Pattern.compile(match) : null; 138 | 139 | CompoundTagUpdater.this.filters.add(helper -> { 140 | Object tag = helper.getTag(); 141 | if (!(tag instanceof Map)) { 142 | return false; 143 | } 144 | Map compound = (Map) tag; 145 | if (!compound.containsKey(name)) { 146 | return false; 147 | } 148 | 149 | boolean success = match.isEmpty(); 150 | if (success) { 151 | return success; 152 | } 153 | 154 | Object matchTag = compound.get(name); 155 | if (regex) { 156 | success = pattern.matcher(getTagValue(matchTag)).matches(); 157 | } else { 158 | success = match.equals(getTagValue(matchTag)); 159 | } 160 | return success; 161 | }); 162 | return this; 163 | } 164 | 165 | public Builder popVisit() { 166 | CompoundTagUpdater.this.filters.add(helper -> { 167 | if (helper.canPopChild()) { 168 | helper.popChild(); 169 | return true; 170 | } 171 | return false; 172 | }); 173 | CompoundTagUpdater.this.updaters.add(CompoundTagEditHelper::popChild); 174 | return this; 175 | } 176 | 177 | public Builder remove(String name) { 178 | CompoundTagUpdater.this.filters.add(new TagNamePredicate(name)); 179 | CompoundTagUpdater.this.updaters.add(helper -> { 180 | helper.getCompoundTag().remove(name); 181 | }); 182 | return this; 183 | } 184 | 185 | public Builder rename(String from, String to) { 186 | CompoundTagUpdater.this.filters.add(new TagNamePredicate(from)); 187 | CompoundTagUpdater.this.updaters.add(helper -> { 188 | Map tag = helper.getCompoundTag(); 189 | tag.put(to, tag.remove(from)); 190 | }); 191 | return this; 192 | } 193 | 194 | public Builder tryEdit(String name, Consumer function) { 195 | CompoundTagUpdater.this.updaters.add(helper -> { 196 | Object tag = helper.getTag(); 197 | if (tag instanceof Map) { 198 | Map compoundTag = (Map) tag; 199 | if (compoundTag.containsKey(name)) { 200 | helper.pushChild(name); 201 | function.accept(helper); 202 | helper.popChild(); 203 | } 204 | } 205 | }); 206 | return this; 207 | } 208 | 209 | public Builder visit(String name) { 210 | CompoundTagUpdater.this.filters.add(helper -> { 211 | Object tag = helper.getTag(); 212 | if (tag instanceof Map && ((Map) tag).containsKey(name)) { 213 | helper.pushChild(name); 214 | return true; 215 | } 216 | return false; 217 | }); 218 | CompoundTagUpdater.this.updaters.add(helper -> helper.pushChild(name)); 219 | return this; 220 | } 221 | 222 | public CompoundTagUpdater build() { 223 | return CompoundTagUpdater.this; 224 | } 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | # Copyright © 2015-2021 the original authors. 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # https://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | ############################################################################## 20 | # 21 | # Gradle start up script for POSIX generated by Gradle. 22 | # 23 | # Important for running: 24 | # 25 | # (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is 26 | # noncompliant, but you have some other compliant shell such as ksh or 27 | # bash, then to run this script, type that shell name before the whole 28 | # command line, like: 29 | # 30 | # ksh Gradle 31 | # 32 | # Busybox and similar reduced shells will NOT work, because this script 33 | # requires all of these POSIX shell features: 34 | # * functions; 35 | # * expansions «$var», «${var}», «${var:-default}», «${var+SET}», 36 | # «${var#prefix}», «${var%suffix}», and «$( cmd )»; 37 | # * compound commands having a testable exit status, especially «case»; 38 | # * various built-in commands including «command», «set», and «ulimit». 39 | # 40 | # Important for patching: 41 | # 42 | # (2) This script targets any POSIX shell, so it avoids extensions provided 43 | # by Bash, Ksh, etc; in particular arrays are avoided. 44 | # 45 | # The "traditional" practice of packing multiple parameters into a 46 | # space-separated string is a well documented source of bugs and security 47 | # problems, so this is (mostly) avoided, by progressively accumulating 48 | # options in "$@", and eventually passing that to Java. 49 | # 50 | # Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, 51 | # and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; 52 | # see the in-line comments for details. 53 | # 54 | # There are tweaks for specific operating systems such as AIX, CygWin, 55 | # Darwin, MinGW, and NonStop. 56 | # 57 | # (3) This script is generated from the Groovy template 58 | # https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt 59 | # within the Gradle project. 60 | # 61 | # You can find Gradle at https://github.com/gradle/gradle/. 62 | # 63 | ############################################################################## 64 | 65 | # Attempt to set APP_HOME 66 | 67 | # Resolve links: $0 may be a link 68 | app_path=$0 69 | 70 | # Need this for daisy-chained symlinks. 71 | while 72 | APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path 73 | [ -h "$app_path" ] 74 | do 75 | ls=$( ls -ld "$app_path" ) 76 | link=${ls#*' -> '} 77 | case $link in #( 78 | /*) app_path=$link ;; #( 79 | *) app_path=$APP_HOME$link ;; 80 | esac 81 | done 82 | 83 | # This is normally unused 84 | # shellcheck disable=SC2034 85 | APP_BASE_NAME=${0##*/} 86 | APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit 87 | 88 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 89 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' 90 | 91 | # Use the maximum available, or set MAX_FD != -1 to use that value. 92 | MAX_FD=maximum 93 | 94 | warn () { 95 | echo "$*" 96 | } >&2 97 | 98 | die () { 99 | echo 100 | echo "$*" 101 | echo 102 | exit 1 103 | } >&2 104 | 105 | # OS specific support (must be 'true' or 'false'). 106 | cygwin=false 107 | msys=false 108 | darwin=false 109 | nonstop=false 110 | case "$( uname )" in #( 111 | CYGWIN* ) cygwin=true ;; #( 112 | Darwin* ) darwin=true ;; #( 113 | MSYS* | MINGW* ) msys=true ;; #( 114 | NONSTOP* ) nonstop=true ;; 115 | esac 116 | 117 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 118 | 119 | 120 | # Determine the Java command to use to start the JVM. 121 | if [ -n "$JAVA_HOME" ] ; then 122 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 123 | # IBM's JDK on AIX uses strange locations for the executables 124 | JAVACMD=$JAVA_HOME/jre/sh/java 125 | else 126 | JAVACMD=$JAVA_HOME/bin/java 127 | fi 128 | if [ ! -x "$JAVACMD" ] ; then 129 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 130 | 131 | Please set the JAVA_HOME variable in your environment to match the 132 | location of your Java installation." 133 | fi 134 | else 135 | JAVACMD=java 136 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 137 | 138 | Please set the JAVA_HOME variable in your environment to match the 139 | location of your Java installation." 140 | fi 141 | 142 | # Increase the maximum file descriptors if we can. 143 | if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then 144 | case $MAX_FD in #( 145 | max*) 146 | # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. 147 | # shellcheck disable=SC3045 148 | MAX_FD=$( ulimit -H -n ) || 149 | warn "Could not query maximum file descriptor limit" 150 | esac 151 | case $MAX_FD in #( 152 | '' | soft) :;; #( 153 | *) 154 | # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. 155 | # shellcheck disable=SC3045 156 | ulimit -n "$MAX_FD" || 157 | warn "Could not set maximum file descriptor limit to $MAX_FD" 158 | esac 159 | fi 160 | 161 | # Collect all arguments for the java command, stacking in reverse order: 162 | # * args from the command line 163 | # * the main class name 164 | # * -classpath 165 | # * -D...appname settings 166 | # * --module-path (only if needed) 167 | # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. 168 | 169 | # For Cygwin or MSYS, switch paths to Windows format before running java 170 | if "$cygwin" || "$msys" ; then 171 | APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) 172 | CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) 173 | 174 | JAVACMD=$( cygpath --unix "$JAVACMD" ) 175 | 176 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 177 | for arg do 178 | if 179 | case $arg in #( 180 | -*) false ;; # don't mess with options #( 181 | /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath 182 | [ -e "$t" ] ;; #( 183 | *) false ;; 184 | esac 185 | then 186 | arg=$( cygpath --path --ignore --mixed "$arg" ) 187 | fi 188 | # Roll the args list around exactly as many times as the number of 189 | # args, so each arg winds up back in the position where it started, but 190 | # possibly modified. 191 | # 192 | # NB: a `for` loop captures its iteration list before it begins, so 193 | # changing the positional parameters here affects neither the number of 194 | # iterations, nor the values presented in `arg`. 195 | shift # remove old arg 196 | set -- "$@" "$arg" # push replacement arg 197 | done 198 | fi 199 | 200 | # Collect all arguments for the java command; 201 | # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of 202 | # shell script including quotes and variable substitutions, so put them in 203 | # double quotes to make sure that they get re-expanded; and 204 | # * put everything else in single quotes, so that it's not re-expanded. 205 | 206 | set -- \ 207 | "-Dorg.gradle.appname=$APP_BASE_NAME" \ 208 | -classpath "$CLASSPATH" \ 209 | org.gradle.wrapper.GradleWrapperMain \ 210 | "$@" 211 | 212 | # Stop when "xargs" is not available. 213 | if ! command -v xargs >/dev/null 2>&1 214 | then 215 | die "xargs is not available" 216 | fi 217 | 218 | # Use "xargs" to parse quoted args. 219 | # 220 | # With -n1 it outputs one arg per line, with the quotes and backslashes removed. 221 | # 222 | # In Bash we could simply go: 223 | # 224 | # readarray ARGS < <( xargs -n1 <<<"$var" ) && 225 | # set -- "${ARGS[@]}" "$@" 226 | # 227 | # but POSIX shell has neither arrays nor command substitution, so instead we 228 | # post-process each arg (as a line of input to sed) to backslash-escape any 229 | # character that might be a shell metacharacter, then use eval to reverse 230 | # that process (while maintaining the separation between arguments), and wrap 231 | # the whole thing up as a single "set" statement. 232 | # 233 | # This will of course break if any of these variables contains a newline or 234 | # an unmatched quote. 235 | # 236 | 237 | eval "set -- $( 238 | printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | 239 | xargs -n1 | 240 | sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | 241 | tr '\n' ' ' 242 | )" '"$@"' 243 | 244 | exec "$JAVACMD" "$@" 245 | -------------------------------------------------------------------------------- /src/main/java/org/cloudburstmc/blockstateupdater/BlockStateUpdater_1_21_10.java: -------------------------------------------------------------------------------- 1 | package org.cloudburstmc.blockstateupdater; 2 | 3 | import org.cloudburstmc.blockstateupdater.util.tagupdater.CompoundTagUpdaterContext; 4 | 5 | import java.util.function.Function; 6 | 7 | public class BlockStateUpdater_1_21_10 implements BlockStateUpdater { 8 | 9 | public static final BlockStateUpdater INSTANCE = new BlockStateUpdater_1_21_10(); 10 | 11 | @Override 12 | public void registerUpdaters(CompoundTagUpdaterContext ctx) { 13 | this.addTypeUpdater(ctx, "minecraft:stone_block_slab2", "stone_slab_type_2", type -> { 14 | switch (type) { 15 | case "prismarine_rough": 16 | return "minecraft:prismarine_slab"; 17 | case "prismarine_dark": 18 | return "minecraft:dark_prismarine_slab"; 19 | case "smooth_sandstone": 20 | return "minecraft:smooth_sandstone_slab"; 21 | case "purpur": 22 | return "minecraft:purpur_slab"; 23 | case "red_nether_brick": 24 | return "minecraft:red_nether_brick_slab"; 25 | case "prismarine_brick": 26 | return "minecraft:prismarine_brick_slab"; 27 | case "mossy_cobblestone": 28 | return "minecraft:mossy_cobblestone_slab"; 29 | case "red_sandstone": 30 | default: 31 | return "minecraft:red_sandstone_slab"; 32 | } 33 | }); 34 | 35 | this.addTypeUpdater(ctx, "minecraft:stone_block_slab3", "stone_slab_type_3", type -> { 36 | switch (type) { 37 | case "smooth_red_sandstone": 38 | return "minecraft:smooth_red_sandstone_slab"; 39 | case "polished_granite": 40 | return "minecraft:polished_granite_slab"; 41 | case "granite": 42 | return "minecraft:granite_slab"; 43 | case "polished_diorite": 44 | return "minecraft:polished_diorite_slab"; 45 | case "andesite": 46 | return "minecraft:andesite_slab"; 47 | case "polished_andesite": 48 | return "minecraft:polished_andesite_slab"; 49 | case "diorite": 50 | return "minecraft:diorite_slab"; 51 | case "end_stone_brick": 52 | default: 53 | return "minecraft:end_stone_brick_slab"; 54 | } 55 | }); 56 | 57 | this.addTypeUpdater(ctx, "minecraft:stone_block_slab4", "stone_slab_type_4", type -> { 58 | switch (type) { 59 | case "smooth_quartz": 60 | return "minecraft:smooth_quartz_slab"; 61 | case "cut_sandstone": 62 | return "minecraft:cut_sandstone_slab"; 63 | case "cut_red_sandstone": 64 | return "minecraft:cut_red_sandstone_slab"; 65 | case "stone": 66 | return "minecraft:normal_stone_slab"; 67 | case "mossy_stone_brick": 68 | default: 69 | return "minecraft:mossy_stone_brick_slab"; 70 | } 71 | }); 72 | 73 | this.addTypeUpdater(ctx, "minecraft:double_stone_block_slab", "stone_slab_type", type -> { 74 | switch (type) { 75 | case "quartz": 76 | return "minecraft:quartz_double_slab"; 77 | case "wood": 78 | return "minecraft:petrified_oak_double_slab"; 79 | case "stone_brick": 80 | return "minecraft:stone_brick_double_slab"; 81 | case "brick": 82 | return "minecraft:brick_double_slab"; 83 | case "sandstone": 84 | return "minecraft:sandstone_double_slab"; 85 | case "nether_brick": 86 | return "minecraft:nether_brick_double_slab"; 87 | case "cobblestone": 88 | return "minecraft:cobblestone_double_slab"; 89 | case "smooth_stone": 90 | default: 91 | return "minecraft:smooth_stone_double_slab"; 92 | } 93 | }); 94 | 95 | this.addTypeUpdater(ctx, "minecraft:double_stone_block_slab2", "stone_slab_type_2", type -> { 96 | switch (type) { 97 | case "prismarine_rough": 98 | return "minecraft:prismarine_double_slab"; 99 | case "prismarine_dark": 100 | return "minecraft:dark_prismarine_double_slab"; 101 | case "smooth_sandstone": 102 | return "minecraft:smooth_sandstone_double_slab"; 103 | case "purpur": 104 | return "minecraft:purpur_double_slab"; 105 | case "red_nether_brick": 106 | return "minecraft:red_nether_brick_double_slab"; 107 | case "prismarine_brick": 108 | return "minecraft:prismarine_brick_double_slab"; 109 | case "mossy_cobblestone": 110 | return "minecraft:mossy_cobblestone_double_slab"; 111 | case "red_sandstone": 112 | default: 113 | return "minecraft:red_sandstone_double_slab"; 114 | } 115 | }); 116 | 117 | this.addTypeUpdater(ctx, "minecraft:double_stone_block_slab3", "stone_slab_type_3", type -> { 118 | switch (type) { 119 | case "smooth_red_sandstone": 120 | return "minecraft:smooth_red_sandstone_double_slab"; 121 | case "polished_granite": 122 | return "minecraft:polished_granite_double_slab"; 123 | case "granite": 124 | return "minecraft:granite_double_slab"; 125 | case "polished_diorite": 126 | return "minecraft:polished_diorite_double_slab"; 127 | case "andesite": 128 | return "minecraft:andesite_double_slab"; 129 | case "polished_andesite": 130 | return "minecraft:polished_andesite_double_slab"; 131 | case "diorite": 132 | return "minecraft:diorite_double_slab"; 133 | case "end_stone_brick": 134 | default: 135 | return "minecraft:end_stone_brick_double_slab"; 136 | } 137 | }); 138 | 139 | this.addTypeUpdater(ctx, "minecraft:double_stone_block_slab4", "stone_slab_type_4", type -> { 140 | switch (type) { 141 | case "smooth_quartz": 142 | return "minecraft:smooth_quartz_double_slab"; 143 | case "cut_sandstone": 144 | return "minecraft:cut_sandstone_double_slab"; 145 | case "cut_red_sandstone": 146 | return "minecraft:cut_red_sandstone_double_slab"; 147 | case "stone": 148 | return "minecraft:normal_stone_double_slab"; 149 | case "mossy_stone_brick": 150 | default: 151 | return "minecraft:mossy_stone_brick_double_slab"; 152 | } 153 | }); 154 | 155 | this.addTypeUpdater(ctx, "minecraft:prismarine", "prismarine_block_type", type -> { 156 | switch (type) { 157 | case "bricks": 158 | return "minecraft:prismarine_bricks"; 159 | case "dark": 160 | return "minecraft:dark_prismarine"; 161 | case "default": 162 | default: 163 | return "minecraft:prismarine"; 164 | } 165 | }); 166 | 167 | this.addCoralUpdater(ctx, "minecraft:coral_fan_hang", "tube_coral_wall_fan", "brain_coral_wall_fan"); 168 | this.addCoralUpdater(ctx, "minecraft:coral_fan_hang2", "bubble_coral_wall_fan", "fire_coral_wall_fan"); 169 | this.addCoralUpdater(ctx, "minecraft:coral_fan_hang3", "horn_coral_wall_fan", null); 170 | 171 | this.addTypeUpdater(ctx, "minecraft:monster_egg", "monster_egg_stone_type", type -> { 172 | switch (type) { 173 | case "cobblestone": 174 | return "minecraft:infested_cobblestone"; 175 | case "stone_brick": 176 | return "minecraft:infested_stone_bricks"; 177 | case "mossy_stone_brick": 178 | return "minecraft:infested_mossy_stone_bricks"; 179 | case "cracked_stone_brick": 180 | return "minecraft:infested_cracked_stone_bricks"; 181 | case "chiseled_stone_brick": 182 | return "minecraft:infested_chiseled_stone_bricks"; 183 | case "stone": 184 | default: 185 | return "minecraft:infested_stone"; 186 | } 187 | }); 188 | 189 | this.addTypeUpdater(ctx, "minecraft:stonebrick", "stone_brick_type", type -> { 190 | switch (type) { 191 | case "mossy": 192 | return "minecraft:mossy_stone_bricks"; 193 | case "cracked": 194 | return "minecraft:cracked_stone_bricks"; 195 | case "chiseled": 196 | return "minecraft:chiseled_stone_bricks"; 197 | case "smooth": 198 | // return "minecraft:smooth_stone_bricks"; // TODO: does not seem to exists anymore 199 | case "default": 200 | default: 201 | return "minecraft:stone_bricks"; 202 | } 203 | }); 204 | } 205 | 206 | private void addTypeUpdater(CompoundTagUpdaterContext context, String identifier, String typeState, Function rename) { 207 | context.addUpdater(1, 21, 10) 208 | .match("name", identifier) 209 | .visit("states") 210 | .edit(typeState, helper -> helper.getRootTag().put("name", rename.apply((String) helper.getTag()))) 211 | .remove(typeState); 212 | 213 | } 214 | 215 | private void addCoralUpdater(CompoundTagUpdaterContext context, String identifier, String type1, String type2) { 216 | context.addUpdater(1, 21, 10) 217 | .match("name", identifier) 218 | .edit("states", helper -> { 219 | Object deadBit = helper.getCompoundTag().remove("dead_bit"); 220 | boolean dead = deadBit instanceof Byte && (byte) deadBit == 1 || deadBit instanceof Boolean && (boolean) deadBit; 221 | 222 | Object typeBit = helper.getCompoundTag().remove("coral_hang_type_bit"); // always remove 223 | 224 | String type; 225 | if (type2 == null) { 226 | type = type1; 227 | } else { 228 | type = (typeBit instanceof Byte && (byte) typeBit == 1 || typeBit instanceof Boolean && (boolean) typeBit) ? type2 : type1; 229 | } 230 | helper.getRootTag().put("name", dead ? "minecraft:dead_" + type : "minecraft:" + type); 231 | }); 232 | 233 | } 234 | } 235 | --------------------------------------------------------------------------------