From f7acb7ce91b9057b60092229cfa60b0060373af4 Mon Sep 17 00:00:00 2001 From: Nassim Jahnke Date: Thu, 9 Mar 2023 11:29:59 +0100 Subject: [PATCH] Read custom model data from nbt mapping files, merge dir and packed data --- .../api/data/BackwardsMappings.java | 21 ++- .../api/data/VBMappingDataLoader.java | 139 +++++++----------- .../viabackwards/api/data/VBMappings.java | 62 -------- 3 files changed, 71 insertions(+), 151 deletions(-) delete mode 100644 common/src/main/java/com/viaversion/viabackwards/api/data/VBMappings.java diff --git a/common/src/main/java/com/viaversion/viabackwards/api/data/BackwardsMappings.java b/common/src/main/java/com/viaversion/viabackwards/api/data/BackwardsMappings.java index c64e3f04..f5594d70 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/data/BackwardsMappings.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/data/BackwardsMappings.java @@ -29,6 +29,7 @@ import com.viaversion.viaversion.api.protocol.Protocol; import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectMap; import com.viaversion.viaversion.libs.fastutil.ints.Int2ObjectOpenHashMap; import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag; +import com.viaversion.viaversion.libs.opennbt.tag.builtin.NumberTag; import com.viaversion.viaversion.libs.opennbt.tag.builtin.StringTag; import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag; import com.viaversion.viaversion.util.Key; @@ -60,11 +61,19 @@ public class BackwardsMappings extends MappingDataBase { if (itemNames != null) { Preconditions.checkNotNull(itemMappings); backwardsItemMappings = new Int2ObjectOpenHashMap<>(itemNames.size()); + + final CompoundTag extraItemData = data.get("itemdata"); for (final Map.Entry entry : itemNames.entrySet()) { final StringTag name = (StringTag) entry.getValue(); final int id = Integer.parseInt(entry.getKey()); - //TODO Custom model data definition - backwardsItemMappings.put(id, new MappedItem(getNewItemId(id), name.getValue())); + Integer customModelData = null; + if (extraItemData != null && extraItemData.contains(entry.getKey())) { + final CompoundTag entryTag = extraItemData.get(entry.getKey()); + final NumberTag customModelDataTag = entryTag.get("custom_model_data"); + customModelData = customModelDataTag != null ? customModelDataTag.asInt() : null; + } + + backwardsItemMappings.put(id, new MappedItem(getNewItemId(id), name.getValue(), customModelData)); } } @@ -72,7 +81,8 @@ public class BackwardsMappings extends MappingDataBase { if (entityNames != null) { this.entityNames = new HashMap<>(entityNames.size()); for (final Map.Entry entry : entityNames.entrySet()) { - this.entityNames.put(entry.getKey(), ((StringTag) entry.getValue()).getValue()); + final StringTag mappedTag = (StringTag) entry.getValue(); + this.entityNames.put(entry.getKey(), mappedTag.getValue()); } } @@ -80,7 +90,8 @@ public class BackwardsMappings extends MappingDataBase { if (soundNames != null) { backwardsSoundMappings = new HashMap<>(soundNames.size()); for (final Map.Entry entry : soundNames.entrySet()) { - backwardsSoundMappings.put(entry.getKey(), ((StringTag) entry.getValue()).getValue()); + final StringTag mappedTag = (StringTag) entry.getValue(); + backwardsSoundMappings.put(entry.getKey(), mappedTag.getValue()); } } } @@ -157,6 +168,6 @@ public class BackwardsMappings extends MappingDataBase { @Override protected @Nullable CompoundTag readNBTFile(final String name) { - return VBMappingDataLoader.loadNBT(name); + return VBMappingDataLoader.loadNBTFromDir(name); } } diff --git a/common/src/main/java/com/viaversion/viabackwards/api/data/VBMappingDataLoader.java b/common/src/main/java/com/viaversion/viabackwards/api/data/VBMappingDataLoader.java index 4de2ef66..ab957483 100644 --- a/common/src/main/java/com/viaversion/viabackwards/api/data/VBMappingDataLoader.java +++ b/common/src/main/java/com/viaversion/viabackwards/api/data/VBMappingDataLoader.java @@ -18,17 +18,12 @@ package com.viaversion.viabackwards.api.data; import com.viaversion.viabackwards.ViaBackwards; -import com.viaversion.viaversion.api.Via; -import com.viaversion.viaversion.api.data.MappingDataLoader; -import com.viaversion.viaversion.libs.fastutil.objects.Object2IntMap; -import com.viaversion.viaversion.libs.gson.JsonArray; -import com.viaversion.viaversion.libs.gson.JsonElement; import com.viaversion.viaversion.libs.gson.JsonIOException; import com.viaversion.viaversion.libs.gson.JsonObject; -import com.viaversion.viaversion.libs.gson.JsonPrimitive; import com.viaversion.viaversion.libs.gson.JsonSyntaxException; import com.viaversion.viaversion.libs.opennbt.NBTIO; import com.viaversion.viaversion.libs.opennbt.tag.builtin.CompoundTag; +import com.viaversion.viaversion.libs.opennbt.tag.builtin.Tag; import com.viaversion.viaversion.util.GsonUtil; import java.io.File; import java.io.FileReader; @@ -53,99 +48,75 @@ public final class VBMappingDataLoader { } } - public static JsonObject loadFromDataDir(String name) { - File file = new File(ViaBackwards.getPlatform().getDataFolder(), name); + /** + * Returns nbt data from the plugin folder or packed assets. + * If a file with the same name exists in the plugin folder, the data of the original packed tag will be merged with the file's tag. + * + * @param name name of the file + * @return nbt data from the plugin folder or packed assets + */ + public static @Nullable CompoundTag loadNBTFromDir(final String name) { + final CompoundTag packedData = loadNBT(name); + + final File file = new File(ViaBackwards.getPlatform().getDataFolder(), name); + if (!file.exists()) { + return packedData; + } + + try { + final CompoundTag fileData = NBTIO.readFile(file, false, false); + return mergeTags(packedData, fileData); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + private static CompoundTag mergeTags(final CompoundTag original, final CompoundTag extra) { + for (final Map.Entry entry : extra.entrySet()) { + if (entry.getValue() instanceof CompoundTag) { + // For compound tags, don't replace the entire tag + final CompoundTag originalEntry = original.get(entry.getKey()); + if (originalEntry != null) { + mergeTags(originalEntry, (CompoundTag) entry.getValue()); + continue; + } + } + + original.put(entry.getKey(), entry.getValue()); + } + return original; + } + + public static JsonObject loadData(final String name) { + try (final InputStream stream = getResource(name)) { + if (stream == null) return null; + return GsonUtil.getGson().fromJson(new InputStreamReader(stream), JsonObject.class); + } catch (final IOException e) { + throw new RuntimeException(e); + } + } + + public static JsonObject loadFromDataDir(final String name) { + final File file = new File(ViaBackwards.getPlatform().getDataFolder(), name); if (!file.exists()) { return loadData(name); } // Load the file from the platform's directory if present - try (FileReader reader = new FileReader(file)) { + try (final FileReader reader = new FileReader(file)) { return GsonUtil.getGson().fromJson(reader, JsonObject.class); - } catch (JsonSyntaxException e) { + } catch (final JsonSyntaxException e) { ViaBackwards.getPlatform().getLogger().warning(name + " is badly formatted!"); e.printStackTrace(); ViaBackwards.getPlatform().getLogger().warning("Falling back to resource's file!"); return loadData(name); - } catch (IOException | JsonIOException e) { + } catch (final IOException | JsonIOException e) { e.printStackTrace(); } return null; } - public static @Nullable InputStream getResource(String name) { + public static @Nullable InputStream getResource(final String name) { return VBMappingDataLoader.class.getClassLoader().getResourceAsStream("assets/viabackwards/data/" + name); } - - public static JsonObject loadData(String name) { - try (InputStream stream = getResource(name)) { - if (stream == null) return null; - return GsonUtil.getGson().fromJson(new InputStreamReader(stream), JsonObject.class); - } catch (IOException e) { - e.printStackTrace(); - return null; - } - } - - public static void mapIdentifiers(int[] output, JsonObject unmappedIdentifiers, JsonObject mappedIdentifiers, JsonObject diffIdentifiers, boolean warnOnMissing) { - Object2IntMap newIdentifierMap = MappingDataLoader.indexedObjectToMap(mappedIdentifiers); - for (Map.Entry entry : unmappedIdentifiers.entrySet()) { - int mappedId = mapIdentifierEntry(entry.getValue().getAsString(), newIdentifierMap, diffIdentifiers, warnOnMissing); - if (mappedId != -1) { - output[Integer.parseInt(entry.getKey())] = mappedId; - } - } - } - - public static void mapIdentifiers(int[] output, JsonArray unmappedIdentifiers, JsonArray mappedIdentifiers, JsonObject diffIdentifiers, boolean warnOnMissing) { - Object2IntMap newIdentifierMap = MappingDataLoader.arrayToMap(mappedIdentifiers); - for (int id = 0; id < unmappedIdentifiers.size(); id++) { - JsonElement unmappedIdentifier = unmappedIdentifiers.get(id); - int mappedId = mapIdentifierEntry(unmappedIdentifier.getAsString(), newIdentifierMap, diffIdentifiers, warnOnMissing); - if (mappedId != -1) { - output[id] = mappedId; - } - } - } - - private static int mapIdentifierEntry(String key, Object2IntMap mappedIdentifiers, @Nullable JsonObject diffIdentifiers, boolean warnOnMissing) { - int mappedId = mappedIdentifiers.getInt(key); - if (mappedId == -1) { - if (diffIdentifiers != null) { - // Search in diff mappings - JsonPrimitive diffValueJson = diffIdentifiers.getAsJsonPrimitive(key); - String diffValue = diffValueJson != null ? diffValueJson.getAsString() : null; - if (diffValue != null && diffValue.isEmpty()) { - return -1; - } - - int dataIndex; - if (diffValue == null && (dataIndex = key.indexOf('[')) != -1 - && (diffValueJson = diffIdentifiers.getAsJsonPrimitive(key.substring(0, dataIndex))) != null) { - // Check for wildcard mappings - diffValue = diffValueJson.getAsString(); - if (diffValue != null && diffValue.isEmpty()) { - return -1; - } - - // Keep original properties if value ends with [ - if (diffValue.endsWith("[")) { - diffValue += key.substring(dataIndex + 1); - } - } - - if (diffValue != null) { - mappedId = mappedIdentifiers.getInt(diffValue); - } - } - - if (mappedId == -1) { - if (warnOnMissing && !Via.getConfig().isSuppressConversionWarnings() || Via.getManager().isDebug()) { - ViaBackwards.getPlatform().getLogger().warning("No key for " + key + " :( "); - } - return -1; - } - } - return mappedId; - } } diff --git a/common/src/main/java/com/viaversion/viabackwards/api/data/VBMappings.java b/common/src/main/java/com/viaversion/viabackwards/api/data/VBMappings.java deleted file mode 100644 index 884b423a..00000000 --- a/common/src/main/java/com/viaversion/viabackwards/api/data/VBMappings.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is part of ViaBackwards - https://github.com/ViaVersion/ViaBackwards - * Copyright (C) 2016-2023 ViaVersion and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package com.viaversion.viabackwards.api.data; - -import com.viaversion.viaversion.api.data.IntArrayMappings; -import com.viaversion.viaversion.api.data.MappingDataLoader; -import com.viaversion.viaversion.api.data.Mappings; -import java.util.Arrays; - -public final class VBMappings extends IntArrayMappings { - - private VBMappings(final int[] oldToNew, final int mappedIds) { - super(oldToNew, mappedIds); - } - - public static Mappings.Builder vbBuilder() { - return new Builder(VBMappings::new); - } - - public static final class Builder extends Mappings.Builder { - - private Builder(final MappingsSupplier supplier) { - super(supplier); - } - - @Override - public VBMappings build() { - final int size = this.size != -1 ? this.size : size(unmapped); - final int mappedSize = this.mappedSize != -1 ? this.mappedSize : size(mapped); - final int[] mappings = new int[size]; - Arrays.fill(mappings, -1); - // Do conversion if one is an array and the other an object, otherwise directly map - if (unmapped.isJsonArray()) { - if (mapped.isJsonObject()) { - VBMappingDataLoader.mapIdentifiers(mappings, toJsonObject(unmapped.getAsJsonArray()), mapped.getAsJsonObject(), diffMappings, warnOnMissing); - } else { - VBMappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonArray(), mapped.getAsJsonArray(), diffMappings, warnOnMissing); - } - } else if (mapped.isJsonArray()) { - VBMappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonObject(), toJsonObject(mapped.getAsJsonArray()), diffMappings, warnOnMissing); - } else { - VBMappingDataLoader.mapIdentifiers(mappings, unmapped.getAsJsonObject(), mapped.getAsJsonObject(), diffMappings, warnOnMissing); - } - return new VBMappings(mappings, mappedSize); - } - } -}