From f81a91a5461ae7a07c80c4e5286173ffe13a4805 Mon Sep 17 00:00:00 2001 From: Caelum Date: Sun, 17 May 2026 14:55:58 +0300 Subject: [PATCH 1/2] Optimise Spell Circles. --- .../block/circle/BlockCircleComponent.java | 32 +++++++++++++ .../casting/circles/CircleExecutionState.java | 47 +++++++++++++++---- 2 files changed, 69 insertions(+), 10 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java index f2c1458c7b..dad93018a9 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java +++ b/Common/src/main/java/at/petrak/hexcasting/api/block/circle/BlockCircleComponent.java @@ -4,13 +4,24 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.context.BlockPlaceContext; import net.minecraft.world.level.Level; +import net.minecraft.world.level.LevelAccessor; import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.block.state.StateDefinition; import net.minecraft.world.level.block.state.properties.BlockStateProperties; import net.minecraft.world.level.block.state.properties.BooleanProperty; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jetbrains.annotations.NotNull; + +import javax.annotation.Nullable; +import java.util.Map; + +import static at.petrak.hexcasting.api.casting.circles.CircleExecutionState.CACHE; // Convenience impl of ICircleComponent public abstract class BlockCircleComponent extends Block implements ICircleComponent { @@ -28,6 +39,27 @@ public BlockState startEnergized(BlockPos pos, BlockState bs, Level world) { return newState; } + @Override + public void destroy(@NotNull LevelAccessor world, @NotNull BlockPos blockPos, @NotNull BlockState blockState) { + // spaghet + for (Map.Entry entry : CACHE.entrySet()) { + Vec3 location = blockPos.getCenter(); + if (!entry.getValue().contains(location)) {continue;} + CACHE.remove(entry.getKey()); + } + } + + @Override + public void setPlacedBy(Level level, BlockPos blockPos, BlockState bs, @Nullable LivingEntity entity, ItemStack stack) { + for (Map.Entry entry : CACHE.entrySet()) { + Vec3 location = blockPos.getCenter(); + AABB aabb = entry.getValue(); + if (!aabb.contains(location)) {continue;} + if (aabb.distanceToSqr(location) > 0.250009) {continue;} + CACHE.remove(entry.getKey()); + } + } + @Override public boolean isEnergized(BlockPos pos, BlockState bs, Level world) { return bs.getValue(ENERGIZED); 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 002a39e5b9..3dcf5dc4f4 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 @@ -24,6 +24,9 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +import static at.petrak.hexcasting.api.HexAPI.LOGGER; /** * See {@link BlockEntityAbstractImpetus}, this is what's stored in it @@ -42,6 +45,9 @@ public class CircleExecutionState { TAG_POSITIVE_POS = "positive_pos", TAG_NEGATIVE_POS = "negative_pos"; + // A cache for reusing previous searches. Invalidated when ICircleComponents are broken within the AABB. + public static final Map CACHE = new ConcurrentHashMap<>(); + public final BlockPos impetusPos; public final Direction impetusDir; // Does contain the starting impetus @@ -107,6 +113,32 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSe var positiveBlock = impetusPos.mutable(); var negativeBlock = impetusPos.mutable(); var lastBlockPos = impetusPos.mutable(); + var reachedPositions = new HashSet(); + reachedPositions.add(impetus.getBlockPos()); + + FrozenPigment colorizer = null; + UUID casterUUID; + if (caster == null) { + casterUUID = null; + } else { + colorizer = HexAPI.instance().getColorizer(caster); + casterUUID = caster.getUUID(); + } + + if (CACHE.containsKey(impetusPos)) { + LOGGER.info("Cache hit!"); + final AABB bounds = CACHE.get(impetusPos); + BlockPos greater = new BlockPos((int) bounds.maxX, (int) bounds.maxY, (int) bounds.maxZ); + BlockPos lesser = new BlockPos((int) bounds.minX, (int) bounds.minY, (int) bounds.minZ); + + return new Result.Ok<>( + new CircleExecutionState( + impetus.getBlockPos(), impetus.getStartDirection(), reachedPositions, + impetusPos.offset(impetus.getStartDirection().getNormal()), impetus.getStartDirection(), + new CastingImage(), casterUUID, colorizer, 0L, greater, lesser + ) + ); + } while (!todo.isEmpty()) { var pair = todo.pop(); @@ -133,6 +165,7 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSe negativeBlock.setZ(Math.min(herePos.getZ(), negativeBlock.getZ())); // it's new var outs = cmp.possibleExitDirections(herePos, hereBs, level); + for (var out : outs) { todo.add(Pair.of(out, herePos.relative(out))); } @@ -152,17 +185,11 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSe return new Result.Err<>(lastBlockPos); } - var reachedPositions = new HashSet(); - reachedPositions.add(impetus.getBlockPos()); + AABB aabb = new AABB(positiveBlock.move(1,1,1), negativeBlock); + + LOGGER.info("Cached for {}.",impetusPos); + CACHE.put(impetusPos, aabb); - FrozenPigment colorizer = null; - UUID casterUUID; - if (caster == null) { - casterUUID = null; - } else { - colorizer = HexAPI.instance().getColorizer(caster); - casterUUID = caster.getUUID(); - } return new Result.Ok<>( new CircleExecutionState(impetus.getBlockPos(), impetus.getStartDirection(), reachedPositions, impetus.getBlockPos().offset(impetus.getStartDirection().getNormal()), From eae41c21707ebefd63a90a4256116e0dce2d9ee8 Mon Sep 17 00:00:00 2001 From: Caelum Date: Sun, 17 May 2026 15:11:00 +0300 Subject: [PATCH 2/2] I forgot to remove that logger statement. --- .../main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt | 1 + .../hexcasting/api/casting/circles/CircleExecutionState.java | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt index c6dda37c9a..e5c5752d95 100644 --- a/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt +++ b/Common/src/main/java/at/petrak/hexcasting/api/casting/ActionUtils.kt @@ -2,6 +2,7 @@ package at.petrak.hexcasting.api.casting +import at.petrak.hexcasting.api.casting.eval.CastingEnvironment import at.petrak.hexcasting.api.casting.iota.* import at.petrak.hexcasting.api.casting.math.HexPattern import at.petrak.hexcasting.api.casting.mishaps.MishapInvalidIota 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 3dcf5dc4f4..806ee7a1c7 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 @@ -26,8 +26,6 @@ import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import static at.petrak.hexcasting.api.HexAPI.LOGGER; - /** * See {@link BlockEntityAbstractImpetus}, this is what's stored in it */ @@ -126,7 +124,6 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSe } if (CACHE.containsKey(impetusPos)) { - LOGGER.info("Cache hit!"); final AABB bounds = CACHE.get(impetusPos); BlockPos greater = new BlockPos((int) bounds.maxX, (int) bounds.maxY, (int) bounds.maxZ); BlockPos lesser = new BlockPos((int) bounds.minX, (int) bounds.minY, (int) bounds.minZ); @@ -187,7 +184,6 @@ protected CircleExecutionState(BlockPos impetusPos, Direction impetusDir, HashSe AABB aabb = new AABB(positiveBlock.move(1,1,1), negativeBlock); - LOGGER.info("Cached for {}.",impetusPos); CACHE.put(impetusPos, aabb); return new Result.Ok<>(