Merge branch '1.20.5' into 1.21.1
This commit is contained in:
@@ -265,7 +265,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
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 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
});
|
||||
}
|
||||
|
||||
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 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
}
|
||||
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
|
||||
|
||||
@@ -34,18 +34,9 @@ public class LitematicaCommand extends Command {
|
||||
|
||||
@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
|
||||
|
||||
@@ -228,12 +228,7 @@ public class SelCommand extends Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
||||
@@ -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 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
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;
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.Optional;
|
||||
*/
|
||||
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 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
|
||||
@Override
|
||||
public Optional<IPath> 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 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
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
|
||||
|
||||
@@ -27,6 +27,7 @@ import baritone.pathing.movement.Movement;
|
||||
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;
|
||||
@@ -68,28 +69,40 @@ 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.end = new BetterBlockPos(end.x, end.y, end.z);
|
||||
this.numNodes = numNodes;
|
||||
this.movements = new ArrayList<>();
|
||||
this.goal = goal;
|
||||
this.context = context;
|
||||
|
||||
PathNode current = end;
|
||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
|
||||
LinkedList<PathNode> 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<BetterBlockPos> tempPath = new ArrayList<>();
|
||||
List<PathNode> 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;
|
||||
}
|
||||
// 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<E> 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -421,7 +421,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
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) {
|
||||
|
||||
@@ -30,6 +30,8 @@ import baritone.api.schematic.ISchematic;
|
||||
import baritone.api.schematic.IStaticSchematic;
|
||||
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;
|
||||
@@ -42,17 +44,13 @@ import baritone.utils.PathingCommandContext;
|
||||
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;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.NbtAccounter;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
@@ -77,7 +75,6 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
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;
|
||||
@@ -120,6 +117,12 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
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);
|
||||
}
|
||||
// TODO this preserves the old behavior, but maybe we should bake the setting value right here
|
||||
this.schematic = new MaskSchematic(this.schematic) {
|
||||
@Override
|
||||
@@ -230,19 +233,13 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
public void buildOpenLitematic(int i) {
|
||||
if (LitematicaHelper.isLitematicaPresent()) {
|
||||
//if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager
|
||||
if (LitematicaHelper.hasLoadedSchematic()) {
|
||||
String name = LitematicaHelper.getName(i);
|
||||
try {
|
||||
LitematicaSchematic schematic1 = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath()), NbtAccounter.unlimitedHeap()), false);
|
||||
Vec3i correctedOrigin = LitematicaHelper.getCorrectedOrigin(schematic1, i);
|
||||
ISchematic schematic2 = LitematicaHelper.blackMagicFuckery(schematic1, i);
|
||||
schematic2 = applyMapArtAndSelection(origin, (IStaticSchematic) schematic2);
|
||||
build(name, schematic2, correctedOrigin);
|
||||
} catch (Exception e) {
|
||||
logDirect("Schematic File could not be loaded.");
|
||||
}
|
||||
if (LitematicaHelper.hasLoadedSchematic(i)) {
|
||||
Tuple<IStaticSchematic, Vec3i> schematic = LitematicaHelper.getSchematic(i);
|
||||
Vec3i correctedOrigin = schematic.getB();
|
||||
ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA());
|
||||
build(schematic.getA().toString(), schematic2, correctedOrigin);
|
||||
} else {
|
||||
logDirect("No schematic currently loaded");
|
||||
logDirect(String.format("List of placements has no entry %s", i + 1));
|
||||
}
|
||||
} else {
|
||||
logDirect("Litematica is not present");
|
||||
@@ -373,7 +370,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
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);
|
||||
@@ -717,13 +718,16 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
List<BetterBlockPos> sourceLiquids = new ArrayList<>();
|
||||
List<BetterBlockPos> flowingLiquids = new ArrayList<>();
|
||||
Map<BlockState, Integer> missing = new HashMap<>();
|
||||
List<BetterBlockPos> 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 +745,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
});
|
||||
incorrectPositions.removeAll(outOfBounds);
|
||||
List<Goal> toBreak = new ArrayList<>();
|
||||
breakable.forEach(pos -> toBreak.add(breakGoal(pos, bcc)));
|
||||
List<Goal> toPlace = new ArrayList<>();
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Selection implements ISelection {
|
||||
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
|
||||
|
||||
@@ -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<BlockState> approxPlaceable) {
|
||||
return this.states[x][z][y];
|
||||
|
||||
@@ -84,7 +84,7 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
|
||||
case 6: //1.18-1.20
|
||||
throw new UnsupportedOperationException("This litematic Version is too old.");
|
||||
case 7: //1.21+
|
||||
return new LitematicaSchematic(nbt, false);
|
||||
return new LitematicaSchematic(nbt);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsuported Version of a Litematica Schematic");
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
|
||||
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.Registry;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@@ -30,6 +31,7 @@ import net.minecraft.world.level.block.state.properties.Property;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -39,35 +41,24 @@ import java.util.Optional;
|
||||
* @author rycbar
|
||||
* @since 22.09.2022
|
||||
*/
|
||||
public final class LitematicaSchematic extends StaticSchematic {
|
||||
private final Vec3i offsetMinCorner;
|
||||
private final CompoundTag nbt;
|
||||
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 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"));
|
||||
}
|
||||
this.states = new BlockState[this.x][this.z][this.y];
|
||||
fillInSchematic();
|
||||
public LitematicaSchematic(CompoundTag nbt) {
|
||||
super(0, 0, 0);
|
||||
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 +67,10 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
* @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 +97,7 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
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,43 +133,19 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
*
|
||||
* @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");
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 nbt, String subReg, int x, int y, int z) {
|
||||
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"));
|
||||
private static long getVolume(CompoundTag subReg) {
|
||||
CompoundTag size = subReg.getCompound("Size");
|
||||
return Math.abs(size.getInt("x") * size.getInt("y") * 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 +153,18 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
/**
|
||||
* 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) {
|
||||
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);
|
||||
|
||||
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, offsetMinCorner, blockList, bitArray);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,65 +174,30 @@ 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 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, 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();
|
||||
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"));
|
||||
BlockState[][][] states = new BlockState[sizeX][sizeZ][sizeY];
|
||||
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)];
|
||||
index++;
|
||||
}
|
||||
for (int y = 0; y < sizeY; y++) {
|
||||
for (int z = 0; z < sizeZ; z++) {
|
||||
for (int x = 0; x < sizeX; x++) {
|
||||
states[x][z][y] = blockList[bitArray.getAt(index)];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.put(new StaticSchematic(states), offsetX, offsetY, offsetZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return offset from the schematic origin to the minimum Corner as a Vec3i.
|
||||
*/
|
||||
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);
|
||||
@Override
|
||||
public BlockState getDirect(int x, int y, int z) {
|
||||
return desiredState(x, y, z, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,15 +17,25 @@
|
||||
|
||||
package baritone.utils.schematic.litematica;
|
||||
|
||||
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
|
||||
import baritone.api.schematic.CompositeSchematic;
|
||||
import baritone.api.schematic.IStaticSchematic;
|
||||
import baritone.utils.schematic.StaticSchematic;
|
||||
import fi.dy.masa.litematica.Litematica;
|
||||
import fi.dy.masa.litematica.data.DataManager;
|
||||
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;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Helper class that provides access or processes data related to Litmatica schematics.
|
||||
@@ -48,168 +58,98 @@ public final class LitematicaHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
public static Vec3i getOrigin(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getOrigin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @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();
|
||||
}
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
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;
|
||||
|
||||
Vec3i correctedOrigin;
|
||||
Mirror mirror = LitematicaHelper.getMirror(i);
|
||||
Rotation rotation = LitematicaHelper.getRotation(i);
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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.
|
||||
*/
|
||||
public 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 - in.getZ();
|
||||
z = -z;
|
||||
} else if (mirror == Mirror.FRONT_BACK) {
|
||||
xOut = sizeX - in.getX();
|
||||
x = -x;
|
||||
}
|
||||
switch (rotation) {
|
||||
case CLOCKWISE_90:
|
||||
return new Vec3i(-z, in.getY(), x);
|
||||
case CLOCKWISE_180:
|
||||
return new Vec3i(-x, in.getY(), -z);
|
||||
case COUNTERCLOCKWISE_90:
|
||||
return new Vec3i(z, in.getY(), -x);
|
||||
default:
|
||||
return new Vec3i(x, in.getY(), z);
|
||||
}
|
||||
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.
|
||||
* @return the corresponding xyz coordinates after rotation them 90° clockwise.
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return The transformed schematic and the position of its minimum corner
|
||||
*/
|
||||
public static Vec3i rotate(Vec3i in, int sizeX, int sizeZ) {
|
||||
return new Vec3i(sizeX - (sizeX - sizeZ) - in.getZ(), in.getY(), in.getX());
|
||||
}
|
||||
|
||||
/**
|
||||
* 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++) {
|
||||
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);
|
||||
}
|
||||
public static Tuple<IStaticSchematic, Vec3i> getSchematic(int i) {
|
||||
SchematicPlacement placement = getPlacement(i);
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int minZ = Integer.MAX_VALUE;
|
||||
HashMap<Vec3i, StaticSchematic> subRegions = new HashMap<>();
|
||||
WorldSchematic schematicWorld = SchematicWorldHandler.getSchematicWorld();
|
||||
for (Map.Entry<String, SubRegionPlacement> entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) {
|
||||
SubRegionPlacement subPlacement = entry.getValue();
|
||||
Vec3i pos = transform(subPlacement.getPos(), placement.getMirror(), placement.getRotation());
|
||||
Vec3i size = placement.getSchematic().getAreaSize(entry.getKey());
|
||||
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);
|
||||
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] = schematicWorld.getBlockState(origin.offset(x, y, z));
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
StaticSchematic schematic = new StaticSchematic(states);
|
||||
subRegions.put(pos.offset(mx, my, mz), schematic);
|
||||
}
|
||||
LitematicaPlacementSchematic composite = new LitematicaPlacementSchematic(placement.getName());
|
||||
for (Map.Entry<Vec3i, StaticSchematic> entry : subRegions.entrySet()) {
|
||||
Vec3i pos = entry.getKey().offset(-minX, -minY, -minZ);
|
||||
composite.put(entry.getValue(), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
return new Tuple<>(composite, placement.getOrigin().offset(minX, minY, minZ));
|
||||
}
|
||||
|
||||
private static class LitematicaPlacementSchematic extends CompositeSchematic implements IStaticSchematic {
|
||||
private final String name;
|
||||
|
||||
public LitematicaPlacementSchematic(String name) {
|
||||
super(0, 0, 0);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@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 String toString() {
|
||||
return name;
|
||||
}
|
||||
return tempSchem;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user