From a07d7d052690419d2881de6ff7ea2dea8c2e5607 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 21 Jul 2024 13:33:00 +0200 Subject: [PATCH 01/21] Sync mixin and asm versions between common and tweaker --- build.gradle | 8 +++----- gradle.properties | 7 ++++++- tweaker/build.gradle | 12 ++++++------ 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 822832aad..5f3776219 100755 --- a/build.gradle +++ b/build.gradle @@ -78,11 +78,9 @@ allprojects { } dependencies { - implementation "org.spongepowered:mixin:0.8.5" - implementation "org.ow2.asm:asm:9.3" - // The following line declares the yarn mappings you may select this one as well. - // mappings "net.fabricmc:yarn:1.17.1+build.32:v2" - //launchImplementation('dev.babbaj:nether-pathfinder:1.3.0') + compileOnly "org.spongepowered:mixin:${project.mixin_version}" + compileOnly "org.ow2.asm:asm:${project.asm_version}" + implementation "dev.babbaj:nether-pathfinder:${project.nether_pathfinder_version}" } diff --git a/gradle.properties b/gradle.properties index 77516438f..845c524f6 100644 --- a/gradle.properties +++ b/gradle.properties @@ -12,4 +12,9 @@ forge_version=45.0.43 fabric_version=0.14.11 -nether_pathfinder_version=1.4.1 \ No newline at end of file +nether_pathfinder_version=1.4.1 + +// These dependencies are used for common and tweaker +// while mod loaders usually ship their own version +mixin_version=0.8.5 +asm_version=9.3 diff --git a/tweaker/build.gradle b/tweaker/build.gradle index d4345485b..3e4758c87 100644 --- a/tweaker/build.gradle +++ b/tweaker/build.gradle @@ -38,14 +38,14 @@ configurations { } dependencies { - implementation "org.spongepowered:mixin:0.8.5" + implementation "org.spongepowered:mixin:${project.mixin_version}" // for some reason mixin isn't including these... - implementation "org.ow2.asm:asm:9.3" - implementation "org.ow2.asm:asm-tree:9.3" - implementation "org.ow2.asm:asm-commons:9.3" - implementation "org.ow2.asm:asm-util:9.3" - implementation "org.ow2.asm:asm-analysis:9.3" + implementation "org.ow2.asm:asm:${project.asm_version}" + implementation "org.ow2.asm:asm-tree:${project.asm_version}" + implementation "org.ow2.asm:asm-commons:${project.asm_version}" + implementation "org.ow2.asm:asm-util:${project.asm_version}" + implementation "org.ow2.asm:asm-analysis:${project.asm_version}" implementation 'com.github.ImpactDevelopment:SimpleTweaker:1.2' From 330089f1e23990a825e6f6eaf9e9ffb22c665511 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sat, 27 Jul 2024 21:26:17 +0200 Subject: [PATCH 02/21] Shorten / simplify some Litematica related things --- .../command/defaults/LitematicaCommand.java | 15 +- .../baritone/command/defaults/SelCommand.java | 7 +- .../java/baritone/process/BuilderProcess.java | 8 +- .../utils/schematic/StaticSchematic.java | 10 ++ .../format/DefaultSchematicFormats.java | 2 +- .../format/defaults/LitematicaSchematic.java | 136 +++++----------- .../litematica/LitematicaHelper.java | 153 ++++++------------ .../dy/masa/litematica/data/DataManager.java | 8 +- .../placement/SchematicPlacement.java | 6 +- .../placement/SchematicPlacementManager.java | 4 +- .../placement/SchematicPlacementUnloaded.java | 10 +- 11 files changed, 115 insertions(+), 244 deletions(-) diff --git a/src/main/java/baritone/command/defaults/LitematicaCommand.java b/src/main/java/baritone/command/defaults/LitematicaCommand.java index bfe0079b3..2e251b224 100644 --- a/src/main/java/baritone/command/defaults/LitematicaCommand.java +++ b/src/main/java/baritone/command/defaults/LitematicaCommand.java @@ -34,18 +34,9 @@ public LitematicaCommand(IBaritone baritone) { @Override public void execute(String label, IArgConsumer args) throws CommandException { - int schematic = 0; - if (args.hasAny()) { - args.requireMax(1); - if (args.is(Integer.class)) { - schematic = args.getAs(Integer.class) - 1; - } - } - try { - baritone.getBuilderProcess().buildOpenLitematic(schematic); - } catch (IndexOutOfBoundsException e) { - logDirect("Pleas provide a valid index."); - } + args.requireMax(1); + int schematic = args.hasAny() ? args.getAs(Integer.class) - 1 : 0; + baritone.getBuilderProcess().buildOpenLitematic(schematic); } @Override diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java index 14d22b0b4..e789dcd97 100644 --- a/src/main/java/baritone/command/defaults/SelCommand.java +++ b/src/main/java/baritone/command/defaults/SelCommand.java @@ -227,12 +227,7 @@ public void execute(String label, IArgConsumer args) throws CommandException { } } } - ISchematic schematic = new StaticSchematic() {{ - states = blockstates; - x = size.getX(); - y = size.getY(); - z = size.getZ(); - }}; + ISchematic schematic = new StaticSchematic(blockstates); composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z); } clipboard = composite; diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 4b49398a0..e2e63fc8e 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -229,19 +229,19 @@ public void buildOpenSchematic() { public void buildOpenLitematic(int i) { if (LitematicaHelper.isLitematicaPresent()) { //if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager - if (LitematicaHelper.hasLoadedSchematic()) { + if (LitematicaHelper.hasLoadedSchematic(i)) { String name = LitematicaHelper.getName(i); try { - LitematicaSchematic schematic1 = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath())), false); + LitematicaSchematic schematic1 = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath()))); Vec3i correctedOrigin = LitematicaHelper.getCorrectedOrigin(schematic1, i); - ISchematic schematic2 = LitematicaHelper.blackMagicFuckery(schematic1, i); + ISchematic schematic2 = LitematicaHelper.applyPlacementRotation(schematic1, i); schematic2 = applyMapArtAndSelection(origin, (IStaticSchematic) schematic2); build(name, schematic2, correctedOrigin); } catch (Exception e) { logDirect("Schematic File could not be loaded."); } } else { - logDirect("No schematic currently loaded"); + logDirect(String.format("List of placements has no entry %s", i + 1)); } } else { logDirect("Litematica is not present"); diff --git a/src/main/java/baritone/utils/schematic/StaticSchematic.java b/src/main/java/baritone/utils/schematic/StaticSchematic.java index 5a110281b..0c875c724 100644 --- a/src/main/java/baritone/utils/schematic/StaticSchematic.java +++ b/src/main/java/baritone/utils/schematic/StaticSchematic.java @@ -32,6 +32,16 @@ public class StaticSchematic extends AbstractSchematic implements IStaticSchemat protected BlockState[][][] states; + public StaticSchematic() {} + + public StaticSchematic(BlockState[][][] states) { + this.states = states; + boolean empty = states.length == 0 || states[0].length == 0 || states[0][0].length == 0; + this.x = empty ? 0 : states.length; + this.z = empty ? 0 : states[0].length; + this.y = empty ? 0 : states[0][0].length; + } + @Override public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { return this.states[x][z][y]; diff --git a/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java b/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java index 17fafc821..40a95b50c 100644 --- a/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java +++ b/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java @@ -81,7 +81,7 @@ public IStaticSchematic parse(InputStream input) throws IOException { case 5: //1.13-1.17 throw new UnsupportedOperationException("This litematic Version is too old."); case 6: //1.18+ - return new LitematicaSchematic(nbt, false); + return new LitematicaSchematic(nbt); default: throw new UnsupportedOperationException("Unsuported Version of a Litematica Schematic"); } diff --git a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java index 65cdec058..160f9c386 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java @@ -18,7 +18,6 @@ package baritone.utils.schematic.format.defaults; import baritone.utils.schematic.StaticSchematic; -import net.minecraft.core.Registry; import net.minecraft.core.Vec3i; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.nbt.CompoundTag; @@ -41,33 +40,28 @@ */ public final class LitematicaSchematic extends StaticSchematic { private final Vec3i offsetMinCorner; - private final CompoundTag nbt; /** * @param nbtTagCompound a decompressed file stream aka nbt data. * @param rotated if the schematic is rotated by 90°. */ - public LitematicaSchematic(CompoundTag nbtTagCompound, boolean rotated) { - this.nbt = nbtTagCompound; - this.offsetMinCorner = new Vec3i(getMinOfSchematic("x"), getMinOfSchematic("y"), getMinOfSchematic("z")); - this.y = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("y")); - - if (rotated) { - this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z")); - this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x")); - } else { - this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x")); - this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z")); - } + public LitematicaSchematic(CompoundTag nbt) { + this.offsetMinCorner = new Vec3i(getMinOfSchematic(nbt, "x"), getMinOfSchematic(nbt, "y"), getMinOfSchematic(nbt, "z")); + CompoundTag size = nbt.getCompound("Metadata").getCompound("EnclosingSize"); + this.x = Math.abs(size.getInt("x")); + this.y = Math.abs(size.getInt("y")); + this.z = Math.abs(size.getInt("z")); this.states = new BlockState[this.x][this.z][this.y]; - fillInSchematic(); + fillInSchematic(nbt); } /** - * @return Array of subregion names. + * @return Array of subregion tags. */ - private static String[] getRegions(CompoundTag nbt) { - return nbt.getCompound("Regions").getAllKeys().toArray(new String[0]); + private static CompoundTag[] getRegions(CompoundTag nbt) { + return nbt.getCompound("Regions").getAllKeys().stream() + .map(nbt.getCompound("Regions")::getCompound) + .toArray(CompoundTag[]::new); } /** @@ -76,14 +70,10 @@ private static String[] getRegions(CompoundTag nbt) { * @param s axis that should be read. * @return the lower coord of the requested axis. */ - private static int getMinOfSubregion(CompoundTag nbt, String subReg, String s) { - int a = nbt.getCompound("Regions").getCompound(subReg).getCompound("Position").getInt(s); - int b = nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt(s); - if (b < 0) { - b++; - } - return Math.min(a, a + b); - + private static int getMinOfSubregion(CompoundTag subReg, String s) { + int a = subReg.getCompound("Position").getInt(s); + int b = subReg.getCompound("Size").getInt(s); + return Math.min(a, a + b + 1); } /** @@ -110,7 +100,7 @@ private static BlockState[] getBlockList(ListTag blockStatePalette) { private static BlockState getBlockState(Block block, CompoundTag properties) { BlockState blockState = block.defaultBlockState(); - for (Object key : properties.getAllKeys().toArray()) { + for (Object key : properties.getAllKeys()) { Property property = block.getStateDefinition().getProperty((String) key); String propertyValue = properties.getString((String) key); if (property != null) { @@ -146,18 +136,9 @@ private static int getBitsPerBlock(int amountOfBlockTypes) { * * @return the volume of the subregion. */ - private static long getVolume(CompoundTag nbt, String subReg) { - return Math.abs( - nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x") * - nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y") * - nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z")); - } - - /** - * @return array of Long values. - */ - private static long[] getBlockStates(CompoundTag nbt, String subReg) { - return nbt.getCompound("Regions").getCompound(subReg).getLongArray("BlockStates"); + private static long getVolume(CompoundTag subReg) { + CompoundTag size = subReg.getCompound("Size"); + return Math.abs(size.getInt("x") * size.getInt("y") * size.getInt("z")); } /** @@ -168,21 +149,22 @@ private static long[] getBlockStates(CompoundTag nbt, String subReg) { * @param z coord of the block relative to the minimum corner. * @return if the current block is part of the subregion. */ - private static boolean inSubregion(CompoundTag nbt, String subReg, int x, int y, int z) { + private static boolean inSubregion(CompoundTag subReg, int x, int y, int z) { + CompoundTag size = subReg.getCompound("Size"); return x >= 0 && y >= 0 && z >= 0 && - x < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x")) && - y < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y")) && - z < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z")); + x < Math.abs(size.getInt("x")) && + y < Math.abs(size.getInt("y")) && + z < Math.abs(size.getInt("z")); } /** * @param s axis. * @return the lowest coordinate of that axis of the schematic. */ - private int getMinOfSchematic(String s) { + private static int getMinOfSchematic(CompoundTag nbt, String s) { int n = Integer.MAX_VALUE; - for (String subReg : getRegions(nbt)) { - n = Math.min(n, getMinOfSubregion(nbt, subReg, s)); + for (CompoundTag subReg : getRegions(nbt)) { + n = Math.min(n, getMinOfSubregion(subReg, s)); } return n; } @@ -190,18 +172,17 @@ private int getMinOfSchematic(String s) { /** * reads the file data. */ - private void fillInSchematic() { - for (String subReg : getRegions(nbt)) { - ListTag usedBlockTypes = nbt.getCompound("Regions").getCompound(subReg).getList("BlockStatePalette", 10); + private void fillInSchematic(CompoundTag nbt) { + for (CompoundTag subReg : getRegions(nbt)) { + ListTag usedBlockTypes = subReg.getList("BlockStatePalette", 10); BlockState[] blockList = getBlockList(usedBlockTypes); int bitsPerBlock = getBitsPerBlock(usedBlockTypes.size()); - long regionVolume = getVolume(nbt, subReg); - long[] blockStateArray = getBlockStates(nbt, subReg); + long regionVolume = getVolume(subReg); + long[] blockStateArray = subReg.getLongArray("BlockStates"); LitematicaBitArray bitArray = new LitematicaBitArray(bitsPerBlock, regionVolume, blockStateArray); - - writeSubregionIntoSchematic(nbt, subReg, blockList, bitArray); + writeSubregionIntoSchematic(subReg, blockList, bitArray); } } @@ -211,14 +192,16 @@ private void fillInSchematic() { * @param blockList list with the different block types used in the schematic. * @param bitArray bit array that holds the placement pattern. */ - private void writeSubregionIntoSchematic(CompoundTag nbt, String subReg, BlockState[] blockList, LitematicaBitArray bitArray) { - Vec3i offsetSubregion = new Vec3i(getMinOfSubregion(nbt, subReg, "x"), getMinOfSubregion(nbt, subReg, "y"), getMinOfSubregion(nbt, subReg, "z")); + private void writeSubregionIntoSchematic(CompoundTag subReg, BlockState[] blockList, LitematicaBitArray bitArray) { + int offsetX = getMinOfSubregion(subReg, "x") - offsetMinCorner.getX(); + int offsetY = getMinOfSubregion(subReg, "y") - offsetMinCorner.getY(); + int offsetZ = getMinOfSubregion(subReg, "z") - offsetMinCorner.getZ(); int index = 0; for (int y = 0; y < this.y; y++) { for (int z = 0; z < this.z; z++) { for (int x = 0; x < this.x; x++) { - if (inSubregion(nbt, subReg, x, y, z)) { - this.states[x - (offsetMinCorner.getX() - offsetSubregion.getX())][z - (offsetMinCorner.getZ() - offsetSubregion.getZ())][y - (offsetMinCorner.getY() - offsetSubregion.getY())] = blockList[bitArray.getAt(index)]; + if (inSubregion(subReg, x, y, z)) { + this.states[x + offsetX][z + offsetZ][y + offsetY] = blockList[bitArray.getAt(index)]; index++; } } @@ -233,45 +216,6 @@ public Vec3i getOffsetMinCorner() { return offsetMinCorner; } - /** - * @return x size of the schematic. - */ - public int getX() { - return this.x; - } - - /** - * @return y size of the schematic. - */ - public int getY() { - return this.y; - } - - /** - * @return z size of the schematic. - */ - public int getZ() { - return this.z; - } - - /** - * @param x position relative to the minimum corner of the schematic. - * @param y position relative to the minimum corner of the schematic. - * @param z position relative to the minimum corner of the schematic. - * @param blockState new blockstate of the block at this position. - */ - public void setDirect(int x, int y, int z, BlockState blockState) { - this.states[x][z][y] = blockState; - } - - /** - * @param rotated if the schematic is rotated by 90°. - * @return a copy of the schematic. - */ - public LitematicaSchematic getCopy(boolean rotated) { - return new LitematicaSchematic(nbt, rotated); - } - /** * @author maruohon * Class from the Litematica mod by maruohon diff --git a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java index 3b05c23ef..c43d79b26 100644 --- a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java +++ b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java @@ -17,9 +17,11 @@ package baritone.utils.schematic.litematica; +import baritone.utils.schematic.StaticSchematic; import baritone.utils.schematic.format.defaults.LitematicaSchematic; import fi.dy.masa.litematica.Litematica; import fi.dy.masa.litematica.data.DataManager; +import fi.dy.masa.litematica.schematic.placement.SchematicPlacement; import net.minecraft.core.Vec3i; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; @@ -48,26 +50,22 @@ public static boolean isLitematicaPresent() { } /** - * @return if there are loaded schematics. + * @return if {@code i} is a valid placement index */ - public static boolean hasLoadedSchematic() { - return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().size() > 0; + public static boolean hasLoadedSchematic(int i) { + return 0 <= i && i < DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().size(); } - /** - * @param i index of the Schematic in the schematic placement list. - * @return the name of the requested schematic. - */ - public static String getName(int i) { - return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getName(); + private static SchematicPlacement getPlacement(int i) { + return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i); } /** * @param i index of the Schematic in the schematic placement list. - * @return the world coordinates of the schematic origin. This can but does not have to be the minimum corner. + * @return the name of the requested schematic. */ - public static Vec3i getOrigin(int i) { - return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getOrigin(); + public static String getName(int i) { + return getPlacement(i).getName(); } /** @@ -75,23 +73,7 @@ public static Vec3i getOrigin(int i) { * @return Filepath of the schematic file. */ public static File getSchematicFile(int i) { - return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getSchematicFile(); - } - - /** - * @param i index of the Schematic in the schematic placement list. - * @return rotation of the schematic placement. - */ - public static Rotation getRotation(int i) { - return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getRotation(); - } - - /** - * @param i index of the Schematic in the schematic placement list. - * @return the mirroring of the schematic placement. - */ - public static Mirror getMirror(int i) { - return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getMirror(); + return getPlacement(i).getSchematicFile(); } /** @@ -100,55 +82,16 @@ public static Mirror getMirror(int i) { * @return the minimum corner coordinates of the schematic, after the original schematic got rotated and mirrored. */ public static Vec3i getCorrectedOrigin(LitematicaSchematic schematic, int i) { - int x = LitematicaHelper.getOrigin(i).getX(); - int y = LitematicaHelper.getOrigin(i).getY(); - int z = LitematicaHelper.getOrigin(i).getZ(); - int mx = schematic.getOffsetMinCorner().getX(); - int my = schematic.getOffsetMinCorner().getY(); - int mz = schematic.getOffsetMinCorner().getZ(); - int sx = (schematic.getX() - 1) * -1; - int sz = (schematic.getZ() - 1) * -1; + SchematicPlacement placement = getPlacement(i); + Vec3i origin = placement.getOrigin(); + Vec3i minCorner = schematic.getOffsetMinCorner(); + int sx = 2 - schematic.widthX(); // this is because the position needs to be adjusted + int sz = 2 - schematic.lengthZ(); // by widthX/lengthZ after every transformation - Vec3i correctedOrigin; - Mirror mirror = LitematicaHelper.getMirror(i); - Rotation rotation = LitematicaHelper.getRotation(i); + Mirror mirror = placement.getMirror(); + Rotation rotation = placement.getRotation(); - //todo there has to be a better way to do this but i cant finde it atm - switch (mirror) { - case FRONT_BACK: - case LEFT_RIGHT: - switch ((mirror.ordinal() * 2 + rotation.ordinal()) % 4) { - case 1: - correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + (sx - mx)); - break; - case 2: - correctedOrigin = new Vec3i(x + mx, y + my, z + (sz - mz)); - break; - case 3: - correctedOrigin = new Vec3i(x + mz, y + my, z + mx); - break; - default: - correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + mz); - break; - } - break; - default: - switch (rotation) { - case CLOCKWISE_90: - correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + mx); - break; - case CLOCKWISE_180: - correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + (sz - mz)); - break; - case COUNTERCLOCKWISE_90: - correctedOrigin = new Vec3i(x + mz, y + my, z + (sx - mx)); - break; - default: - correctedOrigin = new Vec3i(x + mx, y + my, z + mz); - break; - } - } - return correctedOrigin; + return origin.offset(rotate(doMirroring(minCorner, sx, sz, mirror), sx, sz, rotation)); } /** @@ -158,13 +101,13 @@ public static Vec3i getCorrectedOrigin(LitematicaSchematic schematic, int i) { * @param mirror the mirroring of the schematic placement. * @return the corresponding xyz coordinates after mirroring them according to the given mirroring. */ - public static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) { + private static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) { int xOut = in.getX(); int zOut = in.getZ(); if (mirror == Mirror.LEFT_RIGHT) { - zOut = sizeZ - in.getZ(); + zOut = sizeZ - 1 - in.getZ(); } else if (mirror == Mirror.FRONT_BACK) { - xOut = sizeX - in.getX(); + xOut = sizeX - 1 - in.getX(); } return new Vec3i(xOut, in.getY(), zOut); } @@ -173,43 +116,45 @@ public static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) { * @param in the xyz offsets of the block relative to the schematic minimum corner. * @param sizeX size of the schematic in the x-axis direction. * @param sizeZ size of the schematic in the z-axis direction. - * @return the corresponding xyz coordinates after rotation them 90° clockwise. + * @param rotation the rotation to apply + * @return the corresponding xyz coordinates after applying {@code rotation}. */ - public static Vec3i rotate(Vec3i in, int sizeX, int sizeZ) { - return new Vec3i(sizeX - (sizeX - sizeZ) - in.getZ(), in.getY(), in.getX()); + private static Vec3i rotate(Vec3i in, int sizeX, int sizeZ, Rotation rotation) { + switch (rotation) { + case CLOCKWISE_90: + return new Vec3i(sizeZ - 1 - in.getZ(), in.getY(), in.getX()); + case CLOCKWISE_180: + return new Vec3i(sizeX - 1 - in.getX(), in.getY(), sizeZ - 1 - in.getZ()); + case COUNTERCLOCKWISE_90: + return new Vec3i(in.getZ(), in.getY(), sizeX - 1 - in.getX()); + default: + return in; + } } /** - * IDFK this just grew and it somehow works. If you understand how, pls tell me. - * * @param schemIn give in the original schematic. * @param i index of the Schematic in the schematic placement list. * @return get it out rotated and mirrored. */ - public static LitematicaSchematic blackMagicFuckery(LitematicaSchematic schemIn, int i) { - LitematicaSchematic tempSchem = schemIn.getCopy(LitematicaHelper.getRotation(i).ordinal() % 2 == 1); - for (int yCounter = 0; yCounter < schemIn.getY(); yCounter++) { - for (int zCounter = 0; zCounter < schemIn.getZ(); zCounter++) { - for (int xCounter = 0; xCounter < schemIn.getX(); xCounter++) { + public static StaticSchematic applyPlacementRotation(LitematicaSchematic schemIn, int i) { + SchematicPlacement placement = getPlacement(i); + Rotation rotation = placement.getRotation(); + Mirror mirror = placement.getMirror(); + boolean flip = rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90; + BlockState[][][] states = new BlockState[flip ? schemIn.lengthZ() : schemIn.widthX()][flip ? schemIn.widthX() : schemIn.lengthZ()][schemIn.heightY()]; + for (int yCounter = 0; yCounter < schemIn.heightY(); yCounter++) { + for (int zCounter = 0; zCounter < schemIn.lengthZ(); zCounter++) { + for (int xCounter = 0; xCounter < schemIn.widthX(); xCounter++) { Vec3i xyzHolder = new Vec3i(xCounter, yCounter, zCounter); - xyzHolder = LitematicaHelper.doMirroring(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1, LitematicaHelper.getMirror(i)); - for (int turns = 0; turns < LitematicaHelper.getRotation(i).ordinal(); turns++) { - if ((turns % 2) == 0) { - xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1); - } else { - xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getZ() - 1, schemIn.getX() - 1); - } - } + xyzHolder = LitematicaHelper.doMirroring(xyzHolder, schemIn.widthX(), schemIn.lengthZ(), mirror); + xyzHolder = rotate(xyzHolder, schemIn.widthX(), schemIn.lengthZ(), rotation); BlockState state = schemIn.getDirect(xCounter, yCounter, zCounter); - try { - state = state.mirror(LitematicaHelper.getMirror(i)).rotate(LitematicaHelper.getRotation(i)); - } catch (NullPointerException e) { - //nothing to worry about it's just a hole in the schematic. - } - tempSchem.setDirect(xyzHolder.getX(), xyzHolder.getY(), xyzHolder.getZ(), state); + state = state == null ? null : state.mirror(mirror).rotate(rotation); + states[xyzHolder.getX()][xyzHolder.getZ()][xyzHolder.getY()] = state; } } } - return tempSchem; + return new StaticSchematic(states); } } \ No newline at end of file diff --git a/src/schematica_api/java/fi/dy/masa/litematica/data/DataManager.java b/src/schematica_api/java/fi/dy/masa/litematica/data/DataManager.java index 4941e7cf3..3f5c6c98f 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/data/DataManager.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/data/DataManager.java @@ -20,14 +20,8 @@ import fi.dy.masa.litematica.schematic.placement.SchematicPlacementManager; public class DataManager { - public static final DataManager INSTANCE = new DataManager(); - private final SchematicPlacementManager schematicPlacementManager = new SchematicPlacementManager(); - - private static DataManager getInstance() { - return INSTANCE; - } public static SchematicPlacementManager getSchematicPlacementManager() { - return getInstance().schematicPlacementManager; + throw new LinkageError(); } } \ No newline at end of file diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java index a267553a9..9d944334b 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java @@ -21,15 +21,13 @@ import net.minecraft.world.level.block.Rotation; public class SchematicPlacement extends SchematicPlacementUnloaded { - private Rotation rotation; - private Mirror mirror; public Rotation getRotation() { - return this.rotation; + throw new LinkageError(); } public Mirror getMirror() { - return this.mirror; + throw new LinkageError(); } } \ No newline at end of file diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementManager.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementManager.java index ab60e27fa..e7f810a5e 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementManager.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementManager.java @@ -17,15 +17,13 @@ package fi.dy.masa.litematica.schematic.placement; -import java.util.ArrayList; import java.util.List; public class SchematicPlacementManager { - private final List schematicPlacements = new ArrayList<>(); //in case of a java.lang.NoSuchMethodError try change the name of this method to getAllSchematicPlacements() //there are inconsistencies in the litematica mod about the naming of this method public List getAllSchematicsPlacements() { - return schematicPlacements; + throw new LinkageError(); } } \ No newline at end of file diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java index 9e705dc7b..39b68f67e 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java @@ -23,21 +23,17 @@ import java.io.File; public class SchematicPlacementUnloaded { - protected String name = "?"; - @Nullable - protected File schematicFile; - protected BlockPos origin = BlockPos.ZERO; public String getName() { - return this.name; + throw new LinkageError(); } @Nullable public File getSchematicFile() { - return this.schematicFile; + throw new LinkageError(); } public BlockPos getOrigin() { - return this.origin; + throw new LinkageError(); } } \ No newline at end of file From b12c4e9f8cf958417d825ecc5db7e2815f44dba2 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Mon, 29 Jul 2024 18:15:13 +0200 Subject: [PATCH 03/21] Merge loading steps --- .../java/baritone/process/BuilderProcess.java | 8 +++---- .../litematica/LitematicaHelper.java | 23 ++++++++----------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index e2e63fc8e..4e04e60f5 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -51,7 +51,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.core.Vec3i; -import net.minecraft.nbt.NbtIo; import net.minecraft.util.Tuple; import net.minecraft.world.InteractionHand; import net.minecraft.world.item.BlockItem; @@ -232,10 +231,9 @@ public void buildOpenLitematic(int i) { if (LitematicaHelper.hasLoadedSchematic(i)) { String name = LitematicaHelper.getName(i); try { - LitematicaSchematic schematic1 = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath()))); - Vec3i correctedOrigin = LitematicaHelper.getCorrectedOrigin(schematic1, i); - ISchematic schematic2 = LitematicaHelper.applyPlacementRotation(schematic1, i); - schematic2 = applyMapArtAndSelection(origin, (IStaticSchematic) schematic2); + Tuple schematic = LitematicaHelper.getSchematic(i); + Vec3i correctedOrigin = schematic.getB(); + ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA()); build(name, schematic2, correctedOrigin); } catch (Exception e) { logDirect("Schematic File could not be loaded."); diff --git a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java index c43d79b26..d300db091 100644 --- a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java +++ b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java @@ -17,17 +17,21 @@ package baritone.utils.schematic.litematica; +import baritone.api.schematic.IStaticSchematic; import baritone.utils.schematic.StaticSchematic; import baritone.utils.schematic.format.defaults.LitematicaSchematic; import fi.dy.masa.litematica.Litematica; import fi.dy.masa.litematica.data.DataManager; import fi.dy.masa.litematica.schematic.placement.SchematicPlacement; import net.minecraft.core.Vec3i; +import net.minecraft.nbt.NbtIo; +import net.minecraft.util.Tuple; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.state.BlockState; -import java.io.File; +import java.io.IOException; +import java.nio.file.Files; /** * Helper class that provides access or processes data related to Litmatica schematics. @@ -68,21 +72,12 @@ public static String getName(int i) { return getPlacement(i).getName(); } - /** - * @param i index of the Schematic in the schematic placement list. - * @return Filepath of the schematic file. - */ - public static File getSchematicFile(int i) { - return getPlacement(i).getSchematicFile(); - } - /** * @param schematic original schematic. * @param i index of the Schematic in the schematic placement list. * @return the minimum corner coordinates of the schematic, after the original schematic got rotated and mirrored. */ - public static Vec3i getCorrectedOrigin(LitematicaSchematic schematic, int i) { - SchematicPlacement placement = getPlacement(i); + private static Vec3i getCorrectedOrigin(SchematicPlacement placement, LitematicaSchematic schematic) { Vec3i origin = placement.getOrigin(); Vec3i minCorner = schematic.getOffsetMinCorner(); int sx = 2 - schematic.widthX(); // this is because the position needs to be adjusted @@ -137,10 +132,12 @@ private static Vec3i rotate(Vec3i in, int sizeX, int sizeZ, Rotation rotation) { * @param i index of the Schematic in the schematic placement list. * @return get it out rotated and mirrored. */ - public static StaticSchematic applyPlacementRotation(LitematicaSchematic schemIn, int i) { + public static Tuple getSchematic(int i) throws IOException { SchematicPlacement placement = getPlacement(i); Rotation rotation = placement.getRotation(); Mirror mirror = placement.getMirror(); + LitematicaSchematic schemIn = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(placement.getSchematicFile().toPath()))); + Vec3i origin = getCorrectedOrigin(placement, schemIn); boolean flip = rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90; BlockState[][][] states = new BlockState[flip ? schemIn.lengthZ() : schemIn.widthX()][flip ? schemIn.widthX() : schemIn.lengthZ()][schemIn.heightY()]; for (int yCounter = 0; yCounter < schemIn.heightY(); yCounter++) { @@ -155,6 +152,6 @@ public static StaticSchematic applyPlacementRotation(LitematicaSchematic schemIn } } } - return new StaticSchematic(states); + return new Tuple<>(new StaticSchematic(states), origin); } } \ No newline at end of file From b87a1fa4200a13942edb54df747469c1e43ae76d Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 28 Jul 2024 23:50:03 +0200 Subject: [PATCH 04/21] Take data directly from Litematica --- .../api/schematic/MirroredSchematic.java | 114 +++++++++++++++ .../api/schematic/RotatedSchematic.java | 136 ++++++++++++++++++ .../format/defaults/LitematicaSchematic.java | 14 +- .../litematica/LitematicaHelper.java | 134 +++++++++++------ .../schematic/LitematicaSchematic.java | 32 +++++ .../LitematicaBlockStateContainer.java | 27 ++++ .../placement/SchematicPlacement.java | 9 ++ .../placement/SchematicPlacementUnloaded.java | 8 -- .../placement/SubRegionPlacement.java | 37 +++++ 9 files changed, 452 insertions(+), 59 deletions(-) create mode 100644 src/api/java/baritone/api/schematic/MirroredSchematic.java create mode 100644 src/api/java/baritone/api/schematic/RotatedSchematic.java create mode 100644 src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java create mode 100644 src/schematica_api/java/fi/dy/masa/litematica/schematic/container/LitematicaBlockStateContainer.java create mode 100644 src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SubRegionPlacement.java diff --git a/src/api/java/baritone/api/schematic/MirroredSchematic.java b/src/api/java/baritone/api/schematic/MirroredSchematic.java new file mode 100644 index 000000000..b9e10808c --- /dev/null +++ b/src/api/java/baritone/api/schematic/MirroredSchematic.java @@ -0,0 +1,114 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Mirror; + +import java.util.List; +import java.util.stream.Collectors; + +public class MirroredSchematic implements ISchematic { + + private final ISchematic schematic; + private final Mirror mirror; + + public MirroredSchematic(ISchematic schematic, Mirror mirror) { + this.schematic = schematic; + this.mirror = mirror; + } + + @Override + public boolean inSchematic(int x, int y, int z, BlockState currentState) { + return schematic.inSchematic( + mirrorX(x, widthX(), mirror), + y, + mirrorZ(z, lengthZ(), mirror), + mirror(currentState, mirror) + ); + } + + @Override + public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { + return mirror(schematic.desiredState( + mirrorX(x, widthX(), mirror), + y, + mirrorZ(z, lengthZ(), mirror), + mirror(current, mirror), + mirror(approxPlaceable, mirror) + ), mirror); + } + + @Override + public void reset() { + schematic.reset(); + } + + @Override + public int widthX() { + return schematic.widthX(); + } + + @Override + public int heightY() { + return schematic.heightY(); + } + + @Override + public int lengthZ() { + return schematic.lengthZ(); + } + + private static int mirrorX(int x, int sizeX, Mirror mirror) { + switch (mirror) { + case NONE: + case LEFT_RIGHT: + return x; + case FRONT_BACK: + return sizeX - x - 1; + } + throw new IllegalArgumentException("Unknown mirror"); + } + + private static int mirrorZ(int z, int sizeZ, Mirror mirror) { + switch (mirror) { + case NONE: + case FRONT_BACK: + return z; + case LEFT_RIGHT: + return sizeZ - z - 1; + } + throw new IllegalArgumentException("Unknown mirror"); + } + + private static BlockState mirror(BlockState state, Mirror mirror) { + if (state == null) { + return null; + } + return state.mirror(mirror); + } + + private static List mirror(List states, Mirror mirror) { + if (states == null) { + return null; + } + return states.stream() + .map(s -> mirror(s, mirror)) + .collect(Collectors.toList()); + } +} diff --git a/src/api/java/baritone/api/schematic/RotatedSchematic.java b/src/api/java/baritone/api/schematic/RotatedSchematic.java new file mode 100644 index 000000000..e3c9ed7aa --- /dev/null +++ b/src/api/java/baritone/api/schematic/RotatedSchematic.java @@ -0,0 +1,136 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Rotation; + +import java.util.List; +import java.util.stream.Collectors; + +public class RotatedSchematic implements ISchematic { + + private final ISchematic schematic; + private final Rotation rotation; + private final Rotation inverseRotation; + + public RotatedSchematic(ISchematic schematic, Rotation rotation) { + this.schematic = schematic; + this.rotation = rotation; + // I don't think a 14 line switch would improve readability + this.inverseRotation = rotation.getRotated(rotation).getRotated(rotation); + } + + @Override + public boolean inSchematic(int x, int y, int z, BlockState currentState) { + return schematic.inSchematic( + rotateX(x, z, widthX(), lengthZ(), inverseRotation), + y, + rotateZ(x, z, widthX(), lengthZ(), inverseRotation), + rotate(currentState, inverseRotation) + ); + } + + @Override + public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { + return rotate(schematic.desiredState( + rotateX(x, z, widthX(), lengthZ(), inverseRotation), + y, + rotateZ(x, z, widthX(), lengthZ(), inverseRotation), + rotate(current, inverseRotation), + rotate(approxPlaceable, inverseRotation) + ), rotation); + } + + @Override + public void reset() { + schematic.reset(); + } + + @Override + public int widthX() { + return flipsCoordinates(rotation) ? schematic.lengthZ() : schematic.widthX(); + } + + @Override + public int heightY() { + return schematic.heightY(); + } + + @Override + public int lengthZ() { + return flipsCoordinates(rotation) ? schematic.widthX() : schematic.lengthZ(); + } + + /** + * Wether {@code rotation} swaps the x and z components + */ + private static boolean flipsCoordinates(Rotation rotation) { + return rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90; + } + + /** + * The x component of x,y after applying the rotation + */ + private static int rotateX(int x, int z, int sizeX, int sizeZ, Rotation rotation) { + switch (rotation) { + case NONE: + return x; + case CLOCKWISE_90: + return sizeZ - z - 1; + case CLOCKWISE_180: + return sizeX - x - 1; + case COUNTERCLOCKWISE_90: + return z; + } + throw new IllegalArgumentException("Unknown rotation"); + } + + /** + * The z component of x,y after applying the rotation + */ + private static int rotateZ(int x, int z, int sizeX, int sizeZ, Rotation rotation) { + switch (rotation) { + case NONE: + return z; + case CLOCKWISE_90: + return x; + case CLOCKWISE_180: + return sizeZ - z - 1; + case COUNTERCLOCKWISE_90: + return sizeX - x - 1; + } + throw new IllegalArgumentException("Unknown rotation"); + } + + private static BlockState rotate(BlockState state, Rotation rotation) { + if (state == null) { + return null; + } + return state.rotate(rotation); + } + + private static List rotate(List states, Rotation rotation) { + if (states == null) { + return null; + } + return states.stream() + .map(s -> rotate(s, rotation)) + .collect(Collectors.toList()); + } +} diff --git a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java index 160f9c386..aa0425bb3 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java @@ -39,14 +39,12 @@ * @since 22.09.2022 */ public final class LitematicaSchematic extends StaticSchematic { - private final Vec3i offsetMinCorner; /** * @param nbtTagCompound a decompressed file stream aka nbt data. * @param rotated if the schematic is rotated by 90°. */ public LitematicaSchematic(CompoundTag nbt) { - this.offsetMinCorner = new Vec3i(getMinOfSchematic(nbt, "x"), getMinOfSchematic(nbt, "y"), getMinOfSchematic(nbt, "z")); CompoundTag size = nbt.getCompound("Metadata").getCompound("EnclosingSize"); this.x = Math.abs(size.getInt("x")); this.y = Math.abs(size.getInt("y")); @@ -173,6 +171,7 @@ private static int getMinOfSchematic(CompoundTag nbt, String s) { * reads the file data. */ private void fillInSchematic(CompoundTag nbt) { + Vec3i offsetMinCorner = new Vec3i(getMinOfSchematic(nbt, "x"), getMinOfSchematic(nbt, "y"), getMinOfSchematic(nbt, "z")); for (CompoundTag subReg : getRegions(nbt)) { ListTag usedBlockTypes = subReg.getList("BlockStatePalette", 10); BlockState[] blockList = getBlockList(usedBlockTypes); @@ -182,7 +181,7 @@ private void fillInSchematic(CompoundTag nbt) { long[] blockStateArray = subReg.getLongArray("BlockStates"); LitematicaBitArray bitArray = new LitematicaBitArray(bitsPerBlock, regionVolume, blockStateArray); - writeSubregionIntoSchematic(subReg, blockList, bitArray); + writeSubregionIntoSchematic(subReg, offsetMinCorner, blockList, bitArray); } } @@ -192,7 +191,7 @@ private void fillInSchematic(CompoundTag nbt) { * @param blockList list with the different block types used in the schematic. * @param bitArray bit array that holds the placement pattern. */ - private void writeSubregionIntoSchematic(CompoundTag subReg, BlockState[] blockList, LitematicaBitArray bitArray) { + private void writeSubregionIntoSchematic(CompoundTag subReg, Vec3i offsetMinCorner, BlockState[] blockList, LitematicaBitArray bitArray) { int offsetX = getMinOfSubregion(subReg, "x") - offsetMinCorner.getX(); int offsetY = getMinOfSubregion(subReg, "y") - offsetMinCorner.getY(); int offsetZ = getMinOfSubregion(subReg, "z") - offsetMinCorner.getZ(); @@ -209,13 +208,6 @@ private void writeSubregionIntoSchematic(CompoundTag subReg, BlockState[] blockL } } - /** - * @return offset from the schematic origin to the minimum Corner as a Vec3i. - */ - public Vec3i getOffsetMinCorner() { - return offsetMinCorner; - } - /** * @author maruohon * Class from the Litematica mod by maruohon diff --git a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java index d300db091..bb7181724 100644 --- a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java +++ b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java @@ -17,21 +17,27 @@ package baritone.utils.schematic.litematica; +import baritone.api.schematic.AbstractSchematic; import baritone.api.schematic.IStaticSchematic; +import baritone.api.schematic.ISchematic; +import baritone.api.schematic.CompositeSchematic; +import baritone.api.schematic.MirroredSchematic; +import baritone.api.schematic.RotatedSchematic; import baritone.utils.schematic.StaticSchematic; -import baritone.utils.schematic.format.defaults.LitematicaSchematic; import fi.dy.masa.litematica.Litematica; import fi.dy.masa.litematica.data.DataManager; +import fi.dy.masa.litematica.schematic.container.LitematicaBlockStateContainer; import fi.dy.masa.litematica.schematic.placement.SchematicPlacement; +import fi.dy.masa.litematica.schematic.placement.SubRegionPlacement; import net.minecraft.core.Vec3i; -import net.minecraft.nbt.NbtIo; import net.minecraft.util.Tuple; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.state.BlockState; -import java.io.IOException; -import java.nio.file.Files; +import java.util.List; +import java.util.Collections; +import java.util.Map; /** * Helper class that provides access or processes data related to Litmatica schematics. @@ -72,23 +78,6 @@ public static String getName(int i) { return getPlacement(i).getName(); } - /** - * @param schematic original schematic. - * @param i index of the Schematic in the schematic placement list. - * @return the minimum corner coordinates of the schematic, after the original schematic got rotated and mirrored. - */ - private static Vec3i getCorrectedOrigin(SchematicPlacement placement, LitematicaSchematic schematic) { - Vec3i origin = placement.getOrigin(); - Vec3i minCorner = schematic.getOffsetMinCorner(); - int sx = 2 - schematic.widthX(); // this is because the position needs to be adjusted - int sz = 2 - schematic.lengthZ(); // by widthX/lengthZ after every transformation - - Mirror mirror = placement.getMirror(); - Rotation rotation = placement.getRotation(); - - return origin.offset(rotate(doMirroring(minCorner, sx, sz, mirror), sx, sz, rotation)); - } - /** * @param in the xyz offsets of the block relative to the schematic minimum corner. * @param sizeX size of the schematic in the x-axis direction. @@ -96,7 +85,7 @@ private static Vec3i getCorrectedOrigin(SchematicPlacement placement, Litematica * @param mirror the mirroring of the schematic placement. * @return the corresponding xyz coordinates after mirroring them according to the given mirroring. */ - private static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) { + static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) { int xOut = in.getX(); int zOut = in.getZ(); if (mirror == Mirror.LEFT_RIGHT) { @@ -114,7 +103,7 @@ private static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) * @param rotation the rotation to apply * @return the corresponding xyz coordinates after applying {@code rotation}. */ - private static Vec3i rotate(Vec3i in, int sizeX, int sizeZ, Rotation rotation) { + static Vec3i rotate(Vec3i in, int sizeX, int sizeZ, Rotation rotation) { switch (rotation) { case CLOCKWISE_90: return new Vec3i(sizeZ - 1 - in.getZ(), in.getY(), in.getX()); @@ -132,26 +121,91 @@ private static Vec3i rotate(Vec3i in, int sizeX, int sizeZ, Rotation rotation) { * @param i index of the Schematic in the schematic placement list. * @return get it out rotated and mirrored. */ - public static Tuple getSchematic(int i) throws IOException { + public static Tuple getSchematic(int i) { + // annoying fun fact: you can't just work in placement coordinates and then apply + // the placement rotation/mirror to the result because litematica applies the + // global transforms *before* applying the local transforms SchematicPlacement placement = getPlacement(i); - Rotation rotation = placement.getRotation(); - Mirror mirror = placement.getMirror(); - LitematicaSchematic schemIn = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(placement.getSchematicFile().toPath()))); - Vec3i origin = getCorrectedOrigin(placement, schemIn); - boolean flip = rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90; - BlockState[][][] states = new BlockState[flip ? schemIn.lengthZ() : schemIn.widthX()][flip ? schemIn.widthX() : schemIn.lengthZ()][schemIn.heightY()]; - for (int yCounter = 0; yCounter < schemIn.heightY(); yCounter++) { - for (int zCounter = 0; zCounter < schemIn.lengthZ(); zCounter++) { - for (int xCounter = 0; xCounter < schemIn.widthX(); xCounter++) { - Vec3i xyzHolder = new Vec3i(xCounter, yCounter, zCounter); - xyzHolder = LitematicaHelper.doMirroring(xyzHolder, schemIn.widthX(), schemIn.lengthZ(), mirror); - xyzHolder = rotate(xyzHolder, schemIn.widthX(), schemIn.lengthZ(), rotation); - BlockState state = schemIn.getDirect(xCounter, yCounter, zCounter); - state = state == null ? null : state.mirror(mirror).rotate(rotation); - states[xyzHolder.getX()][xyzHolder.getZ()][xyzHolder.getY()] = state; + CompositeSchematic composite = new CompositeSchematic(0, 0, 0); + int minX = Integer.MAX_VALUE; + int minY = Integer.MAX_VALUE; + int minZ = Integer.MAX_VALUE; + for (Map.Entry entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) { + SubRegionPlacement subPlacement = entry.getValue(); + Vec3i pos = subPlacement.getPos(); + Vec3i size = placement.getSchematic().getAreaSize(entry.getKey()); + minX = Math.min(pos.getX() + Math.min(size.getX() + 1, 0), minX); + minY = Math.min(pos.getY() + Math.min(size.getY() + 1, 0), minY); + minZ = Math.min(pos.getZ() + Math.min(size.getZ() + 1, 0), minZ); + } + for (Map.Entry entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) { + SubRegionPlacement subPlacement = entry.getValue(); + Vec3i size = placement.getSchematic().getAreaSize(entry.getKey()); + LitematicaBlockStateContainer container = placement.getSchematic().getSubRegionContainer(entry.getKey()); + BlockState[][][] states = new BlockState[Math.abs(size.getX())][Math.abs(size.getZ())][Math.abs(size.getY())]; + for (int x = 0; x < states.length; x++) { + for (int z = 0; z < states[x].length; z++) { + for (int y = 0; y < states[x][z].length; y++) { + states[x][z][y] = container.get(x, y, z); + } } } + ISchematic schematic = new StaticSchematic(states); + Mirror mirror = subPlacement.getMirror(); + Rotation rotation = subPlacement.getRotation(); + if (placement.getRotation() == Rotation.CLOCKWISE_90 || placement.getRotation() == Rotation.COUNTERCLOCKWISE_90) { + mirror = mirror == Mirror.LEFT_RIGHT ? Mirror.FRONT_BACK : Mirror.LEFT_RIGHT; + } + if (placement.getMirror() != Mirror.NONE) { + rotation = rotation.getRotated(rotation).getRotated(rotation); // inverse rotation + } + schematic = new MirroredSchematic(schematic, mirror); + schematic = new RotatedSchematic(schematic, rotation); + int mx = Math.min(size.getX() + 1, 0); + int my = Math.min(size.getY() + 1, 0); + int mz = Math.min(size.getZ() + 1, 0); + int sx = 2 - Math.abs(size.getX()); // this is because the position needs to be adjusted + int sz = 2 - Math.abs(size.getZ()); // by widthX/lengthZ after every transformation + Vec3i minCorner = new Vec3i(mx, my, mz); + minCorner = rotate(doMirroring(minCorner, sx, sz, mirror), sx, sz, rotation); + Vec3i pos = subPlacement.getPos().offset(minCorner).offset(-minX, -minY, -minZ); + composite.put(schematic, pos.getX(), pos.getY(), pos.getZ()); + } + int sx = 2 - composite.widthX(); // this is because the position needs to be adjusted + int sz = 2 - composite.lengthZ(); // by widthX/lengthZ after every transformation + Vec3i minCorner = new Vec3i(minX, minY, minZ); + Mirror mirror = placement.getMirror(); + Rotation rotation = placement.getRotation(); + minCorner = rotate(doMirroring(minCorner, sx, sz, mirror), sx, sz, rotation); + ISchematic schematic = new MirroredSchematic(composite, mirror); + schematic = new RotatedSchematic(schematic, rotation); + return new Tuple<>(new LitematicaPlacementSchematic(schematic), placement.getOrigin().offset(minCorner)); + } + + private static class LitematicaPlacementSchematic extends AbstractSchematic implements IStaticSchematic { + private final ISchematic schematic; + + public LitematicaPlacementSchematic(ISchematic schematic) { + super(schematic.widthX(), schematic.heightY(), schematic.lengthZ()); + this.schematic = schematic; + } + + @Override + public BlockState getDirect(int x, int y, int z) { + if (inSchematic(x, y, z, null)) { + return desiredState(x, y, z, null, Collections.emptyList()); + } + return null; + } + + @Override + public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { + return schematic.desiredState(x, y, z, current, approxPlaceable); + } + + @Override + public boolean inSchematic(int x, int y, int z, BlockState current) { + return schematic.inSchematic(x, y, z, current); } - return new Tuple<>(new StaticSchematic(states), origin); } } \ No newline at end of file diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java new file mode 100644 index 000000000..6fee9f403 --- /dev/null +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java @@ -0,0 +1,32 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package fi.dy.masa.litematica.schematic; + +import fi.dy.masa.litematica.schematic.container.LitematicaBlockStateContainer; +import net.minecraft.core.BlockPos; + +public class LitematicaSchematic { + + public LitematicaBlockStateContainer getSubRegionContainer(String name) { + throw new LinkageError(); + } + + public BlockPos getAreaSize(String name) { + throw new LinkageError(); + } +} \ No newline at end of file diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/container/LitematicaBlockStateContainer.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/container/LitematicaBlockStateContainer.java new file mode 100644 index 000000000..213b4fa58 --- /dev/null +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/container/LitematicaBlockStateContainer.java @@ -0,0 +1,27 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package fi.dy.masa.litematica.schematic.container; + +import net.minecraft.world.level.block.state.BlockState; + +public class LitematicaBlockStateContainer { + + public BlockState get(int x, int y, int z) { + throw new LinkageError(); + } +} diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java index 9d944334b..58eaf6021 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java @@ -17,6 +17,8 @@ package fi.dy.masa.litematica.schematic.placement; +import com.google.common.collect.ImmutableMap; +import fi.dy.masa.litematica.schematic.LitematicaSchematic; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; @@ -30,4 +32,11 @@ public Mirror getMirror() { throw new LinkageError(); } + public ImmutableMap getEnabledRelativeSubRegionPlacements() { + throw new LinkageError(); + } + + public LitematicaSchematic getSchematic() { + throw new LinkageError(); + } } \ No newline at end of file diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java index 39b68f67e..54bb3fb79 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java @@ -19,20 +19,12 @@ import net.minecraft.core.BlockPos; -import javax.annotation.Nullable; -import java.io.File; - public class SchematicPlacementUnloaded { public String getName() { throw new LinkageError(); } - @Nullable - public File getSchematicFile() { - throw new LinkageError(); - } - public BlockPos getOrigin() { throw new LinkageError(); } diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SubRegionPlacement.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SubRegionPlacement.java new file mode 100644 index 000000000..ec28ee95d --- /dev/null +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SubRegionPlacement.java @@ -0,0 +1,37 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package fi.dy.masa.litematica.schematic.placement; + +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.block.Mirror; +import net.minecraft.world.level.block.Rotation; + +public class SubRegionPlacement { + + public BlockPos getPos() { + throw new LinkageError(); + } + + public Rotation getRotation() { + throw new LinkageError(); + } + + public Mirror getMirror() { + throw new LinkageError(); + } +} \ No newline at end of file From 246a246cb7a76a193a690c4999ce839b213df82e Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Mon, 29 Jul 2024 23:17:49 +0200 Subject: [PATCH 05/21] Less nested schematics --- .../litematica/LitematicaHelper.java | 137 +++++++----------- 1 file changed, 49 insertions(+), 88 deletions(-) diff --git a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java index bb7181724..2b79134aa 100644 --- a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java +++ b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java @@ -17,10 +17,9 @@ package baritone.utils.schematic.litematica; -import baritone.api.schematic.AbstractSchematic; -import baritone.api.schematic.IStaticSchematic; -import baritone.api.schematic.ISchematic; import baritone.api.schematic.CompositeSchematic; +import baritone.api.schematic.ISchematic; +import baritone.api.schematic.IStaticSchematic; import baritone.api.schematic.MirroredSchematic; import baritone.api.schematic.RotatedSchematic; import baritone.utils.schematic.StaticSchematic; @@ -35,8 +34,8 @@ import net.minecraft.world.level.block.Rotation; import net.minecraft.world.level.block.state.BlockState; -import java.util.List; import java.util.Collections; +import java.util.HashMap; import java.util.Map; /** @@ -78,71 +77,50 @@ public static String getName(int i) { return getPlacement(i).getName(); } - /** - * @param in the xyz offsets of the block relative to the schematic minimum corner. - * @param sizeX size of the schematic in the x-axis direction. - * @param sizeZ size of the schematic in the z-axis direction. - * @param mirror the mirroring of the schematic placement. - * @return the corresponding xyz coordinates after mirroring them according to the given mirroring. - */ - static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) { - int xOut = in.getX(); - int zOut = in.getZ(); + private static Vec3i transform(Vec3i in, Mirror mirror, Rotation rotation) { + int x = in.getX(); + int z = in.getZ(); if (mirror == Mirror.LEFT_RIGHT) { - zOut = sizeZ - 1 - in.getZ(); + z = -z; } else if (mirror == Mirror.FRONT_BACK) { - xOut = sizeX - 1 - in.getX(); + x = -x; } - return new Vec3i(xOut, in.getY(), zOut); - } - - /** - * @param in the xyz offsets of the block relative to the schematic minimum corner. - * @param sizeX size of the schematic in the x-axis direction. - * @param sizeZ size of the schematic in the z-axis direction. - * @param rotation the rotation to apply - * @return the corresponding xyz coordinates after applying {@code rotation}. - */ - static Vec3i rotate(Vec3i in, int sizeX, int sizeZ, Rotation rotation) { switch (rotation) { case CLOCKWISE_90: - return new Vec3i(sizeZ - 1 - in.getZ(), in.getY(), in.getX()); + return new Vec3i(-z, in.getY(), x); case CLOCKWISE_180: - return new Vec3i(sizeX - 1 - in.getX(), in.getY(), sizeZ - 1 - in.getZ()); + return new Vec3i(-x, in.getY(), -z); case COUNTERCLOCKWISE_90: - return new Vec3i(in.getZ(), in.getY(), sizeX - 1 - in.getX()); + return new Vec3i(z, in.getY(), -x); default: - return in; + return new Vec3i(x, in.getY(), z); } } /** - * @param schemIn give in the original schematic. - * @param i index of the Schematic in the schematic placement list. - * @return get it out rotated and mirrored. + * @param i index of the Schematic in the schematic placement list. + * @return The transformed schematic and the position of its minimum corner */ public static Tuple getSchematic(int i) { - // annoying fun fact: you can't just work in placement coordinates and then apply - // the placement rotation/mirror to the result because litematica applies the - // global transforms *before* applying the local transforms SchematicPlacement placement = getPlacement(i); - CompositeSchematic composite = new CompositeSchematic(0, 0, 0); int minX = Integer.MAX_VALUE; int minY = Integer.MAX_VALUE; int minZ = Integer.MAX_VALUE; + HashMap subRegions = new HashMap<>(); for (Map.Entry entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) { SubRegionPlacement subPlacement = entry.getValue(); - Vec3i pos = subPlacement.getPos(); - Vec3i size = placement.getSchematic().getAreaSize(entry.getKey()); - minX = Math.min(pos.getX() + Math.min(size.getX() + 1, 0), minX); - minY = Math.min(pos.getY() + Math.min(size.getY() + 1, 0), minY); - minZ = Math.min(pos.getZ() + Math.min(size.getZ() + 1, 0), minZ); - } - for (Map.Entry entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) { - SubRegionPlacement subPlacement = entry.getValue(); + Vec3i pos = transform(subPlacement.getPos(), placement.getMirror(), placement.getRotation()); Vec3i size = placement.getSchematic().getAreaSize(entry.getKey()); - LitematicaBlockStateContainer container = placement.getSchematic().getSubRegionContainer(entry.getKey()); BlockState[][][] states = new BlockState[Math.abs(size.getX())][Math.abs(size.getZ())][Math.abs(size.getY())]; + size = transform(size, placement.getMirror(), placement.getRotation()); + size = transform(size, subPlacement.getMirror(), subPlacement.getRotation()); + int mx = Math.min(size.getX() + 1, 0); + int my = Math.min(size.getY() + 1, 0); + int mz = Math.min(size.getZ() + 1, 0); + minX = Math.min(minX, pos.getX() + mx); + minY = Math.min(minY, pos.getY() + my); + minZ = Math.min(minZ, pos.getZ() + mz); + LitematicaBlockStateContainer container = placement.getSchematic().getSubRegionContainer(entry.getKey()); for (int x = 0; x < states.length; x++) { for (int z = 0; z < states[x].length; z++) { for (int y = 0; y < states[x][z].length; y++) { @@ -152,42 +130,35 @@ public static Tuple getSchematic(int i) { } ISchematic schematic = new StaticSchematic(states); Mirror mirror = subPlacement.getMirror(); - Rotation rotation = subPlacement.getRotation(); - if (placement.getRotation() == Rotation.CLOCKWISE_90 || placement.getRotation() == Rotation.COUNTERCLOCKWISE_90) { - mirror = mirror == Mirror.LEFT_RIGHT ? Mirror.FRONT_BACK : Mirror.LEFT_RIGHT; + Rotation rotation = subPlacement.getRotation().getRotated(placement.getRotation()); + if (mirror != Mirror.NONE) { + rotation = rotation.getRotated(placement.getRotation()).getRotated(placement.getRotation()); } - if (placement.getMirror() != Mirror.NONE) { - rotation = rotation.getRotated(rotation).getRotated(rotation); // inverse rotation + if (mirror == placement.getMirror()) { + // nothing :) + } else if (mirror != Mirror.NONE && placement.getMirror() != Mirror.NONE) { + rotation = rotation.getRotated(Rotation.CLOCKWISE_180); + } else if (mirror != Mirror.NONE) { + schematic = new MirroredSchematic(schematic, mirror); + } else { + schematic = new MirroredSchematic(schematic, placement.getMirror()); } - schematic = new MirroredSchematic(schematic, mirror); - schematic = new RotatedSchematic(schematic, rotation); - int mx = Math.min(size.getX() + 1, 0); - int my = Math.min(size.getY() + 1, 0); - int mz = Math.min(size.getZ() + 1, 0); - int sx = 2 - Math.abs(size.getX()); // this is because the position needs to be adjusted - int sz = 2 - Math.abs(size.getZ()); // by widthX/lengthZ after every transformation - Vec3i minCorner = new Vec3i(mx, my, mz); - minCorner = rotate(doMirroring(minCorner, sx, sz, mirror), sx, sz, rotation); - Vec3i pos = subPlacement.getPos().offset(minCorner).offset(-minX, -minY, -minZ); - composite.put(schematic, pos.getX(), pos.getY(), pos.getZ()); + if (rotation != Rotation.NONE) { + schematic = new RotatedSchematic(schematic, rotation); + } + subRegions.put(pos.offset(mx, my, mz), schematic); + } + LitematicaPlacementSchematic composite = new LitematicaPlacementSchematic(); + for (Map.Entry entry : subRegions.entrySet()) { + Vec3i pos = entry.getKey().offset(-minX, -minY, -minZ); + composite.put(entry.getValue(), pos.getX(), pos.getY(), pos.getZ()); } - int sx = 2 - composite.widthX(); // this is because the position needs to be adjusted - int sz = 2 - composite.lengthZ(); // by widthX/lengthZ after every transformation - Vec3i minCorner = new Vec3i(minX, minY, minZ); - Mirror mirror = placement.getMirror(); - Rotation rotation = placement.getRotation(); - minCorner = rotate(doMirroring(minCorner, sx, sz, mirror), sx, sz, rotation); - ISchematic schematic = new MirroredSchematic(composite, mirror); - schematic = new RotatedSchematic(schematic, rotation); - return new Tuple<>(new LitematicaPlacementSchematic(schematic), placement.getOrigin().offset(minCorner)); + return new Tuple<>(composite, placement.getOrigin().offset(minX, minY, minZ)); } - private static class LitematicaPlacementSchematic extends AbstractSchematic implements IStaticSchematic { - private final ISchematic schematic; - - public LitematicaPlacementSchematic(ISchematic schematic) { - super(schematic.widthX(), schematic.heightY(), schematic.lengthZ()); - this.schematic = schematic; + private static class LitematicaPlacementSchematic extends CompositeSchematic implements IStaticSchematic { + public LitematicaPlacementSchematic() { + super(0, 0, 0); } @Override @@ -197,15 +168,5 @@ public BlockState getDirect(int x, int y, int z) { } return null; } - - @Override - public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { - return schematic.desiredState(x, y, z, current, approxPlaceable); - } - - @Override - public boolean inSchematic(int x, int y, int z, BlockState current) { - return schematic.inSchematic(x, y, z, current); - } } } \ No newline at end of file From e71547b9ef9a89625733a32d806c190a92858923 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 30 Jul 2024 00:43:21 +0200 Subject: [PATCH 06/21] Take blocks from the schematic world --- .../api/schematic/MirroredSchematic.java | 114 --------------- .../api/schematic/RotatedSchematic.java | 136 ------------------ .../litematica/LitematicaHelper.java | 37 ++--- .../schematic/LitematicaSchematic.java | 5 - .../SchematicWorldHandler.java} | 8 +- .../masa/litematica/world/WorldSchematic.java | 27 ++++ 6 files changed, 40 insertions(+), 287 deletions(-) delete mode 100644 src/api/java/baritone/api/schematic/MirroredSchematic.java delete mode 100644 src/api/java/baritone/api/schematic/RotatedSchematic.java rename src/schematica_api/java/fi/dy/masa/litematica/{schematic/container/LitematicaBlockStateContainer.java => world/SchematicWorldHandler.java} (78%) create mode 100644 src/schematica_api/java/fi/dy/masa/litematica/world/WorldSchematic.java diff --git a/src/api/java/baritone/api/schematic/MirroredSchematic.java b/src/api/java/baritone/api/schematic/MirroredSchematic.java deleted file mode 100644 index b9e10808c..000000000 --- a/src/api/java/baritone/api/schematic/MirroredSchematic.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.schematic; - -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.Mirror; - -import java.util.List; -import java.util.stream.Collectors; - -public class MirroredSchematic implements ISchematic { - - private final ISchematic schematic; - private final Mirror mirror; - - public MirroredSchematic(ISchematic schematic, Mirror mirror) { - this.schematic = schematic; - this.mirror = mirror; - } - - @Override - public boolean inSchematic(int x, int y, int z, BlockState currentState) { - return schematic.inSchematic( - mirrorX(x, widthX(), mirror), - y, - mirrorZ(z, lengthZ(), mirror), - mirror(currentState, mirror) - ); - } - - @Override - public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { - return mirror(schematic.desiredState( - mirrorX(x, widthX(), mirror), - y, - mirrorZ(z, lengthZ(), mirror), - mirror(current, mirror), - mirror(approxPlaceable, mirror) - ), mirror); - } - - @Override - public void reset() { - schematic.reset(); - } - - @Override - public int widthX() { - return schematic.widthX(); - } - - @Override - public int heightY() { - return schematic.heightY(); - } - - @Override - public int lengthZ() { - return schematic.lengthZ(); - } - - private static int mirrorX(int x, int sizeX, Mirror mirror) { - switch (mirror) { - case NONE: - case LEFT_RIGHT: - return x; - case FRONT_BACK: - return sizeX - x - 1; - } - throw new IllegalArgumentException("Unknown mirror"); - } - - private static int mirrorZ(int z, int sizeZ, Mirror mirror) { - switch (mirror) { - case NONE: - case FRONT_BACK: - return z; - case LEFT_RIGHT: - return sizeZ - z - 1; - } - throw new IllegalArgumentException("Unknown mirror"); - } - - private static BlockState mirror(BlockState state, Mirror mirror) { - if (state == null) { - return null; - } - return state.mirror(mirror); - } - - private static List mirror(List states, Mirror mirror) { - if (states == null) { - return null; - } - return states.stream() - .map(s -> mirror(s, mirror)) - .collect(Collectors.toList()); - } -} diff --git a/src/api/java/baritone/api/schematic/RotatedSchematic.java b/src/api/java/baritone/api/schematic/RotatedSchematic.java deleted file mode 100644 index e3c9ed7aa..000000000 --- a/src/api/java/baritone/api/schematic/RotatedSchematic.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.schematic; - -import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.block.Rotation; - -import java.util.List; -import java.util.stream.Collectors; - -public class RotatedSchematic implements ISchematic { - - private final ISchematic schematic; - private final Rotation rotation; - private final Rotation inverseRotation; - - public RotatedSchematic(ISchematic schematic, Rotation rotation) { - this.schematic = schematic; - this.rotation = rotation; - // I don't think a 14 line switch would improve readability - this.inverseRotation = rotation.getRotated(rotation).getRotated(rotation); - } - - @Override - public boolean inSchematic(int x, int y, int z, BlockState currentState) { - return schematic.inSchematic( - rotateX(x, z, widthX(), lengthZ(), inverseRotation), - y, - rotateZ(x, z, widthX(), lengthZ(), inverseRotation), - rotate(currentState, inverseRotation) - ); - } - - @Override - public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { - return rotate(schematic.desiredState( - rotateX(x, z, widthX(), lengthZ(), inverseRotation), - y, - rotateZ(x, z, widthX(), lengthZ(), inverseRotation), - rotate(current, inverseRotation), - rotate(approxPlaceable, inverseRotation) - ), rotation); - } - - @Override - public void reset() { - schematic.reset(); - } - - @Override - public int widthX() { - return flipsCoordinates(rotation) ? schematic.lengthZ() : schematic.widthX(); - } - - @Override - public int heightY() { - return schematic.heightY(); - } - - @Override - public int lengthZ() { - return flipsCoordinates(rotation) ? schematic.widthX() : schematic.lengthZ(); - } - - /** - * Wether {@code rotation} swaps the x and z components - */ - private static boolean flipsCoordinates(Rotation rotation) { - return rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90; - } - - /** - * The x component of x,y after applying the rotation - */ - private static int rotateX(int x, int z, int sizeX, int sizeZ, Rotation rotation) { - switch (rotation) { - case NONE: - return x; - case CLOCKWISE_90: - return sizeZ - z - 1; - case CLOCKWISE_180: - return sizeX - x - 1; - case COUNTERCLOCKWISE_90: - return z; - } - throw new IllegalArgumentException("Unknown rotation"); - } - - /** - * The z component of x,y after applying the rotation - */ - private static int rotateZ(int x, int z, int sizeX, int sizeZ, Rotation rotation) { - switch (rotation) { - case NONE: - return z; - case CLOCKWISE_90: - return x; - case CLOCKWISE_180: - return sizeZ - z - 1; - case COUNTERCLOCKWISE_90: - return sizeX - x - 1; - } - throw new IllegalArgumentException("Unknown rotation"); - } - - private static BlockState rotate(BlockState state, Rotation rotation) { - if (state == null) { - return null; - } - return state.rotate(rotation); - } - - private static List rotate(List states, Rotation rotation) { - if (states == null) { - return null; - } - return states.stream() - .map(s -> rotate(s, rotation)) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java index 2b79134aa..c5bf57e41 100644 --- a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java +++ b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java @@ -18,16 +18,15 @@ package baritone.utils.schematic.litematica; import baritone.api.schematic.CompositeSchematic; -import baritone.api.schematic.ISchematic; import baritone.api.schematic.IStaticSchematic; -import baritone.api.schematic.MirroredSchematic; -import baritone.api.schematic.RotatedSchematic; import baritone.utils.schematic.StaticSchematic; import fi.dy.masa.litematica.Litematica; import fi.dy.masa.litematica.data.DataManager; -import fi.dy.masa.litematica.schematic.container.LitematicaBlockStateContainer; import fi.dy.masa.litematica.schematic.placement.SchematicPlacement; import fi.dy.masa.litematica.schematic.placement.SubRegionPlacement; +import fi.dy.masa.litematica.world.SchematicWorldHandler; +import fi.dy.masa.litematica.world.WorldSchematic; +import net.minecraft.core.BlockPos; import net.minecraft.core.Vec3i; import net.minecraft.util.Tuple; import net.minecraft.world.level.block.Mirror; @@ -106,12 +105,12 @@ public static Tuple getSchematic(int i) { int minX = Integer.MAX_VALUE; int minY = Integer.MAX_VALUE; int minZ = Integer.MAX_VALUE; - HashMap subRegions = new HashMap<>(); + HashMap subRegions = new HashMap<>(); + WorldSchematic schematicWorld = SchematicWorldHandler.getSchematicWorld(); for (Map.Entry entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) { SubRegionPlacement subPlacement = entry.getValue(); Vec3i pos = transform(subPlacement.getPos(), placement.getMirror(), placement.getRotation()); Vec3i size = placement.getSchematic().getAreaSize(entry.getKey()); - BlockState[][][] states = new BlockState[Math.abs(size.getX())][Math.abs(size.getZ())][Math.abs(size.getY())]; size = transform(size, placement.getMirror(), placement.getRotation()); size = transform(size, subPlacement.getMirror(), subPlacement.getRotation()); int mx = Math.min(size.getX() + 1, 0); @@ -120,36 +119,20 @@ public static Tuple getSchematic(int i) { minX = Math.min(minX, pos.getX() + mx); minY = Math.min(minY, pos.getY() + my); minZ = Math.min(minZ, pos.getZ() + mz); - LitematicaBlockStateContainer container = placement.getSchematic().getSubRegionContainer(entry.getKey()); + BlockPos origin = placement.getOrigin().offset(pos).offset(mx, my, mz); + BlockState[][][] states = new BlockState[Math.abs(size.getX())][Math.abs(size.getZ())][Math.abs(size.getY())]; for (int x = 0; x < states.length; x++) { for (int z = 0; z < states[x].length; z++) { for (int y = 0; y < states[x][z].length; y++) { - states[x][z][y] = container.get(x, y, z); + states[x][z][y] = schematicWorld.getBlockState(origin.offset(x, y, z)); } } } - ISchematic schematic = new StaticSchematic(states); - Mirror mirror = subPlacement.getMirror(); - Rotation rotation = subPlacement.getRotation().getRotated(placement.getRotation()); - if (mirror != Mirror.NONE) { - rotation = rotation.getRotated(placement.getRotation()).getRotated(placement.getRotation()); - } - if (mirror == placement.getMirror()) { - // nothing :) - } else if (mirror != Mirror.NONE && placement.getMirror() != Mirror.NONE) { - rotation = rotation.getRotated(Rotation.CLOCKWISE_180); - } else if (mirror != Mirror.NONE) { - schematic = new MirroredSchematic(schematic, mirror); - } else { - schematic = new MirroredSchematic(schematic, placement.getMirror()); - } - if (rotation != Rotation.NONE) { - schematic = new RotatedSchematic(schematic, rotation); - } + StaticSchematic schematic = new StaticSchematic(states); subRegions.put(pos.offset(mx, my, mz), schematic); } LitematicaPlacementSchematic composite = new LitematicaPlacementSchematic(); - for (Map.Entry entry : subRegions.entrySet()) { + for (Map.Entry entry : subRegions.entrySet()) { Vec3i pos = entry.getKey().offset(-minX, -minY, -minZ); composite.put(entry.getValue(), pos.getX(), pos.getY(), pos.getZ()); } diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java index 6fee9f403..fc8ef5c6e 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/LitematicaSchematic.java @@ -17,15 +17,10 @@ package fi.dy.masa.litematica.schematic; -import fi.dy.masa.litematica.schematic.container.LitematicaBlockStateContainer; import net.minecraft.core.BlockPos; public class LitematicaSchematic { - public LitematicaBlockStateContainer getSubRegionContainer(String name) { - throw new LinkageError(); - } - public BlockPos getAreaSize(String name) { throw new LinkageError(); } diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/container/LitematicaBlockStateContainer.java b/src/schematica_api/java/fi/dy/masa/litematica/world/SchematicWorldHandler.java similarity index 78% rename from src/schematica_api/java/fi/dy/masa/litematica/schematic/container/LitematicaBlockStateContainer.java rename to src/schematica_api/java/fi/dy/masa/litematica/world/SchematicWorldHandler.java index 213b4fa58..dfe6e9807 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/container/LitematicaBlockStateContainer.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/world/SchematicWorldHandler.java @@ -15,13 +15,11 @@ * along with Baritone. If not, see . */ -package fi.dy.masa.litematica.schematic.container; +package fi.dy.masa.litematica.world; -import net.minecraft.world.level.block.state.BlockState; +public class SchematicWorldHandler { -public class LitematicaBlockStateContainer { - - public BlockState get(int x, int y, int z) { + public static WorldSchematic getSchematicWorld() { throw new LinkageError(); } } diff --git a/src/schematica_api/java/fi/dy/masa/litematica/world/WorldSchematic.java b/src/schematica_api/java/fi/dy/masa/litematica/world/WorldSchematic.java new file mode 100644 index 000000000..58f28b3a6 --- /dev/null +++ b/src/schematica_api/java/fi/dy/masa/litematica/world/WorldSchematic.java @@ -0,0 +1,27 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package fi.dy.masa.litematica.world; + +import net.minecraft.world.level.Level; + +public abstract class WorldSchematic extends Level { + private WorldSchematic() { + super(null, null, null, null, null, false, false, 0, 0); + throw new LinkageError(); + } +} From 1a0cca794c3e0b5d953a181280387b195e9b6869 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 30 Jul 2024 01:29:24 +0200 Subject: [PATCH 07/21] Use toString like for schematica --- .../java/baritone/process/BuilderProcess.java | 3 +-- .../litematica/LitematicaHelper.java | 20 +++++++++---------- 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 4e04e60f5..346748eff 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -229,12 +229,11 @@ public void buildOpenLitematic(int i) { if (LitematicaHelper.isLitematicaPresent()) { //if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager if (LitematicaHelper.hasLoadedSchematic(i)) { - String name = LitematicaHelper.getName(i); try { Tuple schematic = LitematicaHelper.getSchematic(i); Vec3i correctedOrigin = schematic.getB(); ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA()); - build(name, schematic2, correctedOrigin); + build(schematic.getA().toString(), schematic2, correctedOrigin); } catch (Exception e) { logDirect("Schematic File could not be loaded."); } diff --git a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java index c5bf57e41..081d32cc8 100644 --- a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java +++ b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java @@ -68,14 +68,6 @@ private static SchematicPlacement getPlacement(int i) { return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i); } - /** - * @param i index of the Schematic in the schematic placement list. - * @return the name of the requested schematic. - */ - public static String getName(int i) { - return getPlacement(i).getName(); - } - private static Vec3i transform(Vec3i in, Mirror mirror, Rotation rotation) { int x = in.getX(); int z = in.getZ(); @@ -131,7 +123,7 @@ public static Tuple getSchematic(int i) { StaticSchematic schematic = new StaticSchematic(states); subRegions.put(pos.offset(mx, my, mz), schematic); } - LitematicaPlacementSchematic composite = new LitematicaPlacementSchematic(); + LitematicaPlacementSchematic composite = new LitematicaPlacementSchematic(placement.getName()); for (Map.Entry entry : subRegions.entrySet()) { Vec3i pos = entry.getKey().offset(-minX, -minY, -minZ); composite.put(entry.getValue(), pos.getX(), pos.getY(), pos.getZ()); @@ -140,8 +132,11 @@ public static Tuple getSchematic(int i) { } private static class LitematicaPlacementSchematic extends CompositeSchematic implements IStaticSchematic { - public LitematicaPlacementSchematic() { + private final String name; + + public LitematicaPlacementSchematic(String name) { super(0, 0, 0); + this.name = name; } @Override @@ -151,5 +146,10 @@ public BlockState getDirect(int x, int y, int z) { } return null; } + + @Override + public String toString() { + return name; + } } } \ No newline at end of file From 99f9dd1671b9b2adb216dcbbdf789c781ebe18ee Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 30 Jul 2024 01:43:39 +0200 Subject: [PATCH 08/21] Performance --- .../format/defaults/LitematicaSchematic.java | 32 ++++++------------- 1 file changed, 9 insertions(+), 23 deletions(-) diff --git a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java index aa0425bb3..faa2eef1e 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java @@ -139,22 +139,6 @@ private static long getVolume(CompoundTag subReg) { return Math.abs(size.getInt("x") * size.getInt("y") * size.getInt("z")); } - /** - * Subregion don't have to be the same size as the enclosing size of the schematic. If they are smaller we check here if the current block is part of the subregion. - * - * @param x coord of the block relative to the minimum corner. - * @param y coord of the block relative to the minimum corner. - * @param z coord of the block relative to the minimum corner. - * @return if the current block is part of the subregion. - */ - private static boolean inSubregion(CompoundTag subReg, int x, int y, int z) { - CompoundTag size = subReg.getCompound("Size"); - return x >= 0 && y >= 0 && z >= 0 && - x < Math.abs(size.getInt("x")) && - y < Math.abs(size.getInt("y")) && - z < Math.abs(size.getInt("z")); - } - /** * @param s axis. * @return the lowest coordinate of that axis of the schematic. @@ -195,14 +179,16 @@ private void writeSubregionIntoSchematic(CompoundTag subReg, Vec3i offsetMinCorn int offsetX = getMinOfSubregion(subReg, "x") - offsetMinCorner.getX(); int offsetY = getMinOfSubregion(subReg, "y") - offsetMinCorner.getY(); int offsetZ = getMinOfSubregion(subReg, "z") - offsetMinCorner.getZ(); + CompoundTag size = subReg.getCompound("Size"); + int sizeX = Math.abs(size.getInt("x")); + int sizeY = Math.abs(size.getInt("y")); + int sizeZ = Math.abs(size.getInt("z")); int index = 0; - for (int y = 0; y < this.y; y++) { - for (int z = 0; z < this.z; z++) { - for (int x = 0; x < this.x; x++) { - if (inSubregion(subReg, x, y, z)) { - this.states[x + offsetX][z + offsetZ][y + offsetY] = blockList[bitArray.getAt(index)]; - index++; - } + for (int y = 0; y < sizeY; y++) { + for (int z = 0; z < sizeZ; z++) { + for (int x = 0; x < sizeX; x++) { + this.states[x + offsetX][z + offsetZ][y + offsetY] = blockList[bitArray.getAt(index)]; + index++; } } } From 7609f3082e6e96a9e23b1d8101ab31d2e1adbb1f Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 30 Jul 2024 02:00:10 +0200 Subject: [PATCH 09/21] Keep subregions as separate boxes --- .../format/defaults/LitematicaSchematic.java | 20 ++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java index faa2eef1e..89684981e 100644 --- a/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java +++ b/src/main/java/baritone/utils/schematic/format/defaults/LitematicaSchematic.java @@ -17,6 +17,8 @@ package baritone.utils.schematic.format.defaults; +import baritone.api.schematic.CompositeSchematic; +import baritone.api.schematic.IStaticSchematic; import baritone.utils.schematic.StaticSchematic; import net.minecraft.core.Vec3i; import net.minecraft.core.registries.BuiltInRegistries; @@ -29,6 +31,7 @@ import org.apache.commons.lang3.Validate; import javax.annotation.Nullable; +import java.util.Collections; import java.util.Optional; /** @@ -38,18 +41,14 @@ * @author rycbar * @since 22.09.2022 */ -public final class LitematicaSchematic extends StaticSchematic { +public final class LitematicaSchematic extends CompositeSchematic implements IStaticSchematic { /** * @param nbtTagCompound a decompressed file stream aka nbt data. * @param rotated if the schematic is rotated by 90°. */ public LitematicaSchematic(CompoundTag nbt) { - CompoundTag size = nbt.getCompound("Metadata").getCompound("EnclosingSize"); - this.x = Math.abs(size.getInt("x")); - this.y = Math.abs(size.getInt("y")); - this.z = Math.abs(size.getInt("z")); - this.states = new BlockState[this.x][this.z][this.y]; + super(0, 0, 0); fillInSchematic(nbt); } @@ -183,15 +182,22 @@ private void writeSubregionIntoSchematic(CompoundTag subReg, Vec3i offsetMinCorn int sizeX = Math.abs(size.getInt("x")); int sizeY = Math.abs(size.getInt("y")); int sizeZ = Math.abs(size.getInt("z")); + BlockState[][][] states = new BlockState[sizeX][sizeZ][sizeY]; int index = 0; for (int y = 0; y < sizeY; y++) { for (int z = 0; z < sizeZ; z++) { for (int x = 0; x < sizeX; x++) { - this.states[x + offsetX][z + offsetZ][y + offsetY] = blockList[bitArray.getAt(index)]; + states[x][z][y] = blockList[bitArray.getAt(index)]; index++; } } } + this.put(new StaticSchematic(states), offsetX, offsetY, offsetZ); + } + + @Override + public BlockState getDirect(int x, int y, int z) { + return desiredState(x, y, z, null, Collections.emptyList()); } /** From b915151ae3743ef9f3b17a704690a17723e66ad4 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 30 Jul 2024 02:27:57 +0200 Subject: [PATCH 10/21] We don't expect any exceptions here anymore --- src/main/java/baritone/process/BuilderProcess.java | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 346748eff..33f3db3f1 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -229,14 +229,10 @@ public void buildOpenLitematic(int i) { if (LitematicaHelper.isLitematicaPresent()) { //if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager if (LitematicaHelper.hasLoadedSchematic(i)) { - try { - Tuple schematic = LitematicaHelper.getSchematic(i); - Vec3i correctedOrigin = schematic.getB(); - ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA()); - build(schematic.getA().toString(), schematic2, correctedOrigin); - } catch (Exception e) { - logDirect("Schematic File could not be loaded."); - } + Tuple schematic = LitematicaHelper.getSchematic(i); + Vec3i correctedOrigin = schematic.getB(); + ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA()); + build(schematic.getA().toString(), schematic2, correctedOrigin); } else { logDirect(String.format("List of placements has no entry %s", i + 1)); } From 6b6931c86d474495a4b1ead1ec4d3ec3651409dc Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 30 Jul 2024 16:39:44 +0200 Subject: [PATCH 11/21] Remove unused stub The class doesn't even exist in the version of Litematica I'm using so it doesn't seem to have an effect on descriptor strings in our bytecode. Otherwise my game would crash. --- .../placement/SchematicPlacement.java | 11 ++++++- .../placement/SchematicPlacementUnloaded.java | 31 ------------------- 2 files changed, 10 insertions(+), 32 deletions(-) delete mode 100644 src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java index 58eaf6021..77f8b629e 100644 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java +++ b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacement.java @@ -19,10 +19,19 @@ import com.google.common.collect.ImmutableMap; import fi.dy.masa.litematica.schematic.LitematicaSchematic; +import net.minecraft.core.BlockPos; import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; -public class SchematicPlacement extends SchematicPlacementUnloaded { +public class SchematicPlacement { + + public String getName() { + throw new LinkageError(); + } + + public BlockPos getOrigin() { + throw new LinkageError(); + } public Rotation getRotation() { throw new LinkageError(); diff --git a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java b/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java deleted file mode 100644 index 54bb3fb79..000000000 --- a/src/schematica_api/java/fi/dy/masa/litematica/schematic/placement/SchematicPlacementUnloaded.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package fi.dy.masa.litematica.schematic.placement; - -import net.minecraft.core.BlockPos; - -public class SchematicPlacementUnloaded { - - public String getName() { - throw new LinkageError(); - } - - public BlockPos getOrigin() { - throw new LinkageError(); - } -} \ No newline at end of file From 42032890ed64af5aeba9a7a040393fbfc56fec9c Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 28 Jul 2024 23:50:03 +0200 Subject: [PATCH 12/21] =?UTF-8?q?=E2=9C=A8=20Setting=20to=20rotate=20schem?= =?UTF-8?q?atics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/java/baritone/api/Settings.java | 14 ++ .../api/schematic/RotatedSchematic.java | 136 ++++++++++++++++++ .../java/baritone/api/utils/SettingsUtil.java | 4 +- .../java/baritone/process/BuilderProcess.java | 4 + 4 files changed, 157 insertions(+), 1 deletion(-) create mode 100644 src/api/java/baritone/api/schematic/RotatedSchematic.java diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 1812fe486..b7612a46e 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -29,6 +29,8 @@ import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.Rotation; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -1089,6 +1091,18 @@ public final class Settings { */ public final Setting schematicOrientationZ = new Setting<>(false); + /** + * Rotates the schematic before building it. + * Possible values are + *
    + *
  • NONE - No rotation
  • + *
  • CLOCKWISE_90 - Rotate 90° clockwise
  • + *
  • CLOCKWISE_180 - Rotate 180° clockwise
  • + *
  • COUNTERCLOCKWISE_90 - Rotate 270° clockwise
  • + *
+ */ + public final Setting buildSchematicRotation = new Setting<>(Rotation.NONE); + /** * The fallback used by the build command when no extension is specified. This may be useful if schematics of a * particular format are used often, and the user does not wish to have to specify the extension with every usage. diff --git a/src/api/java/baritone/api/schematic/RotatedSchematic.java b/src/api/java/baritone/api/schematic/RotatedSchematic.java new file mode 100644 index 000000000..e3c9ed7aa --- /dev/null +++ b/src/api/java/baritone/api/schematic/RotatedSchematic.java @@ -0,0 +1,136 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Rotation; + +import java.util.List; +import java.util.stream.Collectors; + +public class RotatedSchematic implements ISchematic { + + private final ISchematic schematic; + private final Rotation rotation; + private final Rotation inverseRotation; + + public RotatedSchematic(ISchematic schematic, Rotation rotation) { + this.schematic = schematic; + this.rotation = rotation; + // I don't think a 14 line switch would improve readability + this.inverseRotation = rotation.getRotated(rotation).getRotated(rotation); + } + + @Override + public boolean inSchematic(int x, int y, int z, BlockState currentState) { + return schematic.inSchematic( + rotateX(x, z, widthX(), lengthZ(), inverseRotation), + y, + rotateZ(x, z, widthX(), lengthZ(), inverseRotation), + rotate(currentState, inverseRotation) + ); + } + + @Override + public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { + return rotate(schematic.desiredState( + rotateX(x, z, widthX(), lengthZ(), inverseRotation), + y, + rotateZ(x, z, widthX(), lengthZ(), inverseRotation), + rotate(current, inverseRotation), + rotate(approxPlaceable, inverseRotation) + ), rotation); + } + + @Override + public void reset() { + schematic.reset(); + } + + @Override + public int widthX() { + return flipsCoordinates(rotation) ? schematic.lengthZ() : schematic.widthX(); + } + + @Override + public int heightY() { + return schematic.heightY(); + } + + @Override + public int lengthZ() { + return flipsCoordinates(rotation) ? schematic.widthX() : schematic.lengthZ(); + } + + /** + * Wether {@code rotation} swaps the x and z components + */ + private static boolean flipsCoordinates(Rotation rotation) { + return rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90; + } + + /** + * The x component of x,y after applying the rotation + */ + private static int rotateX(int x, int z, int sizeX, int sizeZ, Rotation rotation) { + switch (rotation) { + case NONE: + return x; + case CLOCKWISE_90: + return sizeZ - z - 1; + case CLOCKWISE_180: + return sizeX - x - 1; + case COUNTERCLOCKWISE_90: + return z; + } + throw new IllegalArgumentException("Unknown rotation"); + } + + /** + * The z component of x,y after applying the rotation + */ + private static int rotateZ(int x, int z, int sizeX, int sizeZ, Rotation rotation) { + switch (rotation) { + case NONE: + return z; + case CLOCKWISE_90: + return x; + case CLOCKWISE_180: + return sizeZ - z - 1; + case COUNTERCLOCKWISE_90: + return sizeX - x - 1; + } + throw new IllegalArgumentException("Unknown rotation"); + } + + private static BlockState rotate(BlockState state, Rotation rotation) { + if (state == null) { + return null; + } + return state.rotate(rotation); + } + + private static List rotate(List states, Rotation rotation) { + if (states == null) { + return null; + } + return states.stream() + .map(s -> rotate(s, rotation)) + .collect(Collectors.toList()); + } +} diff --git a/src/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java index 23c2acddb..53c95f441 100644 --- a/src/api/java/baritone/api/utils/SettingsUtil.java +++ b/src/api/java/baritone/api/utils/SettingsUtil.java @@ -27,6 +27,8 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Rotation; + import java.awt.*; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -220,7 +222,7 @@ private enum Parser implements ISettingParser { FLOAT(Float.class, Float::parseFloat), LONG(Long.class, Long::parseLong), STRING(String.class, String::new), - DIRECTION(Direction.class, Direction::byName), + ROTATION(Rotation.class, Rotation::valueOf, Rotation::name), COLOR( Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 4b49398a0..5202d03b2 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -30,6 +30,7 @@ import baritone.api.schematic.IStaticSchematic; import baritone.api.schematic.MaskSchematic; import baritone.api.schematic.SubstituteSchematic; +import baritone.api.schematic.RotatedSchematic; import baritone.api.schematic.format.ISchematicFormat; import baritone.api.utils.*; import baritone.api.utils.input.Input; @@ -119,6 +120,9 @@ public void build(String name, ISchematic schematic, Vec3i origin) { if (!Baritone.settings().buildSubstitutes.value.isEmpty()) { this.schematic = new SubstituteSchematic(this.schematic, Baritone.settings().buildSubstitutes.value); } + if (Baritone.settings().buildSchematicRotation.value != net.minecraft.world.level.block.Rotation.NONE) { + this.schematic = new RotatedSchematic(this.schematic, Baritone.settings().buildSchematicRotation.value); + } // TODO this preserves the old behavior, but maybe we should bake the setting value right here this.schematic = new MaskSchematic(this.schematic) { @Override From 7e8c852528308cc0a877d7f2b6c48383678e7d5c Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Mon, 29 Jul 2024 00:20:25 +0200 Subject: [PATCH 13/21] =?UTF-8?q?=E2=9C=A8=20Setting=20to=20mirror=20schem?= =?UTF-8?q?atics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/java/baritone/api/Settings.java | 11 ++ .../api/schematic/MirroredSchematic.java | 114 ++++++++++++++++++ .../java/baritone/api/utils/SettingsUtil.java | 2 + .../java/baritone/process/BuilderProcess.java | 4 + 4 files changed, 131 insertions(+) create mode 100644 src/api/java/baritone/api/schematic/MirroredSchematic.java diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index b7612a46e..d9cb501ef 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -29,6 +29,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; +import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; import org.slf4j.Logger; @@ -1103,6 +1104,16 @@ public final class Settings { */ public final Setting buildSchematicRotation = new Setting<>(Rotation.NONE); + /** + * Mirrors the schematic before building it. + * Possible values are + *
    + *
  • FRONT_BACK - mirror the schematic along its local x axis
  • + *
  • LEFT_RIGHT - mirror the schematic along its local z axis
  • + *
+ */ + public final Setting buildSchematicMirror = new Setting<>(Mirror.NONE); + /** * The fallback used by the build command when no extension is specified. This may be useful if schematics of a * particular format are used often, and the user does not wish to have to specify the extension with every usage. diff --git a/src/api/java/baritone/api/schematic/MirroredSchematic.java b/src/api/java/baritone/api/schematic/MirroredSchematic.java new file mode 100644 index 000000000..b9e10808c --- /dev/null +++ b/src/api/java/baritone/api/schematic/MirroredSchematic.java @@ -0,0 +1,114 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.schematic; + +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.Mirror; + +import java.util.List; +import java.util.stream.Collectors; + +public class MirroredSchematic implements ISchematic { + + private final ISchematic schematic; + private final Mirror mirror; + + public MirroredSchematic(ISchematic schematic, Mirror mirror) { + this.schematic = schematic; + this.mirror = mirror; + } + + @Override + public boolean inSchematic(int x, int y, int z, BlockState currentState) { + return schematic.inSchematic( + mirrorX(x, widthX(), mirror), + y, + mirrorZ(z, lengthZ(), mirror), + mirror(currentState, mirror) + ); + } + + @Override + public BlockState desiredState(int x, int y, int z, BlockState current, List approxPlaceable) { + return mirror(schematic.desiredState( + mirrorX(x, widthX(), mirror), + y, + mirrorZ(z, lengthZ(), mirror), + mirror(current, mirror), + mirror(approxPlaceable, mirror) + ), mirror); + } + + @Override + public void reset() { + schematic.reset(); + } + + @Override + public int widthX() { + return schematic.widthX(); + } + + @Override + public int heightY() { + return schematic.heightY(); + } + + @Override + public int lengthZ() { + return schematic.lengthZ(); + } + + private static int mirrorX(int x, int sizeX, Mirror mirror) { + switch (mirror) { + case NONE: + case LEFT_RIGHT: + return x; + case FRONT_BACK: + return sizeX - x - 1; + } + throw new IllegalArgumentException("Unknown mirror"); + } + + private static int mirrorZ(int z, int sizeZ, Mirror mirror) { + switch (mirror) { + case NONE: + case FRONT_BACK: + return z; + case LEFT_RIGHT: + return sizeZ - z - 1; + } + throw new IllegalArgumentException("Unknown mirror"); + } + + private static BlockState mirror(BlockState state, Mirror mirror) { + if (state == null) { + return null; + } + return state.mirror(mirror); + } + + private static List mirror(List states, Mirror mirror) { + if (states == null) { + return null; + } + return states.stream() + .map(s -> mirror(s, mirror)) + .collect(Collectors.toList()); + } +} diff --git a/src/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java index 53c95f441..7a18b61c3 100644 --- a/src/api/java/baritone/api/utils/SettingsUtil.java +++ b/src/api/java/baritone/api/utils/SettingsUtil.java @@ -27,6 +27,7 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.Item; import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.Mirror; import net.minecraft.world.level.block.Rotation; import java.awt.*; @@ -222,6 +223,7 @@ private enum Parser implements ISettingParser { FLOAT(Float.class, Float::parseFloat), LONG(Long.class, Long::parseLong), STRING(String.class, String::new), + MIRROR(Mirror.class, Mirror::valueOf, Mirror::name), ROTATION(Rotation.class, Rotation::valueOf, Rotation::name), COLOR( Color.class, diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 5202d03b2..8f9a5ba0d 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -31,6 +31,7 @@ import baritone.api.schematic.MaskSchematic; import baritone.api.schematic.SubstituteSchematic; import baritone.api.schematic.RotatedSchematic; +import baritone.api.schematic.MirroredSchematic; import baritone.api.schematic.format.ISchematicFormat; import baritone.api.utils.*; import baritone.api.utils.input.Input; @@ -120,6 +121,9 @@ public void build(String name, ISchematic schematic, Vec3i origin) { if (!Baritone.settings().buildSubstitutes.value.isEmpty()) { this.schematic = new SubstituteSchematic(this.schematic, Baritone.settings().buildSubstitutes.value); } + if (Baritone.settings().buildSchematicMirror.value != net.minecraft.world.level.block.Mirror.NONE) { + this.schematic = new MirroredSchematic(this.schematic, Baritone.settings().buildSchematicMirror.value); + } if (Baritone.settings().buildSchematicRotation.value != net.minecraft.world.level.block.Rotation.NONE) { this.schematic = new RotatedSchematic(this.schematic, Baritone.settings().buildSchematicRotation.value); } From e682fc75a6fd5156b4d52a97efd430e31a8f5a49 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Fri, 9 Aug 2024 13:54:29 +0200 Subject: [PATCH 14/21] Fix selection box aabbs --- src/main/java/baritone/selection/Selection.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/selection/Selection.java b/src/main/java/baritone/selection/Selection.java index 69c77d668..116e048c5 100644 --- a/src/main/java/baritone/selection/Selection.java +++ b/src/main/java/baritone/selection/Selection.java @@ -37,7 +37,7 @@ public Selection(BetterBlockPos pos1, BetterBlockPos pos2) { max.z - min.z + 1 ); - this.aabb = new AABB(this.min); + this.aabb = new AABB(min.x, min.y, min.z, max.x + 1, max.y + 1, max.z + 1); } @Override From a690e1eca4b46b896e532b75016e95c4e314fe19 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 14 Oct 2024 00:46:27 -0400 Subject: [PATCH 15/21] prepend feet to the path if start is adjacent to feet --- .../java/baritone/behavior/PathingBehavior.java | 13 ++++++++++--- .../java/baritone/pathing/calc/AStarPathFinder.java | 6 +++--- .../pathing/calc/AbstractNodeCostSearch.java | 8 +++++--- src/main/java/baritone/pathing/calc/Path.java | 12 ++++++++++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index d3bd62d6b..d8df46681 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -265,7 +265,7 @@ public boolean secretInternalSetGoalAndPath(PathingCommand command) { if (goal == null) { return false; } - if (goal.isInGoal(ctx.playerFeet()) || goal.isInGoal(expectedSegmentStart)) { + if (goal.isInGoal(ctx.playerFeet())) { return false; } synchronized (pathPlanLock) { @@ -553,7 +553,7 @@ private void findPathInNewThread(final BlockPos start, final boolean talkAboutIt }); } - private static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) { + private AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) { Goal transformed = goal; if (Baritone.settings().simplifyUnloadedYCoord.value && goal instanceof IGoalRenderPos) { BlockPos pos = ((IGoalRenderPos) goal).getGoalPos(); @@ -562,7 +562,14 @@ private static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal } } Favoring favoring = new Favoring(context.getBaritone().getPlayerContext(), previous, context); - return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoring, context); + BetterBlockPos feet = ctx.playerFeet(); + var realStart = new BetterBlockPos(start); + var sub = feet.subtract(realStart); + if (feet.getY() == realStart.getY() && Math.abs(sub.getX()) <= 1 && Math.abs(sub.getZ()) <= 1) { + realStart = feet; + } + return new AStarPathFinder(realStart, start.getX(), start.getY(), start.getZ(), transformed, favoring, context); + } @Override diff --git a/src/main/java/baritone/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/pathing/calc/AStarPathFinder.java index b37b598ff..0537eac5f 100644 --- a/src/main/java/baritone/pathing/calc/AStarPathFinder.java +++ b/src/main/java/baritone/pathing/calc/AStarPathFinder.java @@ -41,8 +41,8 @@ public final class AStarPathFinder extends AbstractNodeCostSearch { private final Favoring favoring; private final CalculationContext calcContext; - public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) { - super(startX, startY, startZ, goal, context); + public AStarPathFinder(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) { + super(realStart, startX, startY, startZ, goal, context); this.favoring = favoring; this.calcContext = context; } @@ -96,7 +96,7 @@ protected Optional calculate0(long primaryTimeout, long failureTimeout) { numNodes++; if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) { logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered"); - return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext)); + return Optional.of(new Path(realStart, startNode, currentNode, numNodes, goal, calcContext)); } for (Moves moves : allMoves) { int newX = currentNode.x + moves.xOffset; diff --git a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java index d20b519dc..0bfb6ac3f 100644 --- a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java +++ b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java @@ -36,6 +36,7 @@ */ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper { + protected final BetterBlockPos realStart; protected final int startX; protected final int startY; protected final int startZ; @@ -81,7 +82,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper { */ protected static final double MIN_IMPROVEMENT = 0.01; - AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) { + AbstractNodeCostSearch(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, CalculationContext context) { + this.realStart = realStart; this.startX = startX; this.startY = startY; this.startZ = startZ; @@ -177,7 +179,7 @@ protected PathNode getNodeAtPosition(int x, int y, int z, long hashCode) { @Override public Optional pathToMostRecentNodeConsidered() { - return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context)); + return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(realStart, startNode, node, 0, goal, context)); } @Override @@ -208,7 +210,7 @@ protected Optional bestSoFar(boolean logInfo, int numNodes) { System.out.println("Path goes for " + Math.sqrt(dist) + " blocks"); logDebug("A* cost coefficient " + COEFFICIENTS[i]); } - return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, context)); + return Optional.of(new Path(realStart, startNode, bestSoFar[i], numNodes, goal, context)); } } // instead of returning bestSoFar[0], be less misleading diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index f7bfbaa24..0e176d5e1 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -68,8 +68,9 @@ class Path extends PathBase { private volatile boolean verified; - Path(PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) { - this.start = new BetterBlockPos(start.x, start.y, start.z); + Path(BetterBlockPos realStart, PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) { + this.start = realStart; + var startNodePos = new BetterBlockPos(start.x, start.y, start.z); this.end = new BetterBlockPos(end.x, end.y, end.z); this.numNodes = numNodes; this.movements = new ArrayList<>(); @@ -85,6 +86,13 @@ class Path extends PathBase { tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z)); current = current.previous; } + if (!realStart.equals(startNodePos)) { + PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); + fakeNode.cost = 0; + tempNodes.addFirst(fakeNode); + tempPath.addFirst(realStart); + } + // Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is // inserting into a LinkedList keeps track of length, then when we addall (which calls .toArray) it's able // to performantly do that conversion since it knows the length. From 1e2ae34dbe452a1eebc12019ae632b2279210cad Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 15 Oct 2024 18:25:42 -0400 Subject: [PATCH 16/21] crucial performance optimization --- src/main/java/baritone/pathing/calc/Path.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index 0e176d5e1..b749dff64 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -27,6 +27,7 @@ import baritone.pathing.movement.Moves; import baritone.pathing.path.CutoffPath; import baritone.utils.pathing.PathBase; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.Collections; @@ -77,27 +78,23 @@ class Path extends PathBase { this.goal = goal; this.context = context; PathNode current = end; - LinkedList tempPath = new LinkedList<>(); - LinkedList tempNodes = new LinkedList<>(); - // Repeatedly inserting to the beginning of an arraylist is O(n^2) - // Instead, do it into a linked list, then convert at the end + List tempPath = new ArrayList<>(); + List tempNodes = new ArrayList<>(); while (current != null) { - tempNodes.addFirst(current); - tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z)); + tempNodes.add(current); + tempPath.add(new BetterBlockPos(current.x, current.y, current.z)); current = current.previous; } + // If the position the player is at is different from the position we told A* to start from if (!realStart.equals(startNodePos)) { PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); fakeNode.cost = 0; - tempNodes.addFirst(fakeNode); - tempPath.addFirst(realStart); + tempNodes.add(fakeNode); + tempPath.add(realStart); } - - // Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is - // inserting into a LinkedList keeps track of length, then when we addall (which calls .toArray) it's able - // to performantly do that conversion since it knows the length. - this.path = new ArrayList<>(tempPath); - this.nodes = new ArrayList<>(tempNodes); + // Nodes are traversed last to first so we need to reverse the list + this.path = Lists.reverse(tempPath); + this.nodes = Lists.reverse(tempNodes); } @Override From d644c5b75401f6b7326caa99034e3363c24c8ae0 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 15 Oct 2024 18:56:46 -0400 Subject: [PATCH 17/21] a bit more elegant --- src/main/java/baritone/pathing/calc/Path.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index b749dff64..0c5dda00f 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -71,12 +71,21 @@ class Path extends PathBase { Path(BetterBlockPos realStart, PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) { this.start = realStart; - var startNodePos = new BetterBlockPos(start.x, start.y, start.z); this.end = new BetterBlockPos(end.x, end.y, end.z); this.numNodes = numNodes; this.movements = new ArrayList<>(); this.goal = goal; this.context = context; + + // If the position the player is at is different from the position we told A* to start from + // see PathingBehavior#createPathfinder and https://github.com/cabaletta/baritone/pull/4519 + var startNodePos = new BetterBlockPos(start.x, start.y, start.z); + if (!realStart.equals(startNodePos)) { + PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); + fakeNode.cost = 0; + start.previous = fakeNode; + } + PathNode current = end; List tempPath = new ArrayList<>(); List tempNodes = new ArrayList<>(); @@ -85,13 +94,6 @@ class Path extends PathBase { tempPath.add(new BetterBlockPos(current.x, current.y, current.z)); current = current.previous; } - // If the position the player is at is different from the position we told A* to start from - if (!realStart.equals(startNodePos)) { - PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); - fakeNode.cost = 0; - tempNodes.add(fakeNode); - tempPath.add(realStart); - } // Nodes are traversed last to first so we need to reverse the list this.path = Lists.reverse(tempPath); this.nodes = Lists.reverse(tempNodes); From ea1de44ca8fba8a9d8d9e1947c852ed88f0cda99 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:13:15 +0200 Subject: [PATCH 18/21] Don't call `shape.bounds()` on empty shapes `minecraft:moving_piston` is the only block I currently know which could cause this to crash. --- src/main/java/baritone/process/BuilderProcess.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index cb6eb9d8a..b691fcd47 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -44,7 +44,6 @@ import baritone.utils.schematic.MapArtSchematic; import baritone.utils.schematic.SelectionSchematic; import baritone.utils.schematic.SchematicSystem; -import baritone.utils.schematic.format.defaults.LitematicaSchematic; import baritone.utils.schematic.litematica.LitematicaHelper; import baritone.utils.schematic.schematica.SchematicaHelper; import com.google.common.collect.ImmutableMap; @@ -77,7 +76,6 @@ import java.io.File; import java.io.FileInputStream; -import java.nio.file.Files; import java.util.*; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -373,7 +371,11 @@ private Optional possibleToPlace(BlockState toPlace, int x, int y, in if (!placementPlausible(new BetterBlockPos(x, y, z), toPlace)) { continue; } - AABB aabb = placeAgainstState.getShape(ctx.world(), placeAgainstPos).bounds(); + VoxelShape shape = placeAgainstState.getShape(ctx.world(), placeAgainstPos); + if (shape.isEmpty()) { + continue; + } + AABB aabb = shape.bounds(); for (Vec3 placementMultiplier : aabbSideMultipliers(against)) { double placeX = placeAgainstPos.x + aabb.minX * placementMultiplier.x + aabb.maxX * (1 - placementMultiplier.x); double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y); From c25b1325daa76d46ebb4262b7dfeb6ff6e8f9eb5 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:34:17 +0200 Subject: [PATCH 19/21] Handle positions going out of bounds between ticks They also have to be removed rather than ignored because they won't be scanned again and would stay in `incorrectPositions` indefinitely. --- src/main/java/baritone/process/BuilderProcess.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index cb6eb9d8a..ff1ec6d13 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -717,13 +717,16 @@ private Goal assemble(BuilderCalculationContext bcc, List approxPlac List sourceLiquids = new ArrayList<>(); List flowingLiquids = new ArrayList<>(); Map missing = new HashMap<>(); + List outOfBounds = new ArrayList<>(); incorrectPositions.forEach(pos -> { BlockState state = bcc.bsi.get0(pos); if (state.getBlock() instanceof AirBlock) { - if (containsBlockState(approxPlaceable, bcc.getSchematic(pos.x, pos.y, pos.z, state))) { + BlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state); + if (desired == null) { + outOfBounds.add(pos); + } else if (containsBlockState(approxPlaceable, desired)) { placeable.add(pos); } else { - BlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state); missing.put(desired, 1 + missing.getOrDefault(desired, 0)); } } else { @@ -741,6 +744,7 @@ private Goal assemble(BuilderCalculationContext bcc, List approxPlac } } }); + incorrectPositions.removeAll(outOfBounds); List toBreak = new ArrayList<>(); breakable.forEach(pos -> toBreak.add(breakGoal(pos, bcc))); List toPlace = new ArrayList<>(); From 991d822557b7004eaa3b04fe11769f2b9550807d Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 20 Oct 2024 20:59:27 +0200 Subject: [PATCH 20/21] Make soul sand `canWalkOn` again --- src/main/java/baritone/pathing/movement/MovementHelper.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 1d97a79c5..0fa326d51 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -429,7 +429,7 @@ static Ternary canWalkOnBlockState(BlockState state) { if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this return YES; } - if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH) { + if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH || block == Blocks.SOUL_SAND) { return YES; } if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) { From f6657846d3dfa4f1997950ce099889112ce36bc0 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 21 Oct 2024 02:09:31 -0400 Subject: [PATCH 21/21] fix loops in path (fixes #4528) --- src/main/java/baritone/pathing/calc/Path.java | 26 ++++++++++++------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index 0c5dda00f..8f5dd52c2 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -70,22 +70,12 @@ class Path extends PathBase { private volatile boolean verified; Path(BetterBlockPos realStart, PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) { - this.start = realStart; this.end = new BetterBlockPos(end.x, end.y, end.z); this.numNodes = numNodes; this.movements = new ArrayList<>(); this.goal = goal; this.context = context; - // If the position the player is at is different from the position we told A* to start from - // see PathingBehavior#createPathfinder and https://github.com/cabaletta/baritone/pull/4519 - var startNodePos = new BetterBlockPos(start.x, start.y, start.z); - if (!realStart.equals(startNodePos)) { - PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); - fakeNode.cost = 0; - start.previous = fakeNode; - } - PathNode current = end; List tempPath = new ArrayList<>(); List tempNodes = new ArrayList<>(); @@ -94,6 +84,22 @@ class Path extends PathBase { tempPath.add(new BetterBlockPos(current.x, current.y, current.z)); current = current.previous; } + + // If the position the player is at is different from the position we told A* to start from, + // and A* gave us no movements, then add a fake node that will allow a movement to be created + // that gets us to the single position in the path. + // See PathingBehavior#createPathfinder and https://github.com/cabaletta/baritone/pull/4519 + var startNodePos = new BetterBlockPos(start.x, start.y, start.z); + if (!realStart.equals(startNodePos) && start.equals(end)) { + this.start = realStart; + PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); + fakeNode.cost = 0; + tempNodes.add(fakeNode); + tempPath.add(realStart); + } else { + this.start = startNodePos; + } + // Nodes are traversed last to first so we need to reverse the list this.path = Lists.reverse(tempPath); this.nodes = Lists.reverse(tempNodes);