diff --git a/build.gradle.kts b/build.gradle.kts index 1204b93..86f40f8 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -80,7 +80,6 @@ repositories { } dependencies { - compile("com.flowpowered:flow-nbt:1.0.1-SNAPSHOT") compile("io.github.opencubicchunks:regionlib:0.78.0-SNAPSHOT") compile("com.carrotsearch:hppc:0.8.1") compile("com.google.guava:guava:27.0.1-jre") diff --git a/nbt b/nbt index 053e72e..084de4b 160000 --- a/nbt +++ b/nbt @@ -1 +1 @@ -Subproject commit 053e72e7b9e30450d1b75a34899d905196d6bf02 +Subproject commit 084de4b817138e20ab3cd5c76431eeaddc8265ec diff --git a/relocatingConfig.txt b/relocatingConfig.txt index 1a457e9..3ebd7a0 100644 --- a/relocatingConfig.txt +++ b/relocatingConfig.txt @@ -1,27 +1 @@ -cut all #cuts EVERYTHING and replaces it with air (newly generated chunks will be normal) -cut 0 0 0 1 1 1 #Cuts out the area from 0 0 0 to 1 1 1 and replaces it with air -cut 2 0 0 3 1 1 to 5 0 0 #Cut out the area from 2 0 0 to 3 1 1 and moves it TO 5 0 0 (meaning it's at 5 0 0), leaving AIR behind -cut 4 0 0 5 1 1 by 5 0 0 #Cut out the area from 4 0 0 to 5 1 1 and moves it BY 5 0 0 (meaning it's at 9 0 0), leaving AIR behind - -config relight dst off #disables relighting destination cubes from this point - -copy 0 0 0 1 1 1 to 5 0 0 #Copies the area from 0 0 0 to 1 1 1 and moves it TO 5 0 0 (meaning it's at 5 0 0), leaving a COPY behind -copy 2 0 0 3 1 1 by 5 0 0 #Copies the area from 2 0 0 to 3 1 1 and moves it BY 5 0 0 (meaning it's at 7 0 0), leaving a COPY behind - -config relight src off #disables relighting source cubes from this point - -move 0 0 0 1 1 1 to 5 0 0 #Moves the area from 0 0 0 to 1 1 1 and moves it TO 5 0 0 (meaning it's at 5 0 0), The world will regenerate this area -move 2 0 0 3 1 1 by 5 0 0 #Moves the area from 2 0 0 to 3 1 1 and moves it BY 5 0 0 (meaning it's at 7 0 0), The world will regenerate this area - -remove all #removes EVERYTHING. The world will regenerate everything -remove 0 0 0 1 1 1 #Removes the area from 0 0 0 to 1 1 1. The world will regenerate this area - -#first number is the block ID, second is the meta data value -set all to 1 0 #Sets the entire world to stone -set 0 0 0 1 1 1 to 1 0 #Sets the area from 0 0 0 to 1 1 1 to stone - -config relight dst on #re-enable relighting all cubes -config relight src on - -replace all like 0 1 with 1 1 #Replaces every stone with granite -replace 0 0 0 1 1 1 like 0 1 with 1 1 #Replaces all stone with granite in the area 0 0 0 1 1 1 \ No newline at end of file +setpopulated all true diff --git a/src/main/java/cubicchunks/converter/lib/conf/command/EditTaskCommands.java b/src/main/java/cubicchunks/converter/lib/conf/command/EditTaskCommands.java index 298dc75..dae2e56 100644 --- a/src/main/java/cubicchunks/converter/lib/conf/command/EditTaskCommands.java +++ b/src/main/java/cubicchunks/converter/lib/conf/command/EditTaskCommands.java @@ -37,7 +37,6 @@ public class EditTaskCommands { private static final CommandDispatcher dispatcher = new CommandDispatcher<>(); - static { CutCommand.register(dispatcher); CopyCommand.register(dispatcher); @@ -47,6 +46,9 @@ public class EditTaskCommands { SetCommand.register(dispatcher); ReplaceCommand.register(dispatcher); SchematicCommand.register(dispatcher); + ReLightCommand.register(dispatcher); + ReTrackCommand.register(dispatcher); + SetPopulatedCommand.register(dispatcher); ConfigCommand.register(dispatcher); } diff --git a/src/main/java/cubicchunks/converter/lib/conf/command/commands/ReLightCommand.java b/src/main/java/cubicchunks/converter/lib/conf/command/commands/ReLightCommand.java new file mode 100644 index 0000000..2811803 --- /dev/null +++ b/src/main/java/cubicchunks/converter/lib/conf/command/commands/ReLightCommand.java @@ -0,0 +1,45 @@ +/* + * This file is part of CubicChunksConverter, licensed under the MIT License (MIT). + * + * Copyright (c) 2017-2021 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package cubicchunks.converter.lib.conf.command.commands; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import cubicchunks.converter.lib.conf.command.EditTaskContext; +import cubicchunks.converter.lib.conf.command.arguments.BoundingBoxArgument; +import cubicchunks.converter.lib.util.BoundingBox; +import cubicchunks.converter.lib.util.edittask.ReLightEditTask; + +public class ReLightCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(LiteralArgumentBuilder.literal("relight") + .then(RequiredArgumentBuilder.argument("box", new BoundingBoxArgument()) + .executes(info -> { + info.getSource().addEditTask(new ReLightEditTask(info.getArgument("box", BoundingBox.class))); + return 1; + }) + ) + ); + } +} \ No newline at end of file diff --git a/src/main/java/cubicchunks/converter/lib/conf/command/commands/ReTrackCommand.java b/src/main/java/cubicchunks/converter/lib/conf/command/commands/ReTrackCommand.java new file mode 100644 index 0000000..64d9852 --- /dev/null +++ b/src/main/java/cubicchunks/converter/lib/conf/command/commands/ReTrackCommand.java @@ -0,0 +1,45 @@ +/* + * This file is part of CubicChunksConverter, licensed under the MIT License (MIT). + * + * Copyright (c) 2017-2021 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package cubicchunks.converter.lib.conf.command.commands; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import cubicchunks.converter.lib.conf.command.EditTaskContext; +import cubicchunks.converter.lib.conf.command.arguments.BoundingBoxArgument; +import cubicchunks.converter.lib.util.BoundingBox; +import cubicchunks.converter.lib.util.edittask.ReTrackEditTask; + +public class ReTrackCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(LiteralArgumentBuilder.literal("relight") + .then(RequiredArgumentBuilder.argument("box", new BoundingBoxArgument()) + .executes(info -> { + info.getSource().addEditTask(new ReTrackEditTask(info.getArgument("box", BoundingBox.class))); + return 1; + }) + ) + ); + } +} \ No newline at end of file diff --git a/src/main/java/cubicchunks/converter/lib/conf/command/commands/SetPopulatedCommand.java b/src/main/java/cubicchunks/converter/lib/conf/command/commands/SetPopulatedCommand.java new file mode 100644 index 0000000..c633d9b --- /dev/null +++ b/src/main/java/cubicchunks/converter/lib/conf/command/commands/SetPopulatedCommand.java @@ -0,0 +1,53 @@ +/* + * This file is part of CubicChunksConverter, licensed under the MIT License (MIT). + * + * Copyright (c) 2017-2021 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package cubicchunks.converter.lib.conf.command.commands; + +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.arguments.BoolArgumentType; +import com.mojang.brigadier.builder.LiteralArgumentBuilder; +import com.mojang.brigadier.builder.RequiredArgumentBuilder; +import cubicchunks.converter.lib.conf.command.EditTaskContext; +import cubicchunks.converter.lib.conf.command.arguments.BoundingBoxArgument; +import cubicchunks.converter.lib.util.BoundingBox; +import cubicchunks.converter.lib.util.edittask.SetPopulatedEditTask; + +public class SetPopulatedCommand { + public static void register(CommandDispatcher dispatcher) { + dispatcher.register(LiteralArgumentBuilder.literal("setpopulated") + .then(RequiredArgumentBuilder.argument("box", new BoundingBoxArgument()) + .then(RequiredArgumentBuilder.argument("populated", BoolArgumentType.bool()) + .executes(info -> { + info.getSource().addEditTask( + new SetPopulatedEditTask( + info.getArgument("box", BoundingBox.class), + info.getArgument("populated", boolean.class) + ) + ); + return 1; + }) + ) + ) + ); + } +} diff --git a/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCDataConverter.java b/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCDataConverter.java index e2c7e4b..733fb79 100644 --- a/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCDataConverter.java +++ b/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCDataConverter.java @@ -23,13 +23,13 @@ */ package cubicchunks.converter.lib.convert.anvil2cc; -import com.flowpowered.nbt.*; import cubicchunks.converter.lib.conf.ConverterConfig; import cubicchunks.converter.lib.convert.ChunkDataConverter; import cubicchunks.converter.lib.convert.data.AnvilChunkData; import cubicchunks.converter.lib.convert.data.CubicChunksColumnData; import cubicchunks.converter.lib.util.Utils; import cubicchunks.regionlib.impl.EntryLocation2D; +import net.kyori.nbt.*; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; @@ -169,25 +169,31 @@ private CompoundTag extractColumnData(CompoundTag tag) throws IOException { * |- Biomes * |- OpacityIndex */ - CompoundMap levelMap = new CompoundMap(); - CompoundMap srcLevel = (CompoundMap) tag.getValue().get("Level").getValue(); - - int[] srcHeightMap = fixHeightmap((int[]) srcLevel.get("HeightMap").getValue()); - - levelMap.put(new IntTag("v", 1)); - levelMap.put(new IntTag("x", (Integer) srcLevel.get("xPos").getValue())); - levelMap.put(new IntTag("z", (Integer) srcLevel.get("zPos").getValue())); - levelMap.put(srcLevel.getOrDefault("InhabitedTime", new IntTag("InhabitedTime", 0))); - levelMap.put(srcLevel.get("Biomes")); - levelMap.put(new ByteArrayTag("OpacityIndex", makeDummyOpacityIndex(srcHeightMap))); - - CompoundMap rootMap = new CompoundMap(); - rootMap.put(new CompoundTag("Level", levelMap)); - if (tag.getValue().containsKey("DataVersion")) { - rootMap.put(tag.getValue().get("DataVersion")); + CompoundTag level = new CompoundTag(); + CompoundTag srcLevel = tag.getCompound("Level"); + + int[] srcHeightMap = fixHeightmap(srcLevel.getIntArray("HeightMap")); + + level.put("v", new IntTag(1)); + + if(!srcLevel.containsAll(TagType.INT, "xPos", "zPos")) + throw new RuntimeException("Anvil chunk does not contain xPos or zPos!"); + + level.put("x", new IntTag(srcLevel.getInt("xPos"))); + level.put("z", new IntTag(srcLevel.getInt("zPos"))); + level.put("InhabitedTime", new IntTag(srcLevel.getInt("InhabitedTime", 0))); + if(srcLevel.contains("Biomes")) { + level.put("Biomes", srcLevel.get("Biomes")); + } + level.put("OpacityIndex", new ByteArrayTag(makeDummyOpacityIndex(srcHeightMap))); + + CompoundTag root = new CompoundTag(); + root.put("Level", level); + if (tag.contains("DataVersion")) { + root.put("DataVersion", tag.get("DataVersion")); } - return new CompoundTag("", rootMap); + return root; } private int[] fixHeightmap(int[] heights) { @@ -222,7 +228,7 @@ private Map extractCubeData(ByteBuffer vanillaData) throws } @SuppressWarnings("unchecked") - private Map extractCubeData(CompoundTag srcRootTag) { + private Map extractCubeData(CompoundTag srcRoot) { /* * * Vanilla Chunk NBT structure: @@ -277,53 +283,61 @@ private Map extractCubeData(CompoundTag srcRootTag) { * |- LightingInfo * |- LastHeightMap */ - CompoundMap srcRoot = srcRootTag.getValue(); Map tags = new HashMap<>(); - CompoundMap srcLevel = ((CompoundTag) srcRoot.get("Level")).getValue(); - int x = (Integer) srcLevel.get("xPos").getValue(); - int z = (Integer) srcLevel.get("zPos").getValue(); - //noinspection unchecked - for (CompoundTag srcSection : ((ListTag) srcLevel.get("Sections")).getValue()) { - int y = ((ByteTag) srcSection.getValue().get("Y")).getValue(); - - CompoundMap root = new CompoundMap(); + CompoundTag srcLevel = srcRoot.getCompound("Level"); + + if(!srcLevel.containsAll(TagType.INT, "xPos", "zPos")) + throw new RuntimeException("Anvil chunk does not contain xPos or zPos!"); + + int x = srcLevel.getInt("xPos"); + int z = srcLevel.getInt("zPos"); + for (Tag srcSectionTag : srcLevel.getList("Sections")) { + if(srcSectionTag.type() != TagType.COMPOUND) + continue; + + CompoundTag srcSection = ((CompoundTag) srcSectionTag); + int y = srcSection.getByte("Y"); + + CompoundTag root = new CompoundTag(); { - if (srcRoot.containsKey("DataVersion")) { - root.put(srcRoot.get("DataVersion")); + if (srcRoot.contains("DataVersion")) { + root.put("DataVersion", srcRoot.get("DataVersion")); } - CompoundMap level = new CompoundMap(); + CompoundTag level = new CompoundTag(); { - level.put(new ByteTag("v", (byte) 1)); - level.put(new IntTag("x", x)); - level.put(new IntTag("y", y)); - level.put(new IntTag("z", z)); + level.put("v", new ByteTag((byte) 1)); + level.put("x", new IntTag(x)); + level.put("y", new IntTag(y)); + level.put("z", new IntTag(z)); - ByteTag populated = (ByteTag) srcLevel.get("TerrainPopulated"); - level.put(new ByteTag("populated", populated == null ? 0 : populated.getValue())); - level.put(new ByteTag("fullyPopulated", populated == null ? 0 : populated.getValue())); // TODO: handle this properly - level.put(new ByteTag("isSurfaceTracked", (byte) 0)); // so that cubic chunks can re-make surface tracking data on it's own + byte populated = srcLevel.getByte("TerrainPopulated", (byte) 0); + level.put("populated", new ByteTag(populated)); + level.put("fullyPopulated", new ByteTag(populated)); // TODO: handle this properly + level.put("isSurfaceTracked", new ByteTag((byte) 0)); // so that cubic chunks can re-make surface tracking data on it's own - ByteTag lightPopulated = (ByteTag) srcLevel.get("LightPopulated"); - level.put(new ByteTag("initLightDone", lightPopulated == null ? 0 : lightPopulated.getValue())); + byte lightPopulated = srcLevel.getByte("LightPopulated", (byte) 0); + level.put("initLightDone", new ByteTag(lightPopulated)); // the vanilla section has additional Y tag, it will be ignored by cubic chunks - level.put(new ListTag<>("Sections", CompoundTag.class, singletonList(fixSection(srcSection)))); + ListTag sectionsTag = new ListTag(TagType.COMPOUND); + sectionsTag.add(fixSection(srcSection)); + level.put("Sections", sectionsTag); - level.put(filterEntities((ListTag) srcLevel.get("Entities"), y)); - ListTag tileEntities = filterTileEntities((ListTag) srcLevel.get("TileEntities"), y); + level.put("Entities", filterEntities(srcLevel.getList("Entities"), y)); + ListTag tileEntities = filterTileEntities(srcLevel.getList("TileEntities"), y); if (fixMissingTileEntities) { - tileEntities = addMissingTileEntities(x, y, z, (ListTag) tileEntities, srcSection); + tileEntities = addMissingTileEntities(x, y, z, tileEntities, srcSection); } - level.put(tileEntities); - if (srcLevel.containsKey("TileTicks")) { - level.put(filterTileTicks((ListTag) srcLevel.get("TileTicks"), y)); + level.put("TileEntities", tileEntities); + if (srcLevel.contains("TileTicks")) { + level.put("TileTicks", filterTileTicks(srcLevel.getList("TileTicks"), y)); } - level.put(makeLightingInfo(srcLevel)); + level.put("LightingInfo", makeLightingInfo(srcLevel)); } - root.put(new CompoundTag("Level", level)); + root.put("Level", level); } - tags.put(y, new CompoundTag("", root)); + tags.put(y, root); } // make sure the 0-15 range is there because it's using vanilla generator which expects it to be the case for (int y = 0; y < 16; y++) { @@ -334,25 +348,23 @@ private Map extractCubeData(CompoundTag srcRootTag) { return tags; } - private ListTag addMissingTileEntities(int cubeX, int cubeY, int cubeZ, ListTag tileEntities, CompoundTag srcSection) { - CompoundMap section = srcSection.getValue(); - if (!section.containsKey("Blocks")) { + private ListTag addMissingTileEntities(int cubeX, int cubeY, int cubeZ, ListTag tileEntities, CompoundTag section) { + if (!section.contains("Blocks")) { return tileEntities; } - final IntTag zeroTag = new IntTag("", 0); - byte[] blocks = ((ByteArrayTag) section.get("Blocks")).getValue(); - byte[] add = section.containsKey("Add") ? ((ByteArrayTag) section.get("Add")).getValue() : null; - byte[] add2neid = section.containsKey("Add2") ? ((ByteArrayTag) section.get("Add2")).getValue() : null; + byte[] blocks = section.getByteArray("Blocks"); + byte[] add = section.getByteArray("Add", null); + byte[] add2neid = section.getByteArray("Add2", null); Map teMap = new HashMap<>(); - for (CompoundTag tag : tileEntities.getValue()) { - CompoundMap te = tag.getValue(); - int x = ((Number) te.getOrDefault("x", zeroTag).getValue()).intValue(); - int y = ((Number) te.getOrDefault("y", zeroTag).getValue()).intValue(); - int z = ((Number) te.getOrDefault("z", zeroTag).getValue()).intValue(); + for (Tag tag : tileEntities) { + CompoundTag te = (CompoundTag) tag; + int x = te.getInt("x", 0); + int y = te.getInt("y", 0); + int z = te.getInt("z", 0); int idx = y & 0xF << 8 | z & 0xF << 4 | x & 0xF; - teMap.put(idx, tag); + teMap.put(idx, te); } for (int i = 0; i < 4096; i++) { int x = i & 15; @@ -364,16 +376,17 @@ private ListTag addMissingTileEntities(int cubeX, int cubeY, int cu int id = (toAdd << 8) | (blocks[i] & 0xFF); String teId = TE_REGISTRY.get(id); if (teId != null && !teMap.containsKey(i)) { - CompoundMap map = new CompoundMap(); - map.put(new StringTag("id", teId)); - map.put(new IntTag("x", cubeX * 16 + x)); - map.put(new IntTag("y", cubeY * 16 + y)); - map.put(new IntTag("z", cubeZ * 16 + z)); - CompoundTag tag = new CompoundTag("", map); + CompoundTag tag = new CompoundTag(); + tag.put("id", new StringTag(teId)); + tag.put("x", new IntTag(cubeX * 16 + x)); + tag.put("y", new IntTag(cubeY * 16 + y)); + tag.put("z", new IntTag(cubeZ * 16 + z)); teMap.put(i, tag); } } - return new ListTag<>(tileEntities.getName(), CompoundTag.class, new ArrayList<>(teMap.values())); + ListTag tileEntitiesList = new ListTag(TagType.COMPOUND); + tileEntitiesList.addAll(teMap.values()); + return tileEntitiesList; } private static int getNibble(byte[] array, int i) { @@ -383,8 +396,7 @@ private static int getNibble(byte[] array, int i) { } private CompoundTag fixSection(CompoundTag srcSection) { - ByteArrayTag data = (ByteArrayTag) srcSection.getValue().get("Blocks"); - byte[] ids = data.getValue(); + byte[] ids = srcSection.getByteArray("Blocks"); // TODO: handle it the forge way for (int i = 0; i < ids.length; i++) { if (ids[i] == 7) { // bedrock @@ -394,57 +406,58 @@ private CompoundTag fixSection(CompoundTag srcSection) { return srcSection; } - private CompoundTag makeLightingInfo(CompoundMap srcLevel) { - IntArrayTag heightmap = new IntArrayTag("LastHeightMap", (int[]) srcLevel.get("HeightMap").getValue()); - CompoundMap lightingInfoMap = new CompoundMap(); - lightingInfoMap.put(heightmap); - return new CompoundTag("LightingInfo", lightingInfoMap); + private CompoundTag makeLightingInfo(CompoundTag srcLevel) { + IntArrayTag heightmap = new IntArrayTag(srcLevel.getIntArray("HeightMap")); + CompoundTag lightingInfoMap = new CompoundTag(); + lightingInfoMap.put("LastHeightMap", heightmap); + return lightingInfoMap; } - @SuppressWarnings("unchecked") - private ListTag filterEntities(ListTag entities, int cubeY) { + private ListTag filterEntities(ListTag entities, int cubeY) { double yMin = cubeY * 16; double yMax = yMin + 16; - List cubeEntities = new ArrayList<>(); - for (CompoundTag entityTag : entities.getValue()) { - List pos = ((ListTag) entityTag.getValue().get("Pos")).getValue(); - double y = pos.get(1).getValue(); + ListTag cubeEntities = new ListTag(TagType.COMPOUND); + for (Tag entityTag : entities) { + CompoundTag entity = (CompoundTag) entityTag; + ListTag pos = entity.getList("Pos"); + double y = pos.getDouble(1); if (y >= yMin && y < yMax) { - cubeEntities.add(entityTag); + cubeEntities.add(entity); } } - return new ListTag<>(entities.getName(), CompoundTag.class, cubeEntities); + return cubeEntities; } - @SuppressWarnings("unchecked") - private ListTag filterTileEntities(ListTag tileEntities, int cubeY) { + private ListTag filterTileEntities(ListTag tileEntities, int cubeY) { // empty list is list of EndTags - if (tileEntities.getValue().isEmpty()) { + if (tileEntities.isEmpty()) { return tileEntities; } int yMin = cubeY * 16; int yMax = yMin + 16; - List cubeTEs = new ArrayList<>(); - for (CompoundTag teTag : ((ListTag) tileEntities).getValue()) { - int y = ((IntTag) teTag.getValue().get("y")).getValue(); + ListTag cubeTEs = new ListTag(TagType.COMPOUND); + for (Tag tileEntityTag : tileEntities) { + CompoundTag teTag = (CompoundTag) tileEntityTag; + int y = teTag.getInt("y"); if (y >= yMin && y < yMax) { cubeTEs.add(teTag); } } - return new ListTag<>(tileEntities.getName(), CompoundTag.class, cubeTEs); + return cubeTEs; } - private ListTag filterTileTicks(ListTag tileTicks, int cubeY) { + private ListTag filterTileTicks(ListTag tileTicks, int cubeY) { int yMin = cubeY * 16; int yMax = yMin + 16; - List cubeTicks = new ArrayList<>(); - for (CompoundTag tileTick : tileTicks.getValue()) { - int y = ((IntTag) tileTick.getValue().get("y")).getValue(); + ListTag cubeTicks = new ListTag(TagType.COMPOUND); + for (Tag tileTickTag : tileTicks) { + CompoundTag tileTick = (CompoundTag) tileTickTag; + int y = tileTick.getInt("y"); if (y >= yMin && y < yMax) { cubeTicks.add(tileTick); } } - return new ListTag<>(tileTicks.getName(), CompoundTag.class, cubeTicks); + return cubeTicks; } } diff --git a/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCLevelInfoConverter.java b/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCLevelInfoConverter.java index 7cbe593..8407d1f 100644 --- a/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCLevelInfoConverter.java +++ b/src/main/java/cubicchunks/converter/lib/convert/anvil2cc/Anvil2CCLevelInfoConverter.java @@ -23,18 +23,12 @@ */ package cubicchunks.converter.lib.convert.anvil2cc; -import com.flowpowered.nbt.ByteTag; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; -import com.flowpowered.nbt.StringTag; -import com.flowpowered.nbt.Tag; -import com.flowpowered.nbt.stream.NBTInputStream; -import com.flowpowered.nbt.stream.NBTOutputStream; import cubicchunks.converter.lib.Dimensions; import cubicchunks.converter.lib.util.Utils; import cubicchunks.converter.lib.convert.data.AnvilChunkData; import cubicchunks.converter.lib.convert.data.CubicChunksColumnData; import cubicchunks.converter.lib.convert.LevelInfoConverter; +import net.kyori.nbt.*; import java.io.IOException; import java.nio.file.Files; @@ -52,49 +46,28 @@ public Anvil2CCLevelInfoConverter(Path srcDir, Path dstDir) { @Override public void convert() throws IOException { Utils.createDirectories(dstDir); - CompoundTag root; - try (NBTInputStream nbtIn = new NBTInputStream(Files.newInputStream(srcDir.resolve("level.dat"))); - NBTOutputStream nbtOut = new NBTOutputStream(Files.newOutputStream(dstDir.resolve("level.dat")))) { - root = (CompoundTag) nbtIn.readTag(); - CompoundMap newRoot = new CompoundMap(); - for (Tag tag : root.getValue()) { - if (tag.getName().equals("Data")) { - CompoundMap data = ((CompoundTag) root.getValue().get("Data")).getValue(); - CompoundMap newData = new CompoundMap(); - for (Tag dataTag : data) { - if (dataTag.getName().equals("generatorName")) { - String value = (String) dataTag.getValue(); - String newValue; - if (value.equalsIgnoreCase("default")) { - newValue = "VanillaCubic"; - } else { - newValue = value; - } - newData.put(new StringTag(dataTag.getName(), newValue)); - } else { - newData.put(dataTag); - } - } - // put isCubicWorld at the end to overwrite previously existing data, if any - newData.put("isCubicWorld", new ByteTag("isCubicWorld", (byte) 1)); - newRoot.put(new CompoundTag(tag.getName(), newData)); - } else { - newRoot.put(tag); - } - } - Files.createDirectories(dstDir); + CompoundTag root = TagIO.readCompressedPath(TagTypeMaps.MINECRAFT, srcDir.resolve("level.dat")); - nbtOut.writeTag(new CompoundTag(root.getName(), newRoot)); + root.getCompound("Data").put("isCubicWorld", new ByteTag((byte) 1)); - Utils.copyEverythingExcept(srcDir, srcDir, dstDir, file -> - file.toString().contains("level.dat") || file.toString().contains("cubicChunksData.dat") || + String value = root.getCompound("Data").getString("generatorName"); + if (value.equalsIgnoreCase("default")) { + root.getCompound("Data").put("generatorName", new StringTag("VanillaCubic")); + } + + Files.createDirectories(dstDir); + + TagIO.writeCompressedPath(TagTypeMaps.MINECRAFT, root, dstDir.resolve("level.dat")); + + Utils.copyEverythingExcept(srcDir, srcDir, dstDir, + file -> file.toString().contains("level.dat") || + file.toString().contains("cubicChunksData.dat") || Dimensions.getDimensions().stream().anyMatch(dim -> - srcDir.resolve(dim.getDirectory()).resolve("region").equals(file) + srcDir.resolve(dim.getDirectory()).resolve("region").equals(file) ), f -> { } // TODO: counting files - ); - } + ); } } diff --git a/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilDataConverter.java b/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilDataConverter.java index c3bad79..efb34d1 100644 --- a/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilDataConverter.java +++ b/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilDataConverter.java @@ -26,19 +26,13 @@ import static cubicchunks.converter.lib.util.Utils.readCompressedCC; import static cubicchunks.converter.lib.util.Utils.writeCompressed; -import com.flowpowered.nbt.ByteTag; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; -import com.flowpowered.nbt.IntArrayTag; -import com.flowpowered.nbt.IntTag; -import com.flowpowered.nbt.ListTag; -import com.flowpowered.nbt.Tag; import cubicchunks.converter.lib.conf.ConverterConfig; import cubicchunks.converter.lib.convert.ChunkDataConverter; import cubicchunks.converter.lib.convert.data.AnvilChunkData; import cubicchunks.converter.lib.convert.data.CubicChunksColumnData; import cubicchunks.converter.lib.convert.data.MultilayerAnvilChunkData; import cubicchunks.regionlib.impl.MinecraftChunkLocation; +import net.kyori.nbt.*; import java.io.ByteArrayInputStream; import java.io.DataInputStream; @@ -136,29 +130,20 @@ private CompoundTag convertWorldLayer(@Nullable CompoundTag column, CompoundTag[ * |- Biomes * |- OpacityIndex */ - CompoundMap vanillaMap = new CompoundMap(); + CompoundTag vanillaTag; // TODO: we expect DataVersion to be the same as column for all cubes, this is not necessarily true. Can we do something about it? if (column != null) { - for (Tag tag : column.getValue()) { - if ("Level".equals(tag.getName())) { - CompoundMap level = new CompoundMap(); - convertLevel(level, column, cubes, layerIdx); - vanillaMap.put(new CompoundTag("Level", level)); - } else { - vanillaMap.put(tag); - } - } + vanillaTag = column.copy(); } else { - CompoundMap level = new CompoundMap(); - convertLevel(level, null, cubes, layerIdx); - vanillaMap.put(new CompoundTag("Level", level)); + vanillaTag = new CompoundTag(); } + CompoundTag level = convertLevel(column, cubes, layerIdx); + vanillaTag.put("Level", level); - return new CompoundTag("", vanillaMap); - + return vanillaTag; } - private void convertLevel(CompoundMap level, @Nullable CompoundTag column, CompoundTag[] cubes, int layerIdx) { + private CompoundTag convertLevel(@Nullable CompoundTag column, CompoundTag[] cubes, int layerIdx) { /* * * Vanilla Chunk NBT structure: @@ -212,105 +197,85 @@ private void convertLevel(CompoundMap level, @Nullable CompoundTag column, Compo * |- LightingInfo * |- LastHeightMap */ + CompoundTag level; if (column != null) { - CompoundMap columnLevel = (CompoundMap) column.getValue().get("Level").getValue(); - for (Tag tag : columnLevel) { - switch (tag.getName()) { - case "x": - level.put(renamedInt(tag, "xPos")); - break; - case "z": - level.put(renamedInt(tag, "zPos")); - break; - case "OpacityIndex": - level.put(getHeightMap(tag, layerIdx)); - break; - default: - level.put(tag); - } - } + CompoundTag columnLevel = column.getCompound("Level"); + level = columnLevel.copy(); + level.put("xPos", level.remove("x")); + level.put("zPos", level.remove("z")); + level.put("HeightMap", getHeightMap((ByteArrayTag) level.remove("OpacityIndex"), layerIdx)); + } else { + level = new CompoundTag(); } - // TODO: use existing heightmap? Is it safe? - int[] heights = new int[256]; - Arrays.fill(heights, -999); - Tag heightsTag = new IntArrayTag("HeightMap", heights); - level.put(heightsTag); for (CompoundTag cube : cubes) { if (cube != null) { - CompoundTag cubeLevel = (CompoundTag) cube.getValue().get("Level"); - for (Tag tag : cubeLevel.getValue()) { - switch (tag.getName()) { - case "x": - level.put(renamedInt(tag, "xPos")); - break; - case "z": - level.put(renamedInt(tag, "zPos")); - break; - } - } + CompoundTag cubeLevel = cube.getCompound("Level"); + cubeLevel.put("xPos", cubeLevel.remove("x")); + cubeLevel.put("zPos", cubeLevel.remove("z")); break; } } - level.put(getIsPopulated(cubes, layerIdx)); - level.put(new ByteTag("LightPopulated", (byte) 1)); // can't let vanilla recalculate lighting because 1.14.x drops such chunks :( + level.put("TerrainPopulated", getIsPopulated(cubes, layerIdx)); + level.put("LightPopulated", new ByteTag((byte) 1)); // can't let vanilla recalculate lighting because 1.14.x drops such chunks :( + + level.put("Sections", getSections(cubes)); + level.put("Entities", getEntities(cubes)); + level.put("TileEntities", getTileEntities(cubes)); + level.put("TileTicks", getTileTicks(cubes)); - level.put(getSections(cubes)); - level.put(getEntities(cubes)); - level.put(getTileEntities(cubes)); - level.put(getTileTicks(cubes)); + return level; } - private Tag getSections(CompoundTag[] cubes) { - List sections = new ArrayList<>(); + private Tag getSections(CompoundTag[] cubes) { + ListTag sections = new ListTag(TagType.COMPOUND); for (int y = 0; y < cubes.length; y++) { if (cubes[y] == null) { continue; } - CompoundMap oldLevel = (CompoundMap) cubes[y].getValue().get("Level").getValue(); + CompoundTag oldLevel = cubes[y].getCompound("Level"); if (oldLevel.get("Sections") == null) { continue; } - CompoundMap newSection = new CompoundMap(); - @SuppressWarnings("unchecked") - List oldSections = (List) oldLevel.get("Sections").getValue(); - CompoundMap oldSection = oldSections.get(0).getValue(); + CompoundTag newSection = new CompoundTag(); + ListTag oldSections = oldLevel.getList("Sections"); + CompoundTag oldSection = oldSections.getCompound(0); newSection.putAll(oldSection); - newSection.put(new ByteTag("Y", (byte) y)); - sections.add(new CompoundTag("", newSection)); + newSection.put("Y", new ByteTag((byte) y)); + sections.add(newSection); } - return new ListTag<>("Sections", CompoundTag.class, sections); + return sections; } - private Tag getEntities(CompoundTag[] cubes) { - return new ListTag<>("Entities", CompoundTag.class, new ArrayList<>()); + private Tag getEntities(CompoundTag[] cubes) { + return new ListTag(TagType.COMPOUND); } - private Tag getTileEntities(CompoundTag[] cubes) { - return new ListTag<>("TileEntities", CompoundTag.class, new ArrayList<>()); + private Tag getTileEntities(CompoundTag[] cubes) { + return new ListTag(TagType.COMPOUND); } - private Tag getTileTicks(CompoundTag[] cubes) { - return new ListTag<>("TileTicks", CompoundTag.class, new ArrayList<>()); + private Tag getTileTicks(CompoundTag[] cubes) { + return new ListTag(TagType.COMPOUND); } - private Tag getIsPopulated(CompoundTag[] cubes, int layerIdx) { + private Tag getIsPopulated(CompoundTag[] cubes, int layerIdx) { // with default world, only those cubes really matter for (int y = 0; y < 8; y++) { if (cubes[y] == null) { - return new ByteTag("TerrainPopulated", (byte) 0); + return new ByteTag((byte) 0); } - CompoundMap map = (CompoundMap) cubes[y].getValue().get("Level").getValue(); - if ((Byte) map.get("populated").getValue() == 0) { - return new ByteTag("TerrainPopulated", (byte) 0); + CompoundTag map = cubes[y].getCompound("Level"); + if (map.getByte("populated") == 0) { + return new ByteTag((byte) 0); } } - return new ByteTag("TerrainPopulated", (byte) 1); + return new ByteTag((byte) 1); } - private Tag getHeightMap(Tag opacityIndex, int layerIdx) { - byte[] array = (byte[]) opacityIndex.getValue(); + private Tag getHeightMap(ByteArrayTag opacityIndex, int layerIdx) { + byte[] array = opacityIndex.value(); int[] output = new int[256]; ByteArrayInputStream buf = new ByteArrayInputStream(array); try (DataInputStream in = new DataInputStream(buf)) { @@ -329,11 +294,7 @@ private Tag getHeightMap(Tag opacityIndex, int layerIdx) { } catch (IOException e) { throw new Error("ByteArrayInputStream doesn't throw IOException"); } - return new IntArrayTag("HeightMap", output); - } - - private IntTag renamedInt(Tag old, String newName) { - return new IntTag(newName, (Integer) old.getValue()); + return new IntArrayTag(output); } @Override public ConverterConfig getConfig() { diff --git a/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilLevelInfoConverter.java b/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilLevelInfoConverter.java index a15e21d..c9c716c 100644 --- a/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilLevelInfoConverter.java +++ b/src/main/java/cubicchunks/converter/lib/convert/cc2anvil/CC2AnvilLevelInfoConverter.java @@ -23,17 +23,15 @@ */ package cubicchunks.converter.lib.convert.cc2anvil; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; -import com.flowpowered.nbt.StringTag; -import com.flowpowered.nbt.Tag; -import com.flowpowered.nbt.stream.NBTInputStream; -import com.flowpowered.nbt.stream.NBTOutputStream; import cubicchunks.converter.lib.Dimensions; import cubicchunks.converter.lib.util.Utils; import cubicchunks.converter.lib.convert.LevelInfoConverter; import cubicchunks.converter.lib.convert.data.CubicChunksColumnData; import cubicchunks.converter.lib.convert.data.MultilayerAnvilChunkData; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.StringTag; +import net.kyori.nbt.TagIO; +import net.kyori.nbt.TagTypeMaps; import java.io.IOException; import java.nio.file.Files; @@ -51,46 +49,28 @@ public CC2AnvilLevelInfoConverter(Path srcPath, Path dstPath) { @Override public void convert() throws IOException { Utils.forEachDirectory(dstPath, dir -> { - CompoundTag root; - try (NBTInputStream nbtIn = new NBTInputStream(Files.newInputStream(srcPath.resolve("level.dat"))); - NBTOutputStream nbtOut = new NBTOutputStream(Files.newOutputStream(dir.resolve("level.dat")))) { - root = (CompoundTag) nbtIn.readTag(); + CompoundTag root = TagIO.readCompressedPath(TagTypeMaps.MINECRAFT, srcPath.resolve("level.dat")); + + root.remove("isCubicWorld"); + root.getCompound("Data") + .put("generatorName", new StringTag(getGeneratorName(root.getCompound("Data").getString("generatorName")))); - CompoundMap newRoot = new CompoundMap(); - for (Tag tag : root.getValue()) { - if (tag.getName().equals("Data")) { - CompoundTag data = (CompoundTag) tag; - CompoundMap newDataMap = new CompoundMap(); - for (Tag dataTag : data.getValue()) { - if (dataTag.getName().equals("isCubicWorld")) { - continue; - } - if (dataTag.getName().equalsIgnoreCase("generatorName")) { - newDataMap.put(new StringTag(dataTag.getName(), getGeneratorName((String) dataTag.getValue()))); - } else { - newDataMap.put(dataTag); - } - } - newRoot.put(new CompoundTag("Data", newDataMap)); - } else { - newRoot.put(tag); - } - } - Files.createDirectories(dir); + Files.createDirectories(dir); - nbtOut.writeTag(new CompoundTag(root.getName(), newRoot)); + TagIO.writeCompressedPath(TagTypeMaps.MINECRAFT, root, dstPath.resolve("level.dat")); - Utils.copyEverythingExcept(srcPath, srcPath, dir, file -> - file.toString().contains("level.dat") || file.toString().endsWith("custom_generator_settings.json") - || file.toString().endsWith("cubicChunksData.dat") || file.toString().endsWith("cubicchunks_spawncubes.dat") || + Utils.copyEverythingExcept(srcPath, srcPath, dir, + file -> file.toString().contains("level.dat") || + file.toString().endsWith("custom_generator_settings.json") || + file.toString().endsWith("cubicChunksData.dat") || + file.toString().endsWith("cubicchunks_spawncubes.dat") || Dimensions.getDimensions().stream().anyMatch(dim -> - srcPath.resolve(dim.getDirectory()).resolve("region2d").equals(file) - || srcPath.resolve(dim.getDirectory()).resolve("region3d").equals(file) + srcPath.resolve(dim.getDirectory()).resolve("region2d").equals(file) || + srcPath.resolve(dim.getDirectory()).resolve("region3d").equals(file) ), f -> { } // TODO: counting files - ); - } + ); }); } diff --git a/src/main/java/cubicchunks/converter/lib/convert/cc2bigCubeCc/Cc2BigCubeCcLevelInfoConverter.java b/src/main/java/cubicchunks/converter/lib/convert/cc2bigCubeCc/Cc2BigCubeCcLevelInfoConverter.java index 523a0c9..fe80f62 100644 --- a/src/main/java/cubicchunks/converter/lib/convert/cc2bigCubeCc/Cc2BigCubeCcLevelInfoConverter.java +++ b/src/main/java/cubicchunks/converter/lib/convert/cc2bigCubeCc/Cc2BigCubeCcLevelInfoConverter.java @@ -23,17 +23,15 @@ */ package cubicchunks.converter.lib.convert.cc2bigCubeCc; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; -import com.flowpowered.nbt.StringTag; -import com.flowpowered.nbt.Tag; -import com.flowpowered.nbt.stream.NBTInputStream; -import com.flowpowered.nbt.stream.NBTOutputStream; import cubicchunks.converter.lib.Dimensions; import cubicchunks.converter.lib.convert.LevelInfoConverter; import cubicchunks.converter.lib.convert.data.CubicChunksBigCube112Data; import cubicchunks.converter.lib.convert.data.CubicChunksProtoBigCubeData; import cubicchunks.converter.lib.util.Utils; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.StringTag; +import net.kyori.nbt.TagIO; +import net.kyori.nbt.TagTypeMaps; import java.io.IOException; import java.nio.file.Files; @@ -51,49 +49,27 @@ public Cc2BigCubeCcLevelInfoConverter(Path srcDir, Path dstDir) { @Override public void convert() throws IOException { Utils.createDirectories(dstDir); - CompoundTag root; - try (NBTInputStream nbtIn = new NBTInputStream(Files.newInputStream(srcDir.resolve("level.dat"))); - NBTOutputStream nbtOut = new NBTOutputStream(Files.newOutputStream(dstDir.resolve("level.dat")))) { - root = (CompoundTag) nbtIn.readTag(); + CompoundTag root = TagIO.readCompressedPath(TagTypeMaps.MINECRAFT, srcDir.resolve("level.dat")); - CompoundMap newRoot = new CompoundMap(); - for (Tag tag : root.getValue()) { - if (tag.getName().equals("Data")) { - CompoundMap data = ((CompoundTag) root.getValue().get("Data")).getValue(); - CompoundMap newData = new CompoundMap(); - for (Tag dataTag : data) { - if (dataTag.getName().equals("generatorName")) { - String value = (String) dataTag.getValue(); - String newValue; - if (value.equalsIgnoreCase("default")) { - newValue = "VanillaCubic"; - } else { - newValue = value; - } - newData.put(new StringTag(dataTag.getName(), newValue)); - } else { - newData.put(dataTag); - } - } - // put isCubicWorld at the end to overwrite previously existing data, if any - newRoot.put(new CompoundTag(tag.getName(), newData)); - } else { - newRoot.put(tag); - } - } - Files.createDirectories(dstDir); + String value = root.getCompound("Data").getString("generatorName"); + if (value.equalsIgnoreCase("default")) { + root.getCompound("Data").put("generatorName", new StringTag("VanillaCubic")); + } - nbtOut.writeTag(new CompoundTag(root.getName(), newRoot)); + Files.createDirectories(dstDir); + + TagIO.writeCompressedPath(TagTypeMaps.MINECRAFT, root, dstDir.resolve("level.dat")); + + Utils.copyEverythingExcept(srcDir, srcDir, dstDir, + file -> file.toString().contains("level.dat") || + file.toString().contains("cubicChunksData.dat") || + Dimensions.getDimensions().stream().anyMatch(dim -> + srcDir.resolve(dim.getDirectory()).resolve("region2d").equals(file) || + srcDir.resolve(dim.getDirectory()).resolve("region3d").equals(file) + ), + f -> { + } // TODO: counting files + ); - Utils.copyEverythingExcept(srcDir, srcDir, dstDir, file -> - file.toString().contains("level.dat") || file.toString().contains("cubicChunksData.dat") || - Dimensions.getDimensions().stream().anyMatch(dim -> - srcDir.resolve(dim.getDirectory()).resolve("region2d").equals(file) - || srcDir.resolve(dim.getDirectory()).resolve("region3d").equals(file) - ), - f -> { - } // TODO: counting files - ); - } } } diff --git a/src/main/java/cubicchunks/converter/lib/convert/cc2ccrelocating/CC2CCRelocatingDataConverter.java b/src/main/java/cubicchunks/converter/lib/convert/cc2ccrelocating/CC2CCRelocatingDataConverter.java index 486fcde..21665fc 100644 --- a/src/main/java/cubicchunks/converter/lib/convert/cc2ccrelocating/CC2CCRelocatingDataConverter.java +++ b/src/main/java/cubicchunks/converter/lib/convert/cc2ccrelocating/CC2CCRelocatingDataConverter.java @@ -23,16 +23,20 @@ */ package cubicchunks.converter.lib.convert.cc2ccrelocating; -import com.flowpowered.nbt.*; import cubicchunks.converter.lib.Dimension; import cubicchunks.converter.lib.conf.ConverterConfig; import cubicchunks.converter.lib.conf.command.EditTaskCommands; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.convert.ChunkDataConverter; import cubicchunks.converter.lib.convert.data.PriorityCubicChunksColumnData; -import cubicchunks.converter.lib.util.*; +import cubicchunks.converter.lib.util.BoundingBox; +import cubicchunks.converter.lib.util.ImmutablePair; +import cubicchunks.converter.lib.util.Vector2i; +import cubicchunks.converter.lib.util.Vector3i; import cubicchunks.converter.lib.util.edittask.EditTask; import cubicchunks.regionlib.impl.EntryLocation2D; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.TagType; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -162,11 +166,16 @@ Map>> relocateCubeData(D Map>> tagMap = new HashMap<>(); for(Map.Entry> entry : cubeDataOld.entrySet()) { - CompoundMap level = (CompoundMap)entry.getValue().getValue().getValue().get("Level").getValue(); + CompoundTag root = entry.getValue().getValue(); + if(root.contains("Level", TagType.COMPOUND)); + CompoundTag level = root.getCompound("Level"); - int cubeX = (Integer) level.get("x").getValue(); - int cubeY = (Integer) level.get("y").getValue(); - int cubeZ = (Integer) level.get("z").getValue(); + if(!level.containsAll(TagType.INT, "x", "y", "z")) + continue; + + int cubeX = level.getInt("x"); + int cubeY = level.getInt("y"); + int cubeZ = level.getInt("z"); for (EditTask task : this.relocateTasks) { if (!task.handlesDimension(dimension.getDirectory())) { @@ -187,7 +196,7 @@ Map>> relocateCubeData(D if(!cubeIsSrc) continue; - List>> outputCubes = task.actOnCube(new Vector3i(cubeX, cubeY, cubeZ), config, entry.getValue().getValue(), entry.getKey()); + List>> outputCubes = task.actOnCube(new Vector3i(cubeX, cubeY, cubeZ), config, root, entry.getKey()); outputCubes.forEach(positionTagPriority -> { Vector3i cubePos = positionTagPriority.getKey(); diff --git a/src/main/java/cubicchunks/converter/lib/util/Utils.java b/src/main/java/cubicchunks/converter/lib/util/Utils.java index b892e94..df7f44f 100644 --- a/src/main/java/cubicchunks/converter/lib/util/Utils.java +++ b/src/main/java/cubicchunks/converter/lib/util/Utils.java @@ -23,18 +23,10 @@ */ package cubicchunks.converter.lib.util; -import com.flowpowered.nbt.ByteArrayTag; -import com.flowpowered.nbt.ByteTag; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; -import com.flowpowered.nbt.IntArrayTag; -import com.flowpowered.nbt.IntTag; -import com.flowpowered.nbt.ListTag; -import com.flowpowered.nbt.stream.NBTInputStream; -import com.flowpowered.nbt.stream.NBTOutputStream; import cubicchunks.regionlib.impl.EntryLocation3D; import cubicchunks.regionlib.util.CheckedConsumer; import cubicchunks.regionlib.util.CheckedFunction; +import net.kyori.nbt.*; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -170,7 +162,8 @@ private static boolean detectCanCopyAttributesForWSL(Path dstDir) throws IOExcep private static void copyEverythingExceptInternal(Path file, Path srcDir, Path dstDir, Predicate excluded, Consumer onCopy, boolean canCopyAttributes) throws IOException{ try (Stream stream = Files.list(file)) { stream.forEach(f -> { - if (!excluded.test(f)) { + //`__MACOSX` is a metadata folder added by macs to zip archives https://superuser.com/questions/104500/what-is-macosx-folder + if (!excluded.test(f) && !f.endsWith("__MACOSX")) { try { copyFile(f, srcDir, dstDir, canCopyAttributes); if (Files.isRegularFile(f)) { @@ -222,13 +215,12 @@ public static CompoundTag readCompressed(InputStream is) throws IOException { throw new UnsupportedOperationException(); } - return (CompoundTag) new NBTInputStream(data, false).readTag(); + return TagIO.readInputStream(TagTypeMaps.MINECRAFT, data); } public static CompoundTag readCompressedCC(InputStream is) throws IOException { - try (NBTInputStream nbtInputStream = new NBTInputStream(new BufferedInputStream(new GZIPInputStream(is)), false)) { - return (CompoundTag) nbtInputStream.readTag(); - } + BufferedInputStream data = new BufferedInputStream(new GZIPInputStream(is)); + return TagIO.readInputStream(TagTypeMaps.MINECRAFT, data); } public static ByteBuffer writeCompressed(CompoundTag tag, boolean prefixFormat) throws IOException { @@ -236,9 +228,9 @@ public static ByteBuffer writeCompressed(CompoundTag tag, boolean prefixFormat) if (prefixFormat) { bytes.write(1); // mark as GZIP } - try (NBTOutputStream nbtOut = new NBTOutputStream(new BufferedOutputStream(new GZIPOutputStream(bytes)), false)) { - nbtOut.writeTag(tag); - } + BufferedOutputStream output = new BufferedOutputStream(new GZIPOutputStream(bytes)); + TagIO.writeOutputStream(TagTypeMaps.MINECRAFT, tag, output); + output.flush(); return ByteBuffer.wrap(bytes.toByteArray()); } @@ -252,49 +244,48 @@ public static ByteBuffer createAirCubeBuffer(EntryLocation3D loc) { } public static CompoundTag emptyCube(int x, int y, int z) { - CompoundMap root = new CompoundMap(); + CompoundTag root = new CompoundTag(); { - CompoundMap level = new CompoundMap(); + CompoundTag level = new CompoundTag(); { - level.put(new ByteTag("v", (byte) 1)); - level.put(new IntTag("x", x)); - level.put(new IntTag("y", y)); - level.put(new IntTag("z", z)); - - level.put(new ByteTag("populated", true)); - level.put(new ByteTag("fullyPopulated", true)); - level.put(new ByteTag("isSurfaceTracked", true)); // it's empty, no need to re-track + level.put("v", new ByteTag((byte) 1)); + level.put("x", new IntTag(x)); + level.put("y", new IntTag(y)); + level.put("z", new IntTag(z)); + level.put("populated", new ByteTag((byte) 1)); + level.put("fullyPopulated", new ByteTag((byte) 1)); + level.put("isSurfaceTracked", new ByteTag((byte) 1)); // it's empty, no need to re-track - level.put(new ListTag<>("Sections", CompoundTag.class, Collections.singletonList(createEmptySectionTag()))); + // no need for Sections, CC has isEmpty check for that - level.put(new ByteTag("initLightDone", false)); + level.put("initLightDone", new ByteTag((byte) 0)); - level.put(new ListTag<>("Entities", CompoundTag.class, emptyList())); - level.put(new ListTag<>("TileEntities", CompoundTag.class, emptyList())); + level.put("Entities", new ListTag(TagType.COMPOUND)); + level.put("TileEntities", new ListTag(TagType.COMPOUND)); - level.put(makeEmptyLightingInfo()); + level.put("LightingInfo", makeEmptyLightingInfo()); } - root.put(new CompoundTag("Level", level)); + root.put("Level", level); } - return new CompoundTag("", root); + return root; } public static CompoundTag createEmptySectionTag() { - CompoundMap sectionData = new CompoundMap(); - sectionData.put("Blocks", new ByteArrayTag("Blocks", new byte[4096])); - sectionData.put("Data", new ByteArrayTag("Data", new byte[2048])); - sectionData.put("BlockLight", new ByteArrayTag("BlockLight", new byte[2048])); - sectionData.put("SkyLight", new ByteArrayTag("SkyLight", new byte[2048])); + CompoundTag sectionData = new CompoundTag(); + sectionData.put("Blocks", new ByteArrayTag(new byte[4096])); + sectionData.put("Data", new ByteArrayTag(new byte[2048])); + sectionData.put("BlockLight", new ByteArrayTag(new byte[2048])); + sectionData.put("SkyLight", new ByteArrayTag(new byte[2048])); - return new CompoundTag("", sectionData); + return sectionData; } private static CompoundTag makeEmptyLightingInfo() { - IntArrayTag heightmap = new IntArrayTag("LastHeightMap", new int[256]); - CompoundMap lightingInfoMap = new CompoundMap(); - lightingInfoMap.put(heightmap); - return new CompoundTag("LightingInfo", lightingInfoMap); + IntArrayTag heightmap = new IntArrayTag(new int[256]); + CompoundTag lightingInfoMap = new CompoundTag(); + lightingInfoMap.put("LastHeightMap", heightmap); + return lightingInfoMap; } /** diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/BaseEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/BaseEditTask.java index 7280cab..5b67330 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/BaseEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/BaseEditTask.java @@ -23,11 +23,11 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.ByteTag; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.IntArrayTag; import cubicchunks.converter.lib.convert.cc2ccrelocating.CC2CCRelocatingDataConverter; import cubicchunks.converter.lib.util.BoundingBox; +import net.kyori.nbt.ByteTag; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.TagType; import javax.annotation.Nonnull; import java.util.ArrayList; @@ -39,7 +39,7 @@ public abstract class BaseEditTask implements EditTask { protected final List srcBoxes = new ArrayList<>(); protected final List dstBoxes = new ArrayList<>(); - protected static final Logger LOGGER = Logger.getLogger(CC2CCRelocatingDataConverter.class.getSimpleName()); + protected static final Logger LOGGER = Logger.getLogger(BaseEditTask.class.getSimpleName()); @Nonnull @Override public List getSrcBoxes() { return srcBoxes; @@ -49,17 +49,28 @@ public abstract class BaseEditTask implements EditTask { return dstBoxes; } - protected void markCubeForLightUpdates(CompoundMap cubeLevelMap) { - cubeLevelMap.put(new ByteTag("isSurfaceTracked", (byte) 0)); - cubeLevelMap.put(new ByteTag("initLightDone", (byte) 1)); + protected void markCubeForLightUpdates(CompoundTag cubeLevelMap) { + this.markCubeForReSurfaceTrack(cubeLevelMap); - CompoundMap lightingInfo = (CompoundMap) cubeLevelMap.get("LightingInfo").getValue(); - Arrays.fill(((IntArrayTag) lightingInfo.get("LastHeightMap")).getValue(), Integer.MAX_VALUE); - lightingInfo.put(new ByteTag("EdgeNeedSkyLightUpdate", (byte) 1)); + if(!cubeLevelMap.contains("LightingInfo", TagType.COMPOUND)) + return; + + CompoundTag lightingInfo = cubeLevelMap.getCompound("LightingInfo"); + Arrays.fill((lightingInfo.getIntArray("LastHeightMap")), Integer.MAX_VALUE); + lightingInfo.put("EdgeNeedSkyLightUpdate", new ByteTag((byte) 1)); + } + + protected void markCubeForReSurfaceTrack(CompoundTag cubeLevelMap) { + cubeLevelMap.put("isSurfaceTracked", new ByteTag((byte) 0)); + cubeLevelMap.put("initLightDone", new ByteTag((byte) 1)); } - public void markCubePopulated(CompoundMap cubeLevelMap) { - cubeLevelMap.put(new ByteTag("populated", (byte) 1)); - cubeLevelMap.put(new ByteTag("fullyPopulated", (byte) 1)); + public void markCubePopulated(CompoundTag cubeLevelMap, boolean populated) { + byte value = 0; + if (populated) { + value = 1; + } + cubeLevelMap.put("populated", new ByteTag(value)); + cubeLevelMap.put("fullyPopulated", new ByteTag(value)); } } diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/ConfigEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/ConfigEditTask.java index aa74bfb..9d4eabd 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/ConfigEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/ConfigEditTask.java @@ -23,10 +23,10 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; import javax.annotation.Nonnull; import java.util.List; diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/CopyEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/CopyEditTask.java index 2694b8d..4d97f5d 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/CopyEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/CopyEditTask.java @@ -23,17 +23,14 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.*; -import com.flowpowered.nbt.stream.NBTInputStream; -import com.flowpowered.nbt.stream.NBTOutputStream; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.IntTag; import javax.annotation.Nonnull; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UncheckedIOException; import java.util.ArrayList; @@ -55,48 +52,38 @@ public CopyEditTask(BoundingBox srcBox, Vector3i dstOffset) { int cubeY = cubePos.getY(); int cubeZ = cubePos.getZ(); - try { - if(!dstBoxes.get(0).intersects(cubeX, cubeY, cubeZ)) { - //this is just doing a deep copy of the tag by writing to byte array then back again - ByteArrayOutputStream bout = new ByteArrayOutputStream(1024); - NBTOutputStream out = new NBTOutputStream(bout, false); - out.writeTag(cubeTag); + //if required, add the src cube + if(!dstBoxes.get(0).intersects(cubeX, cubeY, cubeZ)) { + CompoundTag copy = cubeTag.copy(); - NBTInputStream is = new NBTInputStream(new ByteArrayInputStream(bout.toByteArray()), false); - CompoundTag tag = (CompoundTag) is.readTag(); - //copy done here ^ - - CompoundMap srcLevel = ((CompoundTag)tag.getValue().get("Level")).getValue(); - if(config.shouldRelightSrc()) { - this.markCubeForLightUpdates(srcLevel); - } - this.markCubePopulated(srcLevel); - - outCubes.add(new ImmutablePair<>(new Vector3i(cubeX, cubeY, cubeZ), new ImmutablePair<>(inCubePriority+1, tag))); + CompoundTag srcLevel = copy.getCompound("Level"); + if(config.shouldRelightSrc()) { + this.markCubeForLightUpdates(srcLevel); } + this.markCubePopulated(srcLevel, true); - CompoundMap level = (CompoundMap) cubeTag.getValue().get("Level").getValue(); + outCubes.add(new ImmutablePair<>(new Vector3i(cubeX, cubeY, cubeZ), new ImmutablePair<>(inCubePriority+1, copy))); + } - int dstX = cubeX + offset.getX(); - int dstY = cubeY + offset.getY(); - int dstZ = cubeZ + offset.getZ(); - level.put(new IntTag("x", dstX)); - level.put(new IntTag("y", dstY)); - level.put(new IntTag("z", dstZ)); + //We always add the dst cube + CompoundTag level = cubeTag.getCompound("Level"); - if(config.shouldRelightDst()) { - this.markCubeForLightUpdates(level); - } - this.markCubePopulated(level); + int dstX = cubeX + offset.getX(); + int dstY = cubeY + offset.getY(); + int dstZ = cubeZ + offset.getZ(); + level.put("x", new IntTag(dstX)); + level.put("y", new IntTag(dstY)); + level.put("z", new IntTag(dstZ)); - this.inplaceMoveTileEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4); - this.inplaceMoveEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4, true); - - outCubes.add(new ImmutablePair<>(new Vector3i(dstX, dstY, dstZ), new ImmutablePair<>(inCubePriority+1, cubeTag))); - } catch (IOException e) { - e.printStackTrace(); - throw new UncheckedIOException(e); + if(config.shouldRelightDst()) { + this.markCubeForLightUpdates(level); } + this.markCubePopulated(level, true); + + this.inplaceMoveTileEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4); + this.inplaceMoveEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4, true); + + outCubes.add(new ImmutablePair<>(new Vector3i(dstX, dstY, dstZ), new ImmutablePair<>(inCubePriority+1, cubeTag))); return outCubes; } } diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/CutEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/CutEditTask.java index a81deb2..2b1d5a4 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/CutEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/CutEditTask.java @@ -23,13 +23,11 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.*; -import com.flowpowered.nbt.stream.NBTInputStream; -import com.flowpowered.nbt.stream.NBTOutputStream; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.*; import javax.annotation.Nonnull; import java.io.ByteArrayInputStream; @@ -64,70 +62,56 @@ public CutEditTask(BoundingBox srcBox, Vector3i dstOffset) { int cubeY = cubePos.getY(); int cubeZ = cubePos.getZ(); - try { - //clearing data from old cube - if(offset == null || !exclusiveDstBox.intersects(cubeX, cubeY, cubeZ)) { - //this is just doing a deep copy of the tag by writing to byte array then back again - ByteArrayOutputStream bout = new ByteArrayOutputStream(1024); - NBTOutputStream out = new NBTOutputStream(bout, false); - out.writeTag(cubeTag); - - NBTInputStream is = new NBTInputStream(new ByteArrayInputStream(bout.toByteArray()), false); - CompoundTag tag = (CompoundTag) is.readTag(); - //copy done here ^ - CompoundMap srcLevel = (CompoundMap) (tag).getValue().get("Level").getValue(); - ListTag sectionsTag = (ListTag) srcLevel.get("Sections"); - - //handle edge-case where cube exists but sections array is null - CompoundMap sectionDetails = sectionsTag == null || sectionsTag.getValue().isEmpty() ? null : - ((CompoundTag)sectionsTag.getValue().get(0)).getValue(); - - if(sectionDetails != null) { - //remove optional "Additional" block data array - sectionDetails.remove("Add"); - - ByteArrayTag emptyArray = new ByteArrayTag("", new byte[0]); - Arrays.fill((byte[]) sectionDetails.getOrDefault("Blocks", emptyArray).getValue(), (byte) 0); - Arrays.fill((byte[]) sectionDetails.getOrDefault("Data", emptyArray).getValue(), (byte) 0); - Arrays.fill((byte[]) sectionDetails.getOrDefault("BlockLight", emptyArray).getValue(), (byte) 0); - Arrays.fill((byte[]) sectionDetails.getOrDefault("SkyLight", emptyArray).getValue(), (byte) 0); - } - - if(config.shouldRelightSrc()) { - this.markCubeForLightUpdates(srcLevel); - } - this.markCubePopulated(srcLevel); - - srcLevel.put(new ListTag<>("TileTicks", CompoundTag.class, new ArrayList<>())); - srcLevel.put(new ListTag<>("Entities", CompoundTag.class, new ArrayList<>())); - srcLevel.put(new ListTag<>("TileEntities", CompoundTag.class, new ArrayList<>())); - - outCubes.add(new ImmutablePair<>(new Vector3i(cubeX, cubeY, cubeZ), new ImmutablePair<>(inCubePriority+1, tag))); + //clearing data from old cube + if(offset == null || !exclusiveDstBox.intersects(cubeX, cubeY, cubeZ)) { + CompoundTag tag = cubeTag.copy(); + + CompoundTag srcLevel = tag.getCompound("Level"); + ListTag sectionsTag = srcLevel.getList("Sections"); + + //handle edge-case where cube exists but sections array is null + CompoundTag sectionDetails = sectionsTag.isEmpty() ? null : sectionsTag.getCompound(0); + if(sectionDetails != null) { + //remove optional "Additional" block data array + sectionDetails.remove("Add"); + + Arrays.fill(sectionDetails.getByteArray("Blocks"), (byte) 0); + Arrays.fill(sectionDetails.getByteArray("Data"), (byte) 0); + Arrays.fill(sectionDetails.getByteArray("BlockLight"), (byte) 0); + Arrays.fill(sectionDetails.getByteArray("SkyLight"), (byte) 0); + } + + if(config.shouldRelightSrc()) { + this.markCubeForLightUpdates(srcLevel); } + this.markCubePopulated(srcLevel, true); - // adjusting new cube data to be valid - CompoundMap level = (CompoundMap)cubeTag.getValue().get("Level").getValue(); - if (offset != null && !offset.equals(new Vector3i(0, 0, 0))) { - int dstX = cubeX + offset.getX(); - int dstY = cubeY + offset.getY(); - int dstZ = cubeZ + offset.getZ(); - level.put(new IntTag("x", dstX)); - level.put(new IntTag("y", dstY)); - level.put(new IntTag("z", dstZ)); - - if(config.shouldRelightDst()) { - this.markCubeForLightUpdates(level); - } - this.markCubePopulated(level); - - this.inplaceMoveTileEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4); - this.inplaceMoveEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4, false); - - outCubes.add(new ImmutablePair<>(new Vector3i(dstX, dstY, dstZ), new ImmutablePair<>(inCubePriority+1, cubeTag))); + srcLevel.remove("TileTicks"); + srcLevel.remove("Entities"); + srcLevel.remove("TileEntities"); + + outCubes.add(new ImmutablePair<>(new Vector3i(cubeX, cubeY, cubeZ), new ImmutablePair<>(inCubePriority+1, tag))); + } + + // adjusting new cube data to be valid + CompoundTag level = cubeTag.getCompound("Level"); + if (offset != null && !offset.equals(new Vector3i(0, 0, 0))) { + int dstX = cubeX + offset.getX(); + int dstY = cubeY + offset.getY(); + int dstZ = cubeZ + offset.getZ(); + level.put("x", new IntTag(dstX)); + level.put("y", new IntTag(dstY)); + level.put("z", new IntTag(dstZ)); + + if(config.shouldRelightDst()) { + this.markCubeForLightUpdates(level); } - } catch(IOException e) { - e.printStackTrace(); - throw new UncheckedIOException(e); + this.markCubePopulated(level, true); + + this.inplaceMoveTileEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4); + this.inplaceMoveEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4, false); + + outCubes.add(new ImmutablePair<>(new Vector3i(dstX, dstY, dstZ), new ImmutablePair<>(inCubePriority+1, cubeTag))); } return outCubes; } diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/EditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/EditTask.java index 85c9907..30dc870 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/EditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/EditTask.java @@ -23,12 +23,11 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; import javax.annotation.Nonnull; import java.util.ArrayList; @@ -37,7 +36,7 @@ public interface EditTask { /** * @param cubeTag The cube to be modified. The {@link Vector3i} is in cube coordinates, not block - * @return The modified cube/s. The {@link CompoundMap} can be null, if so the cube will be regenerated the next time it's loaded by the game + * @return The modified cube/s. The {@link CompoundTag} can be null, if so the cube will be regenerated the next time it's loaded by the game */ @Nonnull List>> actOnCube(Vector3i cubePos, EditTaskContext.EditTaskConfig config, CompoundTag cubeTag, long inCubePriority); diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/KeepEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/KeepEditTask.java index dbf1908..7dc80c2 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/KeepEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/KeepEditTask.java @@ -23,11 +23,11 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; import javax.annotation.Nonnull; import java.util.List; diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/MoveEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/MoveEditTask.java index 43bf80c..3630e35 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/MoveEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/MoveEditTask.java @@ -23,15 +23,16 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; -import com.flowpowered.nbt.IntTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.IntTag; import javax.annotation.Nonnull; +import java.io.IOException; +import java.io.UncheckedIOException; import java.util.ArrayList; import java.util.List; @@ -52,17 +53,17 @@ public MoveEditTask(BoundingBox srcBox, Vector3i dstOffset) { outCubes.add(new ImmutablePair<>(cubePos, new ImmutablePair<>(inCubePriority+1, null))); return outCubes; } - CompoundMap level = (CompoundMap) cubeTag.getValue().get("Level").getValue(); + CompoundTag level = cubeTag.getCompound("Level"); Vector3i dstPos = cubePos.add(offset); - level.put(new IntTag("x", dstPos.getX())); - level.put(new IntTag("y", dstPos.getY())); - level.put(new IntTag("z", dstPos.getZ())); + level.put("x", new IntTag(dstPos.getX())); + level.put("y", new IntTag(dstPos.getY())); + level.put("z", new IntTag(dstPos.getZ())); if(config.shouldRelightDst()) { this.markCubeForLightUpdates(level); } - this.markCubePopulated(level); + this.markCubePopulated(level, true); this.inplaceMoveTileEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4); this.inplaceMoveEntitiesBy(level, offset.getX() << 4, offset.getY() << 4, offset.getZ() << 4, false); diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/ReLightEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/ReLightEditTask.java new file mode 100644 index 0000000..6893fff --- /dev/null +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/ReLightEditTask.java @@ -0,0 +1,51 @@ +/* + * This file is part of CubicChunksConverter, licensed under the MIT License (MIT). + * + * Copyright (c) 2017-2021 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package cubicchunks.converter.lib.util.edittask; + +import com.google.common.collect.Lists; +import cubicchunks.converter.lib.conf.command.EditTaskContext; +import cubicchunks.converter.lib.util.BoundingBox; +import cubicchunks.converter.lib.util.ImmutablePair; +import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; + +import javax.annotation.Nonnull; +import java.util.List; + +public class ReLightEditTask extends BaseEditTask { + public ReLightEditTask(BoundingBox affectedBox) { + srcBoxes.add(affectedBox); + dstBoxes.add(affectedBox); + } + + @Nonnull + @Override + public List>> actOnCube(Vector3i cubePos, EditTaskContext.EditTaskConfig config, CompoundTag cubeTag, long inCubePriority) { + CompoundTag level = cubeTag.getCompound("Level"); + + this.markCubeForLightUpdates(level); + + return Lists.newArrayList(new ImmutablePair<>(cubePos, new ImmutablePair<>(inCubePriority+1, cubeTag))); + } +} diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/ReTrackEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/ReTrackEditTask.java new file mode 100644 index 0000000..9d7ec3a --- /dev/null +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/ReTrackEditTask.java @@ -0,0 +1,51 @@ +/* + * This file is part of CubicChunksConverter, licensed under the MIT License (MIT). + * + * Copyright (c) 2017-2021 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package cubicchunks.converter.lib.util.edittask; + +import com.google.common.collect.Lists; +import cubicchunks.converter.lib.conf.command.EditTaskContext; +import cubicchunks.converter.lib.util.BoundingBox; +import cubicchunks.converter.lib.util.ImmutablePair; +import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; + +import javax.annotation.Nonnull; +import java.util.List; + +public class ReTrackEditTask extends BaseEditTask { + public ReTrackEditTask(BoundingBox affectedBox) { + srcBoxes.add(affectedBox); + dstBoxes.add(affectedBox); + } + + @Nonnull + @Override + public List>> actOnCube(Vector3i cubePos, EditTaskContext.EditTaskConfig config, CompoundTag cubeTag, long inCubePriority) { + CompoundTag level = cubeTag.getCompound("Level"); + + this.markCubeForReSurfaceTrack(level); + + return Lists.newArrayList(new ImmutablePair<>(cubePos, new ImmutablePair<>(inCubePriority+1, cubeTag))); + } +} diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/RemoveEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/RemoveEditTask.java index 18a21a5..3ef6b5e 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/RemoveEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/RemoveEditTask.java @@ -23,11 +23,11 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; import javax.annotation.Nonnull; import java.util.ArrayList; diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/ReplaceEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/ReplaceEditTask.java index 50f69a7..2ba41c7 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/ReplaceEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/ReplaceEditTask.java @@ -23,12 +23,12 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.TagType; import javax.annotation.Nonnull; import java.util.ArrayList; @@ -53,22 +53,18 @@ public ReplaceEditTask(BoundingBox srcBox, byte inBlockID, byte inBlockMeta, byt @Nonnull @Override public List>> actOnCube(Vector3i cubePos, EditTaskContext.EditTaskConfig config, CompoundTag cubeTag, long inCubePriority) { List>> outCubes = new ArrayList<>(); - CompoundMap level = (CompoundMap) cubeTag.getValue().get("Level").getValue(); + CompoundTag level = cubeTag.getCompound("Level"); if(config.shouldRelightDst()) { this.markCubeForLightUpdates(level); } - this.markCubePopulated(level); + this.markCubePopulated(level, true); - CompoundMap sectionDetails; - try { - sectionDetails = ((CompoundTag)((List) (level).get("Sections").getValue()).get(0)).getValue(); //POSSIBLE ARRAY OUT OF BOUNDS EXCEPTION ON A MALFORMED CUBE - } catch(NullPointerException | ArrayIndexOutOfBoundsException e) { - LOGGER.warning("Malformed cube at position (" + cubePos.getX() + ", " + cubePos.getY() + ", " + cubePos.getZ() + "), skipping!"); - return outCubes; - } + CompoundTag sectionDetails = level.getList("Sections", TagType.COMPOUND).getCompound(0); - byte[] blocks = (byte[]) sectionDetails.get("Blocks").getValue(); - byte[] meta = (byte[]) sectionDetails.get("Data").getValue(); + byte[] blocks = sectionDetails.getByteArray("Blocks"); + byte[] meta = sectionDetails.getByteArray("Data"); + if(blocks.length != 4096 || meta.length != 2048) + throw new RuntimeException("Cube contains invalid Blocks or Data arrays!"); if(inBlockMeta == -1) { //-1 is a sentinel flag, meaning "any block metadata" for (int i = 0; i < 4096; i++) { diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/SchematicTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/SchematicTask.java index 7e4b009..6203db0 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/SchematicTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/SchematicTask.java @@ -23,11 +23,11 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; -import com.flowpowered.nbt.ListTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.*; +import net.kyori.nbt.CompoundTag; +import net.kyori.nbt.ListTag; +import net.kyori.nbt.TagType; import java.util.ArrayList; import java.util.Collections; @@ -133,28 +133,30 @@ public boolean handlesDimension(String dirName) { @Nonnull @Override public List>> actOnCube(Vector3i cubePos, EditTaskContext.EditTaskConfig config, - CompoundTag cubeTag, long inCubePriority) { + CompoundTag cubeTag, long inCubePriority) { List>> outCubes = new ArrayList<>(); - CompoundMap level = (CompoundMap) cubeTag.getValue().get("Level").getValue(); + CompoundTag level = cubeTag.getCompound("Level"); if(config.shouldRelightDst()) { this.markCubeForLightUpdates(level); } - this.markCubePopulated(level); + this.markCubePopulated(level, true); - CompoundMap sectionDetails; + CompoundTag sectionDetails; try { - if (!level.containsKey("Sections")) { - level.put(new ListTag<>("Sections", CompoundTag.class, Collections.singletonList(Utils.createEmptySectionTag()))); + if (!level.contains("Sections")) { + ListTag tags = new ListTag(TagType.COMPOUND); + tags.add(Utils.createEmptySectionTag()); + level.put("Sections", tags); } - sectionDetails = ((CompoundTag)((List) (level).get("Sections").getValue()).get(0)).getValue(); //POSSIBLE ARRAY OUT OF BOUNDS EXCEPTION ON A MALFORMED CUBE + sectionDetails = ((CompoundTag)((List) (level).get("Sections")).get(0)); //POSSIBLE ARRAY OUT OF BOUNDS EXCEPTION ON A MALFORMED CUBE } catch(NullPointerException | ArrayIndexOutOfBoundsException e) { LOGGER.warning("Malformed cube at position (" + cubePos.getX() + ", " + cubePos.getY() + ", " + cubePos.getZ() + "), skipping!"); return outCubes; } - byte[] blocks = (byte[]) sectionDetails.get("Blocks").getValue(); - byte[] meta = (byte[]) sectionDetails.get("Data").getValue(); + byte[] blocks = sectionDetails.getByteArray("Blocks"); + byte[] meta = sectionDetails.getByteArray("Data"); int baseX = cubePos.getX() * 16; int baseY = cubePos.getY() * 16; diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/SetEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/SetEditTask.java index 262af54..94a104b 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/SetEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/SetEditTask.java @@ -23,12 +23,11 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.CompoundMap; -import com.flowpowered.nbt.CompoundTag; import cubicchunks.converter.lib.conf.command.EditTaskContext; import cubicchunks.converter.lib.util.BoundingBox; import cubicchunks.converter.lib.util.ImmutablePair; import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; import javax.annotation.Nonnull; import java.util.ArrayList; @@ -49,21 +48,16 @@ public SetEditTask(BoundingBox srcBox, byte blockID, byte blockMeta) { @Nonnull @Override public List>> actOnCube(Vector3i cubePos, EditTaskContext.EditTaskConfig config, CompoundTag cubeTag, long inCubePriority) { List>> outCubes = new ArrayList<>(); - CompoundMap level = (CompoundMap) cubeTag.getValue().get("Level").getValue(); + CompoundTag level = cubeTag.getCompound("Level"); if(config.shouldRelightDst()) { this.markCubeForLightUpdates(level); } - this.markCubePopulated(level); + this.markCubePopulated(level, true); - CompoundMap sectionDetails; - try { - sectionDetails = ((CompoundTag)((List) (level).get("Sections").getValue()).get(0)).getValue(); //POSSIBLE ARRAY OUT OF BOUNDS EXCEPTION ON A MALFORMED CUBE - } catch(NullPointerException | ArrayIndexOutOfBoundsException e) { - LOGGER.warning("Malformed cube at position (" + cubePos.getX() + ", " + cubePos.getY() + ", " + cubePos.getZ() + "), skipping!"); - return outCubes; - } - Arrays.fill((byte[]) sectionDetails.get("Blocks").getValue(), blockID); - Arrays.fill((byte[]) sectionDetails.get("Data").getValue(), (byte) (blockMeta | blockMeta << 4)); + CompoundTag sectionDetails = level.getList("Sections").getCompound(0); //POSSIBLE ARRAY OUT OF BOUNDS EXCEPTION ON A MALFORMED CUBE + + Arrays.fill(sectionDetails.getByteArray("Blocks"), blockID); + Arrays.fill(sectionDetails.getByteArray("Data"), (byte) (blockMeta | blockMeta << 4)); outCubes.add(new ImmutablePair<>(cubePos, new ImmutablePair<>(inCubePriority+1, cubeTag))); return outCubes; diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/SetPopulatedEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/SetPopulatedEditTask.java new file mode 100644 index 0000000..a4a3224 --- /dev/null +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/SetPopulatedEditTask.java @@ -0,0 +1,55 @@ +/* + * This file is part of CubicChunksConverter, licensed under the MIT License (MIT). + * + * Copyright (c) 2017-2021 contributors + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package cubicchunks.converter.lib.util.edittask; + +import com.google.common.collect.Lists; +import cubicchunks.converter.lib.conf.command.EditTaskContext; +import cubicchunks.converter.lib.util.BoundingBox; +import cubicchunks.converter.lib.util.ImmutablePair; +import cubicchunks.converter.lib.util.Vector3i; +import net.kyori.nbt.CompoundTag; + +import javax.annotation.Nonnull; +import java.util.List; + +public class SetPopulatedEditTask extends BaseEditTask { + private final boolean populated; + + public SetPopulatedEditTask(BoundingBox affectedBox, boolean populated) { + srcBoxes.add(affectedBox); + dstBoxes.add(affectedBox); + + this.populated = populated; + } + + @Nonnull + @Override + public List>> actOnCube(Vector3i cubePos, EditTaskContext.EditTaskConfig config, CompoundTag cubeTag, long inCubePriority) { + CompoundTag level = cubeTag.getCompound("Level"); + + this.markCubePopulated(level, this.populated); + + return Lists.newArrayList(new ImmutablePair<>(cubePos, new ImmutablePair<>(inCubePriority+1, cubeTag))); + } +} \ No newline at end of file diff --git a/src/main/java/cubicchunks/converter/lib/util/edittask/TranslationEditTask.java b/src/main/java/cubicchunks/converter/lib/util/edittask/TranslationEditTask.java index 297c528..f38b448 100644 --- a/src/main/java/cubicchunks/converter/lib/util/edittask/TranslationEditTask.java +++ b/src/main/java/cubicchunks/converter/lib/util/edittask/TranslationEditTask.java @@ -23,41 +23,50 @@ */ package cubicchunks.converter.lib.util.edittask; -import com.flowpowered.nbt.*; +import net.kyori.nbt.*; -import java.util.ArrayList; -import java.util.List; import java.util.UUID; public abstract class TranslationEditTask extends BaseEditTask { - protected void inplaceMoveTileEntitiesBy(CompoundMap cubeLevel, int blockX, int blockY, int blockZ) { - List tileEntities = ((ListTag) cubeLevel.get("TileEntities")).getValue(); - for (int idx = 0, size = tileEntities.size(); idx < size; idx++) { - CompoundMap tileEntityData = tileEntities.get(idx).getValue(); - tileEntityData.put("x", new IntTag("x", ((IntTag)tileEntityData.get("x")).getValue() + blockX)); - tileEntityData.put("y", new IntTag("y", ((IntTag)tileEntityData.get("y")).getValue() + blockY)); - tileEntityData.put("z", new IntTag("z", ((IntTag)tileEntityData.get("z")).getValue() + blockZ)); + protected void inplaceMoveTileEntitiesBy(CompoundTag cubeLevel, int blockX, int blockY, int blockZ) { + ListTag tileEntities = cubeLevel.getList("TileEntities"); + if(tileEntities.type() != TagType.COMPOUND) + return; + + for (Tag tileEntity : tileEntities) { + CompoundTag tileEntityData = (CompoundTag) tileEntity; + if(!(tileEntityData.containsAll(TagType.INT, "x", "y", "z"))) + throw new RuntimeException("TileEntity data did not contain INT tags x, y, z"); + + tileEntityData.put("x", new IntTag((tileEntityData.getInt("x") + blockX))); + tileEntityData.put("y", new IntTag((tileEntityData.getInt("y") + blockY))); + tileEntityData.put("z", new IntTag((tileEntityData.getInt("z") + blockZ))); } } - protected void inplaceMoveEntitiesBy(CompoundMap cubeLevel, int blockX, int blockY, int blockZ, boolean replaceUUIDs) { - List entities = ((ListTag) cubeLevel.get("Entities")).getValue(); + protected void inplaceMoveEntitiesBy(CompoundTag cubeLevel, int blockX, int blockY, int blockZ, boolean replaceUUIDs) { + ListTag entities = cubeLevel.getList("Entities"); + if(entities.type() != TagType.COMPOUND) + return; + for (int idx = 0, size = entities.size(); idx < size; idx++) { - CompoundMap entityData = entities.get(idx).getValue(); - List pos = ((ListTag) entityData.get("Pos")).getValue(); - List newPos = new ArrayList<>(); + CompoundTag entityData = entities.getCompound(idx); + ListTag pos = entityData.getList("Pos", TagType.DOUBLE); + if(pos.size() < 3) + throw new RuntimeException("TileEntity data did not contain INT tags x, y, z"); + + ListTag newPos = new ListTag(TagType.DOUBLE); - //they don't have names WHAT, ordered x, y, z - newPos.add(new DoubleTag("", pos.get(0).getValue() + blockX)); - newPos.add(new DoubleTag("", pos.get(1).getValue() + blockY)); - newPos.add(new DoubleTag("", pos.get(2).getValue() + blockZ)); + newPos.add(new DoubleTag(pos.getDouble(0) + blockX)); + newPos.add(new DoubleTag(pos.getDouble(1) + blockY)); + newPos.add(new DoubleTag(pos.getDouble(2) + blockZ)); - entityData.put(new ListTag<>("Pos", DoubleTag.class, newPos)); + entityData.put("Pos", newPos); if(replaceUUIDs) { UUID uuid = UUID.randomUUID(); - entityData.put(new LongTag("UUIDLeast", uuid.getLeastSignificantBits())); - entityData.put(new LongTag("UUIDMost", uuid.getMostSignificantBits())); + entityData.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits())); + entityData.put("UUIDMost", new LongTag(uuid.getMostSignificantBits())); } } }