From 39246717b1ee25441e0e2e2ca273409793b4a849 Mon Sep 17 00:00:00 2001 From: Stickia Date: Tue, 15 Jul 2025 16:12:02 -0400 Subject: [PATCH 1/5] Optimized Spell Circles Decreased saving/loading times --- .../casting/circles/CircleExecutionState.java | 88 +++++++++++-------- .../api/casting/circles/ICircleComponent.java | 4 +- 2 files changed, 55 insertions(+), 37 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java index f95fa84f01..8a10c8026b 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java @@ -31,42 +31,51 @@ 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 knownPositions; - public final List reachedPositions; + public final HashSet reachedPositions; public BlockPos currentPos; public Direction enteredFrom; public CastingImage currentImage; public @Nullable UUID caster; public @Nullable FrozenPigment casterPigment; + // This controls the speed of the current slate + public long reachedSlate; + + // Tracks the highest pos, and lowest pos of the AABB + public BlockPos positivePos; + public BlockPos negativePos; public final AABB bounds; - protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set knownPositions, - List reachedPositions, BlockPos currentPos, Direction enteredFrom, - CastingImage currentImage, @Nullable UUID caster, @Nullable FrozenPigment casterPigment) { + protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSet reachedPositions, + BlockPos currentPos, Direction enteredFrom, CastingImage currentImage, @Nullable UUID caster, + @Nullable FrozenPigment casterPigment, Long reachedSlate, BlockPos positivePos, BlockPos negativePos) { 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.positivePos = positivePos; + this.negativePos = negativePos; + this.bounds = new AABB(positivePos,negativePos); } public @Nullable ServerPlayer getCaster(ServerLevel world) { @@ -94,7 +103,10 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set>(); todo.add(Pair.of(impetus.getStartDirection(), impetus.getBlockPos().relative(impetus.getStartDirection()))); var seenGoodPosSet = new HashSet(); - var seenGoodPositions = new ArrayList(); + var positiveBlock = new BlockPos.MutableBlockPos(); + var negativeBlock = new BlockPos.MutableBlockPos(); + var impetusPos = impetus.getBlockPos(); + var lastBlockPos = new BlockPos.MutableBlockPos(impetusPos.getX(),impetusPos.getY(),impetusPos.getZ()); while (!todo.isEmpty()) { var pair = todo.pop(); @@ -110,8 +122,17 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set positiveBlock.getX()) positiveBlock.setX(herePos.getX()); + if (herePos.getX() < negativeBlock.getX()) negativeBlock.setX(herePos.getX()); + + if (herePos.getY() > positiveBlock.getY()) positiveBlock.setY(herePos.getY()); + if (herePos.getY() < negativeBlock.getY()) negativeBlock.setY(herePos.getY()); + + if (herePos.getZ() > positiveBlock.getZ()) positiveBlock.setZ(herePos.getZ()); + if (herePos.getZ() < negativeBlock.getZ()) negativeBlock.setZ(herePos.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))); @@ -119,20 +140,16 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set(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. // 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(); - reachedPositions.add(impetus.getBlockPos()); - var start = seenGoodPositions.get(0); - + seenGoodPosSet.add(impetus.getBlockPos()); FrozenPigment colorizer = null; UUID casterUUID; if (caster == null) { @@ -142,8 +159,10 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, Set( - new CircleExecutionState(impetus.getBlockPos(), impetus.getStartDirection(), knownPositions, - reachedPositions, start, impetus.getStartDirection(), new CastingImage(), casterUUID, colorizer)); + new CircleExecutionState(impetus.getBlockPos(), impetus.getStartDirection(), + seenGoodPosSet, impetus.getBlockPos().offset(impetus.getStartDirection().getNormal()), + impetus.getStartDirection(), new CastingImage(), casterUUID, colorizer, 0L, + positiveBlock.move(1,1,1), negativeBlock)); } public CompoundTag save() { @@ -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)); @@ -174,6 +187,11 @@ 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.positivePos)); + out.put(TAG_NEGATIVE_POS,NbtUtils.writeBlockPos(this.negativePos)); + return out; } @@ -181,12 +199,7 @@ 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(); - 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(); + var reachedPositions = new HashSet(); var reachedTag = nbt.getList(TAG_REACHED_POSITIONS, Tag.TAG_COMPOUND); for (var tag : reachedTag) { reachedPositions.add(NbtUtils.readBlockPos(HexUtils.downcast(tag, CompoundTag.TYPE))); @@ -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); @@ -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); } /** @@ -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; @@ -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) { diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java index 66e06b4d0d..d5010047b9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/ICircleComponent.java @@ -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); From 926b33974989e58c9a5fb69939dfd0b74eeba49c Mon Sep 17 00:00:00 2001 From: Stickia Date: Wed, 16 Jul 2025 10:28:41 -0400 Subject: [PATCH 2/5] Removed a Null Printer in `BlockEntityRedstoneImpetus#getPlayerName` that was made obsolete by Playerless Casting --- .../blocks/circles/impetuses/BlockEntityRedstoneImpetus.java | 1 - 1 file changed, 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java index b776d156ce..b668591aab 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java @@ -88,7 +88,6 @@ public ServerPlayer getStoredPlayer() { if (e instanceof ServerPlayer player) { return player; } else { - HexAPI.LOGGER.error("Entity {} stored in a cleric impetus wasn't a player somehow", e); return null; } } From 2fc0524cec0ab11717d8e42022b0e427813fcc57 Mon Sep 17 00:00:00 2001 From: Stickia Date: Fri, 8 Aug 2025 10:20:35 -0400 Subject: [PATCH 3/5] Readded Null Logger print in BlockEntityRedstoneImpetus --- .../blocks/circles/impetuses/BlockEntityRedstoneImpetus.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java index b668591aab..4bc878d645 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java @@ -88,7 +88,7 @@ public ServerPlayer getStoredPlayer() { if (e instanceof ServerPlayer player) { return player; } else { - return null; + HexAPI.LOGGER.error("Entity {} stored in a cleric impetus wasn't a player somehow", e); } } From 18fa722aaa87cd79f9aa3e5fe346980622f8b4bb Mon Sep 17 00:00:00 2001 From: Stickia Date: Fri, 8 Aug 2025 10:20:35 -0400 Subject: [PATCH 4/5] Readded Null Logger print in BlockEntityRedstoneImpetus --- .../blocks/circles/impetuses/BlockEntityRedstoneImpetus.java | 1 + 1 file changed, 1 insertion(+) diff --git a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java index b668591aab..b776d156ce 100644 --- a/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java +++ b/Common/src/main/java/at/petrak/hexcasting/common/blocks/circles/impetuses/BlockEntityRedstoneImpetus.java @@ -88,6 +88,7 @@ public ServerPlayer getStoredPlayer() { if (e instanceof ServerPlayer player) { return player; } else { + HexAPI.LOGGER.error("Entity {} stored in a cleric impetus wasn't a player somehow", e); return null; } } From 5880a31e4835e9a870a2972b7616ca90520b57d8 Mon Sep 17 00:00:00 2001 From: Stickia Date: Sun, 24 Aug 2025 19:36:15 -0400 Subject: [PATCH 5/5] Updated variable names, and used feedback on GitHub --- .../casting/circles/CircleExecutionState.java | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java index 8a10c8026b..b937a84644 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/circles/CircleExecutionState.java @@ -50,19 +50,18 @@ public class CircleExecutionState { public CastingImage currentImage; public @Nullable UUID caster; public @Nullable FrozenPigment casterPigment; - // This controls the speed of the current slate public long reachedSlate; // Tracks the highest pos, and lowest pos of the AABB - public BlockPos positivePos; - public BlockPos negativePos; + public BlockPos greaterCorner; + public BlockPos lesserCorner; public final AABB bounds; protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSet reachedPositions, - BlockPos currentPos, Direction enteredFrom, CastingImage currentImage, @Nullable UUID caster, - @Nullable FrozenPigment casterPigment, Long reachedSlate, BlockPos positivePos, BlockPos negativePos) { + 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.reachedPositions = reachedPositions; @@ -73,9 +72,9 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSe this.casterPigment = casterPigment; this.reachedSlate = reachedSlate; - this.positivePos = positivePos; - this.negativePos = negativePos; - this.bounds = new AABB(positivePos,negativePos); + this.greaterCorner = greaterCorner; + this.lesserCorner = lesserPos; + this.bounds = new AABB(greaterCorner, lesserPos); } public @Nullable ServerPlayer getCaster(ServerLevel world) { @@ -123,15 +122,14 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSe if (seenGoodPosSet.add(herePos)) { lastBlockPos.set(herePos); - // Checks to see if it should update the most positive/negative block pos - if (herePos.getX() > positiveBlock.getX()) positiveBlock.setX(herePos.getX()); - if (herePos.getX() < negativeBlock.getX()) negativeBlock.setX(herePos.getX()); - - if (herePos.getY() > positiveBlock.getY()) positiveBlock.setY(herePos.getY()); - if (herePos.getY() < negativeBlock.getY()) negativeBlock.setY(herePos.getY()); - - if (herePos.getZ() > positiveBlock.getZ()) positiveBlock.setZ(herePos.getZ()); - if (herePos.getZ() < negativeBlock.getZ()) negativeBlock.setZ(herePos.getZ()); + // 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 var outs = cmp.possibleExitDirections(herePos, hereBs, level); for (var out : outs) { @@ -189,8 +187,8 @@ public CompoundTag save() { out.putLong(TAG_REACHED_NUMBER, this.reachedSlate); - out.put(TAG_POSITIVE_POS,NbtUtils.writeBlockPos(this.positivePos)); - out.put(TAG_NEGATIVE_POS,NbtUtils.writeBlockPos(this.negativePos)); + out.put(TAG_POSITIVE_POS,NbtUtils.writeBlockPos(this.greaterCorner)); + out.put(TAG_NEGATIVE_POS,NbtUtils.writeBlockPos(this.lesserCorner)); return out; }