Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,12 @@ public void startExecution(@Nullable ServerPlayer player) {
this.getBlockState().setValue(BlockCircleComponent.ENERGIZED, true));
}

/**
* Generate the AABB bounds of a spell circle from the list of block positions that make it up.
*
* @deprecated No longer used, since the AABB is now generated during startup and stored as a pair of corners.
*/
@Deprecated(since = "0.11.4")
@Contract(pure = true)
protected static AABB getBounds(List<BlockPos> poses) {
int minX = Integer.MAX_VALUE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,42 +31,50 @@ public class CircleExecutionState {
public static final String
TAG_IMPETUS_POS = "impetus_pos",
TAG_IMPETUS_DIR = "impetus_dir",
TAG_KNOWN_POSITIONS = "known_positions",
TAG_REACHED_POSITIONS = "reached_positions",
TAG_CURRENT_POS = "current_pos",
TAG_ENTERED_FROM = "entered_from",
TAG_IMAGE = "image",
TAG_CASTER = "caster",
TAG_PIGMENT = "pigment";
TAG_PIGMENT = "pigment",
TAG_REACHED_NUMBER = "reached_slate",
TAG_POSITIVE_POS = "positive_pos",
TAG_NEGATIVE_POS = "negative_pos";

public final BlockPos impetusPos;
public final Direction impetusDir;
// Does contain the starting impetus
public final Set<BlockPos> knownPositions;
public final List<BlockPos> reachedPositions;
public final HashSet<BlockPos> reachedPositions;
public BlockPos currentPos;
public Direction enteredFrom;
public CastingImage currentImage;
public @Nullable UUID caster;
public @Nullable FrozenPigment casterPigment;
public long reachedSlate;

// Tracks the highest pos, and lowest pos of the AABB
public BlockPos greaterCorner;
public BlockPos lesserCorner;

public final AABB bounds;


protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set<BlockPos> knownPositions,
List<BlockPos> reachedPositions, BlockPos currentPos, Direction enteredFrom,
CastingImage currentImage, @Nullable UUID caster, @Nullable FrozenPigment casterPigment) {
protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSet<BlockPos> reachedPositions,
BlockPos currentPos, Direction enteredFrom, CastingImage currentImage, @Nullable UUID caster,
@Nullable FrozenPigment casterPigment, Long reachedSlate, BlockPos greaterCorner, BlockPos lesserPos) {
this.impetusPos = impetusPos;
this.impetusDir = impetusDir;
this.knownPositions = knownPositions;
this.reachedPositions = reachedPositions;
this.currentPos = currentPos;
this.enteredFrom = enteredFrom;
this.currentImage = currentImage;
this.caster = caster;
this.casterPigment = casterPigment;
this.reachedSlate = reachedSlate;

this.bounds = BlockEntityAbstractImpetus.getBounds(new ArrayList<>(this.knownPositions));
this.greaterCorner = greaterCorner;
this.lesserCorner = lesserPos;
this.bounds = new AABB(greaterCorner, lesserPos);
}

public @Nullable ServerPlayer getCaster(ServerLevel world) {
Expand Down Expand Up @@ -94,7 +102,10 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set<Bl
var todo = new Stack<Pair<Direction, BlockPos>>();
todo.add(Pair.of(impetus.getStartDirection(), impetus.getBlockPos().relative(impetus.getStartDirection())));
var seenGoodPosSet = new HashSet<BlockPos>();
var seenGoodPositions = new ArrayList<BlockPos>();
var impetusPos = impetus.getBlockPos();
var positiveBlock = impetusPos.mutable();
var negativeBlock = impetusPos.mutable();
var lastBlockPos = impetusPos.mutable();

while (!todo.isEmpty()) {
var pair = todo.pop();
Expand All @@ -110,28 +121,34 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set<Bl
}

if (seenGoodPosSet.add(herePos)) {
lastBlockPos.set(herePos);
// Updates the highest and or lowest corner of the Circle
positiveBlock.setX(Math.max(herePos.getX(), positiveBlock.getX()));
positiveBlock.setY(Math.max(herePos.getY(), positiveBlock.getY()));
positiveBlock.setZ(Math.max(herePos.getZ(), positiveBlock.getZ()));

negativeBlock.setX(Math.min(herePos.getX(), negativeBlock.getX()));
negativeBlock.setY(Math.min(herePos.getY(), negativeBlock.getY()));
negativeBlock.setZ(Math.min(herePos.getZ(), negativeBlock.getZ()));
// it's new
seenGoodPositions.add(herePos);
var outs = cmp.possibleExitDirections(herePos, hereBs, level);
for (var out : outs) {
todo.add(Pair.of(out, herePos.relative(out)));
}
}
}

if (seenGoodPositions.isEmpty()) {
if (lastBlockPos == impetus.getBlockPos()) {
return new Result.Err<>(null);
} else if (!seenGoodPosSet.contains(impetus.getBlockPos())) {
// we can't enter from the side the directrix exits from, so this means we couldn't loop back.
// we can't enter from the side the impetus exits from, so this means we couldn't loop back.
// the last item we tried to examine will always be a terminal slate (b/c if it wasn't,
// then the *next* slate would be last qed)
return new Result.Err<>(seenGoodPositions.get(seenGoodPositions.size() - 1));
return new Result.Err<>(lastBlockPos);
}

var knownPositions = new HashSet<>(seenGoodPositions);
var reachedPositions = new ArrayList<BlockPos>();
var reachedPositions = new HashSet<BlockPos>();
reachedPositions.add(impetus.getBlockPos());
var start = seenGoodPositions.get(0);

FrozenPigment colorizer = null;
UUID casterUUID;
Expand All @@ -142,8 +159,10 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set<Bl
casterUUID = caster.getUUID();
}
return new Result.Ok<>(
new CircleExecutionState(impetus.getBlockPos(), impetus.getStartDirection(), knownPositions,
reachedPositions, start, impetus.getStartDirection(), new CastingImage(), casterUUID, colorizer));
new CircleExecutionState(impetus.getBlockPos(), impetus.getStartDirection(),
reachedPositions, impetus.getBlockPos().offset(impetus.getStartDirection().getNormal()),
impetus.getStartDirection(), new CastingImage(), casterUUID, colorizer, 0L,
positiveBlock.move(1,1,1), negativeBlock));
}

