diff --git a/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java b/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java index 6f52ad33..088a01ba 100644 --- a/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java +++ b/src/main/java/ru/bclib/api/datafixer/DataFixerAPI.java @@ -416,7 +416,7 @@ public class DataFixerAPI { for (int z = 0; z < 32; z++) { ChunkPos pos = new ChunkPos(x, z); changed[0] = false; - if (region.hasChunk(pos)) { + if (region.hasChunk(pos) && !state.didFail) { DataInputStream input = region.getChunkDataInputStream(pos); CompoundTag root = NbtIo.read(input); // if ((root.toString().contains("betternether:chest") || root.toString().contains("bclib:chest"))) { @@ -442,6 +442,16 @@ public class DataFixerAPI { CompoundTag blockTagCompound = ((CompoundTag) blockTag); changed[0] |= data.replaceStringFromIDs(blockTagCompound, "Name"); }); + + try { + changed[0] |= data.patchBlockState(palette, ((CompoundTag) tag).getList("BlockStates", Tag.TAG_LONG)); + } + catch (PatchDidiFailException e) { + BCLib.LOGGER.error("Failed fixing BlockState in " + pos); + state.didFail = true; + changed[0] = false; + e.printStackTrace(); + } }); if (changed[0]) { @@ -450,7 +460,6 @@ public class DataFixerAPI { DataOutputStream output = region.getChunkDataOutputStream(pos); NbtIo.write(root, output); output.close(); - } } } @@ -458,7 +467,7 @@ public class DataFixerAPI { region.close(); } catch (Exception e) { - BCLib.LOGGER.error("Failed fixing Player Data."); + BCLib.LOGGER.error("Failed fixing Region."); state.didFail = true; e.printStackTrace(); } diff --git a/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java b/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java index 2cf92fdd..3cc514ce 100644 --- a/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java +++ b/src/main/java/ru/bclib/api/datafixer/MigrationProfile.java @@ -25,6 +25,7 @@ public class MigrationProfile { final Set mods; final Map idReplacements; final List> levelPatchers; + final List> statePatchers; final List worldDataPatchers; final Map> worldDataIDPaths; @@ -46,6 +47,7 @@ public class MigrationProfile { HashMap replacements = new HashMap(); List> levelPatches = new LinkedList<>(); List worldDataPatches = new LinkedList<>(); + List> statePatches = new LinkedList<>(); HashMap> worldDataIDPaths = new HashMap<>(); for (String modID : mods) { @@ -62,6 +64,8 @@ public class MigrationProfile { levelPatches.add(patch.getLevelDatPatcher()); if (patch.getWorldDataPatcher()!=null) worldDataPatches.add(patch); + if (patch.getBlockStatePatcher()!=null) + statePatches.add(patch.getBlockStatePatcher()); DataFixerAPI.LOGGER.info("Applying " + patch); } else { @@ -74,6 +78,7 @@ public class MigrationProfile { this.idReplacements = Collections.unmodifiableMap(replacements); this.levelPatchers = Collections.unmodifiableList(levelPatches); this.worldDataPatchers = Collections.unmodifiableList(worldDataPatches); + this.statePatchers = Collections.unmodifiableList(statePatches); } /** @@ -305,4 +310,12 @@ public class MigrationProfile { } } } + + public boolean patchBlockState(ListTag palette, ListTag states) throws PatchDidiFailException{ + boolean changed = false; + for (PatchBiFunction f : statePatchers) { + changed |= f.apply(palette, states, this); + } + return changed; + } } diff --git a/src/main/java/ru/bclib/api/datafixer/Patch.java b/src/main/java/ru/bclib/api/datafixer/Patch.java index fe025d9e..dafa6dd3 100644 --- a/src/main/java/ru/bclib/api/datafixer/Patch.java +++ b/src/main/java/ru/bclib/api/datafixer/Patch.java @@ -1,6 +1,7 @@ package ru.bclib.api.datafixer; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; import org.jetbrains.annotations.NotNull; import ru.bclib.util.ModUtil; @@ -145,6 +146,22 @@ public abstract class Patch { */ public PatchFunction getWorldDataPatcher() { return null; } + /** + * Return a {@link PatchBiFunction} that is called with pallette and blockstate of + * each chunk in every region. This method is called AFTER all ID replacements + * from {@link #getIDReplacements()} were applied to the pallete. + * + * The first parameter is the palette and the second is the blockstate. + * + * The function needs to return {@code true}, if changes were made to the data. + * If an error occurs, the method should throw a {@link PatchDidiFailException} + * + * The default implementation of this method returns null. + * + * @return {@code true} if changes were applied and we need to save the data + */ + public PatchBiFunction getBlockStatePatcher() { return null; } + /** * Generates ready to use data for all currently registered patches. The list of * patches is selected by the current patch-level of the world. diff --git a/src/main/java/ru/bclib/api/datafixer/PatchBiFunction.java b/src/main/java/ru/bclib/api/datafixer/PatchBiFunction.java new file mode 100644 index 00000000..6bd8da12 --- /dev/null +++ b/src/main/java/ru/bclib/api/datafixer/PatchBiFunction.java @@ -0,0 +1,6 @@ +package ru.bclib.api.datafixer; + +@FunctionalInterface +public interface PatchBiFunction { + R apply(U t, V v, MigrationProfile profile) throws PatchDidiFailException; +} \ No newline at end of file