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 @@ import java.util.Optional; * @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 @@ public final class LitematicaSchematic extends StaticSchematic { * 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 @@ public final class LitematicaSchematic extends StaticSchematic { 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 @@ public final class LitematicaSchematic extends StaticSchematic { * @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 @@ public final class LitematicaSchematic extends StaticSchematic { } } - /** - * @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 final class LitematicaHelper { 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 @@ public final class LitematicaHelper { * @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 @@ public final class LitematicaHelper { * @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 @@ public final class LitematicaHelper { * @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 class SchematicPlacement extends SchematicPlacementUnloaded { 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 @@ package fi.dy.masa.litematica.schematic.placement; 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