diff --git a/patches/unapplied/server/Rewrite-dataconverter-system.patch b/patches/server/Rewrite-dataconverter-system.patch similarity index 89% rename from patches/unapplied/server/Rewrite-dataconverter-system.patch rename to patches/server/Rewrite-dataconverter-system.patch index 79898568a4..59be9b9dc3 100644 --- a/patches/unapplied/server/Rewrite-dataconverter-system.patch +++ b/patches/server/Rewrite-dataconverter-system.patch @@ -104,9 +104,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +import ca.spottedleaf.dataconverter.types.MapType; + -+public interface DataWalker { ++public interface DataWalker { + -+ public MapType walk(final MapType data, final long fromVersion, final long toVersion); ++ public T walk(final T data, final long fromVersion, final long toVersion); + +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCDataConverter.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCDataConverter.java @@ -120,6 +120,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.converters.datatypes.DataType; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCDataType; ++import ca.spottedleaf.dataconverter.minecraft.versions.V99; +import ca.spottedleaf.dataconverter.types.json.JsonMapType; +import ca.spottedleaf.dataconverter.types.nbt.NBTMapType; +import com.google.gson.JsonObject; @@ -159,7 +160,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static R convert(final DataType type, final T data, int fromVersion, final int toVersion) { + Object ret = data; + -+ long currentVersion = DataConverter.encodeVersions(fromVersion < 99 ? 99 : fromVersion, Integer.MAX_VALUE); ++ long currentVersion = DataConverter.encodeVersions(fromVersion < V99.VERSION ? V99.VERSION : fromVersion, Integer.MAX_VALUE); + final long nextVersion = DataConverter.encodeVersions(toVersion, Integer.MAX_VALUE); + + for (int i = 0, len = BREAKPOINTS.size(); i < len; ++i) { @@ -192,7 +193,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private MCDataConverter() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersionRegistry.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersionRegistry.java new file mode 100644 @@ -220,15 +220,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final Logger LOGGER = LogUtils.getLogger(); + -+ protected static final Int2ObjectLinkedOpenHashMap VERSION_NAMES = new Int2ObjectLinkedOpenHashMap<>(); -+ protected static final IntArrayList VERSION_LIST; -+ protected static final LongArrayList DATA_VERSION_LIST; ++ private static final Int2ObjectLinkedOpenHashMap VERSION_NAMES = new Int2ObjectLinkedOpenHashMap<>(); ++ private static final IntArrayList VERSION_LIST; ++ private static final LongArrayList DATA_VERSION_LIST; + -+ protected static final IntArrayList DATACONVERTER_VERSIONS_LIST; -+ protected static final IntLinkedOpenHashSet DATACONVERTER_VERSIONS_MAJOR = new IntLinkedOpenHashSet(); -+ protected static final LongLinkedOpenHashSet DATACONVERTER_VERSIONS = new LongLinkedOpenHashSet(); -+ protected static final Int2ObjectLinkedOpenHashMap SUBVERSIONS = new Int2ObjectLinkedOpenHashMap<>(); -+ protected static final LongArrayList BREAKPOINTS = new LongArrayList(); ++ private static final IntArrayList DATACONVERTER_VERSIONS_LIST; ++ private static final IntLinkedOpenHashSet DATACONVERTER_VERSIONS_MAJOR = new IntLinkedOpenHashSet(); ++ private static final LongLinkedOpenHashSet DATACONVERTER_VERSIONS = new LongLinkedOpenHashSet(); ++ private static final Int2ObjectLinkedOpenHashMap SUBVERSIONS = new Int2ObjectLinkedOpenHashMap<>(); ++ private static final LongArrayList BREAKPOINTS = new LongArrayList(); + static { + // Note: Some of these are nameless. + // Unless a data version is specified here, it will NOT have converters ran for it. Please add them on update! @@ -426,7 +426,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 3683, + 3685, + 3692, -+ // All up to 1.20.3 ++ 3800, ++ 3803, ++ 3807, ++ 3808, ++ 3809, ++ 3812, ++ 3813, ++ 3814, ++ 3818, ++ 3820, ++ 3825, ++ 3828, ++ 3833 ++ // All up to 1.20.5 + }; + Arrays.sort(converterVersions); + @@ -443,22 +456,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerSubVersion(MCVersions.V17W47A, 6); + registerSubVersion(MCVersions.V17W47A, 7); + ++ registerSubVersion(MCVersions.V24W04A + 1, 1); ++ registerSubVersion(MCVersions.V24W04A + 2, 1); ++ ++ registerSubVersion(MCVersions.V24W07A + 1, 1); ++ registerSubVersion(MCVersions.V24W07A + 1, 2); ++ registerSubVersion(MCVersions.V24W07A + 1, 4); ++ registerSubVersion(MCVersions.V24W07A + 1, 5); ++ registerSubVersion(MCVersions.V24W07A + 1, 6); ++ + // register breakpoints here + // for all major releases after 1.16, add them. this reduces the work required to determine if a breakpoint + // is needed for new converters + + // Too much changed in this version. + registerBreakpoint(MCVersions.V17W47A); -+ registerBreakpoint(MCVersions.V17W47A, Integer.MAX_VALUE); ++ registerBreakpointAfter(MCVersions.V17W47A, Integer.MAX_VALUE); + + // final release of major version -+ registerBreakpoint(MCVersions.V1_17_1, Integer.MAX_VALUE); ++ registerBreakpointAfter(MCVersions.V1_17_1, Integer.MAX_VALUE); + + // final release of major version -+ registerBreakpoint(MCVersions.V1_18_2, Integer.MAX_VALUE); ++ registerBreakpointAfter(MCVersions.V1_18_2, Integer.MAX_VALUE); + + // final release of major version -+ registerBreakpoint(MCVersions.V1_19_4, Integer.MAX_VALUE); ++ registerBreakpointAfter(MCVersions.V1_19_4, Integer.MAX_VALUE); ++ ++ // Too much changed in this version. ++ registerBreakpoint(MCVersions.V24W07A + 1, 5); ++ registerBreakpointAfter(MCVersions.V24W07A + 1, Integer.MAX_VALUE); + } + + static { @@ -553,6 +579,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + BREAKPOINTS.add(DataConverter.encodeVersions(version, step)); + } + ++ private static void registerBreakpointAfter(final int version) { ++ registerBreakpointAfter(version, 0); ++ } ++ ++ private static void registerBreakpointAfter(final int version, final int step) { ++ BREAKPOINTS.add(DataConverter.encodeVersions(version, step) + 1L); ++ } ++ + // returns only versions that have dataconverters + public static boolean hasDataConverters(final int version) { + return DATACONVERTER_VERSIONS_MAJOR.contains(version); @@ -587,6 +621,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + throw new IllegalStateException("Version " + DataConverter.encodedToString(version) + " is not registered to have dataconverters, yet has a dataconverter"); + } + } ++ ++ private MCVersionRegistry() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersions.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/MCVersions.java new file mode 100644 @@ -1091,7 +1127,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final int V1_20_3_PRE4 = 3696; + public static final int V1_20_3_RC1 = 3697; + public static final int V1_20_3 = 3698; ++ public static final int V1_20_4_RC1 = 3699; ++ public static final int V1_20_4 = 3700; ++ public static final int V23W51A = 3801; ++ public static final int V23W51B = 3802; ++ public static final int V24W03A = 3804; ++ public static final int V24W03B = 3805; ++ public static final int V24W04A = 3806; ++ public static final int V24W05A = 3809; ++ public static final int V24W05B = 3811; ++ public static final int V24W06A = 3815; ++ public static final int V24W07A = 3817; ++ public static final int V24W09A = 3819; ++ public static final int V24W10A = 3821; ++ public static final int V24W11A = 3823; ++ public static final int V24W12A = 3824; ++ public static final int V24W13A = 3826; ++ public static final int V24W14A = 3827; ++ public static final int V1_20_5_PRE1 = 3829; ++ public static final int V1_20_5_PRE2 = 3830; ++ public static final int V1_20_5_PRE3 = 3831; ++ public static final int V1_20_5_PRE4 = 3832; ++ public static final int V1_20_5_RC1 = 3834; ++ public static final int V1_20_5_RC2 = 3835; ++ public static final int V1_20_5_RC3 = 3836; ++ public static final int V1_20_5 = 3837; + ++ private MCVersions() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/advancements/ConverterAbstractAdvancementsRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/advancements/ConverterAbstractAdvancementsRename.java new file mode 100644 @@ -1175,6 +1237,69 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + +} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractAttributesRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractAttributesRename.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/attributes/ConverterAbstractAttributesRename.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.converters.attributes; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++import java.util.function.Function; ++ ++public final class ConverterAbstractAttributesRename { ++ ++ public static void register(final int version, final Function renamer) { ++ register(version, 0, renamer); ++ } ++ ++ public static void register(final int version, final int versionStep, final Function renamer) { ++ final DataConverter, MapType> entityConverter = new DataConverter<>(version, versionStep) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final ListType attributes = data.getList("Attributes", ObjectType.MAP); ++ ++ if (attributes == null) { ++ return null; ++ } ++ ++ for (int i = 0, len = attributes.size(); i < len; ++i) { ++ RenameHelper.renameString(attributes.getMap(i), "Name", renamer); ++ } ++ ++ return null; ++ } ++ }; ++ ++ MCTypeRegistry.ENTITY.addStructureConverter(entityConverter); ++ MCTypeRegistry.PLAYER.addStructureConverter(entityConverter); ++ ++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(version, versionStep) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final ListType attributes = data.getList("AttributeModifiers", ObjectType.MAP); ++ ++ if (attributes == null) { ++ return null; ++ } ++ ++ for (int i = 0, len = attributes.size(); i < len; ++i) { ++ RenameHelper.renameString(attributes.getMap(i), "AttributeName", renamer); ++ } ++ ++ return null; ++ } ++ }); ++ } ++ ++ private ConverterAbstractAttributesRename() {} ++} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/blockname/ConverterAbstractBlockRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/blockname/ConverterAbstractBlockRename.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -1212,44 +1337,35 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + }); -+ } -+ -+ public static void registerAndFixJigsaw(final int version, final Function renamer) { -+ registerAndFixJigsaw(version, 0, renamer); -+ } -+ -+ public static void registerAndFixJigsaw(final int version, final int subVersion, final Function renamer) { -+ register(version, subVersion, renamer); -+ // TODO check on update, minecraft:jigsaw can change -+ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:jigsaw", new DataConverter<>(version, subVersion) { ++ MCTypeRegistry.FLAT_BLOCK_STATE.addConverter(new DataConverter<>(version, subVersion) { + @Override -+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { -+ final String finalState = data.getString("final_state"); -+ if (finalState == null || finalState.isEmpty()) { ++ public Object convert(final Object data, final long sourceVersion, final long toVersion) { ++ if (!(data instanceof String string)) { + return null; + } + -+ final int nbtStart1 = finalState.indexOf('['); -+ final int nbtStart2 = finalState.indexOf('{'); -+ int stateNameEnd = finalState.length(); ++ if (string.isEmpty()) { ++ return null; ++ } ++ ++ final int nbtStart1 = string.indexOf('['); ++ final int nbtStart2 = string.indexOf('{'); ++ int stateNameEnd = string.length(); + if (nbtStart1 > 0) { -+ stateNameEnd = Math.min(stateNameEnd, nbtStart1); ++ stateNameEnd = nbtStart1; + } + + if (nbtStart2 > 0) { + stateNameEnd = Math.min(stateNameEnd, nbtStart2); + } + -+ final String blockStateName = finalState.substring(0, stateNameEnd); ++ final String blockStateName = string.substring(0, stateNameEnd); + final String converted = renamer.apply(blockStateName); + if (converted == null) { + return null; + } + -+ final String convertedState = converted.concat(finalState.substring(stateNameEnd)); -+ data.setString("final_state", convertedState); -+ -+ return null; ++ return converted.concat(string.substring(stateNameEnd)); + } + }); + } @@ -2385,6 +2501,300 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } +} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/custom/V3818_Commands.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/custom/V3818_Commands.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/custom/V3818_Commands.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.converters.custom; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCDataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++import ca.spottedleaf.dataconverter.util.CommandArgumentUpgrader; ++import com.google.common.base.Suppliers; ++import com.google.gson.JsonArray; ++import com.google.gson.JsonElement; ++import com.google.gson.JsonObject; ++import com.google.gson.JsonParseException; ++import com.google.gson.JsonParser; ++import com.google.gson.JsonPrimitive; ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import com.mojang.serialization.Dynamic; ++import com.mojang.serialization.JsonOps; ++import net.minecraft.SharedConstants; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.NbtOps; ++import net.minecraft.nbt.Tag; ++import net.minecraft.nbt.TagParser; ++import net.minecraft.util.GsonHelper; ++import java.util.Iterator; ++import java.util.function.Supplier; ++ ++public final class V3818_Commands { ++ ++ private static final int VERSION = MCVersions.V24W07A + 1; ++ ++ private static final boolean DISABLE_COMMAND_CONVERTER = Boolean.getBoolean("Paper.DisableCommandConverter"); ++ ++ public static String toCommandFormat(final CompoundTag components) { ++ final StringBuilder ret = new StringBuilder(); ++ ret.append('['); ++ for (final Iterator iterator = components.getAllKeys().iterator(); iterator.hasNext();) { ++ final String key = iterator.next(); ++ ret.append(key); ++ ret.append('='); ++ ret.append(components.get(key).toString()); ++ if (iterator.hasNext()) { ++ ret.append(','); ++ } ++ } ++ ret.append(']'); ++ ++ return ret.toString(); ++ } ++ ++ public static JsonElement convertToJson(final Tag tag) { ++ // We don't have conversion utilities, but DFU does... ++ ++ return new Dynamic<>(NbtOps.INSTANCE, tag).convert(JsonOps.INSTANCE).getValue(); ++ } ++ ++ public static void walkComponent(final JsonElement primitive) { ++ if (!(primitive instanceof JsonObject root)) { ++ if (primitive instanceof JsonArray array) { ++ for (final JsonElement component : array) { ++ walkComponent(component); ++ } ++ } ++ return; ++ } ++ ++ final JsonElement clickEventElement = root.get("clickEvent"); ++ if (clickEventElement instanceof JsonObject clickEvent) { ++ final JsonElement actionElement = clickEvent.get("action"); ++ final JsonElement cmdElement = clickEvent.get("value"); ++ if (actionElement instanceof JsonPrimitive action && cmdElement instanceof JsonPrimitive cmd) { ++ final String actionString = action.getAsString(); ++ final String cmdString = cmd.getAsString(); ++ ++ if ((actionString.equals("suggest_command") && cmdString.startsWith("/")) || actionString.equals("run_command")) { ++ final Object res = MCTypeRegistry.DATACONVERTER_CUSTOM_TYPE_COMMAND.convert( ++ cmdString, MCVersions.V1_20_4, SharedConstants.getCurrentVersion().getDataVersion().getVersion() ++ ); ++ if (res instanceof String newCmd) { ++ clickEvent.addProperty("value", newCmd); ++ } ++ } ++ } ++ } ++ ++ final JsonElement hoverEventElement = root.get("hoverEvent"); ++ if (hoverEventElement instanceof JsonObject hoverEvent) { ++ final JsonElement showText = hoverEvent.get("action"); ++ if (showText instanceof JsonPrimitive showTextPrimitive && showTextPrimitive.getAsString().equals("show_item")) { ++ final JsonElement contentsElement = hoverEvent.get("contents"); ++ if (contentsElement instanceof JsonObject contents) { ++ final JsonElement idElement = contents.get("id"); ++ final JsonElement tagElement = contents.get("tag"); ++ ++ if (idElement instanceof JsonPrimitive idPrimitive) { ++ final CompoundTag itemNBT = new CompoundTag(); ++ itemNBT.putString("id", idPrimitive.getAsString()); ++ itemNBT.putInt("Count", 1); ++ ++ if (tagElement instanceof JsonPrimitive tagPrimitive) { ++ try { ++ final CompoundTag tag = TagParser.parseTag(tagPrimitive.getAsString()); ++ itemNBT.put("tag", tag); ++ } catch (final CommandSyntaxException ignore) {} ++ } ++ ++ final CompoundTag converted = MCDataConverter.convertTag( ++ MCTypeRegistry.ITEM_STACK, itemNBT, MCVersions.V1_20_4, ++ SharedConstants.getCurrentVersion().getDataVersion().getVersion() ++ ); ++ ++ contents.remove("tag"); ++ ++ contents.addProperty("id", converted.getString("id")); ++ ++ if (converted.contains("components", Tag.TAG_COMPOUND)) { ++ contents.add("components", convertToJson(converted.getCompound("components"))); ++ } ++ } ++ } ++ final JsonElement valueElement = hoverEvent.get("value"); ++ if (valueElement instanceof JsonPrimitive valuePrimitive) { ++ try { ++ final CompoundTag itemNBT = TagParser.parseTag(valuePrimitive.getAsString()); ++ if (itemNBT.contains("id", Tag.TAG_STRING)) { ++ final boolean explicitCount = itemNBT.contains("Count", Tag.TAG_ANY_NUMERIC); ++ if (!explicitCount) { ++ itemNBT.putInt("Count", 1); ++ } ++ final CompoundTag converted = MCDataConverter.convertTag( ++ MCTypeRegistry.ITEM_STACK, itemNBT, MCVersions.V1_20_4, ++ SharedConstants.getCurrentVersion().getDataVersion().getVersion() ++ ); ++ ++ hoverEvent.remove("value"); ++ ++ final JsonObject contents = new JsonObject(); ++ hoverEvent.add("contents", contents); ++ ++ contents.addProperty("id", converted.getString("id")); ++ if (explicitCount) { ++ contents.addProperty("count", converted.getInt("count")); ++ } ++ ++ if (converted.contains("components", Tag.TAG_COMPOUND)) { ++ contents.add("components", convertToJson(converted.getCompound("components"))); ++ } ++ } ++ } catch (final CommandSyntaxException ignore) {} ++ } ++ } ++ } ++ ++ final JsonElement extra = root.get("extra"); ++ if (extra instanceof JsonArray array) { ++ for (final JsonElement component : array) { ++ walkComponent(component); ++ } ++ } ++ } ++ ++ private static String walkComponent(final String json) { ++ if (json == null || json.isEmpty()) { ++ return json; ++ } ++ ++ try { ++ final JsonElement element = JsonParser.parseString(json); ++ walkComponent(element); ++ return GsonHelper.toStableString(element); ++ } catch (final JsonParseException ex) { ++ return json; ++ } ++ } ++ ++ // this is AFTER all the converters for subversion 5, so these run AFTER them ++ public static void register_5() { ++ if (DISABLE_COMMAND_CONVERTER) { ++ return; ++ } ++ // Command is already registered in walker for command blocks ++ MCTypeRegistry.DATACONVERTER_CUSTOM_TYPE_COMMAND.addConverter(new DataConverter<>(VERSION, 5) { ++ private static final Supplier COMMAND_UPGRADER = Suppliers.memoize(() -> ++ CommandArgumentUpgrader.upgrader_1_20_4_to_1_20_5(999)); ++ ++ @Override ++ public Object convert(final Object data, final long sourceVersion, final long toVersion) { ++ if (!(data instanceof String cmd)) { ++ return null; ++ } ++ // We use startsWith("/") because we aren't supporting WorldEdit style commands, ++ // and passing the context of whether the use supports leading slash would be high effort low return ++ return COMMAND_UPGRADER.get().upgradeCommandArguments(cmd, cmd.startsWith("/")); ++ } ++ }); ++ ++ // command is not registered in any walkers for books/signs, and we don't want to do that as we would parse ++ // the json every walk. instead, we create a one time converter to avoid the additional cost of parsing the json ++ // for future updates ++ ++ // books ++ // note: at this stage, item is converted to components, so we can use the data components type ++ MCTypeRegistry.DATA_COMPONENTS.addStructureConverter(new DataConverter<>(VERSION, 5) { ++ private static void walkPath(final MapType data, final String path) { ++ final String str = data.getString(path); ++ if (str == null) { ++ return; ++ } ++ ++ final String newStr = walkComponent(str); ++ if (newStr != null) { ++ data.setString(path, newStr); ++ } ++ } ++ ++ private static void walkBookContent(final MapType data, final String path) { ++ if (data == null) { ++ return; ++ } ++ ++ final MapType content = data.getMap(path); ++ if (content == null) { ++ return; ++ } ++ ++ final ListType pages = content.getList("pages", ObjectType.MAP); ++ if (pages == null) { ++ return; ++ } ++ ++ for (int i = 0, len = pages.size(); i < len; ++i) { ++ final MapType text = pages.getMap(i); ++ ++ walkPath(text, "raw"); ++ walkPath(text, "filtered"); ++ } ++ } ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ walkBookContent(data, "minecraft:written_book_content"); ++ return null; ++ } ++ }); ++ ++ // signs ++ ++ final DataConverter, MapType> signTileConverter = new DataConverter<>(VERSION, 5) { ++ private static void walkText(final MapType data, final String path) { ++ if (data == null) { ++ return; ++ } ++ ++ final MapType text = data.getMap(path); ++ if (text == null) { ++ return; ++ } ++ ++ final ListType messages = text.getList("messages", ObjectType.STRING); ++ if (messages != null) { ++ for (int i = 0, len = Math.min(4, messages.size()); i < len; ++i) { ++ messages.setString(i, walkComponent(messages.getString(i))); ++ } ++ } ++ ++ final ListType filteredMessages = text.getList("filtered_messages", ObjectType.STRING); ++ ++ if (filteredMessages != null) { ++ for (int i = 0, len = Math.min(4, filteredMessages.size()); i < len; ++i) { ++ filteredMessages.setString(i, walkComponent(filteredMessages.getString(i))); ++ } ++ } ++ } ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ walkText(data, "front_text"); ++ walkText(data, "back_text"); ++ return null; ++ } ++ }; ++ ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:sign", signTileConverter); ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:hanging_sign", signTileConverter); ++ } ++} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/entity/ConverterAbstractEntityRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/entity/ConverterAbstractEntityRename.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -5382,8 +5792,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ID_TO_STRING[46] = "MinecartHopper"; + ID_TO_STRING[47] = "MinecartSpawner"; + ID_TO_STRING[40] = "MinecartCommandBlock"; -+ ID_TO_STRING[48] = "Mob"; -+ ID_TO_STRING[49] = "Monster"; + ID_TO_STRING[50] = "Creeper"; + ID_TO_STRING[51] = "Skeleton"; + ID_TO_STRING[52] = "Spider"; @@ -5432,7 +5840,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package ca.spottedleaf.dataconverter.minecraft.converters.helpers; + ++import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Function; @@ -5516,8 +5926,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + data.setString(key, renamed); + } + -+ private RenameHelper() {} ++ public static void renameListMapItems(final MapType data, final String listPath, final String mapPath, ++ final Function renamer) { ++ if (data == null) { ++ return; ++ } + ++ final ListType list = data.getList(listPath, ObjectType.MAP); ++ if (list == null) { ++ return; ++ } ++ ++ for (int i = 0, len = list.size(); i < len; ++i) { ++ RenameHelper.renameString(list.getMap(i), mapPath, renamer); ++ } ++ } ++ ++ private RenameHelper() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemname/ConverterAbstractItemRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemname/ConverterAbstractItemRename.java new file mode 100644 @@ -5543,6 +5968,47 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + +} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterEnchantmentsRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterEnchantmentsRename.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterEnchantmentsRename.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.converters.itemstack; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper; ++import ca.spottedleaf.dataconverter.types.MapType; ++import java.util.function.Function; ++ ++public final class ConverterEnchantmentsRename extends DataConverter, MapType> { ++ ++ private final Function renamer; ++ ++ public ConverterEnchantmentsRename(final int toVersion, final Function renamer) { ++ this(toVersion, 0, renamer); ++ } ++ ++ public ConverterEnchantmentsRename(final int toVersion, final int versionStep, final Function renamer) { ++ super(toVersion, versionStep); ++ ++ this.renamer = renamer; ++ } ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType tag = data.getMap("tag"); ++ ++ if (tag == null) { ++ return null; ++ } ++ ++ RenameHelper.renameListMapItems(tag, "Enchantments", "id", this.renamer); ++ RenameHelper.renameListMapItems(tag, "StoredEnchantments", "id", this.renamer); ++ ++ return null; ++ } ++} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterFlattenItemStack.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterFlattenItemStack.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -6102,6 +6568,1256 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } +} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterItemStackToDataComponents.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterItemStackToDataComponents.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/itemstack/ConverterItemStackToDataComponents.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.converters.itemstack; ++ ++import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper; ++import ca.spottedleaf.dataconverter.minecraft.util.ComponentUtils; ++import ca.spottedleaf.dataconverter.minecraft.versions.V3818; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++import ca.spottedleaf.dataconverter.types.TypeUtil; ++import ca.spottedleaf.dataconverter.util.NamespaceUtil; ++import net.minecraft.util.Mth; ++import java.util.Arrays; ++import java.util.HashSet; ++import java.util.Set; ++ ++public final class ConverterItemStackToDataComponents { ++ ++ private static final int TOOLTIP_FLAG_HIDE_ENCHANTMENTS = 1 << 0; ++ private static final int TOOLTIP_FLAG_HIDE_MODIFIERS = 1 << 1; ++ private static final int TOOLTIP_FLAG_HIDE_UNBREAKABLE = 1 << 2; ++ private static final int TOOLTIP_FLAG_HIDE_CAN_DESTROY = 1 << 3; ++ private static final int TOOLTIP_FLAG_HIDE_CAN_PLACE = 1 << 4; ++ private static final int TOOLTIP_FLAG_HIDE_ADDITIONAL = 1 << 5; ++ private static final int TOOLTIP_FLAG_HIDE_DYE = 1 << 6; ++ private static final int TOOLTIP_FLAG_HIDE_UPGRADES = 1 << 7; ++ ++ private static final int DEFAULT_LEATHER_COLOUR = (160 << 16) | (101 << 8) | (64 << 0); // r, g, b ++ ++ private static final String[] BUCKETED_MOB_TAGS = new String[] { ++ "NoAI", ++ "Silent", ++ "NoGravity", ++ "Glowing", ++ "Invulnerable", ++ "Health", ++ "Age", ++ "Variant", ++ "HuntingCooldown", ++ "BucketVariantTag" ++ }; ++ private static final Set BOOLEAN_BLOCK_STATE_PROPERTIES = new HashSet<>( ++ Arrays.asList( ++ "attached", ++ "bottom", ++ "conditional", ++ "disarmed", ++ "drag", ++ "enabled", ++ "extended", ++ "eye", ++ "falling", ++ "hanging", ++ "has_bottle_0", ++ "has_bottle_1", ++ "has_bottle_2", ++ "has_record", ++ "has_book", ++ "inverted", ++ "in_wall", ++ "lit", ++ "locked", ++ "occupied", ++ "open", ++ "persistent", ++ "powered", ++ "short", ++ "signal_fire", ++ "snowy", ++ "triggered", ++ "unstable", ++ "waterlogged", ++ "berries", ++ "bloom", ++ "shrieking", ++ "can_summon", ++ "up", ++ "down", ++ "north", ++ "east", ++ "south", ++ "west", ++ "slot_0_occupied", ++ "slot_1_occupied", ++ "slot_2_occupied", ++ "slot_3_occupied", ++ "slot_4_occupied", ++ "slot_5_occupied", ++ "cracked", ++ "crafting" ++ ) ++ ); ++ private static final String[] MAP_DECORATION_CONVERSION_TABLE = new String[34]; ++ static { ++ MAP_DECORATION_CONVERSION_TABLE[0] = "player"; ++ MAP_DECORATION_CONVERSION_TABLE[1] = "frame"; ++ MAP_DECORATION_CONVERSION_TABLE[2] = "red_marker"; ++ MAP_DECORATION_CONVERSION_TABLE[3] = "blue_marker"; ++ MAP_DECORATION_CONVERSION_TABLE[4] = "target_x"; ++ MAP_DECORATION_CONVERSION_TABLE[5] = "target_point"; ++ MAP_DECORATION_CONVERSION_TABLE[6] = "player_off_map"; ++ MAP_DECORATION_CONVERSION_TABLE[7] = "player_off_limits"; ++ MAP_DECORATION_CONVERSION_TABLE[8] = "mansion"; ++ MAP_DECORATION_CONVERSION_TABLE[9] = "monument"; ++ MAP_DECORATION_CONVERSION_TABLE[10] = "banner_white"; ++ MAP_DECORATION_CONVERSION_TABLE[11] = "banner_orange"; ++ MAP_DECORATION_CONVERSION_TABLE[12] = "banner_magenta"; ++ MAP_DECORATION_CONVERSION_TABLE[13] = "banner_light_blue"; ++ MAP_DECORATION_CONVERSION_TABLE[14] = "banner_yellow"; ++ MAP_DECORATION_CONVERSION_TABLE[15] = "banner_lime"; ++ MAP_DECORATION_CONVERSION_TABLE[16] = "banner_pink"; ++ MAP_DECORATION_CONVERSION_TABLE[17] = "banner_gray"; ++ MAP_DECORATION_CONVERSION_TABLE[18] = "banner_light_gray"; ++ MAP_DECORATION_CONVERSION_TABLE[19] = "banner_cyan"; ++ MAP_DECORATION_CONVERSION_TABLE[20] = "banner_purple"; ++ MAP_DECORATION_CONVERSION_TABLE[21] = "banner_blue"; ++ MAP_DECORATION_CONVERSION_TABLE[22] = "banner_brown"; ++ MAP_DECORATION_CONVERSION_TABLE[23] = "banner_green"; ++ MAP_DECORATION_CONVERSION_TABLE[24] = "banner_red"; ++ MAP_DECORATION_CONVERSION_TABLE[25] = "banner_black"; ++ MAP_DECORATION_CONVERSION_TABLE[26] = "red_x"; ++ MAP_DECORATION_CONVERSION_TABLE[27] = "village_desert"; ++ MAP_DECORATION_CONVERSION_TABLE[28] = "village_plains"; ++ MAP_DECORATION_CONVERSION_TABLE[29] = "village_savanna"; ++ MAP_DECORATION_CONVERSION_TABLE[30] = "village_snowy"; ++ MAP_DECORATION_CONVERSION_TABLE[31] = "village_taiga"; ++ MAP_DECORATION_CONVERSION_TABLE[32] = "jungle_temple"; ++ MAP_DECORATION_CONVERSION_TABLE[33] = "swamp_hut"; ++ } ++ ++ private static String convertMapDecorationId(final int type) { ++ return type >= 0 && type < MAP_DECORATION_CONVERSION_TABLE.length ? MAP_DECORATION_CONVERSION_TABLE[type] : MAP_DECORATION_CONVERSION_TABLE[0]; ++ } ++ ++ private static void convertBlockStateProperties(final MapType properties) { ++ // convert values stored as boolean/integer to string ++ for (final String key : properties.keys()) { ++ final Object value = properties.getGeneric(key); ++ if (value instanceof Number number) { ++ if (BOOLEAN_BLOCK_STATE_PROPERTIES.contains(key)) { ++ properties.setString(key, Boolean.toString(number.byteValue() != (byte)0)); ++ } else { ++ properties.setString(key, number.toString()); ++ } ++ } ++ } ++ } ++ ++ private static void convertTileEntity(final MapType tileEntity, final TransientItemStack transientItem) { ++ final Object lock = tileEntity.getGeneric("Lock"); ++ if (lock != null) { ++ tileEntity.remove("Lock"); ++ transientItem.componentSetGeneric("minecraft:lock", lock); ++ } ++ ++ final Object lootTable = tileEntity.getGeneric("LootTable"); ++ if (lootTable != null) { ++ final MapType containerLoot = tileEntity.getTypeUtil().createEmptyMap(); ++ transientItem.componentSetMap("minecraft:container_loot", containerLoot); ++ ++ containerLoot.setGeneric("loot_table", lootTable); ++ ++ final long seed = tileEntity.getLong("LootTableSeed", 0L); ++ if (seed != 0L) { ++ containerLoot.setLong("seed", seed); ++ } ++ ++ tileEntity.remove("LootTable"); ++ tileEntity.remove("LootTableSeed"); ++ } ++ ++ final String id = NamespaceUtil.correctNamespace(tileEntity.getString("id", "")); ++ ++ switch (id) { ++ case "minecraft:skull": { ++ final Object noteBlockSound = tileEntity.getGeneric("note_block_sound"); ++ if (noteBlockSound != null) { ++ tileEntity.remove("note_block_sound"); ++ transientItem.componentSetGeneric("minecraft:note_block_sound", noteBlockSound); ++ } ++ ++ break; ++ } ++ case "minecraft:decorated_pot": { ++ final Object sherds = tileEntity.getGeneric("sherds"); ++ if (sherds != null) { ++ tileEntity.remove("sherds"); ++ transientItem.componentSetGeneric("minecraft:pot_decorations", sherds); ++ } ++ ++ final Object item = tileEntity.getGeneric("item"); ++ if (item != null) { ++ tileEntity.remove("item"); ++ ++ final ListType container = tileEntity.getTypeUtil().createEmptyList(); ++ transientItem.componentSetList("minecraft:container", container); ++ ++ final MapType wrappedItem = tileEntity.getTypeUtil().createEmptyMap(); ++ container.addMap(wrappedItem); ++ ++ wrappedItem.setInt("slot", 0); ++ wrappedItem.setGeneric("item", item); ++ } ++ ++ break; ++ } ++ case "minecraft:banner": { ++ final Object patterns = tileEntity.getGeneric("patterns"); ++ if (patterns != null) { ++ tileEntity.remove("patterns"); ++ ++ transientItem.componentSetGeneric("minecraft:banner_patterns", patterns); ++ } ++ ++ final Number base = tileEntity.getNumber("Base"); ++ if (base != null) { ++ tileEntity.remove("Base"); ++ ++ transientItem.componentSetString("minecraft:base_color", V3818.getBannerColour(base.intValue())); ++ } ++ ++ break; ++ } ++ ++ case "minecraft:shulker_box": ++ case "minecraft:chest": ++ case "minecraft:trapped_chest": ++ case "minecraft:furnace": ++ case "minecraft:ender_chest": ++ case "minecraft:dispenser": ++ case "minecraft:dropper": ++ case "minecraft:brewing_stand": ++ case "minecraft:hopper": ++ case "minecraft:barrel": ++ case "minecraft:smoker": ++ case "minecraft:blast_furnace": ++ case "minecraft:campfire": ++ case "minecraft:chiseled_bookshelf": ++ case "minecraft:crafter": { ++ final ListType items = tileEntity.getList("Items", ObjectType.MAP); ++ tileEntity.remove("Items"); ++ if (items != null && items.size() > 1) { ++ transientItem.componentSetList("minecraft:container", items); ++ ++ for (int i = 0, len = items.size(); i < len; ++i) { ++ final MapType item = items.getMap(i); ++ final int slot = (int)item.getByte("Slot", (byte)0) & 0xFF; ++ item.remove("Slot"); ++ ++ final MapType wrappedItem = item.getTypeUtil().createEmptyMap(); ++ items.setMap(i, wrappedItem); ++ ++ wrappedItem.setInt("slot", slot); ++ wrappedItem.setMap("item", item); ++ } ++ } ++ ++ break; ++ } ++ ++ case "minecraft:beehive": { ++ final Object bees = tileEntity.getGeneric("bees"); ++ if (bees != null) { ++ tileEntity.remove("bees"); ++ ++ transientItem.componentSetGeneric("minecraft:bees", bees); ++ } ++ break; ++ } ++ } ++ } ++ ++ private static void convertEnchantments(final TransientItemStack transientItem, final TypeUtil type, ++ final String tagKey, final String componentKey, ++ final boolean hideToolTip) { ++ final ListType enchantments = transientItem.tagRemoveList(tagKey, ObjectType.MAP); ++ if (enchantments == null || enchantments.size() == 0) { ++ if (hideToolTip) { ++ final MapType newEnchants = type.createEmptyMap(); ++ transientItem.componentSetMap(componentKey, newEnchants); ++ ++ newEnchants.setMap("levels", type.createEmptyMap()); ++ newEnchants.setBoolean("show_in_tooltip", false); ++ } ++ } else { ++ final MapType newEnchantments = type.createEmptyMap(); ++ ++ for (int i = 0, len = enchantments.size(); i < len; ++i) { ++ final MapType enchantment = enchantments.getMap(i); ++ ++ final String id = enchantment.getString("id"); ++ final Number level = enchantment.getNumber("lvl"); ++ ++ if (id == null || level == null) { ++ continue; ++ } ++ ++ newEnchantments.setInt(id, Mth.clamp(level.intValue(), 0, 0xFF)); ++ } ++ ++ if (!newEnchantments.isEmpty() || hideToolTip) { ++ final MapType newEnchants = type.createEmptyMap(); ++ transientItem.componentSetMap(componentKey, newEnchants); ++ ++ newEnchants.setMap("levels", newEnchantments); ++ if (hideToolTip) { ++ newEnchants.setBoolean("show_in_tooltip", false); ++ } ++ } ++ } ++ ++ if (enchantments != null && enchantments.size() == 0) { ++ transientItem.componentSetBoolean("minecraft:enchantment_glint_override", true); ++ } ++ } ++ ++ private static void convertDisplay(final TransientItemStack transientItem, final TypeUtil type, final int flags) { ++ final MapType display = transientItem.tag.getMap("display"); ++ ++ if (display != null) { ++ final Object name = display.getGeneric("Name"); ++ if (name != null) { ++ display.remove("Name"); ++ ++ transientItem.componentSetGeneric("minecraft:custom_name", name); ++ } ++ ++ final Object lore = display.getGeneric("Lore"); ++ if (lore != null) { ++ display.remove("Lore"); ++ ++ transientItem.componentSetGeneric("minecraft:lore", lore); ++ } ++ } ++ ++ final Number color = display == null ? null : display.getNumber("color"); ++ final boolean hideDye = (flags & TOOLTIP_FLAG_HIDE_DYE) != 0; ++ ++ if (hideDye || color != null) { ++ if (color != null) { ++ display.remove("color"); ++ } ++ ++ final MapType dyedColor = type.createEmptyMap(); ++ transientItem.componentSetMap("minecraft:dyed_color", dyedColor); ++ ++ dyedColor.setInt("rgb", color == null ? DEFAULT_LEATHER_COLOUR : color.intValue()); ++ if (hideDye) { ++ dyedColor.setBoolean("show_in_tooltip", false); ++ } ++ } ++ ++ final Object locName = display == null ? null : display.getGeneric("LocName"); ++ if (locName != null) { ++ display.remove("LocName"); ++ ++ if (locName instanceof String locNameString) { ++ transientItem.componentSetString("minecraft:item_name", ComponentUtils.createTranslatableComponent(locNameString)); ++ } ++ } ++ ++ if (display != null && "minecraft:filled_map".equals(transientItem.id)) { ++ final Object mapColor = display.getGeneric("MapColor"); ++ if (mapColor != null) { ++ display.remove("MapColor"); ++ ++ transientItem.componentSetGeneric("minecraft:map_color", mapColor); ++ } ++ } ++ ++ // mirror behavior of fixSubTag ++ if (display != null && display.isEmpty()) { ++ transientItem.tagRemoveMap("display"); ++ } ++ } ++ ++ public static MapType convertBlockStatePredicate(final String value, final TypeUtil type) { ++ final int propertyStart = value.indexOf('['); ++ final int nbtStart = value.indexOf('{'); ++ int blockNameEnd = value.length(); ++ ++ if (propertyStart != -1) { ++ blockNameEnd = propertyStart; ++ } ++ if (nbtStart != -1) { ++ blockNameEnd = Math.min(blockNameEnd, nbtStart); ++ } ++ ++ final MapType ret = type.createEmptyMap(); ++ ++ final String blockName = value.substring(0, blockNameEnd); ++ ++ // string is fine here, the underlying type accepts string AND list under the same name... ++ ret.setString("blocks", blockName.trim()); ++ ++ if (propertyStart != -1) { ++ // unlike DFU, set the fromIndex so that on malformed data we do not IOOBE ++ final int propertyEnd = value.indexOf(']', propertyStart + 1); ++ if (propertyEnd != -1) { ++ final MapType state = type.createEmptyMap(); ++ ret.setMap("state", state); ++ ++ for (final String property : value.substring(propertyStart + 1, propertyEnd).split(",")) { ++ final int separatorIdx = property.indexOf('='); ++ if (separatorIdx == -1) { ++ continue; ++ } ++ ++ final String propertyKey = property.substring(0, separatorIdx).trim(); ++ final String propertyValue = property.substring(separatorIdx + 1); ++ ++ state.setString(propertyKey, propertyValue); ++ } ++ } ++ } ++ ++ if (nbtStart != -1) { ++ // unlike DFU, set the fromIndex so that on malformed data we do not IOOBE ++ final int nbtEnd = value.indexOf('}', nbtStart + 1); ++ if (nbtEnd != -1) { ++ // note: want to include { and } ++ ret.setString("nbt", value.substring(nbtStart, nbtEnd + 1)); ++ } ++ } ++ ++ return ret; ++ } ++ ++ private static void convertBlockStatePredicates(final TransientItemStack item, final TypeUtil type, ++ final String tagKey, final String componentKey, ++ final boolean hideInTooltip) { ++ final ListType blocks = item.tagRemoveListUnchecked(tagKey); ++ if (blocks == null) { ++ return; ++ } ++ ++ final MapType blockPredicates = type.createEmptyMap(); ++ item.componentSetMap(componentKey, blockPredicates); ++ ++ if (hideInTooltip) { ++ blockPredicates.setBoolean("show_in_tooltip", false); ++ } ++ ++ final ListType predicates = type.createEmptyList(); ++ blockPredicates.setList("predicates", predicates); ++ ++ for (int i = 0, len = blocks.size(); i < len; ++i) { ++ final Object block = blocks.getGeneric(i); ++ if (!(block instanceof String blockString)) { ++ // cannot type error here, if block is not a string then nothing in `blocks` is as they have the same type ++ predicates.addGeneric(block); ++ continue; ++ } ++ ++ final MapType predicate = convertBlockStatePredicate(blockString, type); ++ ++ predicates.addMap(predicate); ++ } ++ } ++ ++ private static void convertAdventureMode(final TransientItemStack item, final TypeUtil type, final int flags) { ++ convertBlockStatePredicates( ++ item, type, "CanDestroy", "minecraft:can_break", ++ (flags & TOOLTIP_FLAG_HIDE_CAN_DESTROY) != 0 ++ ); ++ convertBlockStatePredicates( ++ item, type, "CanPlaceOn", "minecraft:can_place_on", ++ (flags & TOOLTIP_FLAG_HIDE_CAN_PLACE) != 0 ++ ); ++ } ++ ++ private static void copy(final MapType src, final String srcKey, final MapType dst, final String dstKey) { ++ if (src == null || dst == null) { ++ return; ++ } ++ ++ final Object srcValue = src.getGeneric(srcKey); ++ if (srcValue != null) { ++ dst.setGeneric(dstKey, srcValue); ++ } ++ } ++ ++ private static MapType convertAttribute(final Object inputGeneric, final TypeUtil type) { ++ final MapType input = inputGeneric instanceof MapType casted ? (MapType)casted : null; ++ ++ final MapType ret = type.createEmptyMap(); ++ ret.setString("name", ""); ++ ret.setDouble("amount", 0.0); ++ ret.setString("operation", "add_value"); ++ ++ copy(input, "AttributeName", ret, "type"); ++ copy(input, "Slot", ret, "slot"); ++ copy(input, "UUID", ret, "uuid"); ++ copy(input, "Name", ret, "name"); ++ copy(input, "Amount", ret, "amount"); ++ ++ // note: no type check on hasKey ++ if (input != null && input.hasKey("Operation")) { ++ final String operation; ++ switch (input.getInt("Operation", 0)) { ++ case 1: { ++ operation = "add_multiplied_base"; ++ break; ++ } ++ case 2: { ++ operation = "add_multiplied_total"; ++ break; ++ } ++ default: { ++ operation = "add_value"; ++ break; ++ } ++ } ++ ret.setString("operation", operation); ++ } ++ ++ return ret; ++ } ++ ++ private static void convertAttributes(final TransientItemStack item, final TypeUtil type, final int flags) { ++ final ListType attributes = item.tagRemoveListUnchecked("AttributeModifiers"); ++ final ListType newAttributes = type.createEmptyList(); ++ ++ if (attributes != null) { ++ for (int i = 0, len = attributes.size(); i < len; ++i) { ++ newAttributes.addMap(convertAttribute(attributes.getGeneric(i), type)); ++ } ++ } ++ ++ final boolean hideModifiers = (flags & TOOLTIP_FLAG_HIDE_MODIFIERS) != 0; ++ if (newAttributes.size() > 0 || hideModifiers) { ++ final MapType newModifiers = type.createEmptyMap(); ++ item.componentSetMap("minecraft:attribute_modifiers", newModifiers); ++ ++ newModifiers.setList("modifiers", newAttributes); ++ if (hideModifiers) { ++ newModifiers.setBoolean("show_in_tooltip", false); ++ } ++ } ++ } ++ ++ private static void convertMap(final TransientItemStack item, final TypeUtil type) { ++ item.tagMigrateToComponent("map", "minecraft:map_id"); ++ ++ final ListType decorations = item.tagRemoveListUnchecked("Decorations"); ++ if (decorations != null) { ++ final MapType newDecorations = type.createEmptyMap(); ++ ++ for (int i = 0, len = decorations.size(); i < len; ++i) { ++ final Object decorationGeneric = decorations.getGeneric(i); ++ ++ final MapType decoration = decorationGeneric instanceof MapType casted ? (MapType)casted : null; ++ ++ // note: getForcedString mirrors DFU converting to string for key ++ final String id = decoration == null ? "" : decoration.getForcedString("id", ""); ++ if (newDecorations.hasKey(id)) { ++ // note: never replace existing decorations by id ++ continue; ++ } ++ ++ final int typeId = decoration == null ? 0 : decoration.getInt("type", 0); ++ final double x = decoration == null ? 0.0 : decoration.getDouble("x", 0.0); ++ final double z = decoration == null ? 0.0 : decoration.getDouble("z", 0.0); ++ final float rot = decoration == null ? 0.0f : (float)decoration.getDouble("rot", 0.0); ++ ++ final MapType newDecoration = type.createEmptyMap(); ++ newDecorations.setMap(id, newDecoration); ++ ++ newDecoration.setString("type", convertMapDecorationId(typeId)); ++ newDecoration.setDouble("x", x); ++ newDecoration.setDouble("z", z); ++ newDecoration.setFloat("rotation", rot); ++ } ++ ++ if (!newDecorations.isEmpty()) { ++ item.componentSetMap("minecraft:map_decorations", newDecorations); ++ } ++ } ++ } ++ ++ private static void convertPotion(final TransientItemStack item, final TypeUtil type) { ++ final MapType potionContents = type.createEmptyMap(); ++ ++ final String potion = item.tagRemoveString("Potion"); ++ ++ if (potion != null && !"minecraft:empty".equals(potion)) { ++ potionContents.setString("potion", potion); ++ } ++ ++ item.migrateTagTo("CustomPotionColor", potionContents, "custom_color"); ++ item.migrateTagTo("custom_potion_effects", potionContents, "custom_effects"); ++ ++ if (!potionContents.isEmpty()) { ++ item.componentSetMap("minecraft:potion_contents", potionContents); ++ } ++ } ++ ++ private static MapType makeFilteredText(final String raw, final String filtered, final TypeUtil type) { ++ final MapType ret = type.createEmptyMap(); ++ ++ ret.setString("raw", raw); ++ if (filtered != null) { ++ ret.setString("filtered", filtered); ++ } ++ ++ return ret; ++ } ++ ++ private static ListType convertBookPages(final TransientItemStack item, final TypeUtil type) { ++ final ListType oldPages = item.tagRemoveListUnchecked("pages"); ++ ++ final MapType filteredPages = item.tagRemoveMap("filtered_pages"); ++ ++ if (oldPages == null || oldPages.size() == 0) { ++ return null; ++ } ++ ++ final ListType ret = type.createEmptyList(); ++ ++ for (int i = 0, len = oldPages.size(); i < len; ++i) { ++ final String page = oldPages.getGeneric(i) instanceof String str ? str : ""; ++ final String filtered = filteredPages == null ? null : filteredPages.getString(Integer.toString(i)); ++ ++ ret.addMap(makeFilteredText(page, filtered, type)); ++ } ++ ++ return ret; ++ } ++ ++ private static void convertWritableBook(final TransientItemStack item, final TypeUtil type) { ++ final ListType pages = convertBookPages(item, type); ++ if (pages != null) { ++ final MapType bookContent = type.createEmptyMap(); ++ item.componentSetMap("minecraft:writable_book_content", bookContent); ++ ++ bookContent.setList("pages", pages); ++ } ++ } ++ ++ private static void convertWrittenBook(final TransientItemStack item, final TypeUtil type) { ++ final ListType pages = convertBookPages(item, type); ++ ++ final MapType bookContent = type.createEmptyMap(); ++ item.componentSetMap("minecraft:written_book_content", bookContent); ++ if (pages != null) { ++ bookContent.setList("pages", pages); ++ } ++ ++ final String title = item.tagRemoveString("title", ""); ++ final String filteredTitle = item.tagRemoveString("filtered_title"); ++ ++ bookContent.setMap("title", makeFilteredText(title, filteredTitle, type)); ++ ++ item.migrateTagTo("author", bookContent, "author"); ++ item.migrateTagTo("resolved", bookContent, "resolved"); ++ item.migrateTagTo("generation", bookContent, "generation"); ++ } ++ ++ private static void convertMobBucket(final TransientItemStack item, final TypeUtil type) { ++ final MapType bucketEntityData = type.createEmptyMap(); ++ ++ for (final String oldKey : BUCKETED_MOB_TAGS) { ++ item.migrateTagTo(oldKey, bucketEntityData, oldKey); ++ } ++ ++ if (!bucketEntityData.isEmpty()) { ++ item.componentSetMap("minecraft:bucket_entity_data", bucketEntityData); ++ } ++ } ++ ++ private static void convertCompass(final TransientItemStack item, final TypeUtil type) { ++ final Object lodestonePos = item.tagRemoveGeneric("LodestonePos"); ++ final Object lodestoneDim = item.tagRemoveGeneric("LodestoneDimension"); ++ ++ if (lodestonePos == null && lodestoneDim == null) { ++ return; ++ } ++ ++ final MapType lodestoneTracker = type.createEmptyMap(); ++ item.componentSetMap("minecraft:lodestone_tracker", lodestoneTracker); ++ ++ if (lodestonePos != null && lodestoneDim != null) { ++ final MapType target = type.createEmptyMap(); ++ lodestoneTracker.setMap("target", target); ++ ++ target.setGeneric("pos", lodestonePos); ++ target.setGeneric("dimension", lodestoneDim); ++ } ++ ++ final boolean tracked = item.tagRemoveBoolean("LodestoneTracked", true); ++ if (!tracked) { ++ lodestoneTracker.setBoolean("tracked", false); ++ } ++ } ++ ++ private static void convertFireworkExplosion(final Object inputGeneric) { ++ if (!(inputGeneric instanceof MapType)) { ++ return; ++ } ++ ++ final MapType input = (MapType)inputGeneric; ++ ++ RenameHelper.renameSingle(input, "Colors", "colors"); ++ RenameHelper.renameSingle(input, "FadeColors", "fade_colors"); ++ RenameHelper.renameSingle(input, "Trail", "has_trail"); ++ RenameHelper.renameSingle(input, "Flicker", "has_twinkle"); ++ ++ final int type = input.getInt("Type", 0); ++ input.remove("Type"); ++ ++ final String newType; ++ switch (type) { ++ case 1: { ++ newType = "large_ball"; ++ break; ++ } ++ case 2: { ++ newType = "star"; ++ break; ++ } ++ case 3: { ++ newType = "creeper"; ++ break; ++ } ++ case 4: { ++ newType = "burst"; ++ break; ++ } ++ default: { ++ newType = "small_ball"; ++ break; ++ } ++ } ++ ++ input.setString("shape", newType); ++ } ++ ++ private static void convertFireworkRocket(final TransientItemStack item, final TypeUtil type) { ++ // adhere to fixSubTag(true) behavior ++ final Object fireworksGeneric = item.tag.getGeneric("Fireworks"); ++ if (fireworksGeneric == null) { ++ return; ++ } ++ ++ if (!(fireworksGeneric instanceof MapType)) { ++ final MapType newFireworks = type.createEmptyMap(); ++ item.componentSetMap("minecraft:fireworks", newFireworks); ++ ++ newFireworks.setList("explosions", type.createEmptyList()); ++ newFireworks.setByte("flight_duration", (byte)0); ++ ++ return; ++ } ++ ++ final MapType fireworks = (MapType)fireworksGeneric; ++ ++ final MapType newFireworks = type.createEmptyMap(); ++ item.componentSetMap("minecraft:fireworks", newFireworks); ++ ++ final int flight = fireworks.getInt("Flight", 0); ++ newFireworks.setByte("flight_duration", (byte)flight); ++ ++ final ListType explosions = fireworks.getListUnchecked("Explosions", type.createEmptyList()); ++ newFireworks.setList("explosions", explosions); ++ ++ for (int i = 0, len = explosions.size(); i < len; ++i) { ++ convertFireworkExplosion(explosions.getGeneric(i)); ++ } ++ ++ fireworks.remove("Explosions"); ++ fireworks.remove("Flight"); ++ if (fireworks.isEmpty()) { ++ item.tag.remove("Fireworks"); ++ } ++ } ++ ++ private static Object copyGeneric(final Object value, final TypeUtil type) { ++ if (value == null || value instanceof Number || value instanceof String) { ++ return value; ++ } ++ if (value instanceof MapType mapType) { ++ return mapType.copy(); ++ } ++ if (value instanceof ListType listType) { ++ return listType.copy(); ++ } ++ // rest of the cases can take the slow path ++ ++ final ListType dummy = type.createEmptyList(); ++ dummy.addGeneric(value); ++ ++ return dummy.copy().getGeneric(0); ++ } ++ ++ private static void convertFireworkStar(final TransientItemStack item, final TypeUtil type) { ++ // note: adhere to fixSubTag(true) behavior ++ final Object explosionGeneric = item.tag.getGeneric("Explosion"); ++ if (explosionGeneric == null) { ++ return; ++ } ++ ++ if (!(explosionGeneric instanceof MapType)) { ++ // important that we copy the generic value when not moving it ++ item.componentSetGeneric("minecraft:firework_explosion", copyGeneric(explosionGeneric, type)); ++ return; ++ } ++ ++ final MapType explosion = (MapType)explosionGeneric; ++ ++ final MapType explosionCopy = explosion.copy(); ++ item.componentSetGeneric("minecraft:firework_explosion", explosionCopy); ++ convertFireworkExplosion(explosionCopy); ++ ++ explosion.remove("Type"); ++ explosion.remove("Colors"); ++ explosion.remove("FadeColors"); ++ explosion.remove("Trail"); ++ explosion.remove("Flicker"); ++ ++ if (explosion.isEmpty()) { ++ item.tag.remove("Explosion"); ++ } ++ } ++ ++ private static boolean isValidPlayerName(final String name) { ++ if (name.length() > 16) { ++ return false; ++ } ++ ++ for (int i = 0, len = name.length(); i < len; ++i) { ++ final char character = name.charAt(i); ++ if (character <= 0x20 || character >= 0x7F) { // printable ascii ++ return false; ++ } ++ } ++ ++ return true; ++ } ++ ++ private static ListType convertProperties(final MapType properties, final TypeUtil type) { ++ final ListType ret = type.createEmptyList(); ++ ++ for (final String propertyKey : properties.keys()) { ++ final ListType propertyValues = properties.getListUnchecked(propertyKey); ++ ++ if (propertyValues == null) { ++ continue; ++ } ++ ++ for (int i = 0, len = propertyValues.size(); i < len; ++i) { ++ final MapType property = propertyValues.getGeneric(i) instanceof MapType casted ? (MapType)casted : null; ++ ++ final String value = property == null ? "" : property.getString("Value", ""); ++ final String signature = property == null ? null : property.getString("Signature"); ++ ++ final MapType newProperty = type.createEmptyMap(); ++ ret.addMap(newProperty); ++ ++ newProperty.setString("name", propertyKey); ++ newProperty.setString("value", value); ++ if (signature != null) { ++ newProperty.setString("signature", signature); ++ } ++ } ++ } ++ ++ return ret; ++ } ++ ++ public static MapType convertProfile(final Object inputGeneric, final TypeUtil type) { ++ final MapType ret = type.createEmptyMap(); ++ ++ if (inputGeneric instanceof String name) { ++ if (!isValidPlayerName(name)) { ++ return ret; ++ } ++ ++ ret.setString("name", name); ++ ++ return ret; ++ } ++ ++ final MapType input = inputGeneric instanceof MapType casted ? (MapType)casted : null; ++ ++ final String name = input == null ? "" : input.getString("Name", ""); ++ ++ if (isValidPlayerName(name)) { ++ ret.setString("name", name); ++ } ++ ++ final Object id = input == null ? null : input.getGeneric("Id"); ++ ++ if (id != null) { ++ ret.setGeneric("id", id); ++ } ++ ++ final MapType properties = input == null ? null : input.getMap("Properties"); ++ if (properties != null && !properties.isEmpty()) { ++ ret.setList("properties", convertProperties(properties, type)); ++ } ++ ++ return ret; ++ } ++ ++ private static void convertSukll(final TransientItemStack item, final TypeUtil type) { ++ final Object skullOwnerGeneric = item.tagRemoveGeneric("SkullOwner"); ++ if (skullOwnerGeneric == null) { ++ return; ++ } ++ ++ item.componentSetMap("minecraft:profile", convertProfile(skullOwnerGeneric, type)); ++ } ++ ++ // input is unmodified ++ public static MapType convertItem(final MapType input) { ++ if (!input.hasKey("id", ObjectType.STRING) || !input.hasKey("Count", ObjectType.NUMBER)) { ++ return input.copy(); ++ } ++ ++ final TypeUtil type = input.getTypeUtil(); ++ ++ final TransientItemStack item = new TransientItemStack(input); ++ ++ item.tagMigrateToComponent("Damage", "minecraft:damage", 0); ++ item.tagMigrateToComponent("RepairCost", "minecraft:repair_cost", 0); ++ item.tagMigrateToComponent("CustomModelData", "minecraft:custom_model_data"); ++ ++ final MapType blockStateProperties = item.tagRemoveMap("BlockStateTag"); ++ if (blockStateProperties != null) { ++ item.componentSetMap("minecraft:block_state", blockStateProperties); ++ convertBlockStateProperties(blockStateProperties); ++ } ++ ++ item.tagMigrateToComponent("EntityTag", "minecraft:entity_data"); ++ ++ final MapType tileEntityTag = item.tagRemoveMap("BlockEntityTag"); ++ if (tileEntityTag != null) { ++ convertTileEntity(tileEntityTag, item); ++ ++ if (tileEntityTag.size() > 1 || (tileEntityTag.size() == 1 && !tileEntityTag.hasKey("id"))) { ++ item.componentSetMap("minecraft:block_entity_data", tileEntityTag); ++ } ++ } ++ ++ final int flags = item.tagRemoveInt("HideFlags", 0); ++ ++ if (item.tagRemoveInt("Unbreakable", 0) != 0) { ++ final MapType unbreakable = type.createEmptyMap(); ++ item.componentSetMap("minecraft:unbreakable", unbreakable); ++ if ((flags & TOOLTIP_FLAG_HIDE_UNBREAKABLE) != 0) { ++ unbreakable.setBoolean("show_in_tooltip", false); ++ } ++ } ++ ++ convertEnchantments( ++ item, type, "Enchantments", "minecraft:enchantments", ++ (flags & TOOLTIP_FLAG_HIDE_ENCHANTMENTS) != 0 ++ ); ++ ++ convertDisplay(item, type, flags); ++ convertAdventureMode(item, type, flags); ++ convertAttributes(item, type, flags); ++ ++ final Object trim = item.tagRemoveGeneric("Trim"); ++ if (trim != null) { ++ // note: DFU set does nothing if not map ++ if ((flags & TOOLTIP_FLAG_HIDE_UPGRADES) != 0 && trim instanceof MapType) { ++ ((MapType)trim).setBoolean("show_in_tooltip", false); ++ } ++ ++ item.componentSetGeneric("minecraft:trim", trim); ++ } ++ ++ if ((flags & TOOLTIP_FLAG_HIDE_ADDITIONAL) != 0) { ++ item.componentSetMap("minecraft:hide_additional_tooltip", type.createEmptyMap()); ++ } ++ ++ switch (item.id) { ++ case "minecraft:enchanted_book": { ++ convertEnchantments( ++ item, type, "StoredEnchantments", "minecraft:stored_enchantments", ++ (flags & TOOLTIP_FLAG_HIDE_ADDITIONAL) != 0 ++ ); ++ break; ++ } ++ case "minecraft:crossbow": { ++ item.tagRemoveGeneric("Charged"); ++ item.tagMigrateNonEmptyListToComponent("ChargedProjectiles", "minecraft:charged_projectiles"); ++ break; ++ } ++ case "minecraft:bundle": { ++ item.tagMigrateNonEmptyListToComponent("Items", "minecraft:bundle_contents"); ++ break; ++ } ++ case "minecraft:filled_map": { ++ convertMap(item, type); ++ break; ++ } ++ case "minecraft:potion": ++ case "minecraft:splash_potion": ++ case "minecraft:lingering_potion": ++ case "minecraft:tipped_arrow": { ++ convertPotion(item, type); ++ break; ++ } ++ case "minecraft:writable_book": { ++ convertWritableBook(item, type); ++ break; ++ } ++ case "minecraft:written_book": { ++ convertWrittenBook(item, type); ++ break; ++ } ++ case "minecraft:suspicious_stew": { ++ item.tagMigrateToComponent("effects", "minecraft:suspicious_stew_effects"); ++ break; ++ } ++ case "minecraft:debug_stick": { ++ item.tagMigrateToComponent("DebugProperty", "minecraft:debug_stick_state"); ++ break; ++ } ++ case "minecraft:pufferfish_bucket": ++ case "minecraft:salmon_bucket": ++ case "minecraft:cod_bucket": ++ case "minecraft:tropical_fish_bucket": ++ case "minecraft:axolotl_bucket": ++ case "minecraft:tadpole_bucket": { ++ convertMobBucket(item, type); ++ break; ++ } ++ case "minecraft:goat_horn": { ++ item.tagMigrateToComponent("instrument", "minecraft:instrument"); ++ break; ++ } ++ case "minecraft:knowledge_book": { ++ item.tagMigrateToComponent("Recipes", "minecraft:recipes"); ++ break; ++ } ++ case "minecraft:compass": { ++ convertCompass(item, type); ++ break; ++ } ++ case "minecraft:firework_rocket": { ++ convertFireworkRocket(item, type); ++ break; ++ } ++ case "minecraft:firework_star": { ++ convertFireworkStar(item, type); ++ break; ++ } ++ case "minecraft:player_head": { ++ convertSukll(item, type); ++ break; ++ } ++ } ++ ++ return item.serialize(); ++ } ++ ++ private ConverterItemStackToDataComponents() {} ++ ++ private static final class TransientItemStack { ++ ++ private final String id; ++ private final int count; ++ ++ private final MapType components; ++ private final MapType tag; ++ private final MapType root; ++ ++ public TransientItemStack(final MapType root) { ++ this.id = root.getString("id"); ++ this.count = root.getInt("Count"); ++ ++ final TypeUtil type = root.getTypeUtil(); ++ ++ this.components = type.createEmptyMap(); ++ ++ final MapType rootCopy = root.copy(); ++ ++ final MapType tag = rootCopy.getMap("tag"); ++ ++ rootCopy.remove("id"); ++ rootCopy.remove("Count"); ++ rootCopy.remove("tag"); ++ ++ this.tag = tag == null ? type.createEmptyMap() : tag; ++ ++ this.root = rootCopy; ++ } ++ ++ public void migrateTagTo(final String tagKey, final MapType dst, final String dstKey) { ++ final Object value = this.tag.getGeneric(tagKey); ++ ++ if (value != null) { ++ this.tag.remove(tagKey); ++ ++ dst.setGeneric(dstKey, value); ++ } ++ } ++ ++ public String tagRemoveString(final String key) { ++ final String ret = this.tag.getString(key); ++ ++ this.tag.remove(key); ++ ++ return ret; ++ } ++ ++ public String tagRemoveString(final String key, final String dfl) { ++ final String ret = this.tag.getString(key, dfl); ++ ++ this.tag.remove(key); ++ ++ return ret; ++ } ++ ++ public ListType tagRemoveListUnchecked(final String key) { ++ final ListType ret = this.tag.getListUnchecked(key); ++ ++ this.tag.remove(key); ++ ++ return ret; ++ } ++ ++ public ListType tagRemoveList(final String key, final ObjectType listType) { ++ final ListType ret = this.tag.getList(key, listType); ++ ++ this.tag.remove(key); ++ ++ return ret; ++ } ++ ++ public MapType tagRemoveMap(final String key) { ++ final MapType ret = this.tag.getMap(key); ++ ++ this.tag.remove(key); ++ ++ return ret; ++ } ++ ++ public boolean tagRemoveBoolean(final String key, final boolean dfl) { ++ final boolean ret = this.tag.getBoolean(key, dfl); ++ ++ this.tag.remove(key); ++ ++ return ret; ++ } ++ ++ public int tagRemoveInt(final String key, final int dfl) { ++ final int ret = this.tag.getInt(key, dfl); ++ ++ this.tag.remove(key); ++ ++ return ret; ++ } ++ ++ public Object tagRemoveGeneric(final String key) { ++ final Object ret = this.tag.getGeneric(key); ++ ++ if (ret != null) { ++ this.tag.remove(key); ++ return ret; ++ } ++ ++ return ret; ++ } ++ ++ public void tagMigrateToComponent(final String tagKey, final String componentKey) { ++ final Object value = this.tag.getGeneric(tagKey); ++ if (value != null) { ++ this.tag.remove(tagKey); ++ ++ this.components.setGeneric(componentKey, value); ++ } ++ } ++ ++ public void tagMigrateNonEmptyListToComponent(final String tagKey, final String componentKey) { ++ final Object value = this.tag.getGeneric(tagKey); ++ if (value != null) { ++ this.tag.remove(tagKey); ++ ++ if (!(value instanceof ListType list) || list.size() > 0) { ++ this.components.setGeneric(componentKey, value); ++ } ++ } ++ } ++ ++ public void tagMigrateToComponent(final String tagKey, final String componentKey, final int defaultComponent) { ++ final int value = this.tag.getInt(tagKey, defaultComponent); ++ this.tag.remove(tagKey); ++ ++ if (value != defaultComponent) { ++ this.components.setGeneric(componentKey, value); ++ } ++ } ++ ++ public void componentSetBoolean(final String key, final boolean value) { ++ this.components.setBoolean(key, value); ++ } ++ ++ public void componentSetString(final String key, final String value) { ++ this.components.setString(key, value); ++ } ++ ++ public void componentSetList(final String key, final ListType value) { ++ this.components.setList(key, value); ++ } ++ ++ public void componentSetMap(final String key, final MapType value) { ++ this.components.setMap(key, value); ++ } ++ ++ public void componentSetGeneric(final String key, final Object value) { ++ this.components.setGeneric(key, value); ++ } ++ ++ public MapType serialize() { ++ final MapType ret = this.components.getTypeUtil().createEmptyMap(); ++ ++ ret.setString("id", this.id); ++ ret.setInt("count", this.count); ++ if (!this.tag.isEmpty()) { ++ this.components.setMap("minecraft:custom_data", this.tag); ++ } ++ ++ if (!this.components.isEmpty()) { ++ ret.setMap("components", this.components); ++ } ++ ++ // merge root to ret, with entries in ret taking priority ++ if (!this.root.isEmpty()) { ++ for (final String key : this.root.keys()) { ++ if (ret.hasKey(key)) { ++ continue; ++ } ++ ++ ret.setGeneric(key, this.root.getGeneric(key)); ++ } ++ } ++ ++ return ret; ++ } ++ } ++} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/leveldat/ConverterRemoveFeatureFlag.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/leveldat/ConverterRemoveFeatureFlag.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -6188,6 +7904,280 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + +} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/particle/ConverterParticleToNBT.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/particle/ConverterParticleToNBT.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/particle/ConverterParticleToNBT.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.converters.particle; ++ ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.TypeUtil; ++import ca.spottedleaf.dataconverter.types.nbt.NBTMapType; ++import ca.spottedleaf.dataconverter.util.NamespaceUtil; ++import com.mojang.brigadier.StringReader; ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import com.mojang.logging.LogUtils; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.TagParser; ++import net.minecraft.util.Mth; ++import org.slf4j.Logger; ++ ++public final class ConverterParticleToNBT { ++ ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ ++ private static CompoundTag parseNBT(final String flat) { ++ try { ++ return TagParser.parseTag(flat); ++ } catch (final Exception ex) { ++ LOGGER.warn("Failed to parse nbt: " + flat, ex); ++ return null; ++ } ++ } ++ ++ private static void convertItem(final MapType nbt, final String data) { ++ final MapType itemNBT = nbt.getTypeUtil().createEmptyMap(); ++ nbt.setMap("item", itemNBT); ++ itemNBT.setInt("Count", 1); ++ ++ final int nbtStart = data.indexOf('{'); ++ if (nbtStart == -1) { ++ // assume data is item name ++ itemNBT.setString("id", NamespaceUtil.correctNamespace(data)); ++ return; ++ } ++ // itemname{tagNBT} ++ itemNBT.setString("id", NamespaceUtil.correctNamespace(data.substring(0, nbtStart))); ++ ++ final CompoundTag tag = parseNBT(data.substring(nbtStart)); ++ if (tag != null) { ++ // do we need to worry about type conversion? ++ itemNBT.setMap("tag", new NBTMapType(tag)); ++ } ++ } ++ ++ private static MapType parseProperties(final String input, final TypeUtil type) { ++ final MapType ret = type.createEmptyMap(); ++ try { ++ // format: [p1=v1, p2=v2, p3=v3, ...] ++ final StringReader reader = new StringReader(input); ++ ++ reader.expect('['); ++ reader.skipWhitespace(); ++ ++ while (reader.canRead() && reader.peek() != ']') { ++ reader.skipWhitespace(); ++ ++ final String property = reader.readString(); ++ ++ reader.skipWhitespace(); ++ reader.expect('='); ++ reader.skipWhitespace(); ++ ++ final String value = reader.readString(); ++ ret.setString(property, value); ++ ++ reader.skipWhitespace(); ++ if (reader.canRead()) { ++ if (reader.peek() != ',') { ++ // invalid character or ']' ++ break; ++ } ++ ++ // skip ',' and move onto next entry ++ reader.peek(); ++ } ++ } ++ ++ reader.expect(']'); ++ return ret; ++ } catch (final Exception ex) { ++ LOGGER.warn("Failed to parse block properties: " + input, ex); ++ return null; ++ } ++ } ++ ++ private static void convertBlock(final MapType nbt, final String data) { ++ final MapType blockNBT = nbt.getTypeUtil().createEmptyMap(); ++ nbt.setMap("block_state", blockNBT); ++ ++ final int propertiesStart = data.indexOf('['); ++ if (propertiesStart == -1) { ++ // assume data is id ++ blockNBT.setString("Name", NamespaceUtil.correctNamespace(data)); ++ return; ++ } ++ blockNBT.setString("Name", NamespaceUtil.correctNamespace(data.substring(0, propertiesStart))); ++ ++ // blockname{properties} ++ final MapType properties = parseProperties(data.substring(propertiesStart), nbt.getTypeUtil()); ++ if (properties != null && !properties.isEmpty()) { ++ blockNBT.setMap("Properties", properties); ++ } ++ } ++ ++ private static ListType parseFloatVector(final StringReader reader, final TypeUtil type) throws CommandSyntaxException { ++ final float x = reader.readFloat(); ++ ++ reader.expect(' '); ++ final float y = reader.readFloat(); ++ ++ reader.expect(' '); ++ final float z = reader.readFloat(); ++ ++ final ListType ret = type.createEmptyList(); ++ ret.addFloat(x); ++ ret.addFloat(y); ++ ret.addFloat(z); ++ ++ return ret; ++ } ++ ++ private static void convertDust(final MapType nbt, final String data) { ++ try { ++ final StringReader reader = new StringReader(data); ++ ++ final ListType color = parseFloatVector(reader, nbt.getTypeUtil()); ++ ++ reader.expect(' '); ++ final float scale = reader.readFloat(); ++ ++ nbt.setList("color", color); ++ nbt.setFloat("scale", scale); ++ } catch (final Exception ex) { ++ LOGGER.warn("Failed to parse dust particle: " + data, ex); ++ } ++ } ++ ++ private static void convertColorDust(final MapType nbt, final String data) { ++ try { ++ final StringReader reader = new StringReader(data); ++ ++ final ListType fromColor = parseFloatVector(reader, nbt.getTypeUtil()); ++ ++ reader.expect(' '); ++ final float scale = reader.readFloat(); ++ ++ reader.expect(' '); ++ final ListType toColor = parseFloatVector(reader, nbt.getTypeUtil()); ++ ++ nbt.setList("from_color", fromColor); ++ nbt.setFloat("scale", scale); ++ nbt.setList("to_color", toColor); ++ } catch (final Exception ex) { ++ LOGGER.warn("Failed to parse color transition dust particle: " + data, ex); ++ } ++ } ++ ++ private static void convertSculk(final MapType nbt, final String data) { ++ try { ++ final StringReader reader = new StringReader(data); ++ ++ final float roll = reader.readFloat(); ++ ++ nbt.setFloat("roll", roll); ++ } catch (final Exception ex) { ++ LOGGER.warn("Failed to parse sculk particle: " + data, ex); ++ } ++ } ++ ++ private static void convertVibration(final MapType nbt, final String data) { ++ try { ++ final StringReader reader = new StringReader(data); ++ ++ final double posX = reader.readDouble(); ++ ++ reader.expect(' '); ++ final double posY = reader.readDouble(); ++ ++ reader.expect(' '); ++ final double posZ = reader.readDouble(); ++ ++ reader.expect(' '); ++ final int arrival = reader.readInt(); ++ ++ nbt.setInt("arrival_in_ticks", arrival); ++ ++ final MapType destination = nbt.getTypeUtil().createEmptyMap(); ++ nbt.setMap("destination", destination); ++ ++ destination.setString("type", "minecraft:block"); ++ ++ final ListType pos = nbt.getTypeUtil().createEmptyList(); ++ destination.setList("pos", pos); ++ ++ pos.addInt(Mth.floor(posX)); ++ pos.addInt(Mth.floor(posY)); ++ pos.addInt(Mth.floor(posZ)); ++ } catch (final Exception ex) { ++ LOGGER.warn("Failed to parse vibration particle: " + data, ex); ++ } ++ } ++ ++ private static void convertShriek(final MapType nbt, final String data) { ++ try { ++ final StringReader reader = new StringReader(data); ++ ++ final int delay = reader.readInt(); ++ ++ nbt.setInt("delay", delay); ++ } catch (final Exception ex) { ++ LOGGER.warn("Failed to parse shriek particle: " + data, ex); ++ } ++ } ++ ++ public static MapType convert(final String flat, final TypeUtil type) { ++ final String[] split = flat.split(" ", 2); ++ final String name = NamespaceUtil.correctNamespace(split[0]); ++ ++ final MapType ret = type.createEmptyMap(); ++ ret.setString("type", name); ++ ++ if (split.length > 1) { ++ final String data = split[1]; ++ switch (name) { ++ case "minecraft:item": { ++ convertItem(ret, data); ++ break; ++ } ++ case "minecraft:block": ++ case "minecraft:block_marker": ++ case "minecraft:falling_dust": ++ case "minecraft:dust_pillar": { ++ convertBlock(ret, data); ++ break; ++ } ++ case "minecraft:dust": { ++ convertDust(ret, data); ++ break; ++ } ++ case "minecraft:dust_color_transition": { ++ convertColorDust(ret, data); ++ break; ++ } ++ case "minecraft:sculk_charge": { ++ convertSculk(ret, data); ++ break; ++ } ++ case "minecraft:vibration": { ++ convertVibration(ret, data); ++ break; ++ } ++ case "minecraft:shriek": { ++ convertShriek(ret, data); ++ break; ++ } ++ } ++ } ++ ++ return ret; ++ } ++ ++ private ConverterParticleToNBT() {} ++} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/poi/ConverterAbstractPOIRename.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/converters/poi/ConverterAbstractPOIRename.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -6769,6 +8759,140 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + +} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/DynamicDataType.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/DynamicDataType.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/DynamicDataType.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.datatypes; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.converters.datatypes.DataHook; ++import ca.spottedleaf.dataconverter.converters.datatypes.DataType; ++import ca.spottedleaf.dataconverter.converters.datatypes.DataWalker; ++import ca.spottedleaf.dataconverter.minecraft.MCVersionRegistry; ++import ca.spottedleaf.dataconverter.util.Long2ObjectArraySortedMap; ++import java.util.ArrayList; ++import java.util.List; ++ ++public class DynamicDataType extends DataType { ++ ++ public final String name; ++ ++ protected final ArrayList> structureConverters = new ArrayList<>(); ++ protected final Long2ObjectArraySortedMap>> structureWalkers = new Long2ObjectArraySortedMap<>(); ++ protected final Long2ObjectArraySortedMap>> structureHooks = new Long2ObjectArraySortedMap<>(); ++ ++ public DynamicDataType(final String name) { ++ this.name = name; ++ } ++ ++ public void addStructureConverter(final DataConverter converter) { ++ MCVersionRegistry.checkVersion(converter.getEncodedVersion()); ++ this.structureConverters.add(converter); ++ this.structureConverters.sort(DataConverter.LOWEST_VERSION_COMPARATOR); ++ } ++ ++ public void addStructureWalker(final int minVersion, final DataWalker walker) { ++ this.addStructureWalker(minVersion, 0, walker); ++ } ++ ++ public void addStructureWalker(final int minVersion, final int versionStep, final DataWalker walker) { ++ this.structureWalkers.computeIfAbsent(DataConverter.encodeVersions(minVersion, versionStep), (final long keyInMap) -> { ++ return new ArrayList<>(); ++ }).add(walker); ++ } ++ ++ public void addStructureHook(final int minVersion, final DataHook hook) { ++ this.addStructureHook(minVersion, 0, hook); ++ } ++ ++ public void addStructureHook(final int minVersion, final int versionStep, final DataHook hook) { ++ this.structureHooks.computeIfAbsent(DataConverter.encodeVersions(minVersion, versionStep), (final long keyInMap) -> { ++ return new ArrayList<>(); ++ }).add(hook); ++ } ++ ++ @Override ++ public Object convert(Object data, final long fromVersion, final long toVersion) { ++ Object ret = null; ++ ++ final List> converters = this.structureConverters; ++ for (int i = 0, len = converters.size(); i < len; ++i) { ++ final DataConverter converter = converters.get(i); ++ final long converterVersion = converter.getEncodedVersion(); ++ ++ if (converterVersion <= fromVersion) { ++ continue; ++ } ++ ++ if (converterVersion > toVersion) { ++ break; ++ } ++ ++ List> hooks = this.structureHooks.getFloor(converterVersion); ++ ++ if (hooks != null) { ++ for (int k = 0, klen = hooks.size(); k < klen; ++k) { ++ final Object replace = hooks.get(k).preHook(data, fromVersion, toVersion); ++ if (replace != null) { ++ ret = data = replace; ++ } ++ } ++ } ++ ++ final Object replace = converter.convert(data, fromVersion, toVersion); ++ if (replace != null) { ++ ret = data = replace; ++ } ++ ++ // possibly new data format, update hooks ++ hooks = this.structureHooks.getFloor(toVersion); ++ ++ if (hooks != null) { ++ for (int klen = hooks.size(), k = klen - 1; k >= 0; --k) { ++ final Object postReplace = hooks.get(k).postHook(data, fromVersion, toVersion); ++ if (postReplace != null) { ++ ret = data = postReplace; ++ } ++ } ++ } ++ } ++ ++ final List> hooks = this.structureHooks.getFloor(toVersion); ++ ++ if (hooks != null) { ++ for (int k = 0, klen = hooks.size(); k < klen; ++k) { ++ final Object replace = hooks.get(k).preHook(data, fromVersion, toVersion); ++ if (replace != null) { ++ ret = data = replace; ++ } ++ } ++ } ++ ++ final List> walkers = this.structureWalkers.getFloor(toVersion); ++ if (walkers != null) { ++ for (int i = 0, len = walkers.size(); i < len; ++i) { ++ final Object replace = walkers.get(i).walk(data, fromVersion, toVersion); ++ if (replace != null) { ++ ret = data = replace; ++ } ++ } ++ } ++ ++ if (hooks != null) { ++ for (int klen = hooks.size(), k = klen - 1; k >= 0; --k) { ++ final Object postReplace = hooks.get(k).postHook(data, fromVersion, toVersion); ++ if (postReplace != null) { ++ ret = data = postReplace; ++ } ++ } ++ } ++ ++ return ret; ++ } ++} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/IDDataType.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/datatypes/IDDataType.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -6791,7 +8915,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public class IDDataType extends MCDataType { + -+ protected final Map>>> walkersById = new HashMap<>(); ++ protected final Map>>>> walkersById = new HashMap<>(); + + public IDDataType(final String name) { + super(name); @@ -6809,11 +8933,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + -+ public void addWalker(final int minVersion, final String id, final DataWalker walker) { ++ public void addWalker(final int minVersion, final String id, final DataWalker> walker) { + this.addWalker(minVersion, 0, id, walker); + } + -+ public void addWalker(final int minVersion, final int versionStep, final String id, final DataWalker walker) { ++ public void addWalker(final int minVersion, final int versionStep, final String id, final DataWalker> walker) { + this.walkersById.computeIfAbsent(id, (final String keyInMap) -> { + return new Long2ObjectArraySortedMap<>(); + }).computeIfAbsent(DataConverter.encodeVersions(minVersion, versionStep), (final long keyInMap) -> { @@ -6827,18 +8951,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public void copyWalkers(final int minVersion, final int versionStep, final String fromId, final String toId) { + final long version = DataConverter.encodeVersions(minVersion, versionStep); -+ final Long2ObjectArraySortedMap>> walkersForId = this.walkersById.get(fromId); ++ final Long2ObjectArraySortedMap>>> walkersForId = this.walkersById.get(fromId); + if (walkersForId == null) { + return; + } + -+ final List> nearest = walkersForId.getFloor(version); ++ final List>> nearest = walkersForId.getFloor(version); + + if (nearest == null) { + return; + } + -+ for (final DataWalker walker : nearest) { ++ for (final DataWalker> walker : nearest) { + this.addWalker(minVersion, versionStep, toId, walker); + } + } @@ -6904,7 +9028,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // run all walkers + -+ final List> walkers = this.structureWalkers.getFloor(toVersion); ++ final List>> walkers = this.structureWalkers.getFloor(toVersion); + if (walkers != null) { + for (int i = 0, len = walkers.size(); i < len; ++i) { + final MapType replace = walkers.get(i).walk(data, fromVersion, toVersion); @@ -6914,9 +9038,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ final Long2ObjectArraySortedMap>> walkersByVersion = this.walkersById.get(data.getString("id")); ++ final Long2ObjectArraySortedMap>>> walkersByVersion = this.walkersById.get(data.getString("id")); + if (walkersByVersion != null) { -+ final List> walkersForId = walkersByVersion.getFloor(toVersion); ++ final List>> walkersForId = walkersByVersion.getFloor(toVersion); + if (walkersForId != null) { + for (int i = 0, len = walkersForId.size(); i < len; ++i) { + final MapType replace = walkersForId.get(i).walk(data, fromVersion, toVersion); @@ -6964,7 +9088,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public final String name; + + protected final ArrayList, MapType>> structureConverters = new ArrayList<>(); -+ protected final Long2ObjectArraySortedMap>> structureWalkers = new Long2ObjectArraySortedMap<>(); ++ protected final Long2ObjectArraySortedMap>>> structureWalkers = new Long2ObjectArraySortedMap<>(); + protected final Long2ObjectArraySortedMap, MapType>>> structureHooks = new Long2ObjectArraySortedMap<>(); + + public MCDataType(final String name) { @@ -6977,11 +9101,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + this.structureConverters.sort(DataConverter.LOWEST_VERSION_COMPARATOR); + } + -+ public void addStructureWalker(final int minVersion, final DataWalker walker) { ++ public void addStructureWalker(final int minVersion, final DataWalker> walker) { + this.addStructureWalker(minVersion, 0, walker); + } + -+ public void addStructureWalker(final int minVersion, final int versionStep, final DataWalker walker) { ++ public void addStructureWalker(final int minVersion, final int versionStep, final DataWalker> walker) { + this.structureWalkers.computeIfAbsent(DataConverter.encodeVersions(minVersion, versionStep), (final long keyInMap) -> { + return new ArrayList<>(); + }).add(walker); @@ -7054,7 +9178,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ final List> walkers = this.structureWalkers.getFloor(toVersion); ++ final List>> walkers = this.structureWalkers.getFloor(toVersion); + if (walkers != null) { + for (int i = 0, len = walkers.size(); i < len; ++i) { + final MapType replace = walkers.get(i).walk(data, fromVersion, toVersion); @@ -7105,6 +9229,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final IDDataType TILE_ENTITY = new IDDataType("TileEntity"); + public static final IDDataType ITEM_STACK = new IDDataType("ItemStack"); + public static final MCDataType BLOCK_STATE = new MCDataType("BlockState"); ++ public static final MCValueType FLAT_BLOCK_STATE = new MCValueType("FlatBlockState"); ++ public static final MCDataType DATA_COMPONENTS = new MCDataType("DataComponents"); ++ public static final MCDataType VILLAGER_TRADE = new MCDataType("VillagerTrade"); ++ public static final DynamicDataType PARTICLE = new DynamicDataType("Particle"); + public static final MCValueType ENTITY_NAME = new MCValueType("EntityName"); + public static final IDDataType ENTITY = new IDDataType("Entity"); + public static final MCValueType BLOCK_NAME = new MCValueType("BlockName"); @@ -7125,12 +9253,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static final MCDataType SAVED_DATA_STRUCTURE_FEATURE_INDICES = new MCDataType("SavedData/StructureFeatureIndices"); + public static final MCDataType SAVED_DATA_MAP_DATA = new MCDataType("SavedData/MapData"); + public static final MCDataType SAVED_DATA_RAIDS = new MCDataType("SavedData/Raids"); ++ public static final MCDataType SAVED_DATA_COMMAND_STORAGE = new MCDataType("SavedData/CommandStorage"); ++ public static final MCDataType SAVED_DATA_FORCED_CHUNKS = new MCDataType("SavedData/Chunks"); ++ public static final MCDataType SAVED_DATA_MAP_INDEX = new MCDataType("SavedData/IdCounts"); ++ ++ public static final MCValueType DATACONVERTER_CUSTOM_TYPE_COMMAND = new MCValueType("DC_Custom/Command"); + + static { + try { + registerAll(); -+ } catch (final ThreadDeath thr) { -+ throw thr; + } catch (final Throwable thr) { + LOGGER.error(LogUtils.FATAL_MARKER, "Failed to register data converters", thr); + throw new RuntimeException(thr); @@ -7221,7 +9352,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + V1904.register(); + V1905.register(); + V1906.register(); -+ // V1909 is just adding a simple block entity (jigsaw) ++ V1909.register(); + V1911.register(); + V1914.register(); + V1917.register(); @@ -7353,6 +9484,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + V3685.register(); + V3689.register(); + V3692.register(); ++ // V1.20.5 ++ V3799.register(); ++ V3800.register(); ++ V3803.register(); ++ V3807.register(); ++ V3808.register(); ++ V3809.register(); ++ V3812.register(); ++ V3813.register(); ++ V3814.register(); ++ V3816.register(); ++ V3818.register(); ++ V3820.register(); ++ V3825.register(); ++ V3828.register(); ++ V3833.register(); + } + + private MCTypeRegistry() {} @@ -7518,7 +9665,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package ca.spottedleaf.dataconverter.minecraft.util; + ++import com.google.gson.JsonElement; +import com.google.gson.JsonObject; ++import com.google.gson.JsonParseException; ++import com.google.gson.JsonParser; ++import com.google.gson.JsonPrimitive; +import net.minecraft.util.GsonHelper; + +public final class ComponentUtils { @@ -7541,6 +9692,53 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return GsonHelper.toStableString(ret); + } + ++ public static String retrieveTranslationString(final String possibleJson) { ++ try { ++ final JsonElement element = JsonParser.parseString(possibleJson); ++ ++ if (element instanceof JsonObject object) { ++ final JsonElement translation = object.get("translate"); ++ if (translation instanceof JsonPrimitive primitive) { ++ return primitive.getAsString(); ++ } ++ } ++ ++ return null; ++ } catch (final Exception ex) { ++ return null; ++ } ++ } ++ ++ public static String convertFromLenient(final String input) { ++ if (input == null) { ++ return input; ++ } ++ ++ if (input.isEmpty() || input.equals("null")) { ++ return EMPTY; ++ } ++ ++ final char firstCharacter = input.charAt(0); ++ final char lastCharacter = input.charAt(input.length() - 1); ++ if ((firstCharacter == '"' && lastCharacter == '"') ++ || (firstCharacter == '{' && lastCharacter == '}') ++ || (firstCharacter == '[' && lastCharacter == ']')) { ++ try { ++ final JsonElement json = JsonParser.parseString(input); ++ ++ if (json.isJsonPrimitive()) { ++ return createPlainTextComponent(json.getAsString()); ++ } ++ ++ return GsonHelper.toStableString(json); ++ } catch (final JsonParseException ignored) { ++ // fall through to plain text ++ } ++ } ++ ++ return createPlainTextComponent(input); ++ } ++ + private ComponentUtils() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V100.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V100.java @@ -7555,6 +9753,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.minecraft.walkers.block_name.DataWalkerBlockNames; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.DataWalkerTypePaths; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItems; +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; @@ -7565,10 +9764,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V100 { + -+ protected static final int VERSION = MCVersions.V15W32A; ++ private static final int VERSION = MCVersions.V15W32A; ++ ++ static void registerEquipment(final int version, final String id) { ++ registerEquipment(version, 0, id); ++ } ++ ++ private static final DataWalkerItemLists EQUIPMENT_ITEM_LISTS = new DataWalkerItemLists("ArmorItems", "HandItems"); ++ private static final DataWalkerItems EQUIPMENT_ITEMS = new DataWalkerItems("body_armor_item"); ++ ++ static void registerEquipment(final int version, final int versionStep, final String id) { ++ MCTypeRegistry.ENTITY.addWalker(version, versionStep, id, EQUIPMENT_ITEM_LISTS); ++ MCTypeRegistry.ENTITY.addWalker(version, versionStep, id, EQUIPMENT_ITEMS); ++ } + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ registerEquipment(VERSION, 0, id); + } + + public static void register() { @@ -7664,18 +9875,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addWalker(VERSION, "Villager", (final MapType data, final long fromVersion, final long toVersion) -> { + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "Inventory", fromVersion, toVersion); + -+ final MapType offers = data.getMap("Offers"); -+ if (offers != null) { -+ final ListType recipes = offers.getList("Recipes", ObjectType.MAP); -+ if (recipes != null) { -+ for (int i = 0, len = recipes.size(); i < len; ++i) { -+ final MapType recipe = recipes.getMap(i); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buy", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buyB", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "sell", fromVersion, toVersion); -+ } -+ } -+ } ++ WalkerUtils.convertList(MCTypeRegistry.VILLAGER_TRADE, data.getMap("Offers"), "Recipes", fromVersion, toVersion); + + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "ArmorItems", fromVersion, toVersion); + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "HandItems", fromVersion, toVersion); @@ -7683,6 +9883,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + }); + registerMob("Shulker"); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "AreaEffectCloud", new DataWalkerTypePaths<>(MCTypeRegistry.PARTICLE, "Particle")); + + MCTypeRegistry.STRUCTURE.addStructureWalker(VERSION, (final MapType data, final long fromVersion, final long toVersion) -> { + final ListType entities = data.getList("entities", ObjectType.MAP); @@ -7706,7 +9907,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V100() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V101.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V101.java new file mode 100644 @@ -7719,55 +9919,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.minecraft.util.ComponentUtils; +import ca.spottedleaf.dataconverter.types.MapType; -+import com.google.gson.JsonParseException; -+import net.minecraft.network.chat.CommonComponents; -+import net.minecraft.network.chat.Component; -+import net.minecraft.util.GsonHelper; -+import net.minecraft.util.datafix.fixes.BlockEntitySignTextStrictJsonFix; + +public final class V101 { + -+ protected static final int VERSION = MCVersions.V15W32A + 1; ++ private static final int VERSION = MCVersions.V15W32A + 1; + -+ protected static void updateLine(final MapType data, final String path) { ++ private static void updateLine(final MapType data, final String path) { + final String textString = data.getString(path); -+ if (textString == null || textString.isEmpty() || "null".equals(textString)) { -+ data.setString(path, Component.Serializer.toJson(CommonComponents.EMPTY)); ++ ++ if (textString == null) { + return; + } + -+ Component component = null; -+ -+ if (textString.charAt(0) == '"' && textString.charAt(textString.length() - 1) == '"' -+ || textString.charAt(0) == '{' && textString.charAt(textString.length() - 1) == '}') { -+ try { -+ component = GsonHelper.fromNullableJson(BlockEntitySignTextStrictJsonFix.GSON, textString, Component.class, true); -+ if (component == null) { -+ component = CommonComponents.EMPTY; -+ } -+ } catch (final JsonParseException ignored) {} -+ -+ if (component == null) { -+ try { -+ component = Component.Serializer.fromJson(textString); -+ } catch (final JsonParseException ignored) {} -+ } -+ -+ if (component == null) { -+ try { -+ component = Component.Serializer.fromJsonLenient(textString); -+ } catch (final JsonParseException ignored) {} -+ } -+ -+ if (component == null) { -+ component = Component.literal(textString); -+ } -+ } else { -+ component = Component.literal(textString); -+ } -+ -+ data.setString(path, Component.Serializer.toJson(component)); ++ data.setString(path, ComponentUtils.convertFromLenient(textString)); + } + + public static void register() { @@ -7785,7 +9951,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V101() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V102.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V102.java new file mode 100644 @@ -7809,7 +9974,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final Logger LOGGER = LogUtils.getLogger(); + -+ protected static final int VERSION = MCVersions.V15W32A + 2; ++ private static final int VERSION = MCVersions.V15W32A + 2; + + public static void register() { + // V102 -> V15W32A + 2 @@ -7878,7 +10043,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V102() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1022.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1022.java new file mode 100644 @@ -7895,14 +10059,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1022 { + -+ protected static final int VERSION = MCVersions.V17W06A; ++ private static final int VERSION = MCVersions.V17W06A; + + public static void register() { + MCTypeRegistry.PLAYER.addStructureWalker(VERSION, (final MapType data, final long fromVersion, final long toVersion) -> { -+ final MapType rootVehicle = data.getMap("RootVehicle"); -+ if (rootVehicle != null) { -+ WalkerUtils.convert(MCTypeRegistry.ENTITY, rootVehicle, "Entity", fromVersion, toVersion); -+ } ++ WalkerUtils.convert(MCTypeRegistry.ENTITY, data.getMap("RootVehicle"), "Entity", fromVersion, toVersion); + + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "Inventory", fromVersion, toVersion); + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "EnderItems", fromVersion, toVersion); @@ -7929,7 +10090,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1022() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V105.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V105.java new file mode 100644 @@ -7949,7 +10109,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V105 { + -+ protected static final int VERSION = MCVersions.V15W32C + 1; ++ private static final int VERSION = MCVersions.V15W32C + 1; + + public static void register() { + MCTypeRegistry.ITEM_STACK.addConverterForId("minecraft:spawn_egg", new DataConverter<>(VERSION) { @@ -8005,7 +10165,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V106 { + -+ protected static final int VERSION = MCVersions.V15W32C + 2; ++ private static final int VERSION = MCVersions.V15W32C + 2; + + public static void register() { + // V106 -> V15W32C + 2 @@ -8074,7 +10234,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V106() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V107.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V107.java new file mode 100644 @@ -8091,7 +10250,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V107 { + -+ protected static final int VERSION = MCVersions.V15W32C + 3; ++ private static final int VERSION = MCVersions.V15W32C + 3; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("Minecart", new DataConverter<>(VERSION) { @@ -8124,7 +10283,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V107() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V108.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V108.java new file mode 100644 @@ -8140,14 +10298,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.types.MapType; +import com.mojang.logging.LogUtils; +import org.slf4j.Logger; -+ +import java.util.UUID; + +public final class V108 { + + private static final Logger LOGGER = LogUtils.getLogger(); + -+ protected static final int VERSION = MCVersions.V15W32C + 4; ++ private static final int VERSION = MCVersions.V15W32C + 4; + + public static void register() { + // Convert String UUID into UUIDMost and UUIDLeast @@ -8178,7 +10335,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V108() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V109.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V109.java new file mode 100644 @@ -8192,51 +10348,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.types.MapType; -+import com.google.common.collect.Sets; -+import java.util.Set; + +public final class V109 { + -+ protected static final int VERSION = MCVersions.V15W32C + 5; -+ -+ // DFU declares this exact field but leaves it unused. Not sure why, legacy conversion system checked if the ID matched. -+ // I'm going to leave it here unused as well, just in case it's needed in the future. -+ protected static final Set ENTITIES = Sets.newHashSet( -+ "ArmorStand", -+ "Bat", -+ "Blaze", -+ "CaveSpider", -+ "Chicken", -+ "Cow", -+ "Creeper", -+ "EnderDragon", -+ "Enderman", -+ "Endermite", -+ "EntityHorse", -+ "Ghast", -+ "Giant", -+ "Guardian", -+ "LavaSlime", -+ "MushroomCow", -+ "Ozelot", -+ "Pig", -+ "PigZombie", -+ "Rabbit", -+ "Sheep", -+ "Shulker", -+ "Silverfish", -+ "Skeleton", -+ "Slime", -+ "SnowMan", -+ "Spider", -+ "Squid", -+ "Villager", -+ "VillagerGolem", -+ "Witch", -+ "WitherBoss", -+ "Wolf", -+ "Zombie" -+ ); ++ private static final int VERSION = MCVersions.V15W32C + 5; + + public static void register() { + // Converts health to be in float, and cleans up whatever the hell was going on with HealF and Health... @@ -8267,7 +10382,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V109() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V110.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V110.java new file mode 100644 @@ -8286,7 +10400,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V110 { + -+ protected static final int VERSION = MCVersions.V15W32C + 6; ++ private static final int VERSION = MCVersions.V15W32C + 6; + + public static void register() { + // Moves the Saddle boolean to be an actual saddle item. Note: The data walker for the SaddleItem exists @@ -8312,7 +10426,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V110() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V111.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V111.java new file mode 100644 @@ -8329,11 +10442,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V111 { + -+ protected static final int VERSION = MCVersions.V15W33B; ++ private static final int VERSION = MCVersions.V15W33B; + + public static void register() { -+ MCTypeRegistry.ENTITY.addConverterForId("Painting", new EntityRotationFix("Painting")); -+ MCTypeRegistry.ENTITY.addConverterForId("ItemFrame", new EntityRotationFix("ItemFrame")); ++ final EntityRotationFix rotationFix = new EntityRotationFix(VERSION); ++ MCTypeRegistry.ENTITY.addConverterForId("Painting", rotationFix); ++ MCTypeRegistry.ENTITY.addConverterForId("ItemFrame", rotationFix); + } + + private V111() {} @@ -8347,11 +10461,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + {1, 0, 0} + }; + -+ protected final String id; -+ -+ public EntityRotationFix(final String id) { -+ super(VERSION); -+ this.id = id; ++ public EntityRotationFix(final int version) { ++ super(version); + } + + @Override @@ -8385,7 +10496,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + } -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1125.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1125.java new file mode 100644 @@ -8407,8 +10517,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1125 { + -+ protected static final int VERSION = MCVersions.V17W15A; -+ protected static final int BED_BLOCK_ID = 416; ++ private static final int VERSION = MCVersions.V17W15A; ++ private static final int BED_BLOCK_ID = 416; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -8493,7 +10603,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1125() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V113.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V113.java new file mode 100644 @@ -8512,9 +10621,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V113 { + -+ protected static final int VERSION = MCVersions.V15W33C + 1; ++ private static final int VERSION = MCVersions.V15W33C + 1; + -+ protected static void checkList(final MapType data, final String id, final int requiredLength) { ++ private static void checkList(final MapType data, final String id, final int requiredLength) { + final ListType list = data.getList(id, ObjectType.FLOAT); + if (list != null && list.size() == requiredLength) { + for (int i = 0; i < requiredLength; ++i) { @@ -8540,7 +10649,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V113() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1344.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1344.java new file mode 100644 @@ -8558,7 +10666,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1344 { + -+ protected static final int VERSION = MCVersions.V1_12_2 + 1; ++ private static final int VERSION = MCVersions.V1_12_2 + 1; + + private static final Int2ObjectOpenHashMap BUTTON_ID_TO_NAME = new Int2ObjectOpenHashMap<>(); + static { @@ -8723,7 +10831,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1344() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V135.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V135.java new file mode 100644 @@ -8745,7 +10852,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V135 { + -+ protected static final int VERSION = MCVersions.V15W40B + 1; ++ private static final int VERSION = MCVersions.V15W40B + 1; + + public static void register() { + // In this update they changed the "Riding" value to be "Passengers", which is now a list. So it added @@ -8790,7 +10897,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V135() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V143.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V143.java new file mode 100644 @@ -8805,7 +10911,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V143 { + -+ protected static final int VERSION = MCVersions.V15W44B; ++ private static final int VERSION = MCVersions.V15W44B; + + public static void register() { + ConverterAbstractEntityRename.register(VERSION, (final String input) -> { @@ -8814,7 +10920,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V143() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1446.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1446.java new file mode 100644 @@ -8831,7 +10936,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1446 { + -+ protected static final int VERSION = MCVersions.V17W43B + 1; ++ private static final int VERSION = MCVersions.V17W43B + 1; + + public static void register() { + MCTypeRegistry.OPTIONS.addStructureConverter(new DataConverter<>(VERSION) { @@ -8856,7 +10961,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1446() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1450.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1450.java new file mode 100644 @@ -8874,7 +10978,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1450 { + -+ protected static final int VERSION = MCVersions.V17W46A + 1; ++ private static final int VERSION = MCVersions.V17W46A + 1; + + public static void register() { + MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) { @@ -8887,7 +10991,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1450() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1451.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1451.java new file mode 100644 @@ -8929,7 +11032,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1451 { + -+ protected static final int VERSION = MCVersions.V17W47A; ++ private static final int VERSION = MCVersions.V17W47A; + + public static String packWithDot(final String string) { + final ResourceLocation resourceLocation = ResourceLocation.tryParse(string); @@ -9010,7 +11113,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + MCTypeRegistry.ENTITY.addWalker(VERSION, 3, "minecraft:potion", new DataWalkerItems("Potion")); + MCTypeRegistry.ENTITY.addWalker(VERSION, 3, "minecraft:arrow", new DataWalkerTypePaths<>(MCTypeRegistry.BLOCK_STATE, "inBlockState")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, 3, "minecraft:enderman", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, 3, "minecraft:enderman"); + MCTypeRegistry.ENTITY.addWalker(VERSION, 3, "minecraft:enderman", new DataWalkerTypePaths<>(MCTypeRegistry.BLOCK_STATE, "carriedBlockState")); + MCTypeRegistry.ENTITY.addWalker(VERSION, 3, "minecraft:falling_block", new DataWalkerTypePaths<>(MCTypeRegistry.BLOCK_STATE, "BlockState")); + MCTypeRegistry.ENTITY.addWalker(VERSION, 3, "minecraft:falling_block", new DataWalkerTileEntities("TileEntityData")); @@ -9423,9 +11526,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1456 { + -+ protected static final int VERSION = MCVersions.V17W49B + 1; ++ private static final int VERSION = MCVersions.V17W49B + 1; + -+ protected static byte direction2dTo3d(final byte old) { ++ private static byte direction2dTo3d(final byte old) { + switch (old) { + case 0: + return 3; @@ -9450,7 +11553,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1456() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1458.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1458.java new file mode 100644 @@ -9468,7 +11570,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1458 { + -+ protected static final int VERSION = MCVersions.V17W50A + 1; ++ private static final int VERSION = MCVersions.V17W50A + 1; + + public static MapType updateCustomName(final MapType data) { + final String customName = data.getString("CustomName", ""); @@ -9518,13 +11620,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final String name = display.getString("Name"); + if (name != null) { + display.setString("Name", ComponentUtils.createPlainTextComponent(name)); -+ } else { ++ } /* In 1.20.5, Mojang removed this branch (ItemCustomNameToComponentFix) */ /*else { + final String localisedName = display.getString("LocName"); + if (localisedName != null) { + display.setString("Name", ComponentUtils.createTranslatableComponent(localisedName)); + display.remove("LocName"); + } -+ } ++ }*/ + + return null; + } @@ -9544,7 +11646,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1458() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1460.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1460.java new file mode 100644 @@ -9573,17 +11674,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MOTIVE_REMAP.put("donkeykong", "donkey_kong"); + MOTIVE_REMAP.put("burningskull", "burning_skull"); + MOTIVE_REMAP.put("skullandroses", "skull_and_roses"); -+ }; -+ -+ protected static final int VERSION = MCVersions.V18W01A + 1; -+ -+ private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); + } + -+ private static void registerThrowableProjectile(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerBlockNames("inTile")); -+ } ++ private static final int VERSION = MCVersions.V18W01A + 1; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:painting", new DataConverter<>(VERSION) { @@ -9603,7 +11696,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1460() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1466.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1466.java new file mode 100644 @@ -9624,9 +11716,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1466 { + -+ protected static final int VERSION = MCVersions.V18W06A; ++ private static final int VERSION = MCVersions.V18W06A; + -+ protected static short packOffsetCoordinates(final int x, final int y, final int z) { ++ private static short packOffsetCoordinates(final int x, final int y, final int z) { + return (short)((x & 15) | ((y & 15) << 4) | ((z & 15) << 8)); + } + @@ -9752,7 +11844,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1466() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V147.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V147.java new file mode 100644 @@ -9769,7 +11860,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V147 { + -+ protected static final int VERSION = MCVersions.V15W46A + 1; ++ private static final int VERSION = MCVersions.V15W46A + 1; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("ArmorStand", new DataConverter<>(VERSION) { @@ -9785,7 +11876,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V147() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1470.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1470.java new file mode 100644 @@ -9798,15 +11888,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.DataWalkerTypePaths; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItems; + +public final class V1470 { + -+ protected static final int VERSION = MCVersions.V18W08A; ++ private static final int VERSION = MCVersions.V18W08A; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -9824,7 +11913,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1470() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1474.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1474.java new file mode 100644 @@ -9843,7 +11931,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1474 { + -+ protected static final int VERSION = MCVersions.V18W10B; ++ private static final int VERSION = MCVersions.V18W10B; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:shulker", new DataConverter<>(VERSION) { @@ -9862,11 +11950,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ConverterAbstractItemRename.register(VERSION, (final String old) -> { + return "minecraft:purple_shulker_box".equals(old) ? "minecraft:shulker_box" : null; + }); -+ + } + + private V1474() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1475.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1475.java new file mode 100644 @@ -9879,21 +11965,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V1475 { + -+ protected static final int VERSION = MCVersions.V18W10B + 1; ++ private static final int VERSION = MCVersions.V18W10B + 1; + + public static void register() { -+ ConverterAbstractBlockRename.register(VERSION, ++ ConverterAbstractBlockRename.register(VERSION, new HashMap<>( + ImmutableMap.of( + "minecraft:flowing_water", "minecraft:water", + "minecraft:flowing_lava", "minecraft:lava" -+ )::get); ++ ) ++ )::get); + } + + private V1475() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1480.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1480.java new file mode 100644 @@ -9912,7 +11999,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1480 { + -+ protected static final int VERSION = MCVersions.V18W14A + 1; ++ private static final int VERSION = MCVersions.V18W14A + 1; + + public static final Map RENAMED_IDS = new HashMap<>( + ImmutableMap.builder() @@ -9958,30 +12045,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.entity.ConverterAbstractEntityRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V1483 { + -+ protected static final int VERSION = MCVersions.V18W16A; -+ -+ private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); -+ } ++ private static final int VERSION = MCVersions.V18W16A; + + public static void register() { -+ ConverterAbstractEntityRename.register(VERSION, ImmutableMap.of( -+ "minecraft:puffer_fish", "minecraft:pufferfish" ++ ConverterAbstractEntityRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:puffer_fish", "minecraft:pufferfish" ++ ) + )::get); -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:puffer_fish_spawn_egg", "minecraft:pufferfish_spawn_egg" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:puffer_fish_spawn_egg", "minecraft:pufferfish_spawn_egg" ++ ) + )::get); + + MCTypeRegistry.ENTITY.copyWalkers(VERSION, "minecraft:puffer_fish", "minecraft:pufferfish"); + } + + private V1483() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1484.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1484.java new file mode 100644 @@ -9998,16 +12084,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.types.MapType; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; +import java.util.Map; + +public final class V1484 { + -+ protected static final int VERSION = MCVersions.V18W19A; ++ private static final int VERSION = MCVersions.V18W19A; + + public static void register() { -+ final Map renamed = ImmutableMap.of( -+ "minecraft:sea_grass", "minecraft:seagrass", -+ "minecraft:tall_sea_grass", "minecraft:tall_seagrass" ++ final Map renamed = new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:sea_grass", "minecraft:seagrass", ++ "minecraft:tall_sea_grass", "minecraft:tall_seagrass" ++ ) + ); + + ConverterAbstractItemRename.register(VERSION, renamed::get); @@ -10060,7 +12149,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1484() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1486.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1486.java new file mode 100644 @@ -10081,11 +12169,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1486 { + -+ protected static final int VERSION = MCVersions.V18W19B + 1; -+ -+ private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); -+ } ++ private static final int VERSION = MCVersions.V18W19B + 1; + + public static final Map RENAMED_ENTITY_IDS = new HashMap<>( + ImmutableMap.builder() @@ -10110,7 +12194,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1486() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1487.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1487.java new file mode 100644 @@ -10124,16 +12207,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; +import java.util.Map; + +public final class V1487 { + -+ protected static final int VERSION = MCVersions.V18W19B + 2; ++ private static final int VERSION = MCVersions.V18W19B + 2; + + public static void register() { -+ final Map remap = ImmutableMap.of( -+ "minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", -+ "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs" ++ final Map remap = new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:prismarine_bricks_slab", "minecraft:prismarine_brick_slab", ++ "minecraft:prismarine_bricks_stairs", "minecraft:prismarine_brick_stairs" ++ ) + ); + + ConverterAbstractItemRename.register(VERSION, remap::get); @@ -10141,7 +12227,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1487() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1488.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1488.java new file mode 100644 @@ -10161,21 +12246,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.types.ObjectType; +import com.google.common.collect.ImmutableMap; + ++import java.util.HashMap; ++ +public final class V1488 { + -+ protected static final int VERSION = MCVersions.V18W19B + 3; ++ private static final int VERSION = MCVersions.V18W19B + 3; + -+ protected static boolean isIglooPiece(final MapType piece) { ++ private static boolean isIglooPiece(final MapType piece) { + return "Iglu".equals(piece.getString("id")); + } + + public static void register() { -+ ConverterAbstractBlockRename.register(VERSION, ImmutableMap.of( -+ "minecraft:kelp_top", "minecraft:kelp", -+ "minecraft:kelp", "minecraft:kelp_plant" ++ ConverterAbstractBlockRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:kelp_top", "minecraft:kelp", ++ "minecraft:kelp", "minecraft:kelp_plant" ++ ) + )::get); -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:kelp_top", "minecraft:kelp" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:kelp_top", "minecraft:kelp" ++ ) + )::get); + + // Don't ask me why in V1458 they wrote the converter to NOT do command blocks and THEN in THIS version @@ -10235,7 +12326,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1488() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1490.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1490.java new file mode 100644 @@ -10250,23 +12340,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; + ++import java.util.HashMap; ++ +public final class V1490 { + -+ protected static final int VERSION = MCVersions.V18W20A + 1; ++ private static final int VERSION = MCVersions.V18W20A + 1; + + public static void register() { -+ ConverterAbstractBlockRename.register(VERSION, ImmutableMap.of( -+ "minecraft:melon_block", "minecraft:melon" ++ ConverterAbstractBlockRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:melon_block", "minecraft:melon" ++ ) + )::get); -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:melon_block", "minecraft:melon", -+ "minecraft:melon", "minecraft:melon_slice", -+ "minecraft:speckled_melon", "minecraft:glistering_melon_slice" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:melon_block", "minecraft:melon", ++ "minecraft:melon", "minecraft:melon_slice", ++ "minecraft:speckled_melon", "minecraft:glistering_melon_slice" ++ ) + )::get); + } + + private V1490() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1492.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1492.java new file mode 100644 @@ -10391,7 +12486,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + .build(); + -+ protected static final int VERSION = MCVersions.V18W20B + 1; ++ private static final int VERSION = MCVersions.V18W20B + 1; + + public static void register() { + MCTypeRegistry.STRUCTURE_FEATURE.addStructureConverter(new DataConverter<>(VERSION) { @@ -10424,7 +12519,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1492() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1494.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1494.java new file mode 100644 @@ -10444,7 +12538,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1494 { + -+ protected static final int VERSION = MCVersions.V18W20C + 1; ++ private static final int VERSION = MCVersions.V18W20C + 1; + + private static final Int2ObjectOpenHashMap ENCH_ID_TO_NAME = new Int2ObjectOpenHashMap<>(); + static { @@ -10519,7 +12613,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V1494() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1496.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1496.java new file mode 100644 @@ -10548,9 +12641,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1496 { + -+ private V1496() {} -+ -+ protected static final int VERSION = MCVersions.V18W21B; ++ private static final int VERSION = MCVersions.V18W21B; + + private static final int[][] DIRECTIONS = new int[][] { + new int[] {-1, 0, 0}, @@ -10754,6 +12845,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return ret; + } + ++ private V1496() {} ++ + public abstract static class Section { + protected final ListType palette; + protected final int sectionY; @@ -10912,9 +13005,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1500 { + -+ protected static final int VERSION = MCVersions.V18W22C + 1; -+ -+ private V1500() {} ++ private static final int VERSION = MCVersions.V18W22C + 1; + + public static void register() { + MCTypeRegistry.TILE_ENTITY.addConverterForId("DUMMY", new DataConverter<>(VERSION) { @@ -10926,6 +13017,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1500() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1501.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1501.java new file mode 100644 @@ -10943,7 +13035,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1501 { + -+ protected static final int VERSION = MCVersions.V1_13_PRE1; ++ private static final int VERSION = MCVersions.V1_13_PRE1; + + private static final Map RENAMES = new HashMap<>( + ImmutableMap.builder() @@ -11005,11 +13097,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ private V1501() {} -+ + public static void register() { + ConverterAbstractAdvancementsRename.register(VERSION, RENAMES::get); + } ++ ++ private V1501() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1502.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1502.java new file mode 100644 @@ -11027,7 +13119,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1502 { + -+ protected static final int VERSION = MCVersions.V1_13_PRE2; ++ private static final int VERSION = MCVersions.V1_13_PRE2; + + private static final Map RECIPES_UPDATES = new HashMap<>( + ImmutableMap.builder() @@ -11088,11 +13180,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ private V1502() {} -+ + public static void register() { + ConverterAbstractRecipeRename.register(VERSION, RECIPES_UPDATES::get); + } ++ ++ private V1502() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1506.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1506.java new file mode 100644 @@ -11131,7 +13223,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1506 { + -+ protected static final int VERSION = MCVersions.V1_13_PRE4 + 2; ++ private static final int VERSION = MCVersions.V1_13_PRE4 + 2; + + static final Map MAP = new HashMap<>(); + static { @@ -11210,8 +13302,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MAP.put("167", "minecraft:modified_badlands_plateau"); + } + -+ private V1506() {} -+ + public static void register() { + MCTypeRegistry.LEVEL.addStructureConverter(new DataConverter<>(VERSION) { + @Override @@ -11318,6 +13408,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return ret; + } ++ ++ private V1506() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1510.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1510.java new file mode 100644 @@ -11397,9 +13489,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ protected static final int VERSION = MCVersions.V1_13_PRE4 + 6; -+ -+ private V1510() {} ++ private static final int VERSION = MCVersions.V1_13_PRE4 + 6; + + public static void register() { + ConverterAbstractBlockRename.register(VERSION, RENAMED_BLOCKS::get); @@ -11435,6 +13525,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.copyWalkers(VERSION, "minecraft:eye_of_ender_signal", "minecraft:eye_of_ender"); + MCTypeRegistry.ENTITY.copyWalkers(VERSION, "minecraft:fireworks_rocket", "minecraft:firework_rocket"); + } ++ ++ private V1510() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1514.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1514.java new file mode 100644 @@ -11452,9 +13544,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1514 { + -+ protected static final int VERSION = MCVersions.V1_13_PRE7 + 1; -+ -+ private V1514() {} ++ private static final int VERSION = MCVersions.V1_13_PRE7 + 1; + + public static void register() { + MCTypeRegistry.OBJECTIVE.addStructureConverter(new DataConverter<>(VERSION) { @@ -11509,6 +13599,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V1514() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1515.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1515.java new file mode 100644 @@ -11526,7 +13618,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1515 { + -+ protected static final int VERSION = MCVersions.V1_13_PRE7 + 2; ++ private static final int VERSION = MCVersions.V1_13_PRE7 + 2; + + public static final Map RENAMED_BLOCK_IDS = new HashMap<>( + ImmutableMap.builder() @@ -11538,11 +13630,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ private V1515() {} -+ + public static void register() { + ConverterAbstractBlockRename.register(VERSION, RENAMED_BLOCK_IDS::get); + } ++ ++ private V1515() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1624.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1624.java new file mode 100644 @@ -11566,9 +13658,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final Logger LOGGER = LogUtils.getLogger(); + -+ protected static final int VERSION = MCVersions.V18W32A + 1; -+ -+ private V1624() {} ++ private static final int VERSION = MCVersions.V18W32A + 1; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -11632,6 +13722,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1624() {} ++ + public static final class TrappedChestSection extends V1496.Section { + + private IntOpenHashSet chestIds; @@ -11671,19 +13763,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.minecraft.util.ComponentUtils; +import ca.spottedleaf.dataconverter.types.ObjectType; +import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.MapType; -+import com.google.gson.JsonParseException; -+import net.minecraft.network.chat.CommonComponents; -+import net.minecraft.network.chat.Component; -+import net.minecraft.util.GsonHelper; -+import net.minecraft.util.datafix.fixes.BlockEntitySignTextStrictJsonFix; -+import org.apache.commons.lang3.StringUtils; + +public final class V165 { + -+ protected static final int VERSION = MCVersions.V1_9_PRE2; ++ private static final int VERSION = MCVersions.V1_9_PRE2; + + public static void register() { + MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) { @@ -11701,40 +13788,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + for (int i = 0, len = pages.size(); i < len; ++i) { + final String page = pages.getString(i); -+ Component component = null; + -+ if (!"null".equals(page) && !StringUtils.isEmpty(page)) { -+ if (page.charAt(0) == '"' && page.charAt(page.length() - 1) == '"' || page.charAt(0) == '{' && page.charAt(page.length() - 1) == '}') { -+ try { -+ component = GsonHelper.fromNullableJson(BlockEntitySignTextStrictJsonFix.GSON, page, Component.class, true); -+ if (component == null) { -+ component = CommonComponents.EMPTY; -+ } -+ } catch (final JsonParseException ignored) {} -+ -+ if (component == null) { -+ try { -+ component = Component.Serializer.fromJson(page); -+ } catch (final JsonParseException ignored) {} -+ } -+ -+ if (component == null) { -+ try { -+ component = Component.Serializer.fromJsonLenient(page); -+ } catch (JsonParseException ignored) {} -+ } -+ -+ if (component == null) { -+ component = Component.literal(page); -+ } -+ } else { -+ component = Component.literal(page); -+ } -+ } else { -+ component = CommonComponents.EMPTY; -+ } -+ -+ pages.setString(i, Component.Serializer.toJson(component)); ++ pages.setString(i, ComponentUtils.convertFromLenient(page)); + } + + return null; @@ -11743,7 +13798,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V165() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1800.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1800.java new file mode 100644 @@ -11763,7 +13817,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1800 { + -+ protected static final int VERSION = MCVersions.V1_13_2 + 169; ++ private static final int VERSION = MCVersions.V1_13_2 + 169; + + public static final Map RENAMED_ITEM_IDS = new HashMap<>( + ImmutableMap.builder() @@ -11773,19 +13827,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ private V1800() {} -+ + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + ConverterAbstractItemRename.register(VERSION, RENAMED_ITEM_IDS::get); + + registerMob("minecraft:panda"); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:pillager", new DataWalkerItemLists("Inventory", "ArmorItems", "HandItems")); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:pillager", new DataWalkerItemLists("Inventory")); ++ V100.registerEquipment(VERSION, "minecraft:pillager"); + } + ++ private V1800() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1801.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1801.java new file mode 100644 @@ -11796,23 +13850,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V1801 { + -+ protected static final int VERSION = MCVersions.V1_13_2 + 170; -+ -+ private V1801() {} ++ private static final int VERSION = MCVersions.V1_13_2 + 170; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:illager_beast"); + } + ++ private V1801() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1802.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1802.java new file mode 100644 @@ -11826,24 +13877,27 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V1802 { + -+ protected static final int VERSION = MCVersions.V1_13_2 + 171; -+ -+ private V1802() {} ++ private static final int VERSION = MCVersions.V1_13_2 + 171; + + public static void register() { -+ ConverterAbstractBlockRename.register(VERSION, ImmutableMap.of( -+ "minecraft:stone_slab", "minecraft:smooth_stone_slab", -+ "minecraft:sign", "minecraft:oak_sign", "minecraft:wall_sign", "minecraft:oak_wall_sign" ++ ConverterAbstractBlockRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:stone_slab", "minecraft:smooth_stone_slab", ++ "minecraft:sign", "minecraft:oak_sign", "minecraft:wall_sign", "minecraft:oak_wall_sign" ++ ) + )::get); -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>(ImmutableMap.of( + "minecraft:stone_slab", "minecraft:smooth_stone_slab", + "minecraft:sign", "minecraft:oak_sign" ++ ) + )::get); + } + ++ private V1802() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1803.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1803.java new file mode 100644 @@ -11863,9 +13917,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1803 { + -+ protected static final int VERSION = MCVersions.V1_13_2 + 172; -+ -+ private V1803() {} ++ private static final int VERSION = MCVersions.V1_13_2 + 172; + + public static void register() { + MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) { @@ -11897,6 +13949,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1803() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1904.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1904.java new file mode 100644 @@ -11914,12 +13967,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1904 { + -+ protected static final int VERSION = MCVersions.V18W43C + 1; -+ -+ private V1904() {} ++ private static final int VERSION = MCVersions.V18W43C + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -11946,7 +13997,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerMob("minecraft:cat"); + } + -+ ++ private V1904() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1905.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1905.java new file mode 100644 @@ -11963,9 +14014,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1905 { + -+ protected static final int VERSION = MCVersions.V18W43C + 2; -+ -+ private V1905() {} ++ private static final int VERSION = MCVersions.V18W43C + 2; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -11988,6 +14037,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1905() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1906.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1906.java new file mode 100644 @@ -12004,9 +14054,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1906 { + -+ protected static final int VERSION = MCVersions.V18W43C + 3; -+ -+ private V1906() {} ++ private static final int VERSION = MCVersions.V18W43C + 3; + + public static void register() { + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:barrel", new DataWalkerItemLists("Items")); @@ -12015,6 +14063,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:lectern", new DataWalkerItems("Book")); + } + ++ private V1906() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1909.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1909.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1909.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.DataWalkerTypePaths; ++ ++public final class V1909 { ++ ++ private static final int VERSION = MCVersions.V18W45A + 1; ++ ++ public static void register() { ++ MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:jigsaw", new DataWalkerTypePaths<>(MCTypeRegistry.FLAT_BLOCK_STATE, "final_state")); ++ } ++ ++ private V1909() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1911.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1911.java new file mode 100644 @@ -12034,7 +14105,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1911 { + -+ protected static final int VERSION = MCVersions.V18W46A + 1; ++ private static final int VERSION = MCVersions.V18W46A + 1; + + private static final Map CHUNK_STATUS_REMAP = new HashMap<>( + ImmutableMap.builder() @@ -12051,9 +14122,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ -+ private V1911() {} -+ + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { + @Override @@ -12072,6 +14140,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1911() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1914.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1914.java new file mode 100644 @@ -12088,7 +14157,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1914 { + -+ protected static final int VERSION = MCVersions.V18W48A; ++ private static final int VERSION = MCVersions.V18W48A; + + public static void register() { + MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:chest", new DataConverter<>(VERSION) { @@ -12105,6 +14174,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1914() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1917.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1917.java new file mode 100644 @@ -12121,9 +14191,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1917 { + -+ protected static final int VERSION = MCVersions.V18W49A + 1; -+ -+ private V1917() {} ++ private static final int VERSION = MCVersions.V18W49A + 1; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:cat", new DataConverter<>(VERSION) { @@ -12137,6 +14205,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1917() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1918.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1918.java new file mode 100644 @@ -12154,9 +14223,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1918 { + -+ protected static final int VERSION = MCVersions.V18W49A + 2; -+ -+ private V1918() {} ++ private static final int VERSION = MCVersions.V18W49A + 2; + + private static String getProfessionString(final int professionId, final int careerId) { + if (professionId == 0) { @@ -12208,6 +14275,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addConverterForId("minecraft:villager", converter); + MCTypeRegistry.ENTITY.addConverterForId("minecraft:zombie_villager", converter); + } ++ ++ private V1918() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1920.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1920.java new file mode 100644 @@ -12226,9 +14295,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1920 { + -+ protected static final int VERSION = MCVersions.V18W50A + 1; -+ -+ private V1920() {} ++ private static final int VERSION = MCVersions.V18W50A + 1; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -12289,6 +14356,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:campfire", new DataWalkerItemLists("Items")); + } ++ ++ private V1920() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1925.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1925.java new file mode 100644 @@ -12306,7 +14375,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1925 { + -+ protected static final int VERSION = MCVersions.V19W03C + 1; ++ private static final int VERSION = MCVersions.V19W03C + 1; + + public static void register() { + MCTypeRegistry.SAVED_DATA_MAP_DATA.addStructureConverter(new DataConverter<>(VERSION) { @@ -12324,6 +14393,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1925() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1928.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1928.java new file mode 100644 @@ -12336,30 +14406,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.entity.ConverterAbstractEntityRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V1928 { + -+ protected static final int VERSION = MCVersions.V19W04B + 1; -+ -+ private V1928() {} ++ private static final int VERSION = MCVersions.V19W04B + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { -+ ConverterAbstractEntityRename.register(VERSION, ImmutableMap.of( -+ "minecraft:illager_beast", "minecraft:ravager" ++ ConverterAbstractEntityRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:illager_beast", "minecraft:ravager" ++ ) + )::get); -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:illager_beast_spawn_egg", "minecraft:ravager_spawn_egg" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:illager_beast_spawn_egg", "minecraft:ravager_spawn_egg" ++ ) + )::get); + + registerMob("minecraft:ravager"); + } ++ ++ private V1928() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1929.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1929.java new file mode 100644 @@ -12372,49 +14445,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; -+import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.MapType; -+import ca.spottedleaf.dataconverter.types.ObjectType; + +public final class V1929 { + -+ protected static final int VERSION = MCVersions.V19W04B + 2; -+ -+ private V1929() {} ++ private static final int VERSION = MCVersions.V19W04B + 2; + + public static void register() { + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:wandering_trader", (final MapType data, final long fromVersion, final long toVersion) -> { + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "Inventory", fromVersion, toVersion); + -+ final MapType offers = data.getMap("Offers"); -+ if (offers != null) { -+ final ListType recipes = offers.getList("Recipes", ObjectType.MAP); -+ if (recipes != null) { -+ for (int i = 0, len = recipes.size(); i < len; ++i) { -+ final MapType recipe = recipes.getMap(i); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buy", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buyB", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "sell", fromVersion, toVersion); -+ } -+ } -+ } -+ -+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "ArmorItems", fromVersion, toVersion); -+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "HandItems", fromVersion, toVersion); ++ WalkerUtils.convertList(MCTypeRegistry.VILLAGER_TRADE, data.getMap("Offers"), "Recipes", fromVersion, toVersion); + + return null; + }); ++ V100.registerEquipment(VERSION, "minecraft:wandering_trader"); ++ + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:trader_llama", (final MapType data, final long fromVersion, final long toVersion) -> { + WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, data, "SaddleItem", fromVersion, toVersion); + WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, data, "DecorItem", fromVersion, toVersion); + + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "Items", fromVersion, toVersion); -+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "ArmorItems", fromVersion, toVersion); -+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "HandItems", fromVersion, toVersion); + + return null; + }); ++ V100.registerEquipment(VERSION, "minecraft:trader_llama"); + } ++ ++ private V1929() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1931.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1931.java new file mode 100644 @@ -12425,23 +14483,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V1931 { + -+ protected static final int VERSION = MCVersions.V19W06A; -+ -+ private V1931() {} ++ private static final int VERSION = MCVersions.V19W06A; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:fox"); + } + ++ private V1931() {} ++ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1936.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1936.java new file mode 100644 @@ -12458,9 +14514,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1936 { + -+ protected static final int VERSION = MCVersions.V19W09A + 1; -+ -+ private V1936() {} ++ private static final int VERSION = MCVersions.V19W09A + 1; + + public static void register() { + MCTypeRegistry.OPTIONS.addStructureConverter(new DataConverter<>(VERSION) { @@ -12485,6 +14539,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return 0.5D; + } + } ++ ++ private V1936() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1946.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1946.java new file mode 100644 @@ -12502,9 +14558,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1946 { + -+ protected static final int VERSION = MCVersions.V19W14B + 1; -+ -+ private V1946() {} ++ private static final int VERSION = MCVersions.V19W14B + 1; + + public static void register() { + MCTypeRegistry.POI_CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -12533,6 +14587,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1946() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1948.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1948.java new file mode 100644 @@ -12549,9 +14604,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1948 { + -+ protected static final int VERSION = MCVersions.V1_14_PRE2; -+ -+ private V1948() {} ++ private static final int VERSION = MCVersions.V1_14_PRE2; + + public static void register() { + MCTypeRegistry.ITEM_STACK.addConverterForId("minecraft:white_banner", new DataConverter<>(VERSION) { @@ -12578,6 +14631,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V1948() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1953.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1953.java new file mode 100644 @@ -12594,9 +14649,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1953 { + -+ protected static final int VERSION = MCVersions.V1_14 + 1; -+ -+ private V1953() {} ++ private static final int VERSION = MCVersions.V1_14 + 1; + + public static void register() { + MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:banner", new DataConverter<>(VERSION) { @@ -12611,6 +14664,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1953() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1955.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1955.java new file mode 100644 @@ -12631,7 +14685,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1955 { + -+ protected static final int VERSION = MCVersions.V1_14_1_PRE1; ++ private static final int VERSION = MCVersions.V1_14_1_PRE1; + + private static final int[] LEVEL_XP_THRESHOLDS = new int[] { + 0, @@ -12641,13 +14695,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + 150 + }; + -+ private V1955() {} -+ -+ static int getMinXpPerLevel(final int level) { ++ private static int getMinXpPerLevel(final int level) { + return LEVEL_XP_THRESHOLDS[Mth.clamp(level - 1, 0, LEVEL_XP_THRESHOLDS.length - 1)]; + } + -+ static void addLevel(final MapType data, final int level) { ++ private static void addLevel(final MapType data, final int level) { + MapType villagerData = data.getMap("VillagerData"); + if (villagerData == null) { + villagerData = Types.NBT.createEmptyMap(); @@ -12656,7 +14708,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + villagerData.setInt("level", level); + } + -+ static void addXpFromLevel(final MapType data, final int level) { ++ private static void addXpFromLevel(final MapType data, final int level) { + data.setInt("Xp", getMinXpPerLevel(level)); + } + @@ -12711,6 +14763,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1955() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1961.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1961.java new file mode 100644 @@ -12727,9 +14780,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1961 { + -+ protected static final int VERSION = MCVersions.V1_14_2_PRE3 + 1; -+ -+ private V1961() {} ++ private static final int VERSION = MCVersions.V1_14_2_PRE3 + 1; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -12747,6 +14798,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1961() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1963.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V1963.java new file mode 100644 @@ -12765,9 +14817,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V1963 { + -+ protected static final int VERSION = MCVersions.V1_14_2; -+ -+ private V1963() {} ++ private static final int VERSION = MCVersions.V1_14_2; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:villager", new DataConverter<>(VERSION) { @@ -12793,6 +14843,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V1963() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2100.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2100.java new file mode 100644 @@ -12807,30 +14858,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.recipe.ConverterAbstractRecipeRename; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.ObjectType; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; +import java.util.Map; + +public final class V2100 { + -+ protected static final int VERSION = MCVersions.V1_14_4 + 124; -+ protected static final Map RECIPE_RENAMES = ImmutableMap.of( -+ "minecraft:sugar", "sugar_from_sugar_cane" ++ private static final int VERSION = MCVersions.V1_14_4 + 124; ++ private static final Map RECIPE_RENAMES = new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:sugar", "minecraft:sugar_from_sugar_cane" ++ ) ++ ); ++ private static final Map ADVANCEMENT_RENAMES = new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:recipes/misc/sugar", "minecraft:recipes/misc/sugar_from_sugar_cane" ++ ) + ); + -+ private V2100() {} -+ + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + ConverterAbstractRecipeRename.register(VERSION, RECIPE_RENAMES::get); -+ ConverterAbstractAdvancementsRename.register(VERSION, ImmutableMap.of( -+ "minecraft:recipes/misc/sugar", "minecraft:recipes/misc/sugar_from_sugar_cane" -+ )::get); ++ ConverterAbstractAdvancementsRename.register(VERSION, ADVANCEMENT_RENAMES::get); + + registerMob("minecraft:bee"); + registerMob("minecraft:bee_stinger"); @@ -12845,6 +14899,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + }); + } ++ ++ private V2100() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2202.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2202.java new file mode 100644 @@ -12861,9 +14917,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2202 { + -+ protected static final int VERSION = MCVersions.V19W35A + 1; -+ -+ private V2202() {} ++ private static final int VERSION = MCVersions.V19W35A + 1; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -12883,24 +14937,25 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final int[] newBiomes = new int[1024]; + level.setInts("Biomes", newBiomes); + -+ int n; -+ for(n = 0; n < 4; ++n) { -+ for(int j = 0; j < 4; ++j) { ++ for (int i = 0; i < 4; ++i) { ++ for (int j = 0; j < 4; ++j) { + int k = (j << 2) + 2; -+ int l = (n << 2) + 2; ++ int l = (i << 2) + 2; + int m = l << 4 | k; -+ newBiomes[n << 2 | j] = oldBiomes[m]; ++ newBiomes[i << 2 | j] = oldBiomes[m]; + } + } + -+ for(n = 1; n < 64; ++n) { -+ System.arraycopy(newBiomes, 0, newBiomes, n * 16, 16); ++ for (int i = 1; i < 64; ++i) { ++ System.arraycopy(newBiomes, 0, newBiomes, i * 16, 16); + } + + return null; + } + }); + } ++ ++ private V2202() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2209.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2209.java new file mode 100644 @@ -12915,17 +14970,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import ca.spottedleaf.dataconverter.minecraft.converters.poi.ConverterAbstractPOIRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; +import java.util.Map; + +public final class V2209 { + -+ protected static final int VERSION = MCVersions.V19W40A + 1; -+ -+ private V2209() {} ++ private static final int VERSION = MCVersions.V19W40A + 1; + + public static void register() { -+ final Map renamedIds = ImmutableMap.of( -+ "minecraft:bee_hive", "minecraft:beehive" ++ final Map renamedIds = new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:bee_hive", "minecraft:beehive" ++ ) + ); + + ConverterAbstractBlockRename.register(VERSION, renamedIds::get); @@ -12933,6 +14989,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ConverterAbstractPOIRename.register(VERSION, renamedIds::get); + } + ++ private V2209() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2211.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2211.java new file mode 100644 @@ -12950,9 +15007,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2211 { + -+ protected static final int VERSION = MCVersions.V19W41A + 1; -+ -+ private V2211() {} ++ private static final int VERSION = MCVersions.V19W41A + 1; + + public static void register() { + MCTypeRegistry.STRUCTURE_FEATURE.addStructureConverter(new DataConverter<>(VERSION) { @@ -12971,6 +15026,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V2211() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2218.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2218.java new file mode 100644 @@ -12987,9 +15043,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2218 { + -+ protected static final int VERSION = MCVersions.V1_15_PRE1; -+ -+ private V2218() {} ++ private static final int VERSION = MCVersions.V1_15_PRE1; + + public static void register() { + MCTypeRegistry.POI_CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -13010,6 +15064,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2218() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2501.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2501.java new file mode 100644 @@ -13028,9 +15084,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2501 { + -+ protected static final int VERSION = MCVersions.V1_15_2 + 271; -+ -+ private V2501() {} ++ private static final int VERSION = MCVersions.V1_15_2 + 271; + + private static void registerFurnace(final String id) { + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, id, (data, fromVersion, toVersion) -> { @@ -13081,6 +15135,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerFurnace("minecraft:smoker"); + registerFurnace("minecraft:blast_furnace"); + } ++ ++ private V2501() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2502.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2502.java new file mode 100644 @@ -13091,22 +15147,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V2502 { + -+ protected static final int VERSION = MCVersions.V1_15_2 + 272; -+ -+ private V2502() {} ++ private static final int VERSION = MCVersions.V1_15_2 + 272; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:hoglin"); + } ++ ++ private V2502() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2503.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2503.java new file mode 100644 @@ -13123,31 +15177,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.types.MapType; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; ++import java.util.HashMap; ++import java.util.HashSet; +import java.util.Set; + +public final class V2503 { + -+ protected static final int VERSION = MCVersions.V1_15_2 + 273; ++ private static final int VERSION = MCVersions.V1_15_2 + 273; + -+ private static final Set WALL_BLOCKS = ImmutableSet.of( -+ "minecraft:andesite_wall", -+ "minecraft:brick_wall", -+ "minecraft:cobblestone_wall", -+ "minecraft:diorite_wall", -+ "minecraft:end_stone_brick_wall", -+ "minecraft:granite_wall", -+ "minecraft:mossy_cobblestone_wall", -+ "minecraft:mossy_stone_brick_wall", -+ "minecraft:nether_brick_wall", -+ "minecraft:prismarine_wall", -+ "minecraft:red_nether_brick_wall", -+ "minecraft:red_sandstone_wall", -+ "minecraft:sandstone_wall", -+ "minecraft:stone_brick_wall" ++ private static final Set WALL_BLOCKS = new HashSet<>( ++ ImmutableSet.of( ++ "minecraft:andesite_wall", ++ "minecraft:brick_wall", ++ "minecraft:cobblestone_wall", ++ "minecraft:diorite_wall", ++ "minecraft:end_stone_brick_wall", ++ "minecraft:granite_wall", ++ "minecraft:mossy_cobblestone_wall", ++ "minecraft:mossy_stone_brick_wall", ++ "minecraft:nether_brick_wall", ++ "minecraft:prismarine_wall", ++ "minecraft:red_nether_brick_wall", ++ "minecraft:red_sandstone_wall", ++ "minecraft:sandstone_wall", ++ "minecraft:stone_brick_wall" ++ ) + ); + -+ private V2503() {} -+ + private static void changeWallProperty(final MapType properties, final String path) { + final String property = properties.getString(path); + if (property != null) { @@ -13176,10 +15232,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + } + }); -+ ConverterAbstractAdvancementsRename.register(VERSION, ImmutableMap.of( -+ "minecraft:recipes/misc/composter", "minecraft:recipes/decorations/composter" ++ ConverterAbstractAdvancementsRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:recipes/misc/composter", "minecraft:recipes/decorations/composter" ++ ) + )::get); + } ++ ++ private V2503() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2505.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2505.java new file mode 100644 @@ -13192,18 +15252,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.types.MapType; +import ca.spottedleaf.dataconverter.types.Types; + +public final class V2505 { + -+ protected static final int VERSION = MCVersions.V20W06A + 1; -+ -+ private V2505() {} ++ private static final int VERSION = MCVersions.V20W06A + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -13235,6 +15292,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + registerMob("minecraft:piglin"); + } ++ ++ private V2505() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2508.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2508.java new file mode 100644 @@ -13248,23 +15307,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; +import java.util.Map; + +public final class V2508 { + -+ protected static final int VERSION = MCVersions.V20W08A + 1; -+ -+ private V2508() {} ++ private static final int VERSION = MCVersions.V20W08A + 1; + + public static void register() { -+ final Map remap = ImmutableMap.of( -+ "minecraft:warped_fungi", "minecraft:warped_fungus", -+ "minecraft:crimson_fungi", "minecraft:crimson_fungus" ++ final Map remap = new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:warped_fungi", "minecraft:warped_fungus", ++ "minecraft:crimson_fungi", "minecraft:crimson_fungus" ++ ) + ); + + ConverterAbstractBlockRename.register(VERSION, remap::get); + ConverterAbstractItemRename.register(VERSION, remap::get); + } ++ ++ private V2508() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2509.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2509.java new file mode 100644 @@ -13277,30 +15339,33 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.entity.ConverterAbstractEntityRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2509 { + -+ protected static final int VERSION = MCVersions.V20W08A + 2; -+ -+ private V2509() {} ++ private static final int VERSION = MCVersions.V20W08A + 2; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:zombie_pigman_spawn_egg", "minecraft:zombified_piglin_spawn_egg" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:zombie_pigman_spawn_egg", "minecraft:zombified_piglin_spawn_egg" ++ ) + )::get); -+ ConverterAbstractEntityRename.register(VERSION, ImmutableMap.of( -+ "minecraft:zombie_pigman", "minecraft:zombified_piglin" ++ ConverterAbstractEntityRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:zombie_pigman", "minecraft:zombified_piglin" ++ ) + )::get); + + registerMob("minecraft:zombified_piglin"); + } ++ ++ private V2509() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2511.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2511.java new file mode 100644 @@ -13319,9 +15384,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2511 { + -+ protected static final int VERSION = MCVersions.V20W09A + 1; -+ -+ private V2511() {} ++ private static final int VERSION = MCVersions.V20W09A + 1; + + private static int[] createUUIDArray(final long most, final long least) { + return new int[] { @@ -13404,6 +15467,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Vanilla migrates the potion item but does not change the schema. + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:potion", new DataWalkerItems("Item")); + } ++ ++ private V2511() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2514.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2514.java new file mode 100644 @@ -13426,7 +15491,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2514 { + -+ protected static final int VERSION = MCVersions.V20W11A + 1; ++ private static final int VERSION = MCVersions.V20W11A + 1; + + private static final Set ABSTRACT_HORSES = Sets.newHashSet(); + private static final Set TAMEABLE_ANIMALS = Sets.newHashSet(); @@ -13590,8 +15655,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private V2514() {} -+ + private static void updatePiglin(final MapType data) { + final MapType brain = data.getMap("Brain"); + if (brain == null) { @@ -14000,6 +16063,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static void updateSkullOwner(final MapType tag) { + replaceUUIDString(tag.getMap("SkullOwner"), "Id", "Id"); + } ++ ++ private V2514() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2516.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2516.java new file mode 100644 @@ -14018,9 +16083,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2516 { + -+ protected static final int VERSION = MCVersions.V20W12A + 1; -+ -+ private V2516() {} ++ private static final int VERSION = MCVersions.V20W12A + 1; + + public static void register() { + final DataConverter, MapType> gossipUUIDConverter = new DataConverter<>(VERSION) { @@ -14043,6 +16106,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addConverterForId("minecraft:villager", gossipUUIDConverter); + MCTypeRegistry.ENTITY.addConverterForId("minecraft:zombie_villager", gossipUUIDConverter); + } ++ ++ private V2516() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2518.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2518.java new file mode 100644 @@ -14062,7 +16127,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2518 { + -+ protected static final int VERSION = MCVersions.V20W12A + 3; ++ private static final int VERSION = MCVersions.V20W12A + 3; + + private static final Map FACING_RENAMES = new HashMap<>( + ImmutableMap.builder() @@ -14075,9 +16140,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ -+ private V2518() {} -+ + public static void register() { + MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:jigsaw", new DataConverter<>(VERSION) { + @Override @@ -14115,6 +16177,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2518() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2519.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2519.java new file mode 100644 @@ -14125,22 +16189,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V2519 { + -+ protected static final int VERSION = MCVersions.V20W12A + 4; -+ -+ private V2519() {} ++ private static final int VERSION = MCVersions.V20W12A + 4; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:strider"); + } ++ ++ private V2519() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2522.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2522.java new file mode 100644 @@ -14151,22 +16213,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V2522 { + -+ protected static final int VERSION = MCVersions.V20W13B + 1; -+ -+ private V2522() {} ++ private static final int VERSION = MCVersions.V20W13B + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:zoglin"); + } ++ ++ private V2522() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2523.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2523.java new file mode 100644 @@ -14176,98 +16236,44 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package ca.spottedleaf.dataconverter.minecraft.versions; + -+import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.types.ListType; -+import ca.spottedleaf.dataconverter.types.MapType; -+import ca.spottedleaf.dataconverter.types.ObjectType; ++import ca.spottedleaf.dataconverter.minecraft.converters.attributes.ConverterAbstractAttributesRename; +import com.google.common.collect.ImmutableMap; +import java.util.HashMap; +import java.util.Map; + +public final class V2523 { + -+ protected static final int VERSION = MCVersions.V20W13B + 2; ++ private static final int VERSION = MCVersions.V20W13B + 2; + + private static final Map RENAMES = new HashMap<>( + ImmutableMap.builder() -+ .put("generic.maxHealth", "generic.max_health") -+ .put("Max Health", "generic.max_health") -+ .put("zombie.spawnReinforcements", "zombie.spawn_reinforcements") -+ .put("Spawn Reinforcements Chance", "zombie.spawn_reinforcements") -+ .put("horse.jumpStrength", "horse.jump_strength") -+ .put("Jump Strength", "horse.jump_strength") -+ .put("generic.followRange", "generic.follow_range") -+ .put("Follow Range", "generic.follow_range") -+ .put("generic.knockbackResistance", "generic.knockback_resistance") -+ .put("Knockback Resistance", "generic.knockback_resistance") -+ .put("generic.movementSpeed", "generic.movement_speed") -+ .put("Movement Speed", "generic.movement_speed") -+ .put("generic.flyingSpeed", "generic.flying_speed") -+ .put("Flying Speed", "generic.flying_speed") -+ .put("generic.attackDamage", "generic.attack_damage") -+ .put("generic.attackKnockback", "generic.attack_knockback") -+ .put("generic.attackSpeed", "generic.attack_speed") -+ .put("generic.armorToughness", "generic.armor_toughness") ++ .put("generic.maxHealth", "minecraft:generic.max_health") ++ .put("Max Health", "minecraft:generic.max_health") ++ .put("zombie.spawnReinforcements", "minecraft:zombie.spawn_reinforcements") ++ .put("Spawn Reinforcements Chance", "minecraft:zombie.spawn_reinforcements") ++ .put("horse.jumpStrength", "minecraft:horse.jump_strength") ++ .put("Jump Strength", "minecraft:horse.jump_strength") ++ .put("generic.followRange", "minecraft:generic.follow_range") ++ .put("Follow Range", "minecraft:generic.follow_range") ++ .put("generic.knockbackResistance", "minecraft:generic.knockback_resistance") ++ .put("Knockback Resistance", "minecraft:generic.knockback_resistance") ++ .put("generic.movementSpeed", "minecraft:generic.movement_speed") ++ .put("Movement Speed", "minecraft:generic.movement_speed") ++ .put("generic.flyingSpeed", "minecraft:generic.flying_speed") ++ .put("Flying Speed", "minecraft:generic.flying_speed") ++ .put("generic.attackDamage", "minecraft:generic.attack_damage") ++ .put("generic.attackKnockback", "minecraft:generic.attack_knockback") ++ .put("generic.attackSpeed", "minecraft:generic.attack_speed") ++ .put("generic.armorToughness", "minecraft:generic.armor_toughness") + .build() + ); + -+ private V2523() {} -+ -+ private static void updateName(final MapType data, final String path) { -+ if (data == null) { -+ return; -+ } -+ -+ final String name = data.getString(path); -+ if (name != null) { -+ final String renamed = RENAMES.get(name); -+ if (renamed != null) { -+ data.setString(path, renamed); -+ } -+ } -+ } -+ + public static void register() { -+ final DataConverter, MapType> entityConverter = new DataConverter<>(VERSION) { -+ @Override -+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { -+ final ListType attributes = data.getList("Attributes", ObjectType.MAP); -+ -+ if (attributes == null) { -+ return null; -+ } -+ -+ for (int i = 0, len = attributes.size(); i < len; ++i) { -+ updateName(attributes.getMap(i), "Name"); -+ } -+ -+ return null; -+ } -+ }; -+ -+ MCTypeRegistry.ENTITY.addStructureConverter(entityConverter); -+ MCTypeRegistry.PLAYER.addStructureConverter(entityConverter); -+ -+ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) { -+ @Override -+ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { -+ final ListType attributes = data.getList("AttributeModifiers", ObjectType.MAP); -+ -+ if (attributes == null) { -+ return null; -+ } -+ -+ for (int i = 0, len = attributes.size(); i < len; ++i) { -+ updateName(attributes.getMap(i), "AttributeName"); -+ } -+ -+ return null; -+ } -+ }); ++ ConverterAbstractAttributesRename.register(VERSION, RENAMES::get); + } + ++ private V2523() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2527.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2527.java new file mode 100644 @@ -14288,9 +16294,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2527 { + -+ protected static final int VERSION = MCVersions.V20W16A + 1; -+ -+ private V2527() {} ++ private static final int VERSION = MCVersions.V20W16A + 1; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -14397,6 +16401,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return padded; + } + } ++ ++ private V2527() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2528.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2528.java new file mode 100644 @@ -14410,24 +16416,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2528 { + -+ protected static final int VERSION = MCVersions.V20W16A + 2; -+ -+ private V2528() {} ++ private static final int VERSION = MCVersions.V20W16A + 2; + + public static void register() { -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:soul_fire_torch", "minecraft:soul_torch", -+ "minecraft:soul_fire_lantern", "minecraft:soul_lantern" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:soul_fire_torch", "minecraft:soul_torch", ++ "minecraft:soul_fire_lantern", "minecraft:soul_lantern" ++ ) + )::get); -+ ConverterAbstractBlockRename.register(VERSION, ImmutableMap.of( -+ "minecraft:soul_fire_torch", "minecraft:soul_torch", -+ "minecraft:soul_fire_wall_torch", "minecraft:soul_wall_torch", -+ "minecraft:soul_fire_lantern", "minecraft:soul_lantern" ++ ConverterAbstractBlockRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:soul_fire_torch", "minecraft:soul_torch", ++ "minecraft:soul_fire_wall_torch", "minecraft:soul_wall_torch", ++ "minecraft:soul_fire_lantern", "minecraft:soul_lantern" ++ ) + )::get); + } ++ ++ private V2528() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2529.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2529.java new file mode 100644 @@ -14444,9 +16455,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2529 { + -+ protected static final int VERSION = MCVersions.V20W17A; -+ -+ private V2529() {} ++ private static final int VERSION = MCVersions.V20W17A; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:strider", new DataConverter<>(VERSION) { @@ -14459,6 +16468,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2529() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2531.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2531.java new file mode 100644 @@ -14475,9 +16486,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2531 { + -+ protected static final int VERSION = MCVersions.V20W17A + 2; -+ -+ private V2531() {} ++ private static final int VERSION = MCVersions.V20W17A + 2; + + private static boolean isConnected(final String facing) { + return !"none".equals(facing); @@ -14528,6 +16537,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2531() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2533.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2533.java new file mode 100644 @@ -14546,9 +16557,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2533 { + -+ protected static final int VERSION = MCVersions.V20W18A + 1; -+ -+ private V2533() {} ++ private static final int VERSION = MCVersions.V20W18A + 1; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:villager", new DataConverter<>(VERSION) { @@ -14577,6 +16586,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V2533() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2535.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2535.java new file mode 100644 @@ -14595,9 +16605,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2535 { + -+ protected static final int VERSION = MCVersions.V20W19A + 1; -+ -+ private V2535() {} ++ private static final int VERSION = MCVersions.V20W19A + 1; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:shulker", new DataConverter<>(VERSION) { @@ -14617,6 +16625,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2535() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2538.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2538.java new file mode 100644 @@ -14664,6 +16674,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2538() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2550.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2550.java new file mode 100644 @@ -14688,7 +16700,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2550 { + -+ protected static final int VERSION = MCVersions.V20W20B + 13; ++ private static final int VERSION = MCVersions.V20W20B + 13; + + private static final Map DEFAULTS = new HashMap<>( + ImmutableMap.builder() @@ -14704,7 +16716,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ record StructureFeatureConfiguration(int spacing, int separation, int salt) { ++ private static record StructureFeatureConfiguration(int spacing, int separation, int salt) { + + public MapType serialize() { + final MapType ret = Types.NBT.createEmptyMap(); @@ -15014,6 +17026,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + structures.put(structureName, new StructureFeatureConfiguration(newSpacing, structure.separation, structure.salt)); + } ++ ++ private V2550() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2551.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2551.java new file mode 100644 @@ -15032,7 +17046,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2551 { + -+ protected static final int VERSION = MCVersions.V20W20B + 14; ++ private static final int VERSION = MCVersions.V20W20B + 14; + + public static void register() { + MCTypeRegistry.WORLD_GEN_SETTINGS.addStructureWalker(VERSION, (final MapType data, final long fromVersion, final long toVersion) -> { @@ -15121,6 +17135,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + }); + } ++ ++ private V2551() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2552.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2552.java new file mode 100644 @@ -15134,19 +17150,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.helpers.ConverterAbstractStringValueTypeRename; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2552 { + -+ protected static final int VERSION = MCVersions.V20W20B + 15; -+ -+ private V2552() {} ++ private static final int VERSION = MCVersions.V20W20B + 15; + + public static void register() { -+ ConverterAbstractStringValueTypeRename.register(VERSION, MCTypeRegistry.BIOME, ImmutableMap.of( -+ "minecraft:nether", "minecraft:nether_wastes" ++ ConverterAbstractStringValueTypeRename.register(VERSION, MCTypeRegistry.BIOME, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:nether", "minecraft:nether_wastes" ++ ) + )::get); + } + ++ private V2552() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2553.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2553.java new file mode 100644 @@ -15165,7 +17183,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2553 { + -+ protected static final int VERSION = MCVersions.V20W20B + 16; ++ private static final int VERSION = MCVersions.V20W20B + 16; + + public static final Map BIOME_RENAMES = new HashMap<>( + ImmutableMap.builder() @@ -15225,12 +17243,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + .build() + ); + -+ -+ private V2553() {} -+ + public static void register() { + ConverterAbstractStringValueTypeRename.register(VERSION, MCTypeRegistry.BIOME, BIOME_RENAMES::get); + } ++ ++ private V2553() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2558.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2558.java new file mode 100644 @@ -15247,16 +17264,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.types.MapType; +import ca.spottedleaf.dataconverter.types.Types; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2558 { + -+ protected static final int VERSION = MCVersions.V1_16_PRE2 + 1; -+ -+ private V2558() {} ++ private static final int VERSION = MCVersions.V1_16_PRE2 + 1; + + public static void register() { -+ ConverterAbstractOptionsRename.register(VERSION, ImmutableMap.of( -+ "key_key.swapHands", "key_key.swapOffhand" ++ ConverterAbstractOptionsRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "key_key.swapHands", "key_key.swapOffhand" ++ ) + )::get); + + MCTypeRegistry.WORLD_GEN_SETTINGS.addStructureConverter(new DataConverter<>(VERSION) { @@ -15282,6 +17300,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return V2550.vanillaLevels(seed, V2550.defaultOverworld(seed), false); + } ++ ++ private V2558() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2568.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2568.java new file mode 100644 @@ -15292,22 +17312,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V2568 { + -+ protected static final int VERSION = MCVersions.V1_16_1 + 1; -+ -+ private V2568() {} ++ private static final int VERSION = MCVersions.V1_16_1 + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:piglin_brute"); + } ++ ++ private V2568() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2671.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2671.java new file mode 100644 @@ -15318,20 +17336,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V2671 { + -+ protected static final int VERSION = MCVersions.V1_16_5 + 85; ++ private static final int VERSION = MCVersions.V1_16_5 + 85; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:goat"); + } ++ ++ private V2671() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2679.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2679.java new file mode 100644 @@ -15348,7 +17366,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2679 { + -+ protected static final int VERSION = MCVersions.V1_16_5 + 93; ++ private static final int VERSION = MCVersions.V1_16_5 + 93; + + public static void register() { + MCTypeRegistry.BLOCK_STATE.addStructureConverter(new DataConverter<>(VERSION) { @@ -15374,6 +17392,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2679() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2680.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2680.java new file mode 100644 @@ -15387,20 +17407,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2680 { + -+ protected static final int VERSION = MCVersions.V1_16_5 + 94; ++ private static final int VERSION = MCVersions.V1_16_5 + 94; + + public static void register() { -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:grass_path", "minecraft:dirt_path" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:grass_path", "minecraft:dirt_path" ++ ) + )::get); -+ ConverterAbstractBlockRename.registerAndFixJigsaw(VERSION, ImmutableMap.of( -+ "minecraft:grass_path", "minecraft:dirt_path" ++ ConverterAbstractBlockRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:grass_path", "minecraft:dirt_path" ++ ) + )::get); + } + ++ private V2680() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2684.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2684.java new file mode 100644 @@ -15416,11 +17442,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2684 { + -+ protected static final int VERSION = MCVersions.V20W48A + 1; ++ private static final int VERSION = MCVersions.V20W48A + 1; + + public static void register() { + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:sculk_sensor", new GameEventListenerWalker()); + } ++ ++ private V2684() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2686.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2686.java new file mode 100644 @@ -15431,20 +17459,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V2686 { + -+ protected static final int VERSION = MCVersions.V20W49A + 1; ++ private static final int VERSION = MCVersions.V20W49A + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:axolotl"); + } ++ ++ private V2686() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2688.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2688.java new file mode 100644 @@ -15461,16 +17489,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2688 { + -+ protected static final int VERSION = MCVersions.V20W51A + 1; ++ private static final int VERSION = MCVersions.V20W51A + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:glow_squid"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:glow_item_frame", new DataWalkerItems("Item")); + } ++ ++ private V2688() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2690.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2690.java new file mode 100644 @@ -15489,9 +17519,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2690 { + -+ protected static final int VERSION = MCVersions.V21W05A; ++ private static final int VERSION = MCVersions.V21W05A; + -+ protected static final Map RENAMES = new HashMap<>( ++ private static final Map RENAMES = new HashMap<>( + ImmutableMap.builder() + .put("minecraft:weathered_copper_block", "minecraft:oxidized_copper_block") + .put("minecraft:semi_weathered_copper_block", "minecraft:weathered_copper_block") @@ -15518,8 +17548,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public static void register() { + ConverterAbstractItemRename.register(VERSION, RENAMES::get); -+ ConverterAbstractBlockRename.registerAndFixJigsaw(VERSION, RENAMES::get); ++ ConverterAbstractBlockRename.register(VERSION, RENAMES::get); + } ++ ++ private V2690() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2691.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2691.java new file mode 100644 @@ -15538,9 +17570,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2691 { + -+ protected static final int VERSION = MCVersions.V21W05A + 1; ++ private static final int VERSION = MCVersions.V21W05A + 1; + -+ protected static final Map RENAMES = new HashMap<>( ++ private static final Map RENAMES = new HashMap<>( + ImmutableMap.builder() + .put("minecraft:waxed_copper", "minecraft:waxed_copper_block") + .put("minecraft:oxidized_copper_block", "minecraft:oxidized_copper") @@ -15551,8 +17583,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public static void register() { + ConverterAbstractItemRename.register(VERSION, RENAMES::get); -+ ConverterAbstractBlockRename.registerAndFixJigsaw(VERSION, RENAMES::get); ++ ConverterAbstractBlockRename.register(VERSION, RENAMES::get); + } ++ ++ private V2691() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2693.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2693.java new file mode 100644 @@ -15568,12 +17602,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2693 { + -+ protected static final int VERSION = MCVersions.V21W05B + 1; ++ private static final int VERSION = MCVersions.V21W05B + 1; + + public static void register() { + MCTypeRegistry.WORLD_GEN_SETTINGS.addStructureConverter(new AddFlagIfAbsent(VERSION, "has_increased_height_already", false)); + } + ++ private V2693() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2696.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2696.java new file mode 100644 @@ -15592,9 +17627,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2696 { + -+ protected static final int VERSION = MCVersions.V21W07A + 1; ++ private static final int VERSION = MCVersions.V21W07A + 1; + -+ protected static final Map RENAMES = new HashMap<>( ++ private static final Map RENAMES = new HashMap<>( + ImmutableMap.builder() + .put("minecraft:grimstone", "minecraft:deepslate") + .put("minecraft:grimstone_slab", "minecraft:cobbled_deepslate_slab") @@ -15618,8 +17653,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public static void register() { + ConverterAbstractItemRename.register(VERSION, RENAMES::get); -+ ConverterAbstractBlockRename.registerAndFixJigsaw(VERSION, RENAMES::get); ++ ConverterAbstractBlockRename.register(VERSION, RENAMES::get); + } ++ ++ private V2696() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2700.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2700.java new file mode 100644 @@ -15632,17 +17669,22 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2700 { + -+ protected static final int VERSION = MCVersions.V21W10A + 1; ++ private static final int VERSION = MCVersions.V21W10A + 1; + + public static void register() { -+ ConverterAbstractBlockRename.registerAndFixJigsaw(VERSION, ImmutableMap.of( -+ "minecraft:cave_vines_head", "minecraft:cave_vines", -+ "minecraft:cave_vines_body", "minecraft:cave_vines_plant" ++ ConverterAbstractBlockRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:cave_vines_head", "minecraft:cave_vines", ++ "minecraft:cave_vines_body", "minecraft:cave_vines_plant" ++ ) + )::get); + } ++ ++ private V2700() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2701.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2701.java new file mode 100644 @@ -15665,7 +17707,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2701 { + -+ protected static final int VERSION = MCVersions.V21W10A + 2; ++ private static final int VERSION = MCVersions.V21W10A + 2; + + private static final Pattern INDEX_PATTERN = Pattern.compile("\\[(\\d+)\\]"); + @@ -15759,7 +17801,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return current instanceof String ? (String)current : ""; + } + -+ protected static String convertToString(final MapType feature) { ++ private static String convertToString(final MapType feature) { + return getReplacement( + getNestedString(feature, "type"), + getNestedString(feature, "name"), @@ -15852,6 +17894,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return null; + } ++ ++ private V2701() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2702.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2702.java new file mode 100644 @@ -15868,7 +17912,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2702 { + -+ protected static final int VERSION = MCVersions.V21W10A + 3; ++ private static final int VERSION = MCVersions.V21W10A + 3; + + public static void register() { + final DataConverter, MapType> arrowConverter = new DataConverter<>(VERSION) { @@ -15891,6 +17935,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addConverterForId("minecraft:spectral_arrow", arrowConverter); + MCTypeRegistry.ENTITY.addConverterForId("minecraft:trident", arrowConverter); + } ++ ++ private V2702() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2707.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2707.java new file mode 100644 @@ -15903,14 +17949,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.helpers.AddFlagIfAbsent; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V2707 { + -+ protected static final int VERSION = MCVersions.V21W14A + 1; ++ private static final int VERSION = MCVersions.V21W14A + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -15918,6 +17963,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + registerMob("minecraft:marker"); // ????????????? + } ++ ++ private V2707() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2710.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2710.java new file mode 100644 @@ -15930,17 +17977,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.stats.ConverterAbstractStatsRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2710 { + -+ protected static final int VERSION = MCVersions.V21W15A + 1; ++ private static final int VERSION = MCVersions.V21W15A + 1; + + public static void register() { -+ ConverterAbstractStatsRename.register(VERSION, ImmutableMap.of( -+ "minecraft:play_one_minute", "minecraft:play_time" ++ ConverterAbstractStatsRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:play_one_minute", "minecraft:play_time" ++ ) + )::get); + } + ++ private V2710() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2717.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2717.java new file mode 100644 @@ -15954,19 +18005,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.converters.blockname.ConverterAbstractBlockRename; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; ++import java.util.Map; + +public final class V2717 { + -+ protected static final int VERSION = MCVersions.V1_17_PRE1 + 1; ++ private static final int VERSION = MCVersions.V1_17_PRE1 + 1; + + public static void register() { -+ final ImmutableMap rename = ImmutableMap.of( -+ "minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves" ++ final Map rename = new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:azalea_leaves_flowers", "minecraft:flowering_azalea_leaves" ++ ) + ); + ConverterAbstractItemRename.register(VERSION, rename::get); + ConverterAbstractBlockRename.register(VERSION, rename::get); + } + ++ private V2717() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2825.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2825.java new file mode 100644 @@ -15982,12 +18038,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2825 { + -+ protected static final int VERSION = MCVersions.V1_17_1 + 95; ++ private static final int VERSION = MCVersions.V1_17_1 + 95; + + public static void register() { + MCTypeRegistry.WORLD_GEN_SETTINGS.addStructureConverter(new AddFlagIfAbsent(VERSION, "has_increased_height_already", false)); + } + ++ private V2825() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2831.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2831.java new file mode 100644 @@ -16008,7 +18065,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2831 { + -+ protected static final int VERSION = MCVersions.V1_17_1 + 101; ++ private static final int VERSION = MCVersions.V1_17_1 + 101; + + public static void register() { + MCTypeRegistry.UNTAGGED_SPAWNER.addStructureWalker(VERSION, (final MapType root, final long fromVersion, final long toVersion) -> { @@ -16063,6 +18120,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2831() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2832.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2832.java new file mode 100644 @@ -16096,7 +18155,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final Logger LOGGER = LogUtils.getLogger(); + -+ protected static final int VERSION = MCVersions.V1_17_1 + 102; ++ private static final int VERSION = MCVersions.V1_17_1 + 102; + + private static final String[] BIOMES_BY_ID = new String[256]; // rip datapacks + static { @@ -16996,6 +19055,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return ret; + } ++ ++ private V2832() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2833.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2833.java new file mode 100644 @@ -17012,7 +19073,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2833 { + -+ protected static final int VERSION = MCVersions.V1_17_1 + 103; ++ private static final int VERSION = MCVersions.V1_17_1 + 103; + + public static void register() { + MCTypeRegistry.WORLD_GEN_SETTINGS.addStructureConverter(new DataConverter<>(VERSION) { @@ -17032,6 +19093,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V2833() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2838.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2838.java new file mode 100644 @@ -17050,7 +19112,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2838 { + -+ protected static final int VERSION = MCVersions.V21W40A; ++ private static final int VERSION = MCVersions.V21W40A; + + public static final Map BIOME_UPDATE = new HashMap<>( + ImmutableMap.builder() @@ -17098,6 +19160,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void register() { + ConverterAbstractStringValueTypeRename.register(VERSION, MCTypeRegistry.BIOME, BIOME_UPDATE::get); + } ++ ++ private V2838() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2841.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2841.java new file mode 100644 @@ -17122,15 +19186,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2841 { + -+ protected static final int VERSION = MCVersions.V21W42A + 1; ++ private static final int VERSION = MCVersions.V21W42A + 1; + -+ protected static final Set ALWAYS_WATERLOGGED = new HashSet<>(Arrays.asList( -+ "minecraft:bubble_column", -+ "minecraft:kelp", -+ "minecraft:kelp_plant", -+ "minecraft:seagrass", -+ "minecraft:tall_seagrass" -+ )); ++ private static final Set ALWAYS_WATERLOGGED = new HashSet<>( ++ Arrays.asList( ++ "minecraft:bubble_column", ++ "minecraft:kelp", ++ "minecraft:kelp_plant", ++ "minecraft:seagrass", ++ "minecraft:tall_seagrass" ++ ) ++ ); + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -17250,15 +19316,18 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + final MapType properties = blockState.getMap("Properties"); ++ // Correctly read block state properties as strings - https://github.com/PaperMC/DataConverter/issues/6 + if ("minecraft:water".equals(name)) { -+ return properties != null && properties.getInt("level") == 0 ? "minecraft:water" : "minecraft:flowing_water"; ++ return properties != null && "0".equals(properties.getString("level")) ? "minecraft:water" : "minecraft:flowing_water"; + } else if ("minecraft:lava".equals(name)) { -+ return properties != null && properties.getInt("level") == 0 ? "minecraft:lava" : "minecraft:flowing_lava"; ++ return properties != null && "0".equals(properties.getString("level")) ? "minecraft:lava" : "minecraft:flowing_lava"; + } + -+ return (properties != null && properties.getBoolean("waterlogged")) ? "minecraft:water" : "minecraft:empty"; ++ return (properties != null && "true".equals(properties.getString("waterlogged"))) ? "minecraft:water" : "minecraft:empty"; + } + ++ private V2841() {} ++ + public static final class SimplePaletteReader { + + public final ListType palette; @@ -17329,7 +19398,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2842 { + -+ protected static final int VERSION = MCVersions.V21W42A + 2; ++ private static final int VERSION = MCVersions.V21W42A + 2; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -17341,7 +19410,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + if (!root.isEmpty()) { + for (final String key : root.keys()) { + if (level.hasKey(key)) { -+ // Don't clobber level's data ++ // Don't clobber Level's data + continue; + } + level.setGeneric(key, root.getGeneric(key)); @@ -17391,6 +19460,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + }); + } ++ ++ private V2842() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2843.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2843.java new file mode 100644 @@ -17409,14 +19480,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.types.MapType; +import ca.spottedleaf.dataconverter.types.ObjectType; +import ca.spottedleaf.dataconverter.types.Types; ++import java.util.HashMap; +import java.util.Map; + +public final class V2843 { + -+ protected static final int VERSION = MCVersions.V21W42A + 3; ++ private static final int VERSION = MCVersions.V21W42A + 3; + + public static void register() { -+ ConverterAbstractStringValueTypeRename.register(VERSION, MCTypeRegistry.BIOME, Map.of("minecraft:deep_warm_ocean", "minecraft:warm_ocean")::get); ++ ConverterAbstractStringValueTypeRename.register(VERSION, MCTypeRegistry.BIOME, ++ new HashMap<>( ++ Map.of("minecraft:deep_warm_ocean", "minecraft:warm_ocean") ++ )::get ++ ); + + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { + private static void moveOutOfBoundTicks(final ListType ticks, final MapType chunkRoot, final int chunkX, final int chunkZ, final String intoKey) { @@ -17500,8 +19576,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + return null; + }); -+ + } ++ ++ private V2843() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2846.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2846.java new file mode 100644 @@ -17514,18 +19591,23 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.advancements.ConverterAbstractAdvancementsRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V2846 { + -+ protected static final int VERSION = MCVersions.V21W44A + 1; ++ private static final int VERSION = MCVersions.V21W44A + 1; + + public static void register() { -+ ConverterAbstractAdvancementsRename.register(VERSION, ImmutableMap.of( -+ "minecraft:husbandry/play_jukebox_in_meadows", "minecraft:adventure/play_jukebox_in_meadows", -+ "minecraft:adventure/caves_and_cliff", "minecraft:adventure/fall_from_world_height", -+ "minecraft:adventure/ride_strider_in_overworld_lava", "minecraft:nether/ride_strider_in_overworld_lava" ++ ConverterAbstractAdvancementsRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:husbandry/play_jukebox_in_meadows", "minecraft:adventure/play_jukebox_in_meadows", ++ "minecraft:adventure/caves_and_cliff", "minecraft:adventure/fall_from_world_height", ++ "minecraft:adventure/ride_strider_in_overworld_lava", "minecraft:nether/ride_strider_in_overworld_lava" ++ ) + )::get); + } ++ ++ private V2846() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2852.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2852.java new file mode 100644 @@ -17542,7 +19624,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2852 { + -+ protected static final int VERSION = MCVersions.V1_18_PRE5 + 1; ++ private static final int VERSION = MCVersions.V1_18_PRE5 + 1; + + public static void register() { + MCTypeRegistry.WORLD_GEN_SETTINGS.addStructureConverter(new DataConverter<>(VERSION) { @@ -17561,6 +19643,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2852() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2967.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2967.java new file mode 100644 @@ -17577,7 +19661,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2967 { + -+ protected static final int VERSION = MCVersions.V22W05A; ++ private static final int VERSION = MCVersions.V22W05A; + + public static void register() { + MCTypeRegistry.WORLD_GEN_SETTINGS.addStructureConverter(new DataConverter<>(VERSION) { @@ -17623,6 +19707,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V2967() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2970.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V2970.java new file mode 100644 @@ -17638,10 +19724,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.MapType; +import ca.spottedleaf.dataconverter.types.ObjectType; -+import ca.spottedleaf.dataconverter.types.Types; +import com.google.common.collect.ImmutableMap; ++import com.mojang.logging.LogUtils; +import it.unimi.dsi.fastutil.objects.Object2IntMap; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; ++import org.slf4j.Logger; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; @@ -17650,7 +19737,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V2970 { + -+ protected static final int VERSION = MCVersions.V22W07A + 1; ++ private static final Logger LOGGER = LogUtils.getLogger(); ++ ++ private static final int VERSION = MCVersions.V22W07A + 1; + private static final Map CONVERSION_MAP = new HashMap<>( + ImmutableMap.builder() + .put("mineshaft", BiomeRemap.create(Map.of(List.of("minecraft:badlands", "minecraft:eroded_badlands", "minecraft:wooded_badlands"), "minecraft:mineshaft_mesa"), "minecraft:mineshaft")) @@ -17711,7 +19800,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + id = id.toLowerCase(Locale.ROOT); + final BiomeRemap remap = CONVERSION_MAP.get(id); + if (remap == null) { -+ throw new IllegalArgumentException("Unknown structure " + id); ++ return null; + } + if (remap.biomeToNewStructure == null || biomeCount == null) { + return remap.dfl; @@ -17755,7 +19844,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + final MapType references = structures.getMap("References"); + + if (starts != null) { -+ final MapType newStarts = Types.NBT.createEmptyMap(); ++ final MapType newStarts = data.getTypeUtil().createEmptyMap(); + structures.setMap("starts", newStarts); + + for (final String key : starts.keys()) { @@ -17765,6 +19854,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + final String remapped = getStructureConverted(key, biomeCounts); ++ ++ if (remapped == null) { ++ LOGGER.warn("Encountered unknown structure in dataconverter: " + key); ++ continue; ++ } ++ + value.setString("id", remapped); + newStarts.setMap(remapped, value); + } @@ -17772,7 +19867,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + // This TRULY is a guess, no idea what biomes the referent has. + if (references != null) { -+ final MapType newReferences = Types.NBT.createEmptyMap(); ++ final MapType newReferences = data.getTypeUtil().createEmptyMap(); + structures.setMap("References", newReferences); + for (final String key : references.keys()) { + final long[] value = references.getLongs(key); @@ -17780,7 +19875,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + continue; + } + -+ newReferences.setLongs(getStructureConverted(key, biomeCounts), value); ++ final String newKey = getStructureConverted(key, biomeCounts); ++ if (newKey == null) { ++ LOGGER.warn("Encountered unknown structure reference in dataconverter: " + key); ++ continue; ++ } ++ ++ newReferences.setLongs(newKey, value); + } + } + @@ -17789,6 +19890,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + } + ++ private V2970() {} ++ + private static final class BiomeRemap { + + public final Map biomeToNewStructure; @@ -17839,7 +19942,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3077 { + -+ protected static final int VERSION = MCVersions.V1_18_2 + 102; ++ private static final int VERSION = MCVersions.V1_18_2 + 102; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new DataConverter<>(VERSION) { @@ -17865,6 +19968,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3077() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3078.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3078.java new file mode 100644 @@ -17881,10 +19986,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3078 { + -+ protected static final int VERSION = MCVersions.V1_18_2 + 103; ++ private static final int VERSION = MCVersions.V1_18_2 + 103; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -17892,6 +19997,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerMob("minecraft:tadpole"); + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:sculk_shrieker", new GameEventListenerWalker()); + } ++ ++ private V3078() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3081.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3081.java new file mode 100644 @@ -17904,20 +20011,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.minecraft.walkers.game_event.GameEventListenerWalker; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V3081 { + -+ protected static final int VERSION = MCVersions.V22W11A + 1; ++ private static final int VERSION = MCVersions.V22W11A + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:warden"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:warden", new GameEventListenerWalker()); + } ++ ++ private V3081() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3082.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3082.java new file mode 100644 @@ -17933,11 +20041,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3082 { + -+ protected static final int VERSION = MCVersions.V22W11A + 2; ++ private static final int VERSION = MCVersions.V22W11A + 2; + + public static void register() { + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:chest_boat", new DataWalkerItemLists("Items")); + } ++ ++ private V3082() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3083.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3083.java new file mode 100644 @@ -17954,16 +20064,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3083 { + -+ protected static final int VERSION = MCVersions.V22W12A + 1; ++ private static final int VERSION = MCVersions.V22W12A + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:allay"); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:allay", new DataWalkerItemLists("Inventory")); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:allay", new GameEventListenerWalker()); + } ++ ++ private V3083() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3084.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3084.java new file mode 100644 @@ -17983,25 +20096,26 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3084 { + -+ protected static final int VERSION = MCVersions.V22W12A + 2; ++ private static final int VERSION = MCVersions.V22W12A + 2; + -+ protected static final Map GAME_EVENT_RENAMES = new HashMap<>(ImmutableMap.builder() -+ .put("minecraft:block_press", "minecraft:block_activate") -+ .put("minecraft:block_switch", "minecraft:block_activate") -+ .put("minecraft:block_unpress", "minecraft:block_deactivate") -+ .put("minecraft:block_unswitch", "minecraft:block_deactivate") -+ .put("minecraft:drinking_finish", "minecraft:drink") -+ .put("minecraft:elytra_free_fall", "minecraft:elytra_glide") -+ .put("minecraft:entity_damaged", "minecraft:entity_damage") -+ .put("minecraft:entity_dying", "minecraft:entity_die") -+ .put("minecraft:entity_killed", "minecraft:entity_die") -+ .put("minecraft:mob_interact", "minecraft:entity_interact") -+ .put("minecraft:ravager_roar", "minecraft:entity_roar") -+ .put("minecraft:ring_bell", "minecraft:block_change") -+ .put("minecraft:shulker_close", "minecraft:container_close") -+ .put("minecraft:shulker_open", "minecraft:container_open") -+ .put("minecraft:wolf_shaking", "minecraft:entity_shake") -+ .build() ++ private static final Map GAME_EVENT_RENAMES = new HashMap<>( ++ ImmutableMap.builder() ++ .put("minecraft:block_press", "minecraft:block_activate") ++ .put("minecraft:block_switch", "minecraft:block_activate") ++ .put("minecraft:block_unpress", "minecraft:block_deactivate") ++ .put("minecraft:block_unswitch", "minecraft:block_deactivate") ++ .put("minecraft:drinking_finish", "minecraft:drink") ++ .put("minecraft:elytra_free_fall", "minecraft:elytra_glide") ++ .put("minecraft:entity_damaged", "minecraft:entity_damage") ++ .put("minecraft:entity_dying", "minecraft:entity_die") ++ .put("minecraft:entity_killed", "minecraft:entity_die") ++ .put("minecraft:mob_interact", "minecraft:entity_interact") ++ .put("minecraft:ravager_roar", "minecraft:entity_roar") ++ .put("minecraft:ring_bell", "minecraft:block_change") ++ .put("minecraft:shulker_close", "minecraft:container_close") ++ .put("minecraft:shulker_open", "minecraft:container_open") ++ .put("minecraft:wolf_shaking", "minecraft:entity_shake") ++ .build() + ); + + public static void register() { @@ -18009,6 +20123,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return GAME_EVENT_RENAMES.get(NamespaceUtil.correctNamespace(name)); + }); + } ++ ++ private V3084() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3086.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3086.java new file mode 100644 @@ -18029,9 +20145,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3086 { + -+ protected static final int VERSION = MCVersions.V22W13A + 1; ++ private static final int VERSION = MCVersions.V22W13A + 1; + -+ protected static final Int2ObjectOpenHashMap CAT_ID_CONVERSION = new Int2ObjectOpenHashMap<>(); ++ private static final Int2ObjectOpenHashMap CAT_ID_CONVERSION = new Int2ObjectOpenHashMap<>(); + static { + CAT_ID_CONVERSION.defaultReturnValue("minecraft:tabby"); + CAT_ID_CONVERSION.put(0, "minecraft:tabby"); @@ -18047,25 +20163,28 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + CAT_ID_CONVERSION.put(10, "minecraft:all_black"); + } + -+ protected static final Map CAT_ADVANCEMENTS_CONVERSION = new HashMap<>(ImmutableMap.builder() -+ .put("textures/entity/cat/tabby.png", "minecraft:tabby") -+ .put("textures/entity/cat/black.png", "minecraft:black") -+ .put("textures/entity/cat/red.png", "minecraft:red") -+ .put("textures/entity/cat/siamese.png", "minecraft:siamese") -+ .put("textures/entity/cat/british_shorthair.png", "minecraft:british") -+ .put("textures/entity/cat/calico.png", "minecraft:calico") -+ .put("textures/entity/cat/persian.png", "minecraft:persian") -+ .put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll") -+ .put("textures/entity/cat/white.png", "minecraft:white") -+ .put("textures/entity/cat/jellie.png", "minecraft:jellie") -+ .put("textures/entity/cat/all_black.png", "minecraft:all_black") -+ .build() ++ private static final Map CAT_ADVANCEMENTS_CONVERSION = new HashMap<>( ++ ImmutableMap.builder() ++ .put("textures/entity/cat/tabby.png", "minecraft:tabby") ++ .put("textures/entity/cat/black.png", "minecraft:black") ++ .put("textures/entity/cat/red.png", "minecraft:red") ++ .put("textures/entity/cat/siamese.png", "minecraft:siamese") ++ .put("textures/entity/cat/british_shorthair.png", "minecraft:british") ++ .put("textures/entity/cat/calico.png", "minecraft:calico") ++ .put("textures/entity/cat/persian.png", "minecraft:persian") ++ .put("textures/entity/cat/ragdoll.png", "minecraft:ragdoll") ++ .put("textures/entity/cat/white.png", "minecraft:white") ++ .put("textures/entity/cat/jellie.png", "minecraft:jellie") ++ .put("textures/entity/cat/all_black.png", "minecraft:all_black") ++ .build() + ); + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:cat", new ConverterEntityToVariant(VERSION, "CatType", CAT_ID_CONVERSION::get)); + MCTypeRegistry.ADVANCEMENTS.addStructureConverter(new ConverterCriteriaRename(VERSION, "minecraft:husbandry/complete_catalogue", CAT_ADVANCEMENTS_CONVERSION::get)); + } ++ ++ private V3086() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3087.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3087.java new file mode 100644 @@ -18082,9 +20201,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3087 { + -+ protected static final int VERSION = MCVersions.V22W13A + 2; ++ private static final int VERSION = MCVersions.V22W13A + 2; + -+ protected static Int2ObjectOpenHashMap FROG_ID_CONVERSION = new Int2ObjectOpenHashMap<>(); ++ private static final Int2ObjectOpenHashMap FROG_ID_CONVERSION = new Int2ObjectOpenHashMap<>(); + static { + FROG_ID_CONVERSION.put(0, "minecraft:temperate"); + FROG_ID_CONVERSION.put(1, "minecraft:warm"); @@ -18094,6 +20213,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:frog", new ConverterEntityToVariant(VERSION, "Variant", FROG_ID_CONVERSION::get)); + } ++ ++ private V3087() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3088.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3088.java new file mode 100644 @@ -18118,11 +20239,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // players load the chunk - they went through a different conversion process, which ultimately creates two versions. + // Unfortunately this fix doesn't exactly resolve it, as anyone running Mojang's converters will now be different + // from DataConverter's. It's broadly a dumb situation all around that could be avoided if Mojang wasn't being careless here. -+ protected static final int VERSION = MCVersions.V22W14A; ++ private static final int VERSION = MCVersions.V22W14A; + + public static void register() { + MCTypeRegistry.CHUNK.addStructureConverter(new ConverterAddBlendingData(VERSION)); + } ++ ++ private V3088() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3090.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3090.java new file mode 100644 @@ -18140,7 +20263,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3090 { + -+ protected static final int VERSION = MCVersions.V22W15A + 1; ++ private static final int VERSION = MCVersions.V22W15A + 1; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:painting", new DataConverter<>(VERSION) { @@ -18152,6 +20275,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3090() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3093.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3093.java new file mode 100644 @@ -18168,7 +20293,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3093 { + -+ protected static final int VERSION = MCVersions.V22W17A; ++ private static final int VERSION = MCVersions.V22W17A; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:goat", new DataConverter<>(VERSION) { @@ -18180,6 +20305,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3093() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3094.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3094.java new file mode 100644 @@ -18196,7 +20323,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V3094 { + -+ public static final int VERSION = MCVersions.V22W17A + 1; ++ private static final int VERSION = MCVersions.V22W17A + 1; + + private static final String[] SOUND_VARIANT_TO_INSTRUMENT = new String[] { + "minecraft:ponder_goat_horn", @@ -18228,6 +20355,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3094() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3097.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3097.java new file mode 100644 @@ -18295,6 +20424,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ADVANCEMENTS.addStructureConverter(new ConverterCriteriaRename(VERSION, "minecraft:husbandry/complete_catalogue", britishRenamer::get)); + MCTypeRegistry.POI_CHUNK.addStructureConverter(new ConverterPoiDelete(VERSION, poiRemove::contains)); + } ++ ++ private V3097() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3108.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3108.java new file mode 100644 @@ -18328,6 +20459,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3108() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3201.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3201.java new file mode 100644 @@ -18367,6 +20500,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3201() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3203.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3203.java new file mode 100644 @@ -18385,12 +20520,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static final int VERSION = MCVersions.V1_19_2 + 83; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:camel"); + } ++ ++ private V3203() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3204.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3204.java new file mode 100644 @@ -18411,6 +20548,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void register() { + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:chiseled_bookshelf", new DataWalkerItemLists("Items")); + } ++ ++ private V3204() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3209.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3209.java new file mode 100644 @@ -18433,6 +20572,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // remapped this version + MCTypeRegistry.ITEM_STACK.addConverterForId("minecraft:pig_spawn_egg", new ConverterFlattenSpawnEgg(VERSION, 0)); + } ++ ++ private V3209() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3214.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3214.java new file mode 100644 @@ -18467,6 +20608,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3214() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3319.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3319.java new file mode 100644 @@ -18494,6 +20637,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3319() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3322.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3322.java new file mode 100644 @@ -18582,6 +20727,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3322() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3325.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3325.java new file mode 100644 @@ -18605,6 +20752,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:block_display", new DataWalkerTypePaths<>(MCTypeRegistry.BLOCK_STATE, "block_state")); + // text_display is a simple entity + } ++ ++ private V3325() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3326.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3326.java new file mode 100644 @@ -18623,12 +20772,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static final int VERSION = MCVersions.V23W06A; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:sniffer"); + } ++ ++ private V3326() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3327.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3327.java new file mode 100644 @@ -18652,6 +20803,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:decorated_pot", new DataWalkerItems("item")); + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:suspicious_sand", new DataWalkerItems("item")); + } ++ ++ private V3327() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3328.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3328.java new file mode 100644 @@ -18671,6 +20824,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void register() { + // registers simple entity "minecraft:interaction" + } ++ ++ private V3328() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3438.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3438.java new file mode 100644 @@ -18697,7 +20852,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public static void register() { + // brushable block rename -+ MCTypeRegistry.TILE_ENTITY.copyWalkers(VERSION,"minecraft:suspicious_sand", "minecraft:brushable_block"); ++ MCTypeRegistry.TILE_ENTITY.copyWalkers(VERSION, "minecraft:suspicious_sand", "minecraft:brushable_block"); + + ConverterAbstractTileEntityRename.register(VERSION, new HashMap<>(Map.of( + "minecraft:suspicious_sand", "minecraft:brushable_block" @@ -18722,6 +20877,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ) + )::get); + } ++ ++ private V3438() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3439.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3439.java new file mode 100644 @@ -18822,6 +20979,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:sign", signTileUpdater); + MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:hanging_sign", signTileUpdater); + } ++ ++ private V3439() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3440.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3440.java new file mode 100644 @@ -18855,6 +21014,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ) + ))); + } ++ ++ private V3440() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3441.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3441.java new file mode 100644 @@ -18876,6 +21037,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // See V3088 for why this converter is duplicated here and in V3088 + MCTypeRegistry.CHUNK.addStructureConverter(new ConverterAddBlendingData(VERSION)); + } ++ ++ private V3441() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3447.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3447.java new file mode 100644 @@ -18929,6 +21092,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + ConverterAbstractItemRename.register(VERSION, rename::get); + } ++ ++ private V3447() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3448.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3448.java new file mode 100644 @@ -18961,6 +21126,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3448() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3450.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3450.java new file mode 100644 @@ -18988,6 +21155,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ) + )::get)); + } ++ ++ private V3450() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3451.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3451.java new file mode 100644 @@ -19030,6 +21199,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3451() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3459.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3459.java new file mode 100644 @@ -19063,13 +21234,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + final MapType endData = dimensionData.getMap("1"); + if (endData != null) { -+ data.setMap("DragonFight", endData.getMap("DragonFight", endData.getTypeUtil().createEmptyMap()).copy()); ++ final MapType dragonFight = endData.getMap("DragonFight", endData.getTypeUtil().createEmptyMap()).copy(); ++ V3807.flattenBlockPos(dragonFight, "ExitPortalLocation"); ++ data.setMap("DragonFight", dragonFight); + } + + return null; + } + }); + } ++ ++ private V3459() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3564.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3564.java new file mode 100644 @@ -19167,6 +21342,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:sign", converter); + MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:hanging_sign", converter); + } ++ ++ private V3564() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3565.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3565.java new file mode 100644 @@ -19203,6 +21380,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3565() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3566.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3566.java new file mode 100644 @@ -19265,6 +21444,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + }); + } ++ ++ private V3566() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3568.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3568.java new file mode 100644 @@ -19514,6 +21695,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + MCTypeRegistry.ITEM_STACK.addStructureConverter(itemConverter); + } ++ ++ private V3568() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3682.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3682.java new file mode 100644 @@ -19534,6 +21717,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void register() { + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:crafter", new DataWalkerItemLists("Items")); + } ++ ++ private V3682() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3683.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3683.java new file mode 100644 @@ -19571,6 +21756,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:tnt", new DataWalkerTypePaths<>(MCTypeRegistry.BLOCK_STATE, "block_state")); + } ++ ++ private V3683() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3685.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3685.java new file mode 100644 @@ -19639,6 +21826,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerArrowEntity("minecraft:spectral_arrow"); + registerArrowEntity("minecraft:arrow"); + } ++ ++ private V3685() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3689.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3689.java new file mode 100644 @@ -19648,11 +21837,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 @@ -0,0 +0,0 @@ +package ca.spottedleaf.dataconverter.minecraft.versions; + -+import ca.spottedleaf.dataconverter.converters.datatypes.DataWalker; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.MapType; +import ca.spottedleaf.dataconverter.types.ObjectType; @@ -19662,12 +21849,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + private static final int VERSION = MCVersions.V23W44A + 1; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { + registerMob("minecraft:breeze"); + // minecraft:wind_charge is a simple entity ++ // minecraft:breeze_wind_charge is a simple entity + + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:trial_spawner", (final MapType data, final long fromVersion, final long toVersion) -> { + final ListType spawnPotentials = data.getList("spawn_potentials", ObjectType.MAP); @@ -19677,11 +21865,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ WalkerUtils.convert(MCTypeRegistry.ENTITY, data, "spawn_data", fromVersion, toVersion); ++ WalkerUtils.convert(MCTypeRegistry.ENTITY, data.getMap("spawn_data"), "entity", fromVersion, toVersion); + return null; + }); + } + ++ private V3689() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3692.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3692.java new file mode 100644 @@ -19708,9 +21897,1210 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ); + + public static void register() { -+ ConverterAbstractBlockRename.registerAndFixJigsaw(VERSION, GRASS_RENAME::get); ++ ConverterAbstractBlockRename.register(VERSION, GRASS_RENAME::get); + ConverterAbstractItemRename.register(VERSION, GRASS_RENAME::get); + } ++ ++ private V3692() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3799.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3799.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3799.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++ ++public final class V3799 { ++ ++ private static final int VERSION = MCVersions.V1_20_4 + 99; ++ ++ public static void register() { ++ V100.registerEquipment(VERSION, "minecraft:armadillo"); ++ } ++ ++ private V3799() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3800.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3800.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3800.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; ++import java.util.HashMap; ++import java.util.Map; ++ ++public final class V3800 { ++ ++ private static final int VERSION = MCVersions.V1_20_4 + 100; ++ ++ public static void register() { ++ final Map renames = new HashMap<>( ++ Map.of( ++ "minecraft:scute", "minecraft:turtle_scute" ++ ) ++ ); ++ ++ ConverterAbstractItemRename.register(VERSION, renames::get); ++ } ++ ++ private V3800() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3803.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3803.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3803.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.converters.itemstack.ConverterEnchantmentsRename; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import java.util.HashMap; ++import java.util.Map; ++ ++public final class V3803 { ++ ++ private static final int VERSION = MCVersions.V23W51B + 1; ++ ++ public static void register() { ++ final Map renames = new HashMap<>( ++ Map.of( ++ "minecraft:sweeping", "minecraft:sweeping_edge" ++ ) ++ ); ++ ++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new ConverterEnchantmentsRename(VERSION, renames::get)); ++ } ++ ++ private V3803() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3807.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3807.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3807.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++ ++public final class V3807 { ++ ++ private static final int VERSION = MCVersions.V24W04A + 1; ++ ++ public static void flattenBlockPos(final MapType data, final String path) { ++ if (data == null) { ++ return; ++ } ++ ++ final MapType pos = data.getMap(path); ++ if (pos == null) { ++ return; ++ } ++ ++ final Number x = pos.getNumber("X"); ++ final Number y = pos.getNumber("Y"); ++ final Number z = pos.getNumber("Z"); ++ ++ if (x == null || y == null || z == null) { ++ return; ++ } ++ ++ data.setInts(path, new int[] { x.intValue(), y.intValue(), z.intValue() }); ++ } ++ ++ public static void register() { ++ // Step 0 ++ MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:vault", (final MapType root, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, root.getMap("config"), "key_item", fromVersion, toVersion); ++ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, root.getMap("server_data"), "items_to_eject", fromVersion, toVersion); ++ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, root.getMap("shared_data"), "display_item", fromVersion, toVersion); ++ ++ return null; ++ }); ++ ++ // Step 1 ++ MCTypeRegistry.SAVED_DATA_MAP_DATA.addStructureConverter(new DataConverter<>(VERSION, 1) { ++ @Override ++ public MapType convert(final MapType root, final long sourceVersion, final long toVersion) { ++ final MapType data = root.getMap("data"); ++ ++ if (data == null) { ++ return null; ++ } ++ ++ final ListType banners = data.getList("banners", ObjectType.MAP); ++ ++ if (banners == null) { ++ return null; ++ } ++ ++ for (int i = 0, len = banners.size(); i < len; ++i) { ++ V3807.flattenBlockPos(banners.getMap(i), "Pos"); ++ } ++ ++ return null; ++ } ++ }); ++ } ++ ++ private V3807() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3808.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3808.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3808.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; ++import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItems; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++ ++public final class V3808 { ++ ++ private static final int VERSION = MCVersions.V24W04A + 2; ++ ++ public static void register() { ++ class BodyArmorConverter extends DataConverter, MapType> { ++ private final String path; ++ private final boolean clearArmor; ++ ++ public BodyArmorConverter(final int toVersion, final String path, final boolean clearArmor) { ++ this(toVersion, 0, path, clearArmor); ++ } ++ ++ public BodyArmorConverter(final int toVersion, final int versionStep, final String path, final boolean clearArmor) { ++ super(toVersion, versionStep); ++ ++ this.path = path; ++ this.clearArmor = clearArmor; ++ } ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType prev = data.getMap(this.path); ++ ++ if (prev == null) { ++ return null; ++ } ++ ++ data.remove(this.path); ++ ++ data.setMap("body_armor_item", prev); ++ data.setFloat("body_armor_drop_chance", 2.0F); ++ ++ if (this.clearArmor) { ++ final ListType armor = data.getList("ArmorItems", ObjectType.MAP); ++ if (armor.size() > 2) { ++ armor.setMap(2, data.getTypeUtil().createEmptyMap()); ++ } ++ ++ final ListType chances = data.getList("ArmorDropChances", ObjectType.FLOAT); ++ if (chances.size() > 2) { ++ chances.setFloat(2, 0.085F); ++ } ++ } ++ ++ return null; ++ } ++ } ++ ++ // Step 0 ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:horse", new BodyArmorConverter(VERSION, "ArmorItem", true)); ++ ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:horse", new DataWalkerItems("SaddleItem")); ++ V100.registerEquipment(VERSION, "minecraft:horse"); ++ ++ // Step 1 ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:llama", new BodyArmorConverter(VERSION, 1, "DecorItem", false)); ++ ++ MCTypeRegistry.ENTITY.addWalker(VERSION, 1, "minecraft:llama", new DataWalkerItemLists("Items")); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, 1, "minecraft:llama", new DataWalkerItems("SaddleItem")); ++ V100.registerEquipment(VERSION, 1, "minecraft:llama"); ++ } ++ ++ private V3808() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3809.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3809.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3809.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++ ++public final class V3809 { ++ ++ private static final int VERSION = MCVersions.V24W05A; ++ ++ public static void register() { ++ final DataConverter, MapType> slotConverter = new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final ListType items = data.getList("Items", ObjectType.MAP); ++ if (items == null) { ++ return null; ++ } ++ ++ for (int i = 0, len = items.size(); i < len; ++i) { ++ final MapType item = items.getMap(i); ++ ++ final int slot = item.getInt("Slot", 2); ++ item.setByte("Slot", (byte)(slot - 2)); ++ } ++ ++ return null; ++ } ++ }; ++ ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:llama", slotConverter); ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:mule", slotConverter); ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:donkey", slotConverter); ++ } ++ ++ private V3809() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3812.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3812.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3812.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++import ca.spottedleaf.dataconverter.util.NamespaceUtil; ++ ++public final class V3812 { ++ ++ private static final int VERSION = MCVersions.V24W05B + 1; ++ ++ public static void register() { ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:wolf", new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ boolean doubleHealth = false; ++ ++ final ListType attributes = data.getList("Attributes", ObjectType.MAP); ++ if (attributes != null) { ++ for (int i = 0, len = attributes.size(); i < len; ++i) { ++ final MapType attribute = attributes.getMap(i); ++ ++ if (!"minecraft:generic.max_health".equals(NamespaceUtil.correctNamespace(attribute.getString("Name")))) { ++ continue; ++ } ++ ++ final double base = attribute.getDouble("Base", 0.0D); ++ if (base == 20.0D) { ++ attribute.setDouble("Base", 40.0D); ++ doubleHealth = true; ++ } ++ } ++ } ++ ++ if (doubleHealth) { ++ data.setFloat("Health", data.getFloat("Health", 0.0F) * 2.0F); ++ } ++ ++ return null; ++ } ++ }); ++ } ++ ++ private V3812() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3813.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3813.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3813.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++ ++public final class V3813 { ++ ++ private static final int VERSION = MCVersions.V24W05B + 2; ++ ++ private static final String[] PATROLLING_MOBS = new String[] { ++ "minecraft:witch", ++ "minecraft:ravager", ++ "minecraft:pillager", ++ "minecraft:illusioner", ++ "minecraft:evoker", ++ "minecraft:vindicator" ++ }; ++ ++ public static void register() { ++ class RootPositionConverter extends DataConverter, MapType> { ++ private final RenamePair[] convert; ++ ++ public RootPositionConverter(final int toVersion, final RenamePair[] convert) { ++ this(toVersion, 0, convert); ++ } ++ ++ public RootPositionConverter(final int toVersion, final int versionStep, final RenamePair[] convert) { ++ super(toVersion, versionStep); ++ this.convert = convert; ++ } ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ for (final RenamePair rename : this.convert) { ++ V3807.flattenBlockPos(data, rename.from); ++ RenameHelper.renameSingle(data, rename.from, rename.to); ++ } ++ return null; ++ } ++ } ++ ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:bee", new RootPositionConverter(VERSION, new RenamePair[] { ++ new RenamePair("HivePos", "hive_pos"), ++ new RenamePair("FlowerPos", "flower_pos") ++ })); ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:end_crystal", new RootPositionConverter(VERSION, new RenamePair[] { ++ new RenamePair("BeamTarget", "beam_target"), ++ })); ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:wandering_trader", new RootPositionConverter(VERSION, new RenamePair[] { ++ new RenamePair("WanderTarget", "wander_target"), ++ })); ++ ++ final RootPositionConverter patrolConverter = new RootPositionConverter(VERSION, new RenamePair[] { ++ new RenamePair("PatrolTarget", "patrol_target"), ++ }); ++ for (final String id : PATROLLING_MOBS) { ++ MCTypeRegistry.ENTITY.addConverterForId(id, patrolConverter); ++ } ++ ++ MCTypeRegistry.ENTITY.addStructureConverter(new RootPositionConverter(VERSION, new RenamePair[] { ++ new RenamePair("Leash", "leash"), ++ })); ++ ++ ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:beehive", new RootPositionConverter(VERSION, new RenamePair[] { ++ new RenamePair("FlowerPos", "flower_pos"), ++ })); ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:end_gateway", new RootPositionConverter(VERSION, new RenamePair[] { ++ new RenamePair("ExitPortal", "exit_portal"), ++ })); ++ ++ MCTypeRegistry.SAVED_DATA_MAP_DATA.addStructureConverter(new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType root, final long sourceVersion, final long toVersion) { ++ final MapType data = root.getMap("data"); ++ ++ if (data == null) { ++ return null; ++ } ++ ++ final ListType frames = data.getList("frames", ObjectType.MAP); ++ if (frames != null) { ++ for (int i = 0, len = frames.size(); i < len; ++i) { ++ final MapType frame = frames.getMap(i); ++ ++ V3807.flattenBlockPos(frame, "Pos"); ++ ++ RenameHelper.renameSingle(frame, "Pos", "pos"); ++ RenameHelper.renameSingle(frame, "Rotation", "rotation"); ++ RenameHelper.renameSingle(frame, "EntityId", "entity_id"); ++ } ++ } ++ ++ final ListType banners = data.getList("banners", ObjectType.MAP); ++ for (int i = 0, len = banners.size(); i < len; ++i) { ++ final MapType banner = banners.getMap(i); ++ ++ RenameHelper.renameSingle(banner, "Pos", "pos"); ++ RenameHelper.renameSingle(banner, "Color", "color"); ++ RenameHelper.renameSingle(banner, "Name", "name"); ++ } ++ ++ return null; ++ } ++ }); ++ ++ MCTypeRegistry.ITEM_STACK.addConverterForId("minecraft:compass", new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType tag = data.getMap("tag"); ++ ++ if (tag == null) { ++ return null; ++ } ++ ++ V3807.flattenBlockPos(tag, "LodestonePos"); ++ ++ return null; ++ } ++ }); ++ } ++ ++ private V3813() {} ++ ++ private static record RenamePair(String from, String to) {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3814.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3814.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3814.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.converters.attributes.ConverterAbstractAttributesRename; ++import java.util.HashMap; ++import java.util.Map; ++ ++public final class V3814 { ++ ++ private static final int VERSION = MCVersions.V24W05B + 3; ++ ++ public static void register() { ++ final Map renames = new HashMap<>( ++ Map.of("minecraft:horse.jump_strength", "minecraft:generic.jump_strength") ++ ); ++ ++ ConverterAbstractAttributesRename.register(VERSION, renames::get); ++ } ++ ++ private V3814() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3816.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3816.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3816.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++ ++public final class V3816 { ++ ++ private static final int VERSION = MCVersions.V24W06A + 1; ++ ++ public static void register() { ++ V100.registerEquipment(VERSION, "minecraft:bogged"); ++ } ++ ++ private V3816() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3818.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3818.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3818.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.converters.datatypes.DataWalker; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.converters.custom.V3818_Commands; ++import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper; ++import ca.spottedleaf.dataconverter.minecraft.converters.itemstack.ConverterItemStackToDataComponents; ++import ca.spottedleaf.dataconverter.minecraft.converters.particle.ConverterParticleToNBT; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++import ca.spottedleaf.dataconverter.types.Types; ++import java.util.HashMap; ++import java.util.Map; ++ ++public final class V3818 { ++ ++ private static final int VERSION = MCVersions.V24W07A + 1; ++ ++ private static final String[] BANNER_COLOURS = new String[] { ++ "white", ++ "orange", ++ "magenta", ++ "light_blue", ++ "yellow", ++ "lime", ++ "pink", ++ "gray", ++ "light_gray", ++ "cyan", ++ "purple", ++ "blue", ++ "brown", ++ "green", ++ "red", ++ "black", ++ }; ++ ++ public static String getBannerColour(final int id) { ++ return id >= 0 && id < BANNER_COLOURS.length ? BANNER_COLOURS[id] : BANNER_COLOURS[0]; ++ } ++ ++ public static void register() { ++ // Step 0 ++ // Note: No breakpoint needed, nothing nests hotbar ++ MCTypeRegistry.HOTBAR.addStructureConverter(new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ for (final String key : data.keys()) { ++ final ListType itemList = data.getList(key, ObjectType.MAP); ++ if (itemList != null) { ++ for (int i = 0, len = itemList.size(); i < len; ++i) { ++ final MapType item = itemList.getMap(i); ++ ++ final String id = item.getString("id"); ++ final int count = item.getInt("Count"); ++ ++ if ("minecraft:air".equals(id) || count <= 0) { ++ itemList.setMap(i, item.getTypeUtil().createEmptyMap()); ++ } ++ } ++ } ++ } ++ ++ return null; ++ } ++ }); ++ ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:beehive", new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ RenameHelper.renameSingle(data, "Bees", "bees"); ++ ++ final ListType bees = data.getList("bees", ObjectType.MAP); ++ if (bees != null) { ++ for (int i = 0, len = bees.size(); i < len; ++i) { ++ final MapType bee = bees.getMap(i); ++ ++ RenameHelper.renameSingle(bee, "EntityData", "entity_data"); ++ RenameHelper.renameSingle(bee, "TicksInHive", "ticks_in_hive"); ++ RenameHelper.renameSingle(bee, "MinOccupationTicks", "min_ticks_in_hive"); ++ } ++ } ++ ++ return null; ++ } ++ }); ++ MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:beehive", (final MapType root, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convertListPath(MCTypeRegistry.ENTITY, root, "bees", "entity_data", fromVersion, toVersion); ++ ++ return null; ++ }); ++ ++ // Step 1 ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:banner", new DataConverter<>(VERSION, 1) { ++ private static final Map PATTERN_UPDATE = new HashMap<>(); ++ static { ++ PATTERN_UPDATE.put("b", "minecraft:base"); ++ PATTERN_UPDATE.put("bl", "minecraft:square_bottom_left"); ++ PATTERN_UPDATE.put("br", "minecraft:square_bottom_right"); ++ PATTERN_UPDATE.put("tl", "minecraft:square_top_left"); ++ PATTERN_UPDATE.put("tr", "minecraft:square_top_right"); ++ PATTERN_UPDATE.put("bs", "minecraft:stripe_bottom"); ++ PATTERN_UPDATE.put("ts", "minecraft:stripe_top"); ++ PATTERN_UPDATE.put("ls", "minecraft:stripe_left"); ++ PATTERN_UPDATE.put("rs", "minecraft:stripe_right"); ++ PATTERN_UPDATE.put("cs", "minecraft:stripe_center"); ++ PATTERN_UPDATE.put("ms", "minecraft:stripe_middle"); ++ PATTERN_UPDATE.put("drs", "minecraft:stripe_downright"); ++ PATTERN_UPDATE.put("dls", "minecraft:stripe_downleft"); ++ PATTERN_UPDATE.put("ss", "minecraft:small_stripes"); ++ PATTERN_UPDATE.put("cr", "minecraft:cross"); ++ PATTERN_UPDATE.put("sc", "minecraft:straight_cross"); ++ PATTERN_UPDATE.put("bt", "minecraft:triangle_bottom"); ++ PATTERN_UPDATE.put("tt", "minecraft:triangle_top"); ++ PATTERN_UPDATE.put("bts", "minecraft:triangles_bottom"); ++ PATTERN_UPDATE.put("tts", "minecraft:triangles_top"); ++ PATTERN_UPDATE.put("ld", "minecraft:diagonal_left"); ++ PATTERN_UPDATE.put("rd", "minecraft:diagonal_up_right"); ++ PATTERN_UPDATE.put("lud", "minecraft:diagonal_up_left"); ++ PATTERN_UPDATE.put("rud", "minecraft:diagonal_right"); ++ PATTERN_UPDATE.put("mc", "minecraft:circle"); ++ PATTERN_UPDATE.put("mr", "minecraft:rhombus"); ++ PATTERN_UPDATE.put("vh", "minecraft:half_vertical"); ++ PATTERN_UPDATE.put("hh", "minecraft:half_horizontal"); ++ PATTERN_UPDATE.put("vhr", "minecraft:half_vertical_right"); ++ PATTERN_UPDATE.put("hhb", "minecraft:half_horizontal_bottom"); ++ PATTERN_UPDATE.put("bo", "minecraft:border"); ++ PATTERN_UPDATE.put("cbo", "minecraft:curly_border"); ++ PATTERN_UPDATE.put("gra", "minecraft:gradient"); ++ PATTERN_UPDATE.put("gru", "minecraft:gradient_up"); ++ PATTERN_UPDATE.put("bri", "minecraft:bricks"); ++ PATTERN_UPDATE.put("glb", "minecraft:globe"); ++ PATTERN_UPDATE.put("cre", "minecraft:creeper"); ++ PATTERN_UPDATE.put("sku", "minecraft:skull"); ++ PATTERN_UPDATE.put("flo", "minecraft:flower"); ++ PATTERN_UPDATE.put("moj", "minecraft:mojang"); ++ PATTERN_UPDATE.put("pig", "minecraft:piglin"); ++ } ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final ListType patterns = data.getList("Patterns", ObjectType.MAP); ++ if (patterns != null) { ++ for (int i = 0, len = patterns.size(); i < len; ++i) { ++ final MapType pattern = patterns.getMap(i); ++ ++ final String patternName = pattern.getString("Pattern"); ++ if (patternName != null) { ++ final String renamed = PATTERN_UPDATE.get(patternName); ++ if (renamed != null) { ++ pattern.setString("Pattern", renamed); ++ } ++ } ++ RenameHelper.renameSingle(pattern, "Pattern", "pattern"); ++ ++ final String newColour = getBannerColour(pattern.getInt("Color")); ++ pattern.setString("Color", newColour); ++ RenameHelper.renameSingle(pattern, "Color", "color"); ++ } ++ } ++ RenameHelper.renameSingle(data, "Patterns", "patterns"); ++ ++ return null; ++ } ++ }); ++ ++ // Step 2 ++ // Note: there is nothing after the previous breakpoint (1.19.4) that reads nested entity item ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:arrow", new DataConverter<>(VERSION, 2) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final Object potion = data.getGeneric("Potion"); ++ final Object customPotionEffects = data.getGeneric("custom_potion_effects"); ++ final Object color = data.getGeneric("Color"); ++ ++ if (potion == null && customPotionEffects == null && color == null) { ++ return null; ++ } ++ ++ data.remove("Potion"); ++ data.remove("custom_potion_effects"); ++ data.remove("Color"); ++ ++ final MapType item = data.getMap("item"); ++ if (item == null) { ++ return null; ++ } ++ ++ final MapType tag = item.getOrCreateMap("tag"); ++ ++ if (potion != null) { ++ tag.setGeneric("Potion", potion); ++ } ++ if (customPotionEffects != null) { ++ tag.setGeneric("custom_potion_effects", customPotionEffects); ++ } ++ if (color != null) { ++ tag.setGeneric("CustomPotionColor", color); ++ } ++ ++ return null; ++ } ++ }); ++ ++ // Step 3 ++ MCTypeRegistry.DATA_COMPONENTS.addStructureWalker(VERSION, new DataWalker<>() { ++ private static void walkBlockPredicates(final MapType root, final long fromVersion, final long toVersion) { ++ if (root.hasKey("blocks", ObjectType.STRING)) { ++ WalkerUtils.convert(MCTypeRegistry.BLOCK_NAME, root, "blocks", fromVersion, toVersion); ++ } else if (root.hasKey("blocks", ObjectType.LIST)) { ++ WalkerUtils.convertList(MCTypeRegistry.BLOCK_NAME, root, "blocks", fromVersion, toVersion); ++ } ++ } ++ ++ @Override ++ public MapType walk(final MapType root, final long fromVersion, final long toVersion) { ++ WalkerUtils.convertListPath(MCTypeRegistry.ENTITY, root, "minecraft:bees", "entity_data", fromVersion, toVersion); ++ ++ WalkerUtils.convert(MCTypeRegistry.TILE_ENTITY, root, "minecraft:block_entity_data", fromVersion, toVersion); ++ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, root, "minecraft:bundle_contents", fromVersion, toVersion); ++ ++ final MapType canBreak = root.getMap("minecraft:can_break"); ++ if (canBreak != null) { ++ final ListType predicates = canBreak.getList("predicates", ObjectType.MAP); ++ if (predicates != null) { ++ for (int i = 0, len = predicates.size(); i < len; ++i) { ++ walkBlockPredicates(predicates.getMap(i), fromVersion, toVersion); ++ } ++ } ++ // Not handled by DFU: simple encoding does not require "predicates" ++ walkBlockPredicates(canBreak, fromVersion, toVersion); ++ } ++ ++ final MapType canPlaceOn = root.getMap("minecraft:can_break"); ++ if (canPlaceOn != null) { ++ final ListType predicates = canPlaceOn.getList("predicates", ObjectType.MAP); ++ if (predicates != null) { ++ for (int i = 0, len = predicates.size(); i < len; ++i) { ++ walkBlockPredicates(predicates.getMap(i), fromVersion, toVersion); ++ } ++ } ++ // Not handled by DFU: simple encoding does not require "predicates" ++ walkBlockPredicates(canPlaceOn, fromVersion, toVersion); ++ } ++ ++ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, root, "minecraft:charged_projectiles", fromVersion, toVersion); ++ WalkerUtils.convertListPath(MCTypeRegistry.ITEM_STACK, root, "minecraft:container", "item", fromVersion, toVersion); ++ WalkerUtils.convert(MCTypeRegistry.ENTITY, root, "minecraft:entity_data", fromVersion, toVersion); ++ WalkerUtils.convertList(MCTypeRegistry.ITEM_NAME, root, "minecraft:pot_decorations", fromVersion, toVersion); ++ ++ return null; ++ } ++ }); ++ ++ // Step 4 ++ MCTypeRegistry.PARTICLE.addStructureConverter(new DataConverter<>(VERSION, 4) { ++ @Override ++ public MapType convert(final Object input, final long sourceVersion, final long toVersion) { ++ if (!(input instanceof String flat)) { ++ return null; ++ } ++ ++ return ConverterParticleToNBT.convert(flat, Types.NBT); ++ } ++ }); ++ ++ MCTypeRegistry.PARTICLE.addStructureWalker(VERSION, 4, (final Object input, final long fromVersion, final long toVersion) -> { ++ if (!(input instanceof MapType)) { ++ return null; ++ } ++ ++ final MapType root = (MapType)input; ++ ++ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, root, "item", fromVersion, toVersion); ++ WalkerUtils.convert(MCTypeRegistry.BLOCK_STATE, root, "block_state", fromVersion, toVersion); ++ ++ return null; ++ }); ++ ++ // Step 5 ++ // Note: needs breakpoint, reads nested tile entity data ++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION, 5) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ return ConverterItemStackToDataComponents.convertItem(data); ++ } ++ }); ++ ++ MCTypeRegistry.ITEM_STACK.addStructureWalker(VERSION, 5, (final MapType root, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convert(MCTypeRegistry.ITEM_NAME, root, "id", fromVersion, toVersion); ++ WalkerUtils.convert(MCTypeRegistry.DATA_COMPONENTS, root, "components", fromVersion, toVersion); ++ ++ return null; ++ }); ++ ++ // Custom converter for converting commands inside signs, books, command blocks ++ V3818_Commands.register_5(); ++ ++ // Step 6 ++ MCTypeRegistry.ENTITY.addConverterForId("minecraft:area_effect_cloud", new DataConverter<>(VERSION, 6) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final Object color = data.getGeneric("Color"); ++ final Object effects = data.getGeneric("effects"); ++ final Object potion = data.getGeneric("Potion"); ++ ++ if (color == null && effects == null && potion == null) { ++ return null; ++ } ++ data.remove("Color"); ++ data.remove("effects"); ++ data.remove("Potion"); ++ ++ final MapType potionContents = data.getTypeUtil().createEmptyMap(); ++ data.setMap("potion_contents", potionContents); ++ ++ if (color != null) { ++ potionContents.setGeneric("custom_color", color); ++ } ++ ++ if (effects != null) { ++ potionContents.setGeneric("custom_effects", effects); ++ } ++ ++ if (potion != null) { ++ potionContents.setGeneric("potion", potion); ++ } ++ ++ return null; ++ } ++ }); ++ } ++ ++ private V3818() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3820.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3820.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3820.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.converters.helpers.RenameHelper; ++import ca.spottedleaf.dataconverter.minecraft.converters.itemstack.ConverterItemStackToDataComponents; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.MapType; ++ ++public final class V3820 { ++ ++ private static final int VERSION = MCVersions.V24W09A + 1; ++ ++ public static void register() { ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:skull", new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final Object skullOwner = data.getGeneric("SkullOwner"); ++ final Object extraType = data.getGeneric("ExtraType"); ++ ++ if (skullOwner == null && extraType == null) { ++ return null; ++ } ++ ++ data.remove("SkullOwner"); ++ data.remove("ExtraType"); ++ ++ data.setMap( ++ "profile", ++ ConverterItemStackToDataComponents.convertProfile( ++ skullOwner == null ? extraType : skullOwner, data.getTypeUtil() ++ ) ++ ); ++ ++ return null; ++ } ++ }); ++ // I don't see why this converter is necessary, V3818 should have converted correctly... ++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType components = data.getMap("components"); ++ ++ if (components == null) { ++ return null; ++ } ++ ++ final MapType oldTarget = components.getMap("minecraft:lodestone_target"); ++ if (oldTarget == null) { ++ return null; ++ } ++ ++ components.remove("minecraft:lodestone_target"); ++ components.setMap("minecraft:lodestone_tracker", oldTarget); ++ ++ final Object pos = oldTarget.getMap("pos"); ++ final Object dim = oldTarget.getMap("dimension"); ++ ++ if (pos == null && dim == null) { ++ return null; ++ } ++ ++ oldTarget.remove("pos"); ++ oldTarget.remove("dimension"); ++ ++ final MapType target = oldTarget.getTypeUtil().createEmptyMap(); ++ oldTarget.setMap("target", target); ++ ++ target.setGeneric("pos", pos); ++ target.setGeneric("dimension", dim); ++ ++ return null; ++ } ++ }); ++ } ++ ++ private V3820() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3825.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3825.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3825.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.minecraft.util.ComponentUtils; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; ++import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItems; ++import ca.spottedleaf.dataconverter.types.ListType; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.types.ObjectType; ++import java.util.Arrays; ++import java.util.HashSet; ++import java.util.Set; ++ ++public final class V3825 { ++ ++ private static final int VERSION = MCVersions.V24W12A + 1; ++ ++ private static final Set BANNER_NAMES = new HashSet<>( ++ Arrays.asList( ++ "block.minecraft.ominous_banner" ++ ) ++ ); ++ private static final Set MAP_NAMES = new HashSet<>( ++ Arrays.asList( ++ "filled_map.buried_treasure", ++ "filled_map.explorer_jungle", ++ "filled_map.explorer_swamp", ++ "filled_map.mansion", ++ "filled_map.monument", ++ "filled_map.trial_chambers", ++ "filled_map.village_desert", ++ "filled_map.village_plains", ++ "filled_map.village_savanna", ++ "filled_map.village_snowy", ++ "filled_map.village_taiga" ++ ) ++ ); ++ ++ public static void register() { ++ MCTypeRegistry.ITEM_STACK.addStructureConverter(new DataConverter<>(VERSION) { ++ private static void convertName(final MapType components, final Set standardNames) { ++ final String customName = components.getString("minecraft:custom_name"); ++ if (customName == null) { ++ return; ++ } ++ ++ final String translation = ComponentUtils.retrieveTranslationString(customName); ++ if (translation == null) { ++ return; ++ } ++ ++ if (standardNames.contains(translation)) { ++ components.remove("minecraft:custom_name"); ++ components.setString("minecraft:item_name", customName); ++ } ++ } ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType components = data.getMap("components"); ++ if (components == null) { ++ return null; ++ } ++ ++ final String id = data.getString("id"); ++ if (id == null) { ++ return null; ++ } ++ ++ switch (id) { ++ case "minecraft:white_banner": { ++ convertName(components, BANNER_NAMES); ++ break; ++ } ++ case "minecraft:filled_map": { ++ convertName(components, MAP_NAMES); ++ break; ++ } ++ } ++ ++ return null; ++ } ++ }); ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:banner", new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final String customName = data.getString("CustomName"); ++ if (customName == null || !"block.minecraft.ominous_banner".equals(ComponentUtils.retrieveTranslationString(customName))) { ++ return null; ++ } ++ ++ data.remove("CustomName"); ++ ++ final MapType components = data.getOrCreateMap("components"); ++ ++ components.setString("minecraft:item_name", customName); ++ components.setMap("minecraft:hide_additional_tooltip", components.getTypeUtil().createEmptyMap()); ++ ++ return null; ++ } ++ }); ++ // DFU does not change the schema, even though it moves spawn_potentials ++ MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:trial_spawner", (final MapType data, final long fromVersion, final long toVersion) -> { ++ final MapType normalConfig = data.getMap("normal_config"); ++ if (normalConfig != null) { ++ WalkerUtils.convertListPath(MCTypeRegistry.ENTITY, normalConfig, "spawn_potentials", "data", "entity", fromVersion, toVersion); ++ } ++ final MapType ominousConfig = data.getMap("ominous_config"); ++ if (ominousConfig != null) { ++ WalkerUtils.convertListPath(MCTypeRegistry.ENTITY, normalConfig, "spawn_potentials", "data", "entity", fromVersion, toVersion); ++ } ++ ++ WalkerUtils.convert(MCTypeRegistry.ENTITY, data.getMap("spawn_data"), "entity", fromVersion, toVersion); ++ return null; ++ }); ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:trial_spawner", new DataConverter<>(VERSION) { ++ private static final String[] NORMAL_CONFIG_KEYS = new String[] { ++ "spawn_range", ++ "total_mobs", ++ "simultaneous_mobs", ++ "total_mobs_added_per_player", ++ "simultaneous_mobs_added_per_player", ++ "ticks_between_spawn", ++ "spawn_potentials", ++ "loot_tables_to_eject", ++ "items_to_drop_when_ominous" ++ }; ++ ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType normalConfig = data.getTypeUtil().createEmptyMap(); ++ ++ for (final String normalKey : NORMAL_CONFIG_KEYS) { ++ final Object normalValue = data.getGeneric(normalKey); ++ if (normalValue != null) { ++ data.remove(normalKey); ++ normalConfig.setGeneric(normalKey, normalValue); ++ } ++ } ++ ++ if (!normalConfig.isEmpty()) { ++ data.setMap("normal_config", normalConfig); ++ } ++ ++ return null; ++ } ++ }); ++ ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:ominous_item_spawner", new DataWalkerItems("item")); ++ } ++ ++ private V3825() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3828.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3828.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3828.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.util.NamespaceUtil; ++ ++public final class V3828 { ++ ++ private static final int VERSION = MCVersions.V24W14A + 1; ++ ++ public static void register() { ++ MCTypeRegistry.VILLAGER_TRADE.addStructureConverter(new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType buyB = data.getMap("buyB"); ++ ++ if (buyB == null) { ++ return null; ++ } ++ ++ final String id = NamespaceUtil.correctNamespace(buyB.getString("id", "minecraft:air")); ++ final int count = buyB.getInt("count", 0); ++ ++ // Fix DFU: use count <= 0 instead of count == 0 ++ if ("minecraft:air".equals(id) || count <= 0) { ++ data.remove("buyB"); ++ } ++ ++ return null; ++ } ++ }); ++ } ++ ++ private V3828() {} ++} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3833.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3833.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V3833.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.minecraft.versions; ++ ++import ca.spottedleaf.dataconverter.converters.DataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.util.NamespaceUtil; ++ ++public final class V3833 { ++ ++ private static final int VERSION = MCVersions.V1_20_5_PRE4 + 1; ++ ++ public static void register() { ++ MCTypeRegistry.TILE_ENTITY.addConverterForId("minecraft:brushable_block", new DataConverter<>(VERSION) { ++ @Override ++ public MapType convert(final MapType data, final long sourceVersion, final long toVersion) { ++ final MapType item = data.getMap("item"); ++ if (item == null) { ++ return null; ++ } ++ ++ ++ final String id = NamespaceUtil.correctNamespace(item.getString("id", "minecraft:air")); ++ final int count = item.getInt("count", 0); ++ ++ // Fix DFU: use count <= 0 instead of count == 0 ++ if ("minecraft:air".equals(id) || count <= 0) { ++ data.remove("item"); ++ } ++ ++ return null; ++ } ++ }); ++ } ++ ++ private V3833() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V501.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V501.java new file mode 100644 @@ -19721,15 +23111,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +package ca.spottedleaf.dataconverter.minecraft.versions; + +import ca.spottedleaf.dataconverter.minecraft.MCVersions; -+import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; + +public final class V501 { + -+ protected static final int VERSION = MCVersions.V16W20A; ++ private static final int VERSION = MCVersions.V16W20A; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -19737,7 +23125,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V501() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V502.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V502.java new file mode 100644 @@ -19756,7 +23143,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V502 { + -+ protected static final int VERSION = MCVersions.V16W20A + 1; ++ private static final int VERSION = MCVersions.V16W20A + 1; + + public static void register() { + ConverterAbstractItemRename.register(VERSION, (final String name) -> { @@ -19789,7 +23176,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V502() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V505.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V505.java new file mode 100644 @@ -19806,7 +23192,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V505 { + -+ protected static final int VERSION = MCVersions.V16W21B + 1; ++ private static final int VERSION = MCVersions.V16W21B + 1; + + public static void register() { + MCTypeRegistry.OPTIONS.addStructureConverter(new DataConverter<>(VERSION) { @@ -19819,7 +23205,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V505() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V700.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V700.java new file mode 100644 @@ -19832,15 +23217,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.types.MapType; + +public final class V700 { + -+ protected static final int VERSION = MCVersions.V1_10_2 + 188; ++ private static final int VERSION = MCVersions.V1_10_2 + 188; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -19871,15 +23255,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.types.MapType; + +public final class V701 { + -+ protected static final int VERSION = MCVersions.V1_10_2 + 189; ++ private static final int VERSION = MCVersions.V1_10_2 + 189; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -19907,7 +23290,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V701() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V702.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V702.java new file mode 100644 @@ -19920,15 +23302,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.DataConverter; +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; -+import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; +import ca.spottedleaf.dataconverter.types.MapType; + +public final class V702 { + -+ protected static final int VERSION = MCVersions.V1_10_2 + 190; ++ private static final int VERSION = MCVersions.V1_10_2 + 190; + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + public static void register() { @@ -19962,11 +23344,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + + registerMob("ZombieVillager"); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "ZombieVillager", (final MapType root, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convertList(MCTypeRegistry.VILLAGER_TRADE, root.getMap("Offers"), "Recipes", fromVersion, toVersion); ++ return null; ++ }); + registerMob( "Husk"); + } + + private V702() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V703.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V703.java new file mode 100644 @@ -19985,7 +23370,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V703 { + -+ protected static final int VERSION = MCVersions.V1_10_2 + 191; ++ private static final int VERSION = MCVersions.V1_10_2 + 191; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("EntityHorse", new DataConverter<>(VERSION) { @@ -20022,23 +23407,24 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + + MCTypeRegistry.ENTITY.addWalker(VERSION, "Horse", new DataWalkerItems("ArmorItem", "SaddleItem")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "Horse", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, "Horse"); + + MCTypeRegistry.ENTITY.addWalker(VERSION, "Donkey", new DataWalkerItems("SaddleItem")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "Donkey", new DataWalkerItemLists("Items", "ArmorItems", "HandItems")); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "Donkey", new DataWalkerItemLists("Items")); ++ V100.registerEquipment(VERSION, "Donkey"); + + MCTypeRegistry.ENTITY.addWalker(VERSION, "Mule", new DataWalkerItems("SaddleItem")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "Mule", new DataWalkerItemLists("Items", "ArmorItems", "HandItems")); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "Mule", new DataWalkerItemLists("Items")); ++ V100.registerEquipment(VERSION, "Mule"); + + MCTypeRegistry.ENTITY.addWalker(VERSION, "ZombieHorse", new DataWalkerItems("SaddleItem")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "ZombieHorse", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, "ZombieHorse"); + + MCTypeRegistry.ENTITY.addWalker(VERSION, "SkeletonHorse", new DataWalkerItems("SaddleItem")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "SkeletonHorse", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, "SkeletonHorse"); + } + + private V703() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V704.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V704.java new file mode 100644 @@ -20052,12 +23438,14 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; +import ca.spottedleaf.dataconverter.minecraft.hooks.DataHookEnforceNamespacedID; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.DataWalkerTypePaths; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.minecraft.walkers.item_name.DataWalkerItemNames; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItems; +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; +import ca.spottedleaf.dataconverter.types.ObjectType; +import ca.spottedleaf.dataconverter.types.MapType; ++import ca.spottedleaf.dataconverter.util.Long2ObjectArraySortedMap; +import com.mojang.logging.LogUtils; +import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; @@ -20075,7 +23463,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final Logger LOGGER = LogUtils.getLogger(); + -+ protected static final int VERSION = MCVersions.V1_10_2 + 192; ++ private static final int VERSION = MCVersions.V1_10_2 + 192; + + public static final Map ITEM_ID_TO_TILE_ENTITY_ID = new HashMap<>() { + @Override @@ -20202,7 +23590,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:decorated_pot", "minecraft:decorated_pot"); + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:crafter", "minecraft:crafter"); + -+ // These are missing from Vanilla (TODO check on update) ++ // These are missing from Vanilla up to 1.20.5 + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:enchanting_table", "minecraft:enchanting_table"); + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:comparator", "minecraft:comparator"); + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:light_gray_bed", "minecraft:bed"); @@ -20230,11 +23618,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:suspicious_gravel", "minecraft:brushable_block"); + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:calibrated_sculk_sensor", "minecraft:calibrated_sculk_sensor"); + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:trial_spawner", "minecraft:trial_spawner"); ++ ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:vault", "minecraft:vault"); + } + + // This class is responsible for also integrity checking the item id to tile id map here, we just use the item registry to figure it out -+ -+ static { ++ // No longer need to do this, as items now use components in 1.20.5 ++ /*static { + for (final Item item : BuiltInRegistries.ITEM) { + if (!(item instanceof BlockItem)) { + continue; @@ -20271,9 +23660,59 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + } ++ }*/ ++ ++ private static Long2ObjectArraySortedMap makeSingle(final long k1, final String v1) { ++ final Long2ObjectArraySortedMap ret = new Long2ObjectArraySortedMap<>(); ++ ++ ret.put(k1, v1); ++ ++ return ret; + } + -+ protected static final Map TILE_ID_UPDATE = new HashMap<>(); ++ private static Long2ObjectArraySortedMap makeDouble(final long k1, final String v1, ++ final long k2, final String v2) { ++ final Long2ObjectArraySortedMap ret = new Long2ObjectArraySortedMap<>(); ++ ++ ret.put(k1, v1); ++ ret.put(k2, v2); ++ ++ return ret; ++ } ++ ++ private static final Map> ITEM_ID_TO_ENTITY_ID = new HashMap<>(); ++ static { ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:armor_stand", makeDouble(V99.VERSION, "ArmorStand", V705.VERSION, "minecraft:armor_stand")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:painting", makeDouble(V99.VERSION, "Painting", V705.VERSION, "minecraft:painting")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:boat", makeDouble(V99.VERSION, "Boat", V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:oak_boat", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:oak_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:spruce_boat",makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:spruce_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:birch_boat", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:birch_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:jungle_boat", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:jungle_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:acacia_boat", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:acacia_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:cherry_boat", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:cherry_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:dark_oak_boat", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:dark_oak_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:mangrove_boat", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:mangrove_chest_boat", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:bamboo_raft", makeSingle(V705.VERSION, "minecraft:boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:bamboo_chest_raft", makeSingle(V705.VERSION, "minecraft:chest_boat")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:minecart", makeDouble(V99.VERSION, "MinecartRideable", V705.VERSION, "minecraft:minecart")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:chest_minecart", makeDouble(V99.VERSION, "MinecartChest", V705.VERSION, "minecraft:chest_minecart")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:furnace_minecart", makeDouble(V99.VERSION, "MinecartFurnace", V705.VERSION, "minecraft:furnace_minecart")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:tnt_minecart", makeDouble(V99.VERSION, "MinecartTNT", V705.VERSION, "minecraft:tnt_minecart")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:hopper_minecart", makeDouble(V99.VERSION, "MinecartHopper", V705.VERSION, "minecraft:hopper_minecart")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:item_frame", makeDouble(V99.VERSION, "ItemFrame", V705.VERSION, "minecraft:item_frame")); ++ ITEM_ID_TO_ENTITY_ID.put("minecraft:glow_item_frame", makeSingle(V705.VERSION, "minecraft:glow_item_frame")); ++ } ++ ++ private static final Map TILE_ID_UPDATE = new HashMap<>(); + static { + TILE_ID_UPDATE.put("Airportal", "minecraft:end_portal"); + TILE_ID_UPDATE.put("Banner", "minecraft:banner"); @@ -20300,7 +23739,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + TILE_ID_UPDATE.put("Trap", "minecraft:dispenser"); + } + -+ protected static void registerInventory(final String id) { ++ private static void registerInventory(final String id) { + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("Items")); + } + @@ -20319,7 +23758,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + + -+ ++ MCTypeRegistry.TILE_ENTITY.addStructureWalker(VERSION, (final MapType data, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convert(MCTypeRegistry.DATA_COMPONENTS, data, "components", fromVersion, toVersion); ++ return null; ++ }); + registerInventory( "minecraft:furnace"); + registerInventory( "minecraft:chest"); + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:jukebox", new DataWalkerItems("RecordItem")); @@ -20332,6 +23774,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerInventory("minecraft:brewing_stand"); + registerInventory("minecraft:hopper"); + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "minecraft:flower_pot", new DataWalkerItemNames("Item")); ++ MCTypeRegistry.TILE_ENTITY.addWalker( ++ VERSION, "minecraft:command_block", ++ new DataWalkerTypePaths<>(MCTypeRegistry.DATACONVERTER_CUSTOM_TYPE_COMMAND, "Command") ++ ); + + MCTypeRegistry.ITEM_STACK.addStructureWalker(VERSION, (final MapType data, final long fromVersion, final long toVersion) -> { + WalkerUtils.convert(MCTypeRegistry.ITEM_NAME, data, "id", fromVersion, toVersion); @@ -20344,43 +23790,29 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // only things here are in tag, if changed update if above + + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, tag, "Items", fromVersion, toVersion); ++ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, tag, "ChargedProjectiles", fromVersion, toVersion); + + MapType entityTag = tag.getMap("EntityTag"); + if (entityTag != null) { + final String itemId = data.getString("id"); + final String entityId; -+ if ("minecraft:armor_stand".equals(itemId)) { -+ // The check for version id is changed here. For whatever reason, the legacy -+ // data converters used entity id "minecraft:armor_stand" when version was greater-than 514, -+ // but entity ids were not namespaced until V705! So somebody fucked up the legacy converters. -+ // DFU agrees with my analysis here, it will only set the entityId here to the namespaced variant -+ // with the V705 schema. -+ entityId = DataConverter.getVersion(fromVersion) < 705 ? "ArmorStand" : "minecraft:armor_stand"; -+ } else if (itemId != null && itemId.contains("_spawn_egg")) { ++ if (itemId != null && itemId.contains("_spawn_egg")) { + // V1451 changes spawn eggs to have the sub entity id be a part of the item id, but of course Mojang never + // bothered to write in logic to set the sub entity id, so we have to. + // format is ALWAYS :_spawn_egg post flattening + entityId = itemId.substring(0, itemId.indexOf("_spawn_egg")); -+ } else if ("minecraft:item_frame".equals(itemId)) { -+ // add missing item_frame entity id -+ // version check is same for armorstand, as both were namespaced at the same time -+ entityId = DataConverter.getVersion(fromVersion) < 705 ? "ItemFrame" : "minecraft:item_frame"; -+ } else if ("minecraft:glow_item_frame".equals(itemId)) { -+ // add missing glow_item_frame entity id -+ entityId = "minecraft:glow_item_frame"; + } else { -+ entityId = entityTag.getString("id"); ++ final Long2ObjectArraySortedMap mappingByVersion = ITEM_ID_TO_ENTITY_ID.get(itemId); ++ final String mapped = mappingByVersion == null ? null : mappingByVersion.getFloor(fromVersion); ++ entityId = mapped == null ? entityTag.getString("id") : mapped; + } + -+ final boolean removeId; + if (entityId == null) { + if (!"minecraft:air".equals(itemId)) { + LOGGER.warn("Unable to resolve Entity for ItemStack (V704): " + itemId); + } -+ removeId = false; + } else { -+ removeId = !entityTag.hasKey("id", ObjectType.STRING); -+ if (removeId) { ++ if (!entityTag.hasKey("id", ObjectType.STRING)) { + entityTag.setString("id", entityId); + } + } @@ -20391,9 +23823,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + entityTag = replace; + tag.setMap("EntityTag", entityTag); + } -+ if (removeId) { -+ entityTag.remove("id"); -+ } + } + + MapType blockEntityTag = tag.getMap("BlockEntityTag"); @@ -20406,25 +23835,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } else { + entityId = ITEM_ID_TO_TILE_ENTITY_ID.get(itemId); + } -+ final boolean removeId; ++ + if (entityId == null) { + if (!"minecraft:air".equals(itemId)) { + LOGGER.warn("Unable to resolve BlockEntity for ItemStack (V704): " + itemId); + } -+ removeId = false; + } else { -+ removeId = !blockEntityTag.hasKey("id", ObjectType.STRING); -+ if (removeId) { ++ if (!blockEntityTag.hasKey("id", ObjectType.STRING)) { + blockEntityTag.setString("id", entityId); + } + } + final MapType replace = MCTypeRegistry.TILE_ENTITY.convert(blockEntityTag, fromVersion, toVersion); + if (replace != null) { + blockEntityTag = replace; -+ tag.setMap("BlockEntityTag", entityTag); -+ } -+ if (removeId) { -+ blockEntityTag.remove("id"); ++ tag.setMap("BlockEntityTag", blockEntityTag); + } + } + @@ -20454,25 +23878,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.hooks.DataHookEnforceNamespacedID; +import ca.spottedleaf.dataconverter.minecraft.hooks.DataHookValueTypeEnforceNamespaced; +import ca.spottedleaf.dataconverter.minecraft.walkers.block_name.DataWalkerBlockNames; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.DataWalkerTypePaths; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItems; +import ca.spottedleaf.dataconverter.minecraft.walkers.tile_entity.DataWalkerTileEntities; +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; -+import ca.spottedleaf.dataconverter.types.ObjectType; -+import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.MapType; -+import com.mojang.logging.LogUtils; -+import org.slf4j.Logger; +import java.util.HashMap; +import java.util.Map; + +public final class V705 { + -+ private static final Logger LOGGER = LogUtils.getLogger(); ++ public static final int VERSION = MCVersions.V1_10_2 + 193; + -+ protected static final int VERSION = MCVersions.V1_10_2 + 193; -+ -+ protected static final Map ENTITY_ID_UPDATE = new HashMap<>(); ++ private static final Map ENTITY_ID_UPDATE = new HashMap<>(); + static { + ENTITY_ID_UPDATE.put("AreaEffectCloud", "minecraft:area_effect_cloud"); + ENTITY_ID_UPDATE.put("ArmorStand", "minecraft:armor_stand"); @@ -20552,7 +23971,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private static void registerMob(final String id) { -+ MCTypeRegistry.ENTITY.addWalker(VERSION, id, new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, id); + } + + private static void registerThrowableProjectile(final String id) { @@ -20562,6 +23981,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + public static void register() { + ConverterAbstractEntityRename.register(VERSION, ENTITY_ID_UPDATE::get); + ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:area_effect_cloud", new DataWalkerTypePaths<>(MCTypeRegistry.PARTICLE, "Particle")); + registerMob("minecraft:armor_stand"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:arrow", new DataWalkerBlockNames("inTile")); + registerMob("minecraft:bat"); @@ -20573,12 +23993,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:commandblock_minecart", new DataWalkerBlockNames("DisplayTile")); + registerMob("minecraft:cow"); + registerMob("minecraft:creeper"); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:donkey", new DataWalkerItemLists("Items", "ArmorItems", "HandItems")); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:donkey", new DataWalkerItemLists("Items")); ++ V100.registerEquipment(VERSION, "minecraft:donkey"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:donkey", new DataWalkerItems("SaddleItem")); + registerThrowableProjectile("minecraft:egg"); + registerMob("minecraft:elder_guardian"); + registerMob("minecraft:ender_dragon"); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:enderman", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, "minecraft:enderman"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:enderman", new DataWalkerBlockNames("carried")); + registerMob("minecraft:endermite"); + registerThrowableProjectile("minecraft:ender_pearl"); @@ -20593,14 +24014,15 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:hopper_minecart", new DataWalkerBlockNames("DisplayTile")); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:hopper_minecart", new DataWalkerItemLists("Items")); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:horse", new DataWalkerItems("ArmorItem", "SaddleItem")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:horse", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, "minecraft:horse"); + registerMob("minecraft:husk"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:item", new DataWalkerItems("Item")); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:item_frame", new DataWalkerItems("Item")); + registerMob("minecraft:magma_cube"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:minecart", new DataWalkerBlockNames("DisplayTile")); + registerMob("minecraft:mooshroom"); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:mule", new DataWalkerItemLists("Items", "ArmorItems", "HandItems")); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:mule", new DataWalkerItemLists("Items")); ++ V100.registerEquipment(VERSION, "minecraft:mule"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:mule", new DataWalkerItems("SaddleItem")); + registerMob("minecraft:ocelot"); + registerMob("minecraft:pig"); @@ -20612,7 +24034,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerMob("minecraft:shulker"); + registerMob("minecraft:silverfish"); + registerMob("minecraft:skeleton"); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:skeleton_horse", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, "minecraft:skeleton_horse"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:skeleton_horse", new DataWalkerItems("SaddleItem")); + registerMob("minecraft:slime"); + registerThrowableProjectile("minecraft:small_fireball"); @@ -20631,24 +24053,11 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:villager", (final MapType data, final long fromVersion, final long toVersion) -> { + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "Inventory", fromVersion, toVersion); + -+ final MapType offers = data.getMap("Offers"); -+ if (offers != null) { -+ final ListType recipes = offers.getList("Recipes", ObjectType.MAP); -+ if (recipes != null) { -+ for (int i = 0, len = recipes.size(); i < len; ++i) { -+ final MapType recipe = recipes.getMap(i); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buy", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buyB", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "sell", fromVersion, toVersion); -+ } -+ } -+ } -+ -+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "ArmorItems", fromVersion, toVersion); -+ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, data, "HandItems", fromVersion, toVersion); ++ WalkerUtils.convertList(MCTypeRegistry.VILLAGER_TRADE, data.getMap("Offers"), "Recipes", fromVersion, toVersion); + + return null; + }); ++ V100.registerEquipment(VERSION, "minecraft:villager"); + registerMob("minecraft:villager_golem"); + registerMob("minecraft:witch"); + registerMob("minecraft:wither"); @@ -20658,11 +24067,17 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerThrowableProjectile("minecraft:xp_bottle"); + registerMob("minecraft:zombie"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:zombie_horse", new DataWalkerItems("SaddleItem")); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:zombie_horse", new DataWalkerItemLists("ArmorItems", "HandItems")); ++ V100.registerEquipment(VERSION, "minecraft:zombie_horse"); + registerMob("minecraft:zombie_pigman"); + registerMob("minecraft:zombie_villager"); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:zombie_villager", (final MapType data, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convertList(MCTypeRegistry.VILLAGER_TRADE, data.getMap("Offers"), "Recipes", fromVersion, toVersion); ++ ++ return null; ++ }); + registerMob("minecraft:evocation_illager"); -+ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:llama", new DataWalkerItemLists("Items", "ArmorItems", "HandItems")); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:llama", new DataWalkerItemLists("Items")); ++ V100.registerEquipment(VERSION, "minecraft:llama"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "minecraft:llama", new DataWalkerItems("SaddleItem", "DecorItem")); + registerMob("minecraft:vex"); + registerMob("minecraft:vindication_illager"); @@ -20675,7 +24090,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V705() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V804.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V804.java new file mode 100644 @@ -20694,7 +24108,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V804 { + -+ protected static final int VERSION = MCVersions.V16W35A + 1; ++ private static final int VERSION = MCVersions.V16W35A + 1; + + public static void register() { + MCTypeRegistry.ITEM_STACK.addConverterForId("minecraft:banner", new DataConverter<>(VERSION) { @@ -20741,7 +24155,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V804() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V806.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V806.java new file mode 100644 @@ -20760,7 +24173,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V806 { + -+ protected static final int VERSION = MCVersions.V16W36A + 1; ++ private static final int VERSION = MCVersions.V16W36A + 1; + + public static void register() { + final DataConverter, MapType> potionWaterUpdater = new DataConverter<>(VERSION) { @@ -20787,7 +24200,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V806() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V808.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V808.java new file mode 100644 @@ -20806,7 +24218,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V808 { + -+ protected static final int VERSION = MCVersions.V16W38A + 1; ++ private static final int VERSION = MCVersions.V16W38A + 1; + + public static void register() { + MCTypeRegistry.ENTITY.addConverterForId("minecraft:shulker", new DataConverter<>(VERSION, 1) { @@ -20823,7 +24235,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V808() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V813.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V813.java new file mode 100644 @@ -20840,9 +24251,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V813 { + -+ protected static final int VERSION = MCVersions.V16W40A; ++ private static final int VERSION = MCVersions.V16W40A; + -+ public static final String[] SHULKER_ID_BY_COLOUR = new String[] { ++ private static final String[] SHULKER_ID_BY_COLOUR = new String[] { + "minecraft:white_shulker_box", + "minecraft:orange_shulker_box", + "minecraft:magenta_shulker_box", @@ -20911,7 +24322,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + +public final class V816 { + -+ protected static final int VERSION = MCVersions.V16W43A; ++ private static final int VERSION = MCVersions.V16W43A; + + public static void register() { + MCTypeRegistry.OPTIONS.addStructureConverter(new DataConverter<>(VERSION) { @@ -20927,7 +24338,6 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + private V816() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V820.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V820.java new file mode 100644 @@ -20940,19 +24350,21 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.MCVersions; +import ca.spottedleaf.dataconverter.minecraft.converters.itemname.ConverterAbstractItemRename; +import com.google.common.collect.ImmutableMap; ++import java.util.HashMap; + +public final class V820 { + -+ protected static final int VERSION = MCVersions.V1_11 + 1; ++ private static final int VERSION = MCVersions.V1_11 + 1; + + public static void register() { -+ ConverterAbstractItemRename.register(VERSION, ImmutableMap.of( -+ "minecraft:totem", "minecraft:totem_of_undying" ++ ConverterAbstractItemRename.register(VERSION, new HashMap<>( ++ ImmutableMap.of( ++ "minecraft:totem", "minecraft:totem_of_undying" ++ ) + )::get); + } + + private V820() {} -+ +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V99.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/versions/V99.java new file mode 100644 @@ -20968,6 +24380,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.hooks.DataHookEnforceNamespacedID; +import ca.spottedleaf.dataconverter.minecraft.hooks.DataHookValueTypeEnforceNamespaced; +import ca.spottedleaf.dataconverter.minecraft.walkers.block_name.DataWalkerBlockNames; ++import ca.spottedleaf.dataconverter.minecraft.walkers.generic.DataWalkerTypePaths; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItemLists; +import ca.spottedleaf.dataconverter.minecraft.walkers.item_name.DataWalkerItemNames; +import ca.spottedleaf.dataconverter.minecraft.walkers.itemstack.DataWalkerItems; @@ -20987,10 +24400,9 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + private static final Logger LOGGER = LogUtils.getLogger(); + -+ protected static final int VERSION = MCVersions.V15W32A - 1; -+ -+ protected static final Map ITEM_ID_TO_TILE_ENTITY_ID = new HashMap<>(); ++ public static final int VERSION = MCVersions.V15W32A - 1; + ++ private static final Map ITEM_ID_TO_TILE_ENTITY_ID = new HashMap<>(); + static { + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:furnace", "Furnace"); + ITEM_ID_TO_TILE_ENTITY_ID.put("minecraft:lit_furnace", "Furnace"); @@ -21123,25 +24535,19 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + registerMob("Rabbit"); + MCTypeRegistry.ENTITY.addWalker(VERSION, "Villager", new DataWalkerItemLists("Inventory", "Equipment")); + MCTypeRegistry.ENTITY.addWalker(VERSION, "Villager", (final MapType data, final long fromVersion, final long toVersion) -> { -+ final MapType offers = data.getMap("Offers"); -+ if (offers != null) { -+ final ListType recipes = offers.getList("Recipes", ObjectType.MAP); -+ if (recipes != null) { -+ for (int i = 0; i < recipes.size(); ++i) { -+ final MapType recipe = recipes.getMap(i); -+ -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buy", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "buyB", fromVersion, toVersion); -+ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, recipe, "sell", fromVersion, toVersion); -+ } -+ } -+ } ++ WalkerUtils.convertList(MCTypeRegistry.VILLAGER_TRADE, data.getMap("Offers"), "Recipes", fromVersion, toVersion); + + return null; + }); + registerMob("Shulker"); ++ MCTypeRegistry.ENTITY.addWalker(VERSION, "AreaEffectCloud", new DataWalkerTypePaths<>(MCTypeRegistry.PARTICLE, "Particle")); + + // tile entities ++ MCTypeRegistry.TILE_ENTITY.addStructureWalker(VERSION, (final MapType data, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convert(MCTypeRegistry.DATA_COMPONENTS, data, "components", fromVersion, toVersion); ++ ++ return null; ++ }); + + // Inventory -> new DataWalkerItemLists("Items") + registerInventory("Furnace"); @@ -21155,8 +24561,12 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + }); + registerInventory("Cauldron"); + registerInventory("Hopper"); -+ // Note: Vanilla does not properly handle this case, it will not convert int ids! ++ // Note: Vanilla does not properly handle this case for FlowerPot, it will not convert int ids! + MCTypeRegistry.TILE_ENTITY.addWalker(VERSION, "FlowerPot", new DataWalkerItemNames("Item")); ++ MCTypeRegistry.TILE_ENTITY.addWalker( ++ VERSION, "Control", ++ new DataWalkerTypePaths<>(MCTypeRegistry.DATACONVERTER_CUSTOM_TYPE_COMMAND, "Command") ++ ); + + // rest + @@ -21171,6 +24581,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // only things here are in tag, if changed update if above + + WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, tag, "Items", fromVersion, toVersion); ++ WalkerUtils.convertList(MCTypeRegistry.ITEM_STACK, tag, "ChargedProjectiles", fromVersion, toVersion); + + MapType entityTag = tag.getMap("EntityTag"); + if (entityTag != null) { @@ -21186,6 +24597,8 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } else if ("minecraft:item_frame".equals(itemId)) { + // add missing item_frame entity id + entityId = "ItemFrame"; ++ } else if ("minecraft:painting".equals(itemId)) { ++ entityId = "Painting"; + } else { + entityId = entityTag.getString("id"); + } @@ -21294,6 +24707,13 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return null; + }); + ++ MCTypeRegistry.VILLAGER_TRADE.addStructureWalker(VERSION, (final MapType root, final long fromVersion, final long toVersion) -> { ++ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, root, "buy", fromVersion, toVersion); ++ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, root, "buyB", fromVersion, toVersion); ++ WalkerUtils.convert(MCTypeRegistry.ITEM_STACK, root, "sell", fromVersion, toVersion); ++ ++ return null; ++ }); + + // Enforce namespacing for ids + MCTypeRegistry.BLOCK_NAME.addStructureHook(VERSION, new DataHookValueTypeEnforceNamespaced()); @@ -21303,7 +24723,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + // Entity is absent; the String form is not yet namespaced, unlike the above. + } + -+ protected static String getStringId(final Object id) { ++ private static String getStringId(final Object id) { + if (id instanceof String) { + return (String)id; + } else if (id instanceof Number) { @@ -21313,9 +24733,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + -+ private V99() { -+ throw new RuntimeException(); -+ } ++ private V99() {} +} diff --git a/src/main/java/ca/spottedleaf/dataconverter/minecraft/walkers/block_name/DataWalkerBlockNames.java b/src/main/java/ca/spottedleaf/dataconverter/minecraft/walkers/block_name/DataWalkerBlockNames.java new file mode 100644 @@ -21347,7 +24765,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.minecraft.walkers.generic.WalkerUtils; +import ca.spottedleaf.dataconverter.types.MapType; + -+public final class GameEventListenerWalker implements DataWalker { ++public final class GameEventListenerWalker implements DataWalker> { + + @Override + public MapType walk(final MapType data, final long fromVersion, final long toVersion) { @@ -21379,7 +24797,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.types.ListType; +import ca.spottedleaf.dataconverter.types.MapType; + -+public class DataWalkerListPaths implements DataWalker { ++public class DataWalkerListPaths implements DataWalker> { + + protected final DataType type; + protected final String[] paths; @@ -21422,7 +24840,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 +import ca.spottedleaf.dataconverter.converters.datatypes.DataWalker; +import ca.spottedleaf.dataconverter.types.MapType; + -+public class DataWalkerTypePaths implements DataWalker { ++public class DataWalkerTypePaths implements DataWalker> { + + protected final DataType type; + protected final String[] paths; @@ -21498,6 +24916,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + ++ public static void convertListPath(final MCDataType type, final MapType data, final String listPath, final String elementPath, ++ final long fromVersion, final long toVersion) { ++ if (data == null) { ++ return; ++ } ++ ++ final ListType list = data.getList(listPath, ObjectType.MAP); ++ if (list != null) { ++ for (int i = 0, len = list.size(); i < len; ++i) { ++ WalkerUtils.convert(type, list.getMap(i), elementPath, fromVersion, toVersion); ++ } ++ } ++ } ++ ++ public static void convertListPath(final MCDataType type, final MapType data, final String listPath, final String elementPath1, ++ final String elementPath2, final long fromVersion, final long toVersion) { ++ if (data == null) { ++ return; ++ } ++ ++ final ListType list = data.getList(listPath, ObjectType.MAP); ++ if (list != null) { ++ for (int i = 0, len = list.size(); i < len; ++i) { ++ WalkerUtils.convert(type, list.getMap(i).getMap(elementPath1), elementPath2, fromVersion, toVersion); ++ } ++ } ++ } ++ + public static void convert(final MCValueType type, final MapType data, final String path, final long fromVersion, final long toVersion) { + if (data == null) { + return; @@ -21537,6 +24983,34 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + } + ++ public static void convertListPath(final MCValueType type, final MapType data, final String listPath, final String elementPath, ++ final long fromVersion, final long toVersion) { ++ if (data == null) { ++ return; ++ } ++ ++ final ListType list = data.getList(listPath, ObjectType.MAP); ++ if (list != null) { ++ for (int i = 0, len = list.size(); i < len; ++i) { ++ WalkerUtils.convert(type, list.getMap(i), elementPath, fromVersion, toVersion); ++ } ++ } ++ } ++ ++ public static void convertListPath(final MCValueType type, final MapType data, final String listPath, final String elementPath1, ++ final String elementPath2, final long fromVersion, final long toVersion) { ++ if (data == null) { ++ return; ++ } ++ ++ final ListType list = data.getList(listPath, ObjectType.MAP); ++ if (list != null) { ++ for (int i = 0, len = list.size(); i < len; ++i) { ++ WalkerUtils.convert(type, list.getMap(i).getMap(elementPath1), elementPath2, fromVersion, toVersion); ++ } ++ } ++ } ++ + public static void convertKeys(final MCValueType type, final MapType data, final String path, final long fromVersion, final long toVersion) { + if (data == null) { + return; @@ -22104,6 +25578,10 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + + public String getString(final K key, final String dfl); + ++ public String getForcedString(final K key); ++ ++ public String getForcedString(final K key, final String dfl); ++ + public void setString(final K key, final String val); + + public default void setGeneric(final K key, final Object value) { @@ -23144,6 +26622,30 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override ++ public String getForcedString(final String key) { ++ return this.getForcedString(key, null); ++ } ++ ++ @Override ++ public String getForcedString(final String key, final String dfl) { ++ final JsonElement element = this.map.get(key); ++ if (element instanceof JsonPrimitive) { ++ final JsonPrimitive primitive = (JsonPrimitive)element; ++ if (primitive.isString()) { ++ return primitive.getAsString(); ++ } else if (primitive.isNumber()) { ++ return primitive.getAsString(); ++ } ++ ++ return primitive.toString(); ++ } else if (element != null) { ++ return element.toString(); ++ } ++ ++ return dfl; ++ } ++ ++ @Override + public void setString(final String key, final String val) { + this.map.addProperty(key, val); + } @@ -24147,6 +27649,20 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + } + + @Override ++ public String getForcedString(final String key) { ++ return this.getForcedString(key, null); ++ } ++ ++ @Override ++ public String getForcedString(final String key, final String dfl) { ++ final Tag tag = this.map.get(key); ++ if (tag != null) { ++ return tag.getAsString(); ++ } ++ return dfl; ++ } ++ ++ @Override + public void setString(final String key, final String val) { + this.map.putString(key, val); + } @@ -24175,6 +27691,447 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 + return new NBTMapType(); + } +} +diff --git a/src/main/java/ca/spottedleaf/dataconverter/util/CommandArgumentUpgrader.java b/src/main/java/ca/spottedleaf/dataconverter/util/CommandArgumentUpgrader.java +new file mode 100644 +index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 +--- /dev/null ++++ b/src/main/java/ca/spottedleaf/dataconverter/util/CommandArgumentUpgrader.java +@@ -0,0 +0,0 @@ ++package ca.spottedleaf.dataconverter.util; ++ ++import ca.spottedleaf.dataconverter.minecraft.MCDataConverter; ++import ca.spottedleaf.dataconverter.minecraft.MCVersions; ++import ca.spottedleaf.dataconverter.minecraft.converters.custom.V3818_Commands; ++import ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry; ++import com.google.gson.JsonElement; ++import com.google.gson.JsonParseException; ++import com.google.gson.internal.Streams; ++import com.google.gson.stream.JsonReader; ++import com.mojang.brigadier.CommandDispatcher; ++import com.mojang.brigadier.LiteralMessage; ++import com.mojang.brigadier.ParseResults; ++import com.mojang.brigadier.StringReader; ++import com.mojang.brigadier.arguments.ArgumentType; ++import com.mojang.brigadier.context.CommandContextBuilder; ++import com.mojang.brigadier.context.ParsedArgument; ++import com.mojang.brigadier.context.StringRange; ++import com.mojang.brigadier.exceptions.CommandSyntaxException; ++import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; ++import com.mojang.brigadier.tree.ArgumentCommandNode; ++import com.mojang.brigadier.tree.CommandNode; ++import com.mojang.brigadier.tree.LiteralCommandNode; ++import com.mojang.serialization.Lifecycle; ++import it.unimi.dsi.fastutil.Pair; ++import java.lang.reflect.Field; ++import java.util.ArrayList; ++import java.util.HashMap; ++import java.util.LinkedHashMap; ++import java.util.List; ++import java.util.Map; ++import java.util.Optional; ++import java.util.function.BiFunction; ++import java.util.function.Consumer; ++import java.util.function.Function; ++import java.util.stream.Stream; ++import net.minecraft.SharedConstants; ++import net.minecraft.Util; ++import net.minecraft.commands.CommandBuildContext; ++import net.minecraft.commands.CommandSource; ++import net.minecraft.commands.CommandSourceStack; ++import net.minecraft.commands.Commands; ++import net.minecraft.commands.arguments.ComponentArgument; ++import net.minecraft.commands.arguments.item.ItemArgument; ++import net.minecraft.core.Holder; ++import net.minecraft.core.HolderLookup; ++import net.minecraft.core.HolderSet; ++import net.minecraft.core.Registry; ++import net.minecraft.nbt.CompoundTag; ++import net.minecraft.nbt.Tag; ++import net.minecraft.nbt.TagParser; ++import net.minecraft.network.chat.CommonComponents; ++import net.minecraft.resources.ResourceKey; ++import net.minecraft.resources.ResourceLocation; ++import net.minecraft.server.commands.ExecuteCommand; ++import net.minecraft.server.commands.ReturnCommand; ++import net.minecraft.tags.TagKey; ++import net.minecraft.util.GsonHelper; ++import net.minecraft.world.phys.Vec2; ++import net.minecraft.world.phys.Vec3; ++import org.jetbrains.annotations.Nullable; ++ ++public final class CommandArgumentUpgrader { ++ private final CommandDispatcher dispatcher; ++ private final CommandBuildContext context; ++ private final CommandSourceStack source; ++ private final Map, BiFunction, CommandBuildContext, ArgumentType>> replacements; ++ ++ public static CommandArgumentUpgrader upgrader_1_20_4_to_1_20_5(final int functionPermissionLevel) { ++ return new CommandArgumentUpgrader(functionPermissionLevel, builder -> { ++ builder.registerReplacement(ItemArgument.class, (argument, ctx) -> new ItemParser_1_20_4()); ++ builder.registerReplacement(ComponentArgument.class, (argument, ctx) -> new ComponentParser_1_20_4()); ++ }); ++ } ++ ++ public CommandArgumentUpgrader( ++ final int functionPermissionLevel, ++ final Consumer consumer ++ ) { ++ this( ++ new Commands(Commands.CommandSelection.DEDICATED, makeDummyCommandBuildContext()).getDispatcher(), ++ functionPermissionLevel, ++ consumer ++ ); ++ } ++ ++ private CommandArgumentUpgrader( ++ final CommandDispatcher dispatcher, ++ final int functionPermissionLevel, ++ final Consumer consumer ++ ) { ++ final ReplacementsBuilder builder = new ReplacementsBuilder(); ++ consumer.accept(builder); ++ this.replacements = Map.copyOf(builder.replacements); ++ ++ final CommandBuildContext context = makeDummyCommandBuildContext(); ++ this.dispatcher = new CommandDispatcher<>(); ++ this.context = context; ++ final List> aliases = new ArrayList<>(); ++ for (final CommandNode child : dispatcher.getRoot().getChildren()) { ++ final CopyResult result = this.copyCommand(this.dispatcher.getRoot(), child, null); ++ if (result.replaced()) { ++ this.dispatcher.getRoot().addChild(result.root); ++ } ++ aliases.addAll(result.aliases); ++ } ++ aliases.forEach(redirectNode -> { ++ final CommandNode toNode = this.dispatcher.getRoot() ++ .getChild(redirectNode.getRedirect().getName()); ++ if (toNode != null) { ++ this.dispatcher.getRoot().addChild( ++ new LiteralCommandNode<>( ++ redirectNode.getName(), ++ null, ++ null, ++ toNode, ++ redirectNode.getRedirectModifier(), ++ redirectNode.isFork() ++ ) ++ ); ++ } ++ }); ++ ExecuteCommand.register(this.dispatcher, context); ++ ReturnCommand.register(this.dispatcher); ++ // This looks weird, but it's what vanilla does when loading functions for datapacks ++ this.source = new CommandSourceStack( ++ CommandSource.NULL, ++ Vec3.ZERO, ++ Vec2.ZERO, ++ null, ++ functionPermissionLevel, ++ "", ++ CommonComponents.EMPTY, ++ null, ++ null ++ ); ++ } ++ ++ public static final class ReplacementsBuilder { ++ private final Map, BiFunction, CommandBuildContext, ArgumentType>> replacements = ++ new HashMap<>(); ++ ++ private ReplacementsBuilder() { ++ } ++ ++ @SuppressWarnings({"unchecked", "rawtypes"}) ++ public > void registerReplacement( ++ final Class type, ++ final BiFunction> upgrader ++ ) { ++ this.replacements.put(type, (BiFunction) upgrader); ++ } ++ } ++ ++ public record UpgradedArgument(String upgraded) {} ++ ++ private static final class ItemParser_1_20_4 implements ArgumentType { ++ @Override ++ public UpgradedArgument parse(final StringReader reader) throws CommandSyntaxException { ++ final ResourceLocation id = ResourceLocation.read(reader); ++ ++ final CompoundTag itemNBT = new CompoundTag(); ++ itemNBT.putString("id", id.toString()); ++ itemNBT.putInt("Count", 1); ++ ++ if (reader.canRead() && reader.peek() == '{') { ++ itemNBT.put("tag", new TagParser(reader).readStruct()); ++ } ++ ++ final CompoundTag converted = MCDataConverter.convertTag( ++ MCTypeRegistry.ITEM_STACK, itemNBT, MCVersions.V1_20_4, SharedConstants.getCurrentVersion().getDataVersion().getVersion() ++ ); ++ ++ final String newId = converted.getString("id"); ++ ++ if (converted.contains("components", Tag.TAG_COMPOUND)) { ++ return new UpgradedArgument(newId + V3818_Commands.toCommandFormat(converted.getCompound("components"))); ++ } else { ++ return new UpgradedArgument(newId); ++ } ++ } ++ } ++ ++ private static final class ComponentParser_1_20_4 implements ArgumentType { ++ private static final Field JSON_READER_POS = Util.make(() -> { ++ try { ++ final Field field = JsonReader.class.getDeclaredField("pos"); ++ field.setAccessible(true); ++ return field; ++ } catch (final NoSuchFieldException var1) { ++ throw new IllegalStateException("Couldn't get field 'pos' for JsonReader", var1); ++ } ++ }); ++ ++ private static final Field JSON_READER_LINESTART = Util.make(() -> { ++ try { ++ final Field field = JsonReader.class.getDeclaredField("lineStart"); ++ field.setAccessible(true); ++ return field; ++ } catch (final NoSuchFieldException var1) { ++ throw new IllegalStateException("Couldn't get field 'lineStart' for JsonReader", var1); ++ } ++ }); ++ ++ @Override ++ public UpgradedArgument parse(final StringReader reader) throws CommandSyntaxException { ++ final JsonElement element; ++ try { ++ element = parseJson(reader); ++ } catch (final Exception e) { ++ throw new SimpleCommandExceptionType(new LiteralMessage(e.getMessage())).createWithContext(reader); ++ } ++ V3818_Commands.walkComponent(element); ++ return new UpgradedArgument(GsonHelper.toStableString(element)); ++ } ++ ++ public static JsonElement parseJson(final StringReader stringReader) { ++ final JsonReader jsonReader = new JsonReader(new java.io.StringReader(stringReader.getRemaining())); ++ jsonReader.setLenient(false); ++ ++ final JsonElement jsonElement; ++ try { ++ jsonElement = Streams.parse(jsonReader); ++ } catch (final StackOverflowError var9) { ++ throw new JsonParseException(var9); ++ } finally { ++ stringReader.setCursor(stringReader.getCursor() + getPos(jsonReader)); ++ } ++ return jsonElement; ++ } ++ ++ private static int getPos(final JsonReader jsonReader) { ++ try { ++ return JSON_READER_POS.getInt(jsonReader) - JSON_READER_LINESTART.getInt(jsonReader); ++ } catch (IllegalAccessException var2) { ++ throw new IllegalStateException("Couldn't read position of JsonReader", var2); ++ } ++ } ++ } ++ ++ // important: leadingSlash should not just be the result of a startsWith on command, ++ // it should reflect whether the command use is in a place that will skip a leading slash when parsing ++ public String upgradeCommandArguments(final String command, final boolean leadingSlash) { ++ final StringReader reader = new StringReader(command); ++ if (leadingSlash && reader.peek() == '/') { ++ reader.skip(); ++ } ++ final ParseResults parseResult = this.dispatcher.parse(reader, this.source); ++ if (!parseResult.getExceptions().isEmpty()) { ++ return command; ++ } ++ final Map replacements = new LinkedHashMap<>(); ++ final List>> mergedArguments = new ArrayList<>(); ++ addArguments(mergedArguments, parseResult.getContext()); ++ mergedArguments.forEach(pair -> { ++ if (pair.value().getResult() instanceof UpgradedArgument upgraded) { ++ replacements.put(pair.value().getRange(), upgraded.upgraded()); ++ } ++ }); ++ String upgradedCommand = command; ++ while (!replacements.isEmpty()) { ++ final Map.Entry next = replacements.entrySet().iterator().next(); ++ replacements.remove(next.getKey()); ++ upgradedCommand = upgradedCommand.substring(0, next.getKey().getStart()) + next.getValue() + upgradedCommand.substring(next.getKey().getEnd()); ++ // Update the offsets for the remaining replacements ++ final int diff = next.getValue().length() - next.getKey().getLength(); ++ final Map replacementsCopy = new LinkedHashMap<>(replacements); ++ replacements.clear(); ++ replacementsCopy.forEach((range, value) -> { ++ replacements.put(new StringRange(range.getStart() + diff, range.getEnd() + diff), value); ++ }); ++ } ++ return upgradedCommand; ++ } ++ ++ public String upgradeSingleArgument( ++ final Function> argumentFactory, ++ final String input ++ ) { ++ final ArgumentType argument = argumentFactory.apply(this.context); ++ final ArgumentType replaced = this.replaceArgumentType(this.context, argument); ++ if (argument == replaced) { ++ return input; ++ } ++ try { ++ final UpgradedArgument parsed = (UpgradedArgument) replaced.parse(new StringReader(input)); ++ return parsed.upgraded(); ++ } catch (final CommandSyntaxException e) { ++ return input; ++ } ++ } ++ ++ private static void addArguments( ++ final List>> mergedArguments, ++ final @Nullable CommandContextBuilder context ++ ) { ++ if (context == null) { ++ return; ++ } ++ context.getArguments().forEach((name, argument) -> mergedArguments.add(Pair.of(name, argument))); ++ addArguments(mergedArguments, context.getChild()); ++ } ++ ++ private ArgumentType replaceArgumentType(final CommandBuildContext ctx, final ArgumentType type) { ++ final BiFunction, CommandBuildContext, ArgumentType> upgrader = ++ this.replacements.get(type.getClass()); ++ if (upgrader != null) { ++ return upgrader.apply(type, ctx); ++ } ++ return type; ++ } ++ ++ record CopyResult( ++ CommandNode root, ++ boolean replaced, ++ List> aliases ++ ) { ++ CopyResult replacedResult() { ++ if (this.replaced) { ++ return this; ++ } ++ return new CopyResult(this.root, true, new ArrayList<>(this.aliases)); ++ } ++ } ++ ++ private CopyResult copyCommand( ++ final CommandNode parent, ++ final CommandNode node, ++ @Nullable CopyResult result ++ ) { ++ final CommandNode copy; ++ final boolean replaced; ++ if (node instanceof LiteralCommandNode literal) { ++ if (node.getName().equals("execute") || node.getName().equals("return")) { ++ return new CopyResult(parent, false, new ArrayList<>()); ++ } ++ if (node.getRedirect() != null) { ++ if (result != null) { ++ throw new IllegalStateException("Cannot handle non-root redirects"); ++ } ++ final List> aliases = new ArrayList<>(); ++ aliases.add(node); ++ return new CopyResult(parent, false, aliases); ++ } ++ copy = new LiteralCommandNode<>( ++ literal.getLiteral(), ++ node.getCommand(), ++ node.getRequirement(), ++ null, ++ node.getRedirectModifier(), ++ node.isFork() ++ ); ++ replaced = false; ++ } else if (node instanceof ArgumentCommandNode) { ++ final ArgumentCommandNode argument = ++ (ArgumentCommandNode) node; ++ final ArgumentType replacedType = this.replaceArgumentType(this.context, argument.getType()); ++ replaced = replacedType != argument.getType(); ++ copy = new ArgumentCommandNode<>( ++ node.getName(), ++ replacedType, ++ node.getCommand(), ++ node.getRequirement(), ++ null, ++ node.getRedirectModifier(), ++ node.isFork(), ++ argument.getCustomSuggestions() ++ ); ++ } else { ++ throw new UnsupportedOperationException(); ++ } ++ if (result == null) { ++ result = new CopyResult(copy, false, new ArrayList<>()); ++ } ++ if (replaced) { ++ result = result.replacedResult(); ++ } ++ for (final CommandNode child : node.getChildren()) { ++ result = this.copyCommand(copy, child, result); ++ } ++ if (parent != this.dispatcher.getRoot()) { ++ parent.addChild(copy); ++ } ++ return result; ++ } ++ ++ private static CommandBuildContext makeDummyCommandBuildContext() { ++ return Commands.createValidationContext( ++ new HolderLookup.Provider() { ++ ++ @Override ++ public Stream>> listRegistries() { ++ return Stream.of(); ++ } ++ ++ @Override ++ public Optional> lookup( ++ final ResourceKey> registryRef ++ ) { ++ return Optional.of(new HolderLookup.RegistryLookup() { ++ @Override ++ public ResourceKey> key() { ++ return registryRef; ++ } ++ ++ @Override ++ public Lifecycle registryLifecycle() { ++ return Lifecycle.stable(); ++ } ++ ++ @Override ++ public Stream> listElements() { ++ return Stream.of(); ++ } ++ ++ @Override ++ public Stream> listTags() { ++ return Stream.of(); ++ } ++ ++ @Override ++ public Optional> get(final ResourceKey key) { ++ return Optional.of(Holder.Reference.createStandAlone(this, key)); ++ } ++ ++ @Override ++ public Optional> get(final TagKey tag) { ++ return Optional.of(HolderSet.emptyNamed(this, tag)); ++ } ++ }); ++ } ++ } ++ ); ++ } ++} diff --git a/src/main/java/ca/spottedleaf/dataconverter/util/Int2IntArraySortedMap.java b/src/main/java/ca/spottedleaf/dataconverter/util/Int2IntArraySortedMap.java new file mode 100644 index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 @@ -24797,7 +28754,7 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/data/structures/StructureUpdater.java +++ b/src/main/java/net/minecraft/data/structures/StructureUpdater.java @@ -0,0 +0,0 @@ public class StructureUpdater implements SnbtToNbt.Filter { - LOGGER.warn("SNBT Too old, do not forget to update: {} < {}: {}", i, 3678, name); + LOGGER.warn("SNBT Too old, do not forget to update: {} < {}: {}", i, 3798, name); } - CompoundTag compoundTag = DataFixTypes.STRUCTURE.updateToCurrentVersion(DataFixers.getDataFixer(), nbt, i); @@ -24810,65 +28767,70 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 --- a/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java +++ b/src/main/java/net/minecraft/world/level/chunk/storage/ChunkStorage.java @@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { - int i = ChunkStorage.getVersion(nbttagcompound); - // CraftBukkit start -- if (i < 1466) { -+ if (false && i < 1466) { // Paper - no longer needed, data converter system handles it now - CompoundTag level = nbttagcompound.getCompound("Level"); - if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { - ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource(); + try { + // CraftBukkit start +- if (i < 1466) { ++ if (false && i < 1466) { // Paper - no longer needed, data converter system / DFU handles it now + CompoundTag level = nbttagcompound.getCompound("Level"); + if (level.getBoolean("TerrainPopulated") && !level.getBoolean("LightPopulated")) { + ServerChunkCache cps = (generatoraccess == null) ? null : ((ServerLevel) generatoraccess).getChunkSource(); @@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { - // CraftBukkit end + // CraftBukkit end - if (i < 1493) { -- nbttagcompound = DataFixTypes.CHUNK.update(this.fixerUpper, nbttagcompound, i, 1493); -+ ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, nbttagcompound, i, 1493); // Paper - replace chunk converter - if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { - LegacyStructureDataHandler persistentstructurelegacy = this.getLegacyStructureHandler(resourcekey, supplier); + if (i < 1493) { +- nbttagcompound = DataFixTypes.CHUNK.update(this.fixerUpper, nbttagcompound, i, 1493); ++ ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, nbttagcompound, i, 1493); // Paper - replace chunk converter + if (nbttagcompound.getCompound("Level").getBoolean("hasLegacyStructureData")) { + LegacyStructureDataHandler persistentstructurelegacy = this.getLegacyStructureHandler(resourcekey, supplier); @@ -0,0 +0,0 @@ public class ChunkStorage implements AutoCloseable { - // Spigot end + // Spigot end - ChunkStorage.injectDatafixingContext(nbttagcompound, resourcekey, optional); -- nbttagcompound = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, nbttagcompound, Math.max(1493, i)); -+ nbttagcompound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, nbttagcompound, Math.max(1493, i), SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper - replace chunk converter - if (i < SharedConstants.getCurrentVersion().getDataVersion().getVersion()) { - NbtUtils.addCurrentDataVersion(nbttagcompound); - } -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java + ChunkStorage.injectDatafixingContext(nbttagcompound, resourcekey, optional); +- nbttagcompound = DataFixTypes.CHUNK.updateToCurrentVersion(this.fixerUpper, nbttagcompound, Math.max(1493, i)); ++ nbttagcompound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.CHUNK, nbttagcompound, Math.max(1493, i), SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper - replace chunk converter + if (i < SharedConstants.getCurrentVersion().getDataVersion().getVersion()) { + NbtUtils.addCurrentDataVersion(nbttagcompound); + } +diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/EntityStorage.java -@@ -0,0 +0,0 @@ public class EntityStorage implements EntityPersistentStorage { - - private CompoundTag upgradeChunkTag(CompoundTag chunkNbt) { - int i = NbtUtils.getDataVersion(chunkNbt, -1); -- return DataFixTypes.ENTITY_CHUNK.updateToCurrentVersion(this.fixerUpper, chunkNbt, i); -+ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY_CHUNK, chunkNbt, i, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper - route to new converter system +--- a/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java ++++ b/src/main/java/net/minecraft/world/level/chunk/storage/SimpleRegionStorage.java +@@ -0,0 +0,0 @@ public class SimpleRegionStorage implements AutoCloseable { + return this.worker.store(pos, nbt); } - @Override -diff --git a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 ---- a/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -+++ b/src/main/java/net/minecraft/world/level/chunk/storage/SectionStorage.java -@@ -0,0 +0,0 @@ public class SectionStorage implements AutoCloseable { - int j = getVersion(dynamic); - int k = SharedConstants.getCurrentVersion().getDataVersion().getVersion(); - boolean bl = j != k; -- Dynamic dynamic2 = this.type.update(this.fixerUpper, dynamic, j, k); -+ // Paper start - route to new converter system -+ Dynamic dynamic2; -+ if (this.type == net.minecraft.util.datafix.DataFixTypes.POI_CHUNK) { -+ dynamic2 = new Dynamic<>(dynamic.getOps(), (T)ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.POI_CHUNK, (CompoundTag)dynamic.getValue(), j, k)); -+ } else { -+ dynamic2 = this.type.update(this.fixerUpper, dynamic, j, k); -+ } -+ // Paper end - route to new converter system - OptionalDynamic optionalDynamic = dynamic2.get("Sections"); ++ // Paper start - rewrite data conversion system ++ private ca.spottedleaf.dataconverter.minecraft.datatypes.MCDataType getDataConverterType() { ++ if (this.dataFixType == DataFixTypes.ENTITY_CHUNK) { ++ return ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY_CHUNK; ++ } else if (this.dataFixType == DataFixTypes.POI_CHUNK) { ++ return ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.POI_CHUNK; ++ } else { ++ throw new UnsupportedOperationException("For " + this.dataFixType.name()); ++ } ++ } ++ // Paper end - rewrite data conversion system ++ + public CompoundTag upgradeChunkTag(CompoundTag nbt, int oldVersion) { +- int i = NbtUtils.getDataVersion(nbt, oldVersion); +- return this.dataFixType.updateToCurrentVersion(this.fixerUpper, nbt, i); ++ // Paper start - rewrite data conversion system ++ final int dataVer = NbtUtils.getDataVersion(nbt, oldVersion); ++ return ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(this.getDataConverterType(), nbt, dataVer, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); ++ // Paper end - rewrite data conversion system + } - for (int l = this.levelHeightAccessor.getMinSection(); l < this.levelHeightAccessor.getMaxSection(); l++) { + public Dynamic upgradeChunkTag(Dynamic nbt, int oldVersion) { +- return this.dataFixType.updateToCurrentVersion(this.fixerUpper, nbt, oldVersion); ++ // Paper start - rewrite data conversion system ++ final CompoundTag converted = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(this.getDataConverterType(), (CompoundTag)nbt.getValue(), oldVersion, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); ++ return new Dynamic<>(net.minecraft.nbt.NbtOps.INSTANCE, converted); ++ // Paper end - rewrite data conversion system + } + + public CompletableFuture synchronize(boolean sync) { diff --git a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java b/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/levelgen/structure/StructureCheck.java @@ -24906,58 +28868,55 @@ index 0000000000000000000000000000000000000000..00000000000000000000000000000000 - int i = NbtUtils.getDataVersion(nbttagcompound1, -1); + int i = NbtUtils.getDataVersion(nbttagcompound1, -1); final int version = i; // Paper - obfuscation helpers Dynamic dynamic = DataFixTypes.LEVEL.updateToCurrentVersion(dataFixer, new Dynamic(NbtOps.INSTANCE, nbttagcompound1), i); - Dynamic dynamic1 = dynamic.get("Player").orElseEmptyMap(); -- Dynamic dynamic2 = DataFixTypes.PLAYER.updateToCurrentVersion(dataFixer, dynamic1, i); -+ Dynamic dynamic2 = LevelStorageSource.dank(dynamic1, version); // Paper - - dynamic = dynamic.set("Player", dynamic2); - Dynamic dynamic3 = dynamic.get("WorldGenSettings").orElseEmptyMap(); -@@ -0,0 +0,0 @@ public class LevelStorageSource { - return dynamic; - } - -+ // Paper start -+ private static Dynamic dank(final Dynamic input, final int version) { -+ return new Dynamic<>(input.getOps(), (T) ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.PLAYER, (CompoundTag)input.getValue(), version, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion())); -+ } -+ // Paper end -+ - private LevelSummary readLevelSummary(LevelStorageSource.LevelDirectory save, boolean locked) { - Path path = save.dataFile(); ++ // Paper start - replace data conversion system + dynamic = dynamic.update("Player", (dynamic1) -> { +- return DataFixTypes.PLAYER.updateToCurrentVersion(dataFixer, dynamic1, i); ++ return new Dynamic<>( ++ NbtOps.INSTANCE, ++ ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag( ++ ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.PLAYER, ++ (net.minecraft.nbt.CompoundTag)dynamic1.getValue(), ++ version, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion() ++ ) ++ ); + }); ++ // Paper end - replace data conversion system + dynamic = dynamic.update("WorldGenSettings", (dynamic1) -> { + return DataFixTypes.WORLD_GEN_SETTINGS.updateToCurrentVersion(dataFixer, dynamic1, i); + }); diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java +++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java @@ -0,0 +0,0 @@ public class PlayerDataStorage { - // CraftBukkit end + }).map((nbttagcompound) -> { int i = NbtUtils.getDataVersion(nbttagcompound, -1); - nbttagcompound = DataFixTypes.PLAYER.updateToCurrentVersion(this.fixerUpper, nbttagcompound, i); -+ nbttagcompound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.PLAYER, nbttagcompound, i, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper - replace player converter - player.load(nbttagcompound); - } - ++ nbttagcompound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.PLAYER, nbttagcompound, i, net.minecraft.SharedConstants.getCurrentVersion().getDataVersion().getVersion()); // Paper - rewrite data conversion system + // entityhuman.load(nbttagcompound); // CraftBukkit - handled above + return nbttagcompound; + }); diff --git a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java index 0000000000000000000000000000000000000000..0000000000000000000000000000000000000000 100644 --- a/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java +++ b/src/main/java/org/bukkit/craftbukkit/util/CraftMagicNumbers.java @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - CompoundTag compound = deserializeNbtFromBytes(data); + net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data); final int dataVersion = compound.getInt("DataVersion"); -- compound = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ITEM_STACK, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue(); -- return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(compound)); -+ return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.of(ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK, compound, dataVersion, this.getDataVersion()))); // Paper - rewrite dataconverter +- compound = (net.minecraft.nbt.CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ITEM_STACK, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue(); ++ compound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ITEM_STACK, compound, dataVersion, this.getDataVersion()); // Paper - replace data conversion system + return CraftItemStack.asCraftMirror(net.minecraft.world.item.ItemStack.parse(MinecraftServer.getServer().registryAccess(), compound).orElseThrow()); } - @Override @@ -0,0 +0,0 @@ public final class CraftMagicNumbers implements UnsafeValues { - CompoundTag compound = deserializeNbtFromBytes(data); + net.minecraft.nbt.CompoundTag compound = deserializeNbtFromBytes(data); int dataVersion = compound.getInt("DataVersion"); -- compound = (CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ENTITY, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue(); -+ compound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY, compound, dataVersion, getDataVersion()); // Paper - rewrite dataconverter +- compound = (net.minecraft.nbt.CompoundTag) MinecraftServer.getServer().fixerUpper.update(References.ENTITY, new Dynamic<>(NbtOps.INSTANCE, compound), dataVersion, this.getDataVersion()).getValue(); ++ compound = ca.spottedleaf.dataconverter.minecraft.MCDataConverter.convertTag(ca.spottedleaf.dataconverter.minecraft.datatypes.MCTypeRegistry.ENTITY, compound, dataVersion, this.getDataVersion()); if (!preserveUUID) { // Generate a new UUID so we don't have to worry about deserializing the same entity twice compound.remove("UUID");