diff --git a/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java b/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java index 0bc48aae..39845952 100644 --- a/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java +++ b/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java @@ -403,7 +403,7 @@ public class DataFixerAPI { } - private static void fixID(CompoundTag inTag, boolean[] changed, MigrationProfile data, boolean recursive) { + static void fixID(CompoundTag inTag, boolean[] changed, MigrationProfile data, boolean recursive) { final CompoundTag tag = inTag; changed[0] |= data.replaceStringFromIDs(tag, "id"); diff --git a/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java b/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java index 8877c0ff..8ee2416a 100644 --- a/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java +++ b/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java @@ -19,6 +19,7 @@ public class MigrationProfile { final Map idReplacements; final List> levelPatchers; final List worldDataPatchers; + final Map> worldDataIDPaths; private final CompoundTag config; @@ -33,11 +34,16 @@ public class MigrationProfile { HashMap replacements = new HashMap(); List> levelPatches = new LinkedList<>(); List worldDataPatches = new LinkedList<>(); + HashMap> worldDataIDPaths = new HashMap<>(); for (String modID : mods) { + Patch.getALL() .stream() .filter(p -> p.modID.equals(modID)) .forEach(patch -> { + List paths = patch.getWorldDataIDPaths(); + if (paths!=null) worldDataIDPaths.put(modID, paths); + if (currentPatchLevel(modID) < patch.level) { replacements.putAll(patch.getIDReplacements()); if (patch.getLevelDatPatcher()!=null) @@ -51,7 +57,8 @@ public class MigrationProfile { } }); } - + + this.worldDataIDPaths = Collections.unmodifiableMap(worldDataIDPaths); this.idReplacements = Collections.unmodifiableMap(replacements); this.levelPatchers = Collections.unmodifiableList(levelPatches); this.worldDataPatchers = Collections.unmodifiableList(worldDataPatches); @@ -97,7 +104,7 @@ public class MigrationProfile { if (level == parts.length-1) { DataFixerAPI.fixItemArrayWithID(list, changed, this, true); } else { - list.forEach(inTag -> changed[0] |= replaceIDatPath((CompoundTag)inTag, parts, level)); + list.forEach(inTag -> changed[0] |= replaceIDatPath((CompoundTag)inTag, parts, level+1)); } return changed[0]; } @@ -107,12 +114,12 @@ public class MigrationProfile { for (int i=level; i0) { - replaceStringFromIDs(tag, parts[parts.length-1]); + final String key = parts[parts.length-1]; + final byte type = tag.getTagType(key); + if (type == Tag.TAG_LIST) { + final ListTag list = tag.getList(key, 10); + final boolean[] _changed = {false}; + DataFixerAPI.fixItemArrayWithID(list, _changed, this, true); + return _changed[0]; + } else if (type == Tag.TAG_STRING) { + return replaceStringFromIDs(tag, key); + } else if (type == Tag.TAG_COMPOUND) { + final CompoundTag cTag = tag.getCompound(key); + boolean[] _changed = {false}; + DataFixerAPI.fixID(cTag, _changed, this, true); + return _changed[0]; + } } @@ -148,5 +169,17 @@ public class MigrationProfile { WorldDataAPI.saveFile(patch.modID); } } + + for (Map.Entry> entry : worldDataIDPaths.entrySet()){ + CompoundTag root = WorldDataAPI.getRootTag(entry.getKey()); + boolean[] changed = {false}; + entry.getValue().forEach(path -> { + changed[0] |= replaceIDatPath(root, path); + }); + + if (changed[0]){ + WorldDataAPI.saveFile(entry.getKey()); + } + } } } diff --git a/src/main/java/ru/bclib/api/datafixer/Patch.java b/src/main/java/ru/bclib/api/datafixer/Patch.java index 56b1d242..24d4d83e 100644 --- a/src/main/java/ru/bclib/api/datafixer/Patch.java +++ b/src/main/java/ru/bclib/api/datafixer/Patch.java @@ -158,12 +158,37 @@ public abstract class Patch { } /** - * Returns a list of paths,where your mod stores IDs in your {@link ru.bclib.api.WorldDataAPI}-File. + * Returns a list of paths,where your mod may IDs in your {@link ru.bclib.api.WorldDataAPI}-File. *

- * {@link DataFixerAPI} will use information from the latest patch that returns a non-null-result. - * @return {@code null} if nothing changes or a list of Paths in your {@link ru.bclib.api.WorldDataAPI}-File + * {@link DataFixerAPI} will use information from the latest patch that returns a non-null-result. This list is used + * to automatically fix changed IDs from all active patches (see {@link Patch#getIDReplacements()} + *

+ * The end of the path can either be a {@link net.minecraft.nbt.StringTag}, a {@link net.minecraft.nbt.ListTag} or + * a {@link CompoundTag}. If the Path contains a non-leaf {@link net.minecraft.nbt.ListTag}, all members of that + * list will be processed. For example: + *

+	 *     - global +
+	 *              | - key (String)
+	 *              | - items (List) +
+	 *                               | - { id (String) }
+	 *                               | - { id (String) }
+	 * 
+ * The path global.items.id will fix all id-entries in the items-list, while the path + * global.key will only fix the key-entry. + *

+ * if the leaf-entry (= the last part of the path, which would be items in global.items) is a + * {@link CompoundTag}, the system will fix any id entry. If the {@link CompoundTag} contains an item + * or tag.BlockEntityTag entry, the system will recursivley continue with those. If an items + * or inventory-{@link net.minecraft.nbt.ListTag} was found, the system will continue recursivley with + * every item of that list. + *

+ * if the leaf-entry is a {@link net.minecraft.nbt.ListTag}, it is handle the same as a child items entry + * of a {@link CompoundTag}. + * + * @return {@code null} if nothing changes or a list of Paths in your {@link ru.bclib.api.WorldDataAPI}-File. + * Paths are dot-seperated (see {@link ru.bclib.api.WorldDataAPI#getCompoundTag(String, String)}). */ - public List getIIDPathsInWorldDataAPI() { + public List getWorldDataIDPaths() { return null; }