Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -62,6 +65,9 @@ public abstract class ExplosionMixin {
// The cached mutable block position used during block traversal.
private final BlockPos.Mutable cachedPos = new BlockPos.Mutable();

//cached block and blast resistance
private final HashMap<BlockPos,Pair<Float,BlockState>> blockAndBlastResCache=new HashMap<>();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use a single class/record or fastutil pair

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

new Long2ObjectOpenHashMap<FloatObjectPair<BlockState>>()


// The chunk coordinate of the most recently stepped through block.
private int prevChunkX = Integer.MIN_VALUE;
private int prevChunkZ = Integer.MIN_VALUE;
Expand All @@ -77,6 +83,7 @@ public abstract class ExplosionMixin {

private int minY, maxY;


@Inject(
method = "<init>(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")
Expand Down Expand Up @@ -149,7 +156,6 @@ public boolean collectBlocks(List<BlockPos> affectedBlocks, Collection<BlockPos>
}
}
}

// 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.
Expand Down Expand Up @@ -186,9 +192,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;

Expand Down Expand Up @@ -232,15 +238,38 @@ 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);

Pair<Float,BlockState> 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(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
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<Float,BlockState> getBlockAndBlastRes(int blockX, int blockY, int blockZ) {
Pair<Float,BlockState> 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<Float> 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;
}


Expand Down Expand Up @@ -293,17 +322,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;
}

}