public CompoundTag save() {
Expand All @@ -152,12 +171,6 @@ public CompoundTag save() {
out.put(TAG_IMPETUS_POS, NbtUtils.writeBlockPos(this.impetusPos));
out.putByte(TAG_IMPETUS_DIR, (byte) this.impetusDir.ordinal());

var knownTag = new ListTag();
for (var bp : this.knownPositions) {
knownTag.add(NbtUtils.writeBlockPos(bp));
}
out.put(TAG_KNOWN_POSITIONS, knownTag);

var reachedTag = new ListTag();
for (var bp : this.reachedPositions) {
reachedTag.add(NbtUtils.writeBlockPos(bp));
Expand All @@ -174,19 +187,19 @@ public CompoundTag save() {
if (this.casterPigment != null)
out.put(TAG_PIGMENT, this.casterPigment.serializeToNBT());

out.putLong(TAG_REACHED_NUMBER, this.reachedSlate);

out.put(TAG_POSITIVE_POS,NbtUtils.writeBlockPos(this.greaterCorner));
out.put(TAG_NEGATIVE_POS,NbtUtils.writeBlockPos(this.lesserCorner));

return out;
}

public static CircleExecutionState load(CompoundTag nbt, ServerLevel world) {
var startPos = NbtUtils.readBlockPos(nbt.getCompound(TAG_IMPETUS_POS));
var startDir = Direction.values()[nbt.getByte(TAG_IMPETUS_DIR)];

var knownPositions = new HashSet<BlockPos>();
var knownTag = nbt.getList(TAG_KNOWN_POSITIONS, Tag.TAG_COMPOUND);
for (var tag : knownTag) {
knownPositions.add(NbtUtils.readBlockPos(HexUtils.downcast(tag, CompoundTag.TYPE)));
}
var reachedPositions = new ArrayList<BlockPos>();
var reachedPositions = new HashSet<BlockPos>();
var reachedTag = nbt.getList(TAG_REACHED_POSITIONS, Tag.TAG_COMPOUND);
for (var tag : reachedTag) {
reachedPositions.add(NbtUtils.readBlockPos(HexUtils.downcast(tag, CompoundTag.TYPE)));
Expand All @@ -196,6 +209,10 @@ public static CircleExecutionState load(CompoundTag nbt, ServerLevel world) {
var enteredFrom = Direction.values()[nbt.getByte(TAG_ENTERED_FROM)];
var image = CastingImage.loadFromNbt(nbt.getCompound(TAG_IMAGE), world);

var reachedSlate = nbt.getLong(TAG_REACHED_NUMBER);
var positivePos = NbtUtils.readBlockPos(nbt.getCompound(TAG_POSITIVE_POS));
var negativePos = NbtUtils.readBlockPos(nbt.getCompound(TAG_NEGATIVE_POS));

UUID caster = null;
if (nbt.hasUUID(TAG_CASTER))
caster = nbt.getUUID(TAG_CASTER);
Expand All @@ -204,8 +221,8 @@ public static CircleExecutionState load(CompoundTag nbt, ServerLevel world) {
if (nbt.contains(TAG_PIGMENT, Tag.TAG_COMPOUND))
pigment = FrozenPigment.fromNBT(nbt.getCompound(TAG_PIGMENT));

return new CircleExecutionState(startPos, startDir, knownPositions, reachedPositions, currentPos,
enteredFrom, image, caster, pigment);
return new CircleExecutionState(startPos, startDir, reachedPositions, currentPos,
enteredFrom, image, caster, pigment, reachedSlate, positivePos, negativePos);
}

/**
Expand All @@ -231,6 +248,7 @@ public boolean tick(BlockEntityAbstractImpetus impetus) {

executorBlockState = executor.startEnergized(this.currentPos, executorBlockState, world);
this.reachedPositions.add(this.currentPos);
this.reachedSlate +=1;

// Do the execution!
boolean halt = false;
Expand Down Expand Up @@ -289,7 +307,7 @@ public boolean tick(BlockEntityAbstractImpetus impetus) {
* How many ticks should pass between activations, given the number of blocks encountered so far.
*/
protected int getTickSpeed() {
return Math.max(2, 10 - (this.reachedPositions.size() - 1) / 3);
return Math.max(2, (int) (10 - (this.reachedSlate - 1) / 3));
}

public void endExecution(BlockEntityAbstractImpetus impetus) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,8 @@ static void sfx(BlockPos pos, BlockState bs, Level world, BlockEntityAbstractImp
var state = impetus.getExecutionState();

// This is a good use of my time
var note = state.reachedPositions.size() - 1;
var semitone = impetus.semitoneFromScale(note);
var note = state.reachedSlate - 1;
var semitone = impetus.semitoneFromScale((int) note);
pitch = (float) Math.pow(2.0, (semitone - 8) / 12d);
}
world.playSound(null, vpos.x, vpos.y, vpos.z, sound, SoundSource.BLOCKS, 1f, pitch);
Expand Down
Loading