From 8d108c552f315f1fe72fb7c0b96af252e0435204 Mon Sep 17 00:00:00 2001 From: pwouik <62726872+pwouik@users.noreply.github.com> Date: Wed, 6 Oct 2021 20:27:36 +0200 Subject: [PATCH 1/2] Update ExplosionMixin.java cache all blockstates and blast resistance --- .../world/explosions/ExplosionMixin.java | 65 +++++++++++++------ 1 file changed, 45 insertions(+), 20 deletions(-) diff --git a/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java b/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java index 8446af251..14d296979 100644 --- a/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java +++ b/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java @@ -9,8 +9,9 @@ import net.minecraft.entity.damage.DamageSource; import net.minecraft.fluid.FluidState; import net.minecraft.fluid.Fluids; +import net.minecraft.util.Pair; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3i; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.ChunkSection; @@ -24,6 +25,8 @@ import java.util.*; +import static net.minecraft.util.math.MathHelper.floor; + /** * Optimizations for Explosions: Reduce allocations and getChunk/getBlockState calls * Original implementation by @@ -62,6 +65,10 @@ public abstract class ExplosionMixin { // The cached mutable block position used during block traversal. private final BlockPos.Mutable cachedPos = new BlockPos.Mutable(); + private BlockPos posOrigin; + //cached block and blast resistance + private final HashMap> blockAndBlastResCache=new HashMap<>(); + // The chunk coordinate of the most recently stepped through block. private int prevChunkX = Integer.MIN_VALUE; private int prevChunkZ = Integer.MIN_VALUE; @@ -77,11 +84,13 @@ public abstract class ExplosionMixin { private int minY, maxY; + @Inject( method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/Entity;Lnet/minecraft/entity/damage/DamageSource;Lnet/minecraft/world/explosion/ExplosionBehavior;DDDFZLnet/minecraft/world/explosion/Explosion$DestructionType;)V", at = @At("TAIL") ) private void init(World world, Entity entity, DamageSource damageSource, ExplosionBehavior explosionBehavior, double d, double e, double f, float g, boolean bl, Explosion.DestructionType destructionType, CallbackInfo ci) { + this.posOrigin=new BlockPos(floor(d),floor(e),floor(f)); this.minY = this.world.getBottomY(); this.maxY = this.world.getTopY(); @@ -149,7 +158,6 @@ public boolean collectBlocks(List affectedBlocks, Collection } } } - // We can now iterate back over the set of positions we modified and re-build BlockPos objects from them // This will only allocate as many objects as there are in the set, where otherwise we would allocate them // each step of a every ray. @@ -186,9 +194,9 @@ private void performRayCast(Random random, double vecX, double vecY, double vecZ // Step through the ray until it is finally stopped while (strength > 0.0F) { - int blockX = MathHelper.floor(stepX); - int blockY = MathHelper.floor(stepY); - int blockZ = MathHelper.floor(stepZ); + int blockX = floor(stepX); + int blockY = floor(stepY); + int blockZ = floor(stepZ); float resistance; @@ -232,15 +240,41 @@ private void performRayCast(Random random, double vecX, double vecY, double vecZ */ private float traverseBlock(float strength, int blockX, int blockY, int blockZ, LongOpenHashSet touched) { BlockPos pos = this.cachedPos.set(blockX, blockY, blockZ); - + int relX=pos.getX()-this.posOrigin.getX(); + int relY=pos.getY()-this.posOrigin.getY(); + int relZ=pos.getZ()-this.posOrigin.getZ(); + Pair blockAndBlastRes = this.blockAndBlastResCache.get(new Vec3i(relX,relY,relZ)); + //test if the block is cached + if(blockAndBlastRes==null) { + //compute values and cache + blockAndBlastRes = getBlockAndBlastRes(blockX,blockY,blockZ); + this.blockAndBlastResCache.put(new Vec3i(relX,relY,relZ),blockAndBlastRes); + } + // Check if this ray is still strong enough to break blocks if not out of bound, and if so, add this position to the set + // of positions to destroy + if(blockAndBlastRes.getRight()!=null) + { + float reducedStrength = strength - blockAndBlastRes.getLeft(); + if (reducedStrength > 0.0F && (this.explodeAirBlocks || !blockAndBlastRes.getRight().isAir())) { + if (this.behavior.canDestroyBlock((Explosion) (Object) this, this.world, pos, blockAndBlastRes.getRight(), reducedStrength)) { + touched.add(pos.asLong()); + } + } + } + return blockAndBlastRes.getLeft(); + } + private Pair getBlockAndBlastRes(int blockX, int blockY, int blockZ) { + Pair result= new Pair(0.0,null); + BlockPos pos = this.cachedPos.set(blockX, blockY, blockZ); // Early-exit if the y-coordinate is out of bounds. if (this.world.isOutOfHeightLimit(blockY)) { Optional blastResistance = this.behavior.getBlastResistance((Explosion) (Object) this, this.world, pos, Blocks.AIR.getDefaultState(), Fluids.EMPTY.getDefaultState()); //noinspection OptionalIsPresent if (blastResistance.isPresent()) { - return (blastResistance.get() + 0.3F) * 0.3F; + result.setLeft((blastResistance.get() + 0.3F) * 0.3F); + return result; } - return 0.0F; + return result; } @@ -293,17 +327,8 @@ private float traverseBlock(float strength, int blockX, int blockY, int blockZ, if (blastResistance.isPresent()) { totalResistance = (blastResistance.get() + 0.3F) * 0.3F; } - - // Check if this ray is still strong enough to break blocks, and if so, add this position to the set - // of positions to destroy - float reducedStrength = strength - totalResistance; - if (reducedStrength > 0.0F && (this.explodeAirBlocks || !blockState.isAir())) { - if (this.behavior.canDestroyBlock((Explosion) (Object) this, this.world, pos, blockState, reducedStrength)) { - touched.add(pos.asLong()); - } - } - - return totalResistance; + result.setLeft(totalResistance); + result.setRight(blockState); + return result; } - } From 5c137e73764f02c02a6ee286a1d7b0a734004c46 Mon Sep 17 00:00:00 2001 From: pwouik <62726872+pwouik@users.noreply.github.com> Date: Thu, 7 Oct 2021 01:58:46 +0200 Subject: [PATCH 2/2] remove pointless previous code --- .../mixin/world/explosions/ExplosionMixin.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java b/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java index 14d296979..4b21f73c1 100644 --- a/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java +++ b/src/main/java/me/jellysquid/mods/lithium/mixin/world/explosions/ExplosionMixin.java @@ -65,9 +65,8 @@ public abstract class ExplosionMixin { // The cached mutable block position used during block traversal. private final BlockPos.Mutable cachedPos = new BlockPos.Mutable(); - private BlockPos posOrigin; //cached block and blast resistance - private final HashMap> blockAndBlastResCache=new HashMap<>(); + private final HashMap> blockAndBlastResCache=new HashMap<>(); // The chunk coordinate of the most recently stepped through block. private int prevChunkX = Integer.MIN_VALUE; @@ -90,7 +89,6 @@ public abstract class ExplosionMixin { at = @At("TAIL") ) private void init(World world, Entity entity, DamageSource damageSource, ExplosionBehavior explosionBehavior, double d, double e, double f, float g, boolean bl, Explosion.DestructionType destructionType, CallbackInfo ci) { - this.posOrigin=new BlockPos(floor(d),floor(e),floor(f)); this.minY = this.world.getBottomY(); this.maxY = this.world.getTopY(); @@ -240,15 +238,12 @@ private void performRayCast(Random random, double vecX, double vecY, double vecZ */ private float traverseBlock(float strength, int blockX, int blockY, int blockZ, LongOpenHashSet touched) { BlockPos pos = this.cachedPos.set(blockX, blockY, blockZ); - int relX=pos.getX()-this.posOrigin.getX(); - int relY=pos.getY()-this.posOrigin.getY(); - int relZ=pos.getZ()-this.posOrigin.getZ(); - Pair blockAndBlastRes = this.blockAndBlastResCache.get(new Vec3i(relX,relY,relZ)); + Pair blockAndBlastRes = this.blockAndBlastResCache.get(pos); //test if the block is cached if(blockAndBlastRes==null) { //compute values and cache blockAndBlastRes = getBlockAndBlastRes(blockX,blockY,blockZ); - this.blockAndBlastResCache.put(new Vec3i(relX,relY,relZ),blockAndBlastRes); + this.blockAndBlastResCache.put(pos,blockAndBlastRes); } // Check if this ray is still strong enough to break blocks if not out of bound, and if so, add this position to the set // of positions to destroy