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/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 002a39e5b9..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 @@ -24,6 +24,7 @@ import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * See {@link BlockEntityAbstractImpetus}, this is what's stored in it @@ -42,6 +43,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 +111,31 @@ 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)) { + 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 +162,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 +182,10 @@ 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); + + 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()),