From 4c0e2e3e5d2b6e93515f859567bc4a1f0d7b023e Mon Sep 17 00:00:00 2001 From: Mitch Date: Thu, 26 Feb 2026 23:13:34 -0800 Subject: [PATCH 1/4] passing item_name through to client added config with explanation,. Populating custom_model_data for 1.21.4+ clients for the resource pack to work better. Not passing this back in to server. --- .../viabackwards/ViaBackwardsConfig.java | 7 +++ .../viabackwards/api/ViaBackwardsConfig.java | 9 ++++ .../BackwardsStructuredItemRewriter.java | 54 ++++++++++++++++--- .../resources/assets/viabackwards/config.yml | 6 +++ 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/common/src/main/java/com/viaversion/viabackwards/ViaBackwardsConfig.java b/common/src/main/java/com/viaversion/viabackwards/ViaBackwardsConfig.java index e4ea4a96..9eca8419 100644 --- a/common/src/main/java/com/viaversion/viabackwards/ViaBackwardsConfig.java +++ b/common/src/main/java/com/viaversion/viabackwards/ViaBackwardsConfig.java @@ -47,6 +47,7 @@ public class ViaBackwardsConfig extends Config implements com.viaversion.viaback private boolean dialogsViaChests; private DialogStyleConfig dialogStyleConfig; private boolean codeOfConductAsDialog; + private boolean passOriginalItemNameToResourcePacks; public ViaBackwardsConfig(File configFile, Logger logger) { super(configFile, logger); @@ -75,6 +76,7 @@ private void loadFields() { dialogsViaChests = getBoolean("dialogs-via-chests", true); dialogStyleConfig = loadDialogStyleConfig(getSection("dialog-style")); codeOfConductAsDialog = getBoolean("code-of-conduct-as-dialog", true); + passOriginalItemNameToResourcePacks = getBoolean("pass-original-item-name-to-resource-packs", true); } private DialogStyleConfig loadDialogStyleConfig(final ConfigSection section) { @@ -179,6 +181,11 @@ public boolean codeOfConductAsDialog() { return codeOfConductAsDialog; } + @Override + public boolean passOriginalItemNameToResourcePacks() { + return passOriginalItemNameToResourcePacks; + } + @Override public URL getDefaultConfigURL() { return getClass().getClassLoader().getResource("assets/viabackwards/config.yml"); diff --git a/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java b/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java index 807a466e..4d41e58e 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java @@ -133,4 +133,13 @@ public interface ViaBackwardsConfig extends Config { * @return true if enabled */ boolean codeOfConductAsDialog(); + + /** + * Injects the original vanilla 1.21.4+ item name into custom_model_data strings for resource packs. + * Disable if your server creates custom items using modern items as their base. + * Tip: For server custom items, always base them on items in the game before 1.21.4 (e.g. saddle) to ensure compatibility. + * + * @return true if enabled + */ + boolean passOriginalItemNameToResourcePacks(); } diff --git a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java index 9e5c1320..f3948f57 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java @@ -24,6 +24,7 @@ import com.viaversion.nbt.tag.ListTag; import com.viaversion.nbt.tag.StringTag; import com.viaversion.nbt.tag.Tag; +import com.viaversion.viabackwards.ViaBackwards; import com.viaversion.viabackwards.api.BackwardsProtocol; import com.viaversion.viabackwards.api.data.BackwardsMappingData; import com.viaversion.viabackwards.api.data.MappedItem; @@ -70,17 +71,42 @@ protected void backupInconvertibleData(final UserConnection connection, final It customTag.putInt(nbtTagName("id"), item.identifier()); // Save original id // Add custom model data - if (mappedItem.customModelData() != null) { + if (mappedItem.customModelData() != null || ViaBackwards.getConfig().passOriginalItemNameToResourcePacks()) { if (connection.getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4)) { - if (!dataContainer.has(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4)) { - dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( - new float[]{mappedItem.customModelData().floatValue()}, + CustomModelData1_21_4 customModelData = dataContainer.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); + if (customModelData == null) { + customModelData = new CustomModelData1_21_4( + mappedItem.customModelData() != null ? new float[]{mappedItem.customModelData().floatValue()} : new float[0], new boolean[0], new String[0], EMPTY_INT_ARRAY - )); + ); + dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, customModelData); } - } else if (!dataContainer.has(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5)) { + + if (ViaBackwards.getConfig().passOriginalItemNameToResourcePacks() && mappingData.getFullItemMappings() != null) { + final String identifier = mappingData.getFullItemMappings().identifier(item.identifier()); + if (identifier != null) { + final String injection = "viabackwards:" + Key.stripMinecraftNamespace(identifier); + boolean exists = false; + for (final String s : customModelData.strings()) { + if (s.equals(injection)) { + exists = true; + break; + } + } + if (!exists) { + final String[] newStrings = new String[customModelData.strings().length + 1]; + System.arraycopy(customModelData.strings(), 0, newStrings, 0, customModelData.strings().length); + newStrings[customModelData.strings().length] = injection; + dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( + customModelData.floats(), customModelData.booleans(), newStrings, customModelData.colors() + )); + customTag.putBoolean(nbtTagName("injected_cmd_string"), true); + } + } + } + } else if (mappedItem.customModelData() != null && !dataContainer.has(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5)) { dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, mappedItem.customModelData()); } } @@ -99,6 +125,22 @@ protected void restoreBackupData(final Item item, final StructuredDataContainer item.setIdentifier(originalTag.asInt()); removeCustomTag(container, customData); } + + if (removeBackupTag(customData, "injected_cmd_string") != null) { + final CustomModelData1_21_4 customModelData = container.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); + if (customModelData != null && customModelData.strings() != null) { + final List strings = new java.util.ArrayList<>(java.util.Arrays.asList(customModelData.strings())); + if (strings.removeIf(s -> s.startsWith("viabackwards:"))) { + if (strings.isEmpty() && customModelData.floats().length == 0 && customModelData.booleans().length == 0 && customModelData.colors().length == 0) { + container.remove(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); + } else { + container.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( + customModelData.floats(), customModelData.booleans(), strings.toArray(new String[0]), customModelData.colors() + )); + } + } + } + } } protected void saveListTag(CompoundTag tag, ListTag original, String name) { diff --git a/common/src/main/resources/assets/viabackwards/config.yml b/common/src/main/resources/assets/viabackwards/config.yml index 0d99df5a..7ab1460c 100644 --- a/common/src/main/resources/assets/viabackwards/config.yml +++ b/common/src/main/resources/assets/viabackwards/config.yml @@ -68,3 +68,9 @@ dialog-style: # Note that this is not supported for clients below 1.21.6 right now due to missing support for # dialogs during the configuration phase. code-of-conduct-as-dialog: true +# +# Passes the original vanilla 1.21.4+ item name into custom_model_data strings. +# This allows client resource packs to restore the appearance of newer items entirely missing from this older version. +# Disable if your server creates custom items using modern items as their base. +# Tip: For server custom items, always base them on items in the game before 1.21.4 (e.g. saddle) to ensure compatibility. +pass-original-item-name-to-resource-packs: true From 96e2fa7c966935531d651ecbabbf168d7ed21696 Mon Sep 17 00:00:00 2001 From: Mitch Date: Sun, 1 Mar 2026 17:25:02 -0800 Subject: [PATCH 2/4] Refactor: Use ArrayUtil and Custom Tag Marker for the injection --- .../viabackwards/api/ViaBackwardsConfig.java | 2 +- .../BackwardsStructuredItemRewriter.java | 33 ++++++++++++------- .../resources/assets/viabackwards/config.yml | 2 +- 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java b/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java index 4d41e58e..b16e54a4 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/ViaBackwardsConfig.java @@ -137,7 +137,7 @@ public interface ViaBackwardsConfig extends Config { /** * Injects the original vanilla 1.21.4+ item name into custom_model_data strings for resource packs. * Disable if your server creates custom items using modern items as their base. - * Tip: For server custom items, always base them on items in the game before 1.21.4 (e.g. saddle) to ensure compatibility. + * Tip: For server custom items, base them on items in the game before 1.21.4 (e.g. saddle) to ensure compatibility. * * @return true if enabled */ diff --git a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java index f3948f57..44d16aa0 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java @@ -41,6 +41,7 @@ import com.viaversion.viaversion.api.protocol.packet.ServerboundPacketType; import com.viaversion.viaversion.api.protocol.version.ProtocolVersion; import com.viaversion.viaversion.rewriter.StructuredItemRewriter; +import com.viaversion.viaversion.util.ArrayUtil; import com.viaversion.viaversion.util.Key; import java.util.ArrayList; import java.util.List; @@ -87,22 +88,18 @@ protected void backupInconvertibleData(final UserConnection connection, final It if (ViaBackwards.getConfig().passOriginalItemNameToResourcePacks() && mappingData.getFullItemMappings() != null) { final String identifier = mappingData.getFullItemMappings().identifier(item.identifier()); if (identifier != null) { - final String injection = "viabackwards:" + Key.stripMinecraftNamespace(identifier); boolean exists = false; for (final String s : customModelData.strings()) { - if (s.equals(injection)) { + if (s.equals(identifier)) { exists = true; break; } } if (!exists) { - final String[] newStrings = new String[customModelData.strings().length + 1]; - System.arraycopy(customModelData.strings(), 0, newStrings, 0, customModelData.strings().length); - newStrings[customModelData.strings().length] = injection; dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( - customModelData.floats(), customModelData.booleans(), newStrings, customModelData.colors() + customModelData.floats(), customModelData.booleans(), ArrayUtil.add(customModelData.strings(), identifier), customModelData.colors() )); - customTag.putBoolean(nbtTagName("injected_cmd_string"), true); + customTag.putString(nbtTagName("injected_cmd_string"), identifier); } } } @@ -126,16 +123,28 @@ protected void restoreBackupData(final Item item, final StructuredDataContainer removeCustomTag(container, customData); } - if (removeBackupTag(customData, "injected_cmd_string") != null) { + final Tag injectedCmdTag = removeBackupTag(customData, "injected_cmd_string"); + if (injectedCmdTag instanceof StringTag stringTag) { final CustomModelData1_21_4 customModelData = container.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); if (customModelData != null && customModelData.strings() != null) { - final List strings = new java.util.ArrayList<>(java.util.Arrays.asList(customModelData.strings())); - if (strings.removeIf(s -> s.startsWith("viabackwards:"))) { - if (strings.isEmpty() && customModelData.floats().length == 0 && customModelData.booleans().length == 0 && customModelData.colors().length == 0) { + final String target = stringTag.getValue(); + final String[] oldStrings = customModelData.strings(); + + int index = -1; + for (int i = 0; i < oldStrings.length; i++) { + if (oldStrings[i].equals(target)) { + index = i; + break; + } + } + + if (index != -1) { + final String[] newStrings = ArrayUtil.remove(oldStrings, index); + if (newStrings.length == 0 && customModelData.floats().length == 0 && customModelData.booleans().length == 0 && customModelData.colors().length == 0) { container.remove(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); } else { container.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( - customModelData.floats(), customModelData.booleans(), strings.toArray(new String[0]), customModelData.colors() + customModelData.floats(), customModelData.booleans(), newStrings, customModelData.colors() )); } } diff --git a/common/src/main/resources/assets/viabackwards/config.yml b/common/src/main/resources/assets/viabackwards/config.yml index 7ab1460c..f2f7ea6c 100644 --- a/common/src/main/resources/assets/viabackwards/config.yml +++ b/common/src/main/resources/assets/viabackwards/config.yml @@ -72,5 +72,5 @@ code-of-conduct-as-dialog: true # Passes the original vanilla 1.21.4+ item name into custom_model_data strings. # This allows client resource packs to restore the appearance of newer items entirely missing from this older version. # Disable if your server creates custom items using modern items as their base. -# Tip: For server custom items, always base them on items in the game before 1.21.4 (e.g. saddle) to ensure compatibility. +# Tip: For server custom items, base them on items in the game before 1.21.4 (e.g. saddle) to ensure compatibility. pass-original-item-name-to-resource-packs: true From 5ac9a12f82d637b2783f7adf7d15830e8026fe4c Mon Sep 17 00:00:00 2001 From: mfishma Date: Thu, 5 Mar 2026 14:08:36 -0800 Subject: [PATCH 3/4] Avoid double-injection of tags when rewriting To assure there's only one tag per item, made a shared VB|injected_cmd marker during the first rewrite, then check for it in subsequent versions to skip any duplicate injections. Also optimized the NBT tag name lookup to be a bit snappier. --- .../api/rewriters/BackwardsStructuredItemRewriter.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java index 44d16aa0..83a24b86 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java @@ -53,9 +53,13 @@ public class BackwardsStructuredItemRewriter> extends StructuredItemRewriter { private static final int[] EMPTY_INT_ARRAY = new int[0]; + private static final String INJECTED_CMD_MARKER = "VB|injected_cmd"; + + private final String nbtTagName; public BackwardsStructuredItemRewriter(T protocol) { super(protocol); + this.nbtTagName = "VB|" + protocol.getClass().getSimpleName(); } @Override @@ -87,7 +91,7 @@ protected void backupInconvertibleData(final UserConnection connection, final It if (ViaBackwards.getConfig().passOriginalItemNameToResourcePacks() && mappingData.getFullItemMappings() != null) { final String identifier = mappingData.getFullItemMappings().identifier(item.identifier()); - if (identifier != null) { + if (identifier != null && !customTag.contains(INJECTED_CMD_MARKER)) { boolean exists = false; for (final String s : customModelData.strings()) { if (s.equals(identifier)) { @@ -100,6 +104,7 @@ protected void backupInconvertibleData(final UserConnection connection, final It customModelData.floats(), customModelData.booleans(), ArrayUtil.add(customModelData.strings(), identifier), customModelData.colors() )); customTag.putString(nbtTagName("injected_cmd_string"), identifier); + customTag.putBoolean(INJECTED_CMD_MARKER, true); } } } @@ -125,6 +130,7 @@ protected void restoreBackupData(final Item item, final StructuredDataContainer final Tag injectedCmdTag = removeBackupTag(customData, "injected_cmd_string"); if (injectedCmdTag instanceof StringTag stringTag) { + customData.remove(INJECTED_CMD_MARKER); final CustomModelData1_21_4 customModelData = container.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); if (customModelData != null && customModelData.strings() != null) { final String target = stringTag.getValue(); @@ -364,6 +370,6 @@ protected Holder restoreSoundEventHolder(final CompoundTag tag, fina @Override public String nbtTagName() { - return "VB|" + protocol.getClass().getSimpleName(); + return this.nbtTagName; } } From 2e6fc560a8ea87ca6e7c4f2abc8b8c8bb65e94cf Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Wed, 1 Apr 2026 11:29:03 +0200 Subject: [PATCH 4/4] Simplify handling --- .../BackwardsStructuredItemRewriter.java | 103 ++++++++---------- 1 file changed, 46 insertions(+), 57 deletions(-) diff --git a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java index 83a24b86..e8040b48 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/rewriters/BackwardsStructuredItemRewriter.java @@ -53,7 +53,7 @@ public class BackwardsStructuredItemRewriter> extends StructuredItemRewriter { private static final int[] EMPTY_INT_ARRAY = new int[0]; - private static final String INJECTED_CMD_MARKER = "VB|injected_cmd"; + private static final String GLOBAL_MODEL_DATA_MARKER = "VB|injected_cmd"; private final String nbtTagName; @@ -76,38 +76,10 @@ protected void backupInconvertibleData(final UserConnection connection, final It customTag.putInt(nbtTagName("id"), item.identifier()); // Save original id // Add custom model data - if (mappedItem.customModelData() != null || ViaBackwards.getConfig().passOriginalItemNameToResourcePacks()) { + final boolean addOriginalIdentifier = ViaBackwards.getConfig().passOriginalItemNameToResourcePacks(); + if (mappedItem.customModelData() != null || addOriginalIdentifier) { if (connection.getProtocolInfo().protocolVersion().newerThanOrEqualTo(ProtocolVersion.v1_21_4)) { - CustomModelData1_21_4 customModelData = dataContainer.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); - if (customModelData == null) { - customModelData = new CustomModelData1_21_4( - mappedItem.customModelData() != null ? new float[]{mappedItem.customModelData().floatValue()} : new float[0], - new boolean[0], - new String[0], - EMPTY_INT_ARRAY - ); - dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, customModelData); - } - - if (ViaBackwards.getConfig().passOriginalItemNameToResourcePacks() && mappingData.getFullItemMappings() != null) { - final String identifier = mappingData.getFullItemMappings().identifier(item.identifier()); - if (identifier != null && !customTag.contains(INJECTED_CMD_MARKER)) { - boolean exists = false; - for (final String s : customModelData.strings()) { - if (s.equals(identifier)) { - exists = true; - break; - } - } - if (!exists) { - dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( - customModelData.floats(), customModelData.booleans(), ArrayUtil.add(customModelData.strings(), identifier), customModelData.colors() - )); - customTag.putString(nbtTagName("injected_cmd_string"), identifier); - customTag.putBoolean(INJECTED_CMD_MARKER, true); - } - } - } + addCustomModelData(item, addOriginalIdentifier, mappedItem, customTag); } else if (mappedItem.customModelData() != null && !dataContainer.has(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5)) { dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_20_5, mappedItem.customModelData()); } @@ -120,6 +92,33 @@ protected void backupInconvertibleData(final UserConnection connection, final It } } + private void addCustomModelData(final Item item, final boolean addOriginalIdentifier, final MappedItem mappedItem, final CompoundTag customTag) { + final StructuredDataContainer dataContainer = item.dataContainer(); + CustomModelData1_21_4 customModelData = dataContainer.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); + if (customModelData == null) { + final String[] strings = addOriginalIdentifier + ? new String[]{protocol.getMappingData().getFullItemMappings().identifier(item.identifier())} + : new String[0]; + customModelData = new CustomModelData1_21_4( + mappedItem.customModelData() != null ? new float[]{mappedItem.customModelData().floatValue()} : new float[0], + new boolean[0], + strings, + EMPTY_INT_ARRAY + ); + dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, customModelData); + // Add one global marker and one for this specific version, so it is removed at the correct protocol + customTag.putBoolean(GLOBAL_MODEL_DATA_MARKER, true); + customTag.putBoolean(nbtTagName("added_custom_model_data"), true); + } else if (addOriginalIdentifier && !customTag.contains(GLOBAL_MODEL_DATA_MARKER)) { + final String identifier = protocol.getMappingData().getFullItemMappings().identifier(item.identifier()); + dataContainer.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( + customModelData.floats(), customModelData.booleans(), ArrayUtil.add(customModelData.strings(), identifier), customModelData.colors() + )); + customTag.putBoolean(GLOBAL_MODEL_DATA_MARKER, true); + customTag.putString(nbtTagName("injected_custom_model_data"), identifier); + } + } + @Override protected void restoreBackupData(final Item item, final StructuredDataContainer container, final CompoundTag customData) { super.restoreBackupData(item, container, customData); @@ -128,33 +127,23 @@ protected void restoreBackupData(final Item item, final StructuredDataContainer removeCustomTag(container, customData); } - final Tag injectedCmdTag = removeBackupTag(customData, "injected_cmd_string"); - if (injectedCmdTag instanceof StringTag stringTag) { - customData.remove(INJECTED_CMD_MARKER); - final CustomModelData1_21_4 customModelData = container.get(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); - if (customModelData != null && customModelData.strings() != null) { - final String target = stringTag.getValue(); - final String[] oldStrings = customModelData.strings(); - - int index = -1; - for (int i = 0; i < oldStrings.length; i++) { - if (oldStrings[i].equals(target)) { - index = i; - break; + if (removeBackupTag(customData, "injected_custom_model_data") instanceof StringTag injectedCustomModelData) { + customData.remove(GLOBAL_MODEL_DATA_MARKER); + container.replace(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, customModelData -> { + final String target = injectedCustomModelData.getValue(); + final String[] strings = customModelData.strings(); + for (int i = 0; i < strings.length; i++) { + if (strings[i].equals(target)) { + // Remove the injected string + final String[] filteredStrings = ArrayUtil.remove(strings, i); + return new CustomModelData1_21_4(customModelData.floats(), customModelData.booleans(), filteredStrings, customModelData.colors()); } } - - if (index != -1) { - final String[] newStrings = ArrayUtil.remove(oldStrings, index); - if (newStrings.length == 0 && customModelData.floats().length == 0 && customModelData.booleans().length == 0 && customModelData.colors().length == 0) { - container.remove(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); - } else { - container.set(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4, new CustomModelData1_21_4( - customModelData.floats(), customModelData.booleans(), newStrings, customModelData.colors() - )); - } - } - } + return customModelData; + }); + } else if (removeBackupTag(customData, "added_custom_model_data") != null) { + customData.remove(GLOBAL_MODEL_DATA_MARKER); + container.remove(StructuredDataKey.CUSTOM_MODEL_DATA1_21_4); } }