diff --git a/src/main/java/de/ellpeck/naturesaura/InternalHooks.java b/src/main/java/de/ellpeck/naturesaura/InternalHooks.java index a020bad5..90d7ba01 100644 --- a/src/main/java/de/ellpeck/naturesaura/InternalHooks.java +++ b/src/main/java/de/ellpeck/naturesaura/InternalHooks.java @@ -109,20 +109,20 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks { @Override public void getAuraSpotsInArea(Level level, BlockPos pos, int radius, BiConsumer consumer) { - Helper.getAuraChunksWithSpotsInArea(level, pos, radius, chunk -> chunk.getSpotsInArea(pos, radius, consumer)); + Helper.getAuraChunksWithSpotsInArea(level, pos, radius, chunk -> chunk.getSpots(pos, radius, consumer)); } @Override public int getSpotAmountInArea(Level level, BlockPos pos, int radius) { var result = new MutableInt(); - this.getAuraSpotsInArea(level, pos, radius, (blockpos, drainSpot) -> result.increment()); + Helper.getAuraChunksWithSpotsInArea(level, pos, radius, chunk -> result.add(chunk.getAuraAndSpotAmount(pos, radius).getRight())); return result.intValue(); } @Override public int getAuraInArea(Level level, BlockPos pos, int radius) { var result = new MutableInt(IAuraChunk.DEFAULT_AURA); - this.getAuraSpotsInArea(level, pos, radius, (blockPos, drainSpot) -> result.add(drainSpot)); + Helper.getAuraChunksWithSpotsInArea(level, pos, radius, chunk -> result.add(chunk.getAuraAndSpotAmount(pos, radius).getLeft())); return result.intValue(); } @@ -130,9 +130,10 @@ public class InternalHooks implements NaturesAuraAPI.IInternalHooks { public Pair getAuraAndSpotAmountInArea(Level level, BlockPos pos, int radius) { var spots = new MutableInt(); var aura = new MutableInt(IAuraChunk.DEFAULT_AURA); - this.getAuraSpotsInArea(level, pos, radius, (blockPos, drainSpot) -> { - aura.add(drainSpot); - spots.increment(); + Helper.getAuraChunksWithSpotsInArea(level, pos, radius, chunk -> { + var auraAndSpots = chunk.getAuraAndSpotAmount(pos, radius); + aura.add(auraAndSpots.getLeft()); + spots.add(auraAndSpots.getRight()); }); return Pair.of(aura.intValue(), spots.intValue()); } diff --git a/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java b/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java index 47a6329d..036197b3 100644 --- a/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java +++ b/src/main/java/de/ellpeck/naturesaura/chunk/AuraChunk.java @@ -1,5 +1,7 @@ package de.ellpeck.naturesaura.chunk; +import com.google.common.collect.HashBasedTable; +import com.google.common.collect.Table; import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.aura.chunk.IAuraChunk; import de.ellpeck.naturesaura.api.aura.chunk.IDrainSpotEffect; @@ -18,6 +20,7 @@ import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.ItemStack; import net.minecraft.world.level.chunk.LevelChunk; import org.apache.commons.lang3.mutable.MutableInt; +import org.apache.commons.lang3.tuple.Pair; import java.util.ArrayList; import java.util.List; @@ -30,6 +33,7 @@ public class AuraChunk implements IAuraChunk { private final LevelChunk chunk; private final IAuraType type; private final Map drainSpots = new ConcurrentHashMap<>(); + private final Table> auraAndSpotAmountCache = HashBasedTable.create(); private final List effects = new ArrayList<>(); private boolean needsSync; @@ -138,6 +142,7 @@ public class AuraChunk implements IAuraChunk { public void markDirty() { this.chunk.setUnsaved(true); this.needsSync = true; + this.auraAndSpotAmountCache.clear(); this.addOrRemoveAsActive(); } @@ -165,7 +170,7 @@ public class AuraChunk implements IAuraChunk { return new PacketAuraChunk(pos.x, pos.z, this.drainSpots); } - public void getSpotsInArea(BlockPos pos, int radius, BiConsumer consumer) { + public void getSpots(BlockPos pos, int radius, BiConsumer consumer) { for (var entry : this.drainSpots.entrySet()) { var drainPos = entry.getKey(); if (drainPos.distSqr(pos) <= radius * radius) { @@ -174,6 +179,21 @@ public class AuraChunk implements IAuraChunk { } } + public Pair getAuraAndSpotAmount(BlockPos pos, int radius) { + var ret = this.auraAndSpotAmountCache.get(pos, radius); + if (ret == null) { + var aura = new MutableInt(); + var spots = new MutableInt(); + this.getSpots(pos, radius, (p, i) -> { + aura.add(i); + spots.increment(); + }); + ret = Pair.of(aura.intValue(), spots.intValue()); + this.auraAndSpotAmountCache.put(pos, radius, ret); + } + return ret; + } + public void getActiveEffectIcons(Player player, Map> icons) { for (var effect : this.effects) { var alreadyThere = icons.get(effect.getName()); diff --git a/src/main/java/de/ellpeck/naturesaura/misc/LevelData.java b/src/main/java/de/ellpeck/naturesaura/misc/LevelData.java index c86a6af0..0b603a3c 100644 --- a/src/main/java/de/ellpeck/naturesaura/misc/LevelData.java +++ b/src/main/java/de/ellpeck/naturesaura/misc/LevelData.java @@ -1,7 +1,9 @@ package de.ellpeck.naturesaura.misc; import com.google.common.collect.ArrayListMultimap; +import com.google.common.collect.HashBasedTable; import com.google.common.collect.ListMultimap; +import com.google.common.collect.Table; import de.ellpeck.naturesaura.Helper; import de.ellpeck.naturesaura.api.NaturesAuraAPI; import de.ellpeck.naturesaura.api.misc.ILevelData; @@ -21,6 +23,7 @@ import net.minecraft.util.Tuple; import net.minecraft.world.phys.Vec3; import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.LazyOptional; +import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -30,6 +33,7 @@ public class LevelData implements ILevelData { public final ListMultimap> effectPowders = ArrayListMultimap.create(); public final Long2ObjectOpenHashMap auraChunksWithSpots = new Long2ObjectOpenHashMap<>(); + public final Table> auraAndSpotAmountCache = HashBasedTable.create(); public final List recentlyConvertedMossStones = new ArrayList<>(); public final Set spawnLamps = new HashSet<>(); private final Map enderStorages = new HashMap<>();