From 6e5f86e6658d259a90dedbd1f0bdee708b0db1ac Mon Sep 17 00:00:00 2001 From: Samsuik Date: Thu, 25 Sep 2025 13:21:15 +0100 Subject: [PATCH] Clean up BlockDensityCache and replicate `optimise-explosions` behaviour --- ...0009-Replace-explosion-density-cache.patch | 12 +- .../0015-Explosion-Durable-Blocks.patch | 6 +- .../0017-Configure-cannon-physics.patch | 4 +- ...anilla-and-eigencraft-redstone-wires.patch | 8 +- .../0032-fixup-Configure-cannon-physics.patch | 29 +++++ .../0033-fixup-Configure-cannon-physics.patch | 19 ++++ .../0034-fixup-Configure-cannon-physics.patch | 27 +++++ .../explosion/density/BlockDensityCache.java | 103 +++++++++++------- .../density/BlockDensityCacheKey.java | 24 ++++ .../explosion/density/CachedBlockDensity.java | 46 ++++++++ .../sakura/explosion/density/DensityData.java | 47 -------- 11 files changed, 223 insertions(+), 102 deletions(-) create mode 100644 sakura-server/minecraft-patches/features/0032-fixup-Configure-cannon-physics.patch create mode 100644 sakura-server/minecraft-patches/features/0033-fixup-Configure-cannon-physics.patch create mode 100644 sakura-server/minecraft-patches/features/0034-fixup-Configure-cannon-physics.patch create mode 100644 sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCacheKey.java create mode 100644 sakura-server/src/main/java/me/samsuik/sakura/explosion/density/CachedBlockDensity.java delete mode 100644 sakura-server/src/main/java/me/samsuik/sakura/explosion/density/DensityData.java diff --git a/sakura-server/minecraft-patches/features/0009-Replace-explosion-density-cache.patch b/sakura-server/minecraft-patches/features/0009-Replace-explosion-density-cache.patch index fa6044d..3bc72c5 100644 --- a/sakura-server/minecraft-patches/features/0009-Replace-explosion-density-cache.patch +++ b/sakura-server/minecraft-patches/features/0009-Replace-explosion-density-cache.patch @@ -5,31 +5,31 @@ Subject: [PATCH] Replace explosion density cache diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 496e23c110cbb3b60a6565e1903545e09715f79e..8c4b4cb9e98b8c0334bb7e247e67206bd57c3de2 100644 +index 496e23c110cbb3b60a6565e1903545e09715f79e..a73395c1ec0f36019de553c39199957032e316c4 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -693,6 +693,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.getCraftServer().addWorld(this.getWorld()); // CraftBukkit this.levelTickScheduler.repeatingTask(this.explosionPositions::clear, 0); // Sakura - client visibility settings this.levelTickScheduler.repeatingTask(this.mergeHandler::expire, 200); // Sakura - merge cannon entities -+ this.levelTickScheduler.repeatingTask(this.densityCache::invalidate, 0); // Sakura - explosion density cache ++ this.levelTickScheduler.repeatingTask(this.densityCache::expire, 0); // Sakura - explosion density cache } // Paper start diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 7b9e61b2286d18f55a365eebda1fe2128023bec9..3e4784e7dbb264e08f944e03d1f59218fafe710b 100644 +index 7b9e61b2286d18f55a365eebda1fe2128023bec9..7a30a227a417ecf9f16ce97d53b238935e652d68 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -829,6 +829,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl public final me.samsuik.sakura.listener.BlockChangeTracker blockChangeTracker = new me.samsuik.sakura.listener.BlockChangeTracker(this); // Sakura end - track block changes and tick scheduler public final me.samsuik.sakura.entity.merge.EntityMergeHandler mergeHandler = new me.samsuik.sakura.entity.merge.EntityMergeHandler(); // Sakura - merge cannon entities -+ public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(); // Sakura - explosion density cache ++ public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(this); // Sakura - optimise explosion density cache protected Level( WritableLevelData levelData, diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java -index cc6ee993470a274cdad124b4a7befb016d9a2b6e..c3c90cc17c4f1ebcaddffea4087929e3708aa22f 100644 +index cc6ee993470a274cdad124b4a7befb016d9a2b6e..fde0528e00939972adc2f48b1456002dcd28343b 100644 --- a/net/minecraft/world/level/ServerExplosion.java +++ b/net/minecraft/world/level/ServerExplosion.java @@ -294,7 +294,12 @@ public class ServerExplosion implements Explosion { @@ -88,7 +88,7 @@ index cc6ee993470a274cdad124b4a7befb016d9a2b6e..c3c90cc17c4f1ebcaddffea4087929e3 - Float blockDensity = this.level.explosionDensityCache.get(key); - if (blockDensity == null) { + // Sakura start - replace density cache -+ float blockDensity = this.level.densityCache.getDensity(vec3d, entity); ++ float blockDensity = this.level.densityCache.getBlockDensity(vec3d, entity); + if (blockDensity == me.samsuik.sakura.explosion.density.BlockDensityCache.UNKNOWN_DENSITY) { blockDensity = this.getSeenFraction(vec3d, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations - this.level.explosionDensityCache.put(key, blockDensity); diff --git a/sakura-server/minecraft-patches/features/0015-Explosion-Durable-Blocks.patch b/sakura-server/minecraft-patches/features/0015-Explosion-Durable-Blocks.patch index 4853c35..ee4fcce 100644 --- a/sakura-server/minecraft-patches/features/0015-Explosion-Durable-Blocks.patch +++ b/sakura-server/minecraft-patches/features/0015-Explosion-Durable-Blocks.patch @@ -40,19 +40,19 @@ index 6db566adf2d0df1d26221eda04aa01738df6d3d2..23c135a6355e920535734e946e5bd4d0 return !interactionResult.consumesAction() && context.getItemInHand().has(DataComponents.CONSUMABLE) ? super.use(context.getLevel(), context.getPlayer(), context.getHand()) diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 4a258b105b4d27f214178439df1c4ee569c12895..d4b2f81aebc888e6fe041537b71ac52d8dc8b4e7 100644 +index a99273ac64a223cc0a728137abca9331e79a546b..f41caed876beff43778e6138ac444f6e2608883d 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -830,6 +830,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl // Sakura end - track block changes and tick scheduler public final me.samsuik.sakura.entity.merge.EntityMergeHandler mergeHandler = new me.samsuik.sakura.entity.merge.EntityMergeHandler(); // Sakura - merge cannon entities - public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(); // Sakura - explosion density cache + public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(this); // Sakura - optimise explosion density cache + public final me.samsuik.sakura.explosion.durable.DurableBlockManager durabilityManager = new me.samsuik.sakura.explosion.durable.DurableBlockManager(); // Sakura - explosion durable blocks protected Level( WritableLevelData levelData, diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java -index d2b33fb06ce9a806466208d7afd65fa8d3da0292..f8933e198a250f2184fb64bb987575b441ae8a32 100644 +index 88192b561c2a071f583d16d1de926917108a8f45..d12473581f5285aff5867e8bebfe34ccbdb1285f 100644 --- a/net/minecraft/world/level/ServerExplosion.java +++ b/net/minecraft/world/level/ServerExplosion.java @@ -131,7 +131,7 @@ public class ServerExplosion implements Explosion { diff --git a/sakura-server/minecraft-patches/features/0017-Configure-cannon-physics.patch b/sakura-server/minecraft-patches/features/0017-Configure-cannon-physics.patch index 80ae140..ef145db 100644 --- a/sakura-server/minecraft-patches/features/0017-Configure-cannon-physics.patch +++ b/sakura-server/minecraft-patches/features/0017-Configure-cannon-physics.patch @@ -462,7 +462,7 @@ index 2146efa860d8323a88f3ad365c0cdb66de42154a..b6ddb1ad889a115daeba64321d38b236 if (!visitor.visit(blockPos, 0)) { return false; diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java -index f79e8f48a1f9a6964e1449c099df39076615dd88..e79de0fc3102c107d2c49e1b084b65d5c667e6e3 100644 +index e6ca200bf17e097f65204d7cead78306573e4782..5ac921b85f4dd200dd9932c7a702c07cfad36e63 100644 --- a/net/minecraft/world/level/ServerExplosion.java +++ b/net/minecraft/world/level/ServerExplosion.java @@ -376,6 +376,7 @@ public class ServerExplosion implements Explosion { @@ -529,7 +529,7 @@ index f79e8f48a1f9a6964e1449c099df39076615dd88..e79de0fc3102c107d2c49e1b084b65d5 d2 /= squareRoot; @@ -913,7 +937,7 @@ public class ServerExplosion implements Explosion { // Sakura start - replace density cache - float blockDensity = this.level.densityCache.getDensity(vec3d, entity); + float blockDensity = this.level.densityCache.getBlockDensity(vec3d, entity); if (blockDensity == me.samsuik.sakura.explosion.density.BlockDensityCache.UNKNOWN_DENSITY) { - blockDensity = this.getSeenFraction(vec3d, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations + blockDensity = this.sakura_getSeenPercent(vec3d, entity); // Sakura - configure server mechanics diff --git a/sakura-server/minecraft-patches/features/0028-Cache-vanilla-and-eigencraft-redstone-wires.patch b/sakura-server/minecraft-patches/features/0028-Cache-vanilla-and-eigencraft-redstone-wires.patch index b88fc7a..486360a 100644 --- a/sakura-server/minecraft-patches/features/0028-Cache-vanilla-and-eigencraft-redstone-wires.patch +++ b/sakura-server/minecraft-patches/features/0028-Cache-vanilla-and-eigencraft-redstone-wires.patch @@ -33,24 +33,24 @@ index ff747a1ecdf3c888bca0d69de4f85dcd810b6139..d90f6aa4557b5863eba6a206226f763c } diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java -index 29e1683741241f4f1e578041371a116170f2d1d2..fa109c801fd556e9e09dd0a81d5e05cb942082dd 100644 +index 8a046ad7590bd358d416f4aa21a3c173d0931d2a..cdcc64da3481ea8ab4bc680fef775bc193e65c41 100644 --- a/net/minecraft/server/level/ServerLevel.java +++ b/net/minecraft/server/level/ServerLevel.java @@ -694,6 +694,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe this.levelTickScheduler.repeatingTask(this.explosionPositions::clear, 0); // Sakura - client visibility settings this.levelTickScheduler.repeatingTask(this.mergeHandler::expire, 200); // Sakura - merge cannon entities - this.levelTickScheduler.repeatingTask(this.densityCache::invalidate, 0); // Sakura - explosion density cache + this.levelTickScheduler.repeatingTask(this.densityCache::expire, 0); // Sakura - explosion density cache + this.levelTickScheduler.repeatingTask(this.redstoneWireCache::expire, 300); // Sakura - cache vanilla and eigencraft wires } // Paper start diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java -index 92b3a69b2f87f44cb0c797d5986d501a649f4fe4..c1f9d65aba951963ebb297393580df3d6969c021 100644 +index 38baa1b6c846fd1f8cdbe9faf5e38300dade87e9..307542eff210e8824f651ca42e15b00c22df98fc 100644 --- a/net/minecraft/world/level/Level.java +++ b/net/minecraft/world/level/Level.java @@ -831,6 +831,7 @@ public abstract class Level implements LevelAccessor, UUIDLookup, AutoCl public final me.samsuik.sakura.entity.merge.EntityMergeHandler mergeHandler = new me.samsuik.sakura.entity.merge.EntityMergeHandler(); // Sakura - merge cannon entities - public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(); // Sakura - explosion density cache + public final me.samsuik.sakura.explosion.density.BlockDensityCache densityCache = new me.samsuik.sakura.explosion.density.BlockDensityCache(this); // Sakura - optimise explosion density cache public final me.samsuik.sakura.explosion.durable.DurableBlockManager durabilityManager = new me.samsuik.sakura.explosion.durable.DurableBlockManager(); // Sakura - explosion durable blocks + public final me.samsuik.sakura.redstone.RedstoneWireCache redstoneWireCache = new me.samsuik.sakura.redstone.RedstoneWireCache(this); // Sakura - cache vanilla and eigencraft wires diff --git a/sakura-server/minecraft-patches/features/0032-fixup-Configure-cannon-physics.patch b/sakura-server/minecraft-patches/features/0032-fixup-Configure-cannon-physics.patch new file mode 100644 index 0000000..8c832c1 --- /dev/null +++ b/sakura-server/minecraft-patches/features/0032-fixup-Configure-cannon-physics.patch @@ -0,0 +1,29 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samsuik +Date: Thu, 25 Sep 2025 11:26:32 +0100 +Subject: [PATCH] fixup! Configure cannon physics + + +diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java +index f8ad47d47ee060be66b735eacdcb19ee8e5c7628..f008ffa972eddf1d6bd0c3c2ef75332a56fb3448 100644 +--- a/net/minecraft/world/level/ServerExplosion.java ++++ b/net/minecraft/world/level/ServerExplosion.java +@@ -391,7 +391,17 @@ public class ServerExplosion implements Explosion { + return this.damageCalculator.getBlockExplosionResistance(this, this.level, pos, blockState, fluidState); + } + // Sakura end - explosion durable blocks +- protected final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget; // Sakura - configure server mechanics ++ // Sakura start - configure server mechanics ++ protected final me.samsuik.sakura.mechanics.MinecraftMechanicsTarget mechanicsTarget; ++ ++ private float sakura$getSeenPercent(final Vec3 explosionPos, final Entity entity) { ++ if (this.mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_16)) { ++ return this.getSeenFraction(explosionPos, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations ++ } else { ++ return getSeenPercent(explosionPos, entity); ++ } ++ } ++ // Sakura end - configure server mechanics + + public ServerExplosion( + ServerLevel level, diff --git a/sakura-server/minecraft-patches/features/0033-fixup-Configure-cannon-physics.patch b/sakura-server/minecraft-patches/features/0033-fixup-Configure-cannon-physics.patch new file mode 100644 index 0000000..2af8ad6 --- /dev/null +++ b/sakura-server/minecraft-patches/features/0033-fixup-Configure-cannon-physics.patch @@ -0,0 +1,19 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samsuik +Date: Thu, 25 Sep 2025 11:26:32 +0100 +Subject: [PATCH] fixup! Configure cannon physics + + +diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java +index f008ffa972eddf1d6bd0c3c2ef75332a56fb3448..ba4979657e65bfc97bb597e7aaa6ce6d030c1346 100644 +--- a/net/minecraft/world/level/ServerExplosion.java ++++ b/net/minecraft/world/level/ServerExplosion.java +@@ -967,7 +967,7 @@ public class ServerExplosion implements Explosion { + // Sakura start - replace density cache + float blockDensity = this.level.densityCache.getBlockDensity(vec3d, entity); + if (blockDensity == me.samsuik.sakura.explosion.density.BlockDensityCache.UNKNOWN_DENSITY) { +- blockDensity = this.sakura_getSeenPercent(vec3d, entity); // Sakura - configure server mechanics ++ blockDensity = this.sakura$getSeenPercent(vec3d, entity); // Sakura - configure server mechanics + this.level.densityCache.putDensity(vec3d, entity, blockDensity); + // Sakura end - replace density cache + } diff --git a/sakura-server/minecraft-patches/features/0034-fixup-Configure-cannon-physics.patch b/sakura-server/minecraft-patches/features/0034-fixup-Configure-cannon-physics.patch new file mode 100644 index 0000000..c2910f1 --- /dev/null +++ b/sakura-server/minecraft-patches/features/0034-fixup-Configure-cannon-physics.patch @@ -0,0 +1,27 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Samsuik +Date: Thu, 25 Sep 2025 11:26:32 +0100 +Subject: [PATCH] fixup! Configure cannon physics + + +diff --git a/net/minecraft/world/level/ServerExplosion.java b/net/minecraft/world/level/ServerExplosion.java +index ba4979657e65bfc97bb597e7aaa6ce6d030c1346..a88add750945a1a374d248ba6b2eb0688d9bec18 100644 +--- a/net/minecraft/world/level/ServerExplosion.java ++++ b/net/minecraft/world/level/ServerExplosion.java +@@ -975,16 +975,6 @@ public class ServerExplosion implements Explosion { + return blockDensity; + } + +- // Sakura start - configure server mechanics +- private float sakura_getSeenPercent(final Vec3 vec3d, final Entity entity) { +- if (this.mechanicsTarget.atLeast(me.samsuik.sakura.mechanics.MechanicVersion.v1_16)) { +- return this.getSeenFraction(vec3d, entity, this.directMappedBlockCache, this.mutablePos); // Paper - collision optimisations +- } else { +- return getSeenPercent(vec3d, entity); +- } +- } +- // Sakura end - configure server mechanics +- + static class CacheKey { + private final Level world; + private final double posX, posY, posZ; diff --git a/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java b/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java index 35454e1..6b6a74d 100644 --- a/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java +++ b/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCache.java @@ -1,62 +1,85 @@ package me.samsuik.sakura.explosion.density; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; -import net.minecraft.util.Mth; +import it.unimi.dsi.fastutil.objects.Object2FloatOpenHashMap; import net.minecraft.world.entity.Entity; +import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; +import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; -/** - * This is a replacement for papers explosion density cache to be more lenient and efficient. - */ +@NullMarked public final class BlockDensityCache { public static final float UNKNOWN_DENSITY = -1.0f; - private final Int2ObjectOpenHashMap densityDataMap = new Int2ObjectOpenHashMap<>(); - private DensityData data; - private int key; + private final Object2FloatOpenHashMap paperExactPosDensityCache = new Object2FloatOpenHashMap<>(); + private final Int2ObjectOpenHashMap lenientDensityCache = new Int2ObjectOpenHashMap<>(); + private @Nullable BlockDensityCacheKey densityCacheKey; + private @Nullable CachedBlockDensity cacheInUse; + private int cacheKeyInUse; private boolean knownSource; + private final Level level; - public float getDensity(Vec3 explosion, Entity entity) { - int key = getKey(explosion, entity); - DensityData data = this.densityDataMap.get(key); + public BlockDensityCache(final Level level) { + this.level = level; + this.paperExactPosDensityCache.defaultReturnValue(UNKNOWN_DENSITY); + } - if (data != null && data.hasPosition(explosion, entity.getBoundingBox())) { - return data.density(); - } else { - this.knownSource = data != null && data.complete() && data.isExplosionPosition(explosion); - this.data = data; - this.key = key; - return UNKNOWN_DENSITY; + public float getBlockDensity(final Vec3 explosionPos, final Entity entity) { + final int lenientKey = BlockDensityCacheKey.getLenientKey(explosionPos, entity.blockPosition()); + final CachedBlockDensity cache = this.lenientDensityCache.get(lenientKey); + + // Check if the density is cached + if (cache != null && cache.hasPosition(explosionPos, entity.getBoundingBox())) { + return cache.blockDensity(); + } + + // Replicate the broken behaviour of optimize-explosions + if (this.level.paperConfig().environment.optimizeExplosions) { + final BlockDensityCacheKey cacheKey = new BlockDensityCacheKey(explosionPos, entity); + final float blockDensity = this.paperExactPosDensityCache.getFloat(cacheKey); + if (blockDensity != UNKNOWN_DENSITY) { + return blockDensity; + } + this.densityCacheKey = cacheKey; + } + + this.knownSource = cache != null && cache.complete() && cache.isExplosionPosition(explosionPos); + this.cacheInUse = cache; + this.cacheKeyInUse = lenientKey; + return UNKNOWN_DENSITY; + } + + public float getKnownDensity(final Vec3 point) { + return this.knownSource && this.cacheInUse.isKnownPosition(point) + ? this.cacheInUse.blockDensity() + : UNKNOWN_DENSITY; + } + + public void putDensity(final Vec3 explosionPos, final Entity entity, final float blockDensity) { + final CachedBlockDensity cache = this.cacheInUse; + if (cache == null || !cache.complete()) { + this.lenientDensityCache.put(this.cacheKeyInUse, new CachedBlockDensity(explosionPos, entity, blockDensity)); + } else if (cache.blockDensity() == blockDensity) { + cache.expand(explosionPos, entity); + } + + if (this.level.paperConfig().environment.optimizeExplosions && this.densityCacheKey != null) { + this.paperExactPosDensityCache.put(this.densityCacheKey, blockDensity); } } - public float getKnownDensity(Vec3 point) { - if (this.knownSource && this.data.isKnownPosition(point)) { - return this.data.density(); - } else { - return UNKNOWN_DENSITY; - } - } + public void expire(final long tick) { + this.invalidate(); - public void putDensity(Vec3 explosion, Entity entity, float density) { - if (this.data == null || !this.data.complete()) { - this.densityDataMap.put(this.key, new DensityData(explosion, entity, density)); - } else if (this.data.density() == density) { - this.data.expand(explosion, entity); + if (tick % 600 == 0) { + // Trim everything down every 600 ticks + this.paperExactPosDensityCache.trim(0); + this.lenientDensityCache.trim(0); } } public void invalidate() { - this.densityDataMap.clear(); - } - - private static int getKey(Vec3 explosion, Entity entity) { - int key = Mth.floor(explosion.x()); - key = 31 * key + Mth.floor(explosion.y()); - key = 31 * key + Mth.floor(explosion.z()); - key = 31 * key + entity.getBlockX(); - key = 31 * key + entity.getBlockY(); - key = 31 * key + entity.getBlockZ(); - return key; + this.lenientDensityCache.clear(); } } diff --git a/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCacheKey.java b/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCacheKey.java new file mode 100644 index 0000000..9ae2615 --- /dev/null +++ b/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/BlockDensityCacheKey.java @@ -0,0 +1,24 @@ +package me.samsuik.sakura.explosion.density; + +import net.minecraft.core.BlockPos; +import net.minecraft.util.Mth; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public record BlockDensityCacheKey(Vec3 explosionPos, Vec3 entityPos) { + public BlockDensityCacheKey(final Vec3 explosionPos, final Entity entity) { + this(explosionPos, entity.position()); + } + + public static int getLenientKey(final Vec3 explosionPos, final BlockPos entityBlockPos) { + int key = Mth.floor(explosionPos.x()); + key = 31 * key + Mth.floor(explosionPos.y()); + key = 31 * key + Mth.floor(explosionPos.z()); + key = 31 * key + entityBlockPos.getX(); + key = 31 * key + entityBlockPos.getY(); + key = 31 * key + entityBlockPos.getZ(); + return key; + } +} diff --git a/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/CachedBlockDensity.java b/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/CachedBlockDensity.java new file mode 100644 index 0000000..eedc4db --- /dev/null +++ b/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/CachedBlockDensity.java @@ -0,0 +1,46 @@ +package me.samsuik.sakura.explosion.density; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; +import org.jspecify.annotations.NullMarked; + +@NullMarked +public final class CachedBlockDensity { + private AABB source; + private AABB entity; + private final float blockDensity; + private final boolean complete; + + public CachedBlockDensity(final Vec3 explosionPos, final Entity entity, final float blockDensity) { + this.source = new AABB(explosionPos, explosionPos); + this.entity = entity.getBoundingBox(); + this.blockDensity = blockDensity; + this.complete = blockDensity == 0.0f || blockDensity == 1.0f; + } + + public float blockDensity() { + return this.blockDensity; + } + + public boolean complete() { + return this.complete; + } + + public boolean hasPosition(final Vec3 explosionPos, final AABB entityBoundingBox) { + return this.isExplosionPosition(explosionPos) && this.entity.containsInclusive(entityBoundingBox); + } + + public boolean isKnownPosition(final Vec3 point) { + return this.entity.containsInclusive(point); + } + + public boolean isExplosionPosition(final Vec3 explosionPos) { + return this.source.containsInclusive(explosionPos); + } + + public void expand(final Vec3 explosionPos, final Entity entity) { + this.source = this.source.expand(explosionPos); + this.entity = this.entity.minmax(entity.getBoundingBox()); + } +} diff --git a/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/DensityData.java b/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/DensityData.java deleted file mode 100644 index 72eaf37..0000000 --- a/sakura-server/src/main/java/me/samsuik/sakura/explosion/density/DensityData.java +++ /dev/null @@ -1,47 +0,0 @@ -package me.samsuik.sakura.explosion.density; - -import net.minecraft.world.entity.Entity; -import net.minecraft.world.phys.AABB; -import net.minecraft.world.phys.Vec3; - -public final class DensityData { - private AABB source; - private AABB known; - private AABB entity; - private final float density; - private final boolean complete; - - public DensityData(Vec3 explosion, Entity entity, float density) { - this.source = new AABB(explosion, explosion); - this.known = new AABB(entity.position(), entity.position()); - this.entity = entity.getBoundingBox(); - this.density = density; - this.complete = Math.abs(density - 0.5f) == 0.5f; - } - - public float density() { - return this.density; - } - - public boolean complete() { - return this.complete; - } - - public boolean hasPosition(Vec3 explosion, AABB entity) { - return this.isExplosionPosition(explosion) && this.entity.containsInclusive(entity); - } - - public boolean isKnownPosition(Vec3 point) { - return this.entity.containsInclusive(point); - } - - public boolean isExplosionPosition(Vec3 explosion) { - return this.source.containsInclusive(explosion); - } - - public void expand(Vec3 explosion, Entity entity) { - this.source = this.source.expand(explosion); - this.known = this.known.expand(entity.position()); - this.entity = this.entity.minmax(entity.getBoundingBox()); - } -}