Fix: Make crate look normal

This commit is contained in:
mlbv 2025-05-23 19:40:45 +08:00
parent 9bb9a56452
commit ea430afe71

View File

@ -86,7 +86,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
} }
private static float getNukeResistance(Block b) { private static float getNukeResistance(Block b) {
// if (b.getMaterial().isLiquid()) return 0.1F; if (b.getMaterial().isLiquid()) return 0.1F;
if (b == Blocks.sandstone) return Blocks.stone.getExplosionResistance(null); if (b == Blocks.sandstone) return Blocks.stone.getExplosionResistance(null);
if (b == Blocks.obsidian) return Blocks.stone.getExplosionResistance(null) * 3; if (b == Blocks.obsidian) return Blocks.stone.getExplosionResistance(null) * 3;
return b.getExplosionResistance(null); return b.getExplosionResistance(null);
@ -128,7 +128,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
Chunk chunk = world.getChunkFromChunkCoords(cp.chunkXPos, cp.chunkZPos); Chunk chunk = world.getChunkFromChunkCoords(cp.chunkXPos, cp.chunkZPos);
ExtendedBlockStorage[] storages = chunk.getBlockStorageArray(); ExtendedBlockStorage[] storages = chunk.getBlockStorageArray();
boolean ChunkModified = false; boolean chunkModified = false;
for (int subY = 0; subY < storages.length; subY++) { for (int subY = 0; subY < storages.length; subY++) {
ExtendedBlockStorage storage = storages[subY]; ExtendedBlockStorage storage = storages[subY];
@ -157,7 +157,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
int zLocal = zGlobal & 0xF; int zLocal = zGlobal & 0xF;
storage.func_150818_a(xLocal, yLocal, zLocal, Blocks.air); storage.func_150818_a(xLocal, yLocal, zLocal, Blocks.air);
storage.setExtBlockMetadata(xLocal, yLocal, zLocal, 0); storage.setExtBlockMetadata(xLocal, yLocal, zLocal, 0);
ChunkModified = true; chunkModified = true;
world.notifyBlocksOfNeighborChange(xGlobal, yGlobal, zGlobal, Blocks.air); world.notifyBlocksOfNeighborChange(xGlobal, yGlobal, zGlobal, Blocks.air);
world.markBlockForUpdate(xGlobal, yGlobal, zGlobal); world.markBlockForUpdate(xGlobal, yGlobal, zGlobal);
@ -170,7 +170,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
} }
} }
if (ChunkModified) { if (chunkModified) {
chunk.setChunkModified(); chunk.setChunkModified();
world.markBlockRangeForRenderUpdate(cp.chunkXPos << 4, 0, cp.chunkZPos << 4, (cp.chunkXPos << 4) | 15, WORLD_HEIGHT - 1, (cp.chunkZPos << 4) | 15); world.markBlockRangeForRenderUpdate(cp.chunkXPos << 4, 0, cp.chunkZPos << 4, (cp.chunkXPos << 4) | 15, WORLD_HEIGHT - 1, (cp.chunkZPos << 4) | 15);
} }
@ -387,7 +387,6 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
} }
} }
} }
private class RayTask { private class RayTask {
final int dirIndex; final int dirIndex;
double px, py, pz; double px, py, pz;
@ -396,40 +395,51 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
double tMaxX, tMaxY, tMaxZ, tDeltaX, tDeltaY, tDeltaZ; double tMaxX, tMaxY, tMaxZ, tDeltaX, tDeltaY, tDeltaZ;
int stepX, stepY, stepZ; int stepX, stepY, stepZ;
boolean initialised = false; boolean initialised = false;
double currentRayPosition;
private static final double RAY_DIRECTION_EPSILON = 1e-6;
private static final double PROCESSING_EPSILON = 1e-9;
private static final float MIN_EFFECTIVE_DIST_FOR_ENERGY_CALC = 0.01f;
RayTask(int dirIdx) { RayTask(int dirIdx) {
this.dirIndex = dirIdx; this.dirIndex = dirIdx;
} }
void init() { void init() {
Vec3 dir = directions.get(dirIndex); Vec3 dir = directions.get(this.dirIndex);
px = explosionX; this.px = explosionX;
py = explosionY; this.py = explosionY;
pz = explosionZ; this.pz = explosionZ;
x = originX; this.x = originX;
y = originY; this.y = originY;
z = originZ; this.z = originZ;
energy = strength; // This scales the crate. higher = bigger crate. Adjust if the radius of the crate deviates from expected.
this.energy = strength * 0.3F;
this.currentRayPosition = 0.0;
double dirX = dir.xCoord;
double dirY = dir.yCoord;
double dirZ = dir.zCoord;
final double EPS = 1e-6; double absDirX = Math.abs(dirX);
double ax = Math.abs(dir.xCoord); this.stepX = (absDirX < RAY_DIRECTION_EPSILON) ? 0 : (dirX > 0 ? 1 : -1);
stepX = ax < EPS ? 0 : (dir.xCoord > 0 ? 1 : -1); this.tDeltaX = (stepX == 0) ? Double.POSITIVE_INFINITY : 1.0 / absDirX;
double invDx = stepX == 0 ? Double.POSITIVE_INFINITY : 1.0 / ax; this.tMaxX = (stepX == 0) ? Double.POSITIVE_INFINITY :
double ay = Math.abs(dir.yCoord); ((stepX > 0 ? (this.x + 1 - this.px) : (this.px - this.x)) * this.tDeltaX);
stepY = ay < EPS ? 0 : (dir.yCoord > 0 ? 1 : -1);
double invDy = stepY == 0 ? Double.POSITIVE_INFINITY : 1.0 / ay;
double az = Math.abs(dir.zCoord);
stepZ = az < EPS ? 0 : (dir.zCoord > 0 ? 1 : -1);
double invDz = stepZ == 0 ? Double.POSITIVE_INFINITY : 1.0 / az;
tDeltaX = invDx; double absDirY = Math.abs(dirY);
tDeltaY = invDy; this.stepY = (absDirY < RAY_DIRECTION_EPSILON) ? 0 : (dirY > 0 ? 1 : -1);
tDeltaZ = invDz; this.tDeltaY = (stepY == 0) ? Double.POSITIVE_INFINITY : 1.0 / absDirY;
tMaxX = stepX == 0 ? Double.POSITIVE_INFINITY : ((stepX > 0 ? (x + 1 - px) : (px - x)) * invDx); this.tMaxY = (stepY == 0) ? Double.POSITIVE_INFINITY :
tMaxY = stepY == 0 ? Double.POSITIVE_INFINITY : ((stepY > 0 ? (y + 1 - py) : (py - y)) * invDy); ((stepY > 0 ? (this.y + 1 - this.py) : (this.py - this.y)) * this.tDeltaY);
tMaxZ = stepZ == 0 ? Double.POSITIVE_INFINITY : ((stepZ > 0 ? (z + 1 - pz) : (pz - z)) * invDz);
initialised = true; double absDirZ = Math.abs(dirZ);
this.stepZ = (absDirZ < RAY_DIRECTION_EPSILON) ? 0 : (dirZ > 0 ? 1 : -1);
this.tDeltaZ = (stepZ == 0) ? Double.POSITIVE_INFINITY : 1.0 / absDirZ;
this.tMaxZ = (stepZ == 0) ? Double.POSITIVE_INFINITY :
((stepZ > 0 ? (this.z + 1 - this.pz) : (this.pz - this.z)) * this.tDeltaZ);
this.initialised = true;
} }
void trace() { void trace() {
@ -440,15 +450,8 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
} }
while (energy > 0) { while (energy > 0) {
if (y < 0 || y >= WORLD_HEIGHT) { if (y < 0 || y >= WORLD_HEIGHT) break;
break; if (currentRayPosition >= radius - PROCESSING_EPSILON) break;
}
double dxBlock = x + 0.5 - explosionX;
double dyBlock = y + 0.5 - explosionY;
double dzBlock = z + 0.5 - explosionZ;
if (dxBlock * dxBlock + dyBlock * dyBlock + dzBlock * dzBlock > radius * radius) {
break;
}
ChunkKey ck = new ChunkKey(x >> 4, z >> 4, y >> 4); ChunkKey ck = new ChunkKey(x >> 4, z >> 4, y >> 4);
SubChunkSnapshot snap = snapshots.get(ck); SubChunkSnapshot snap = snapshots.get(ck);
@ -458,21 +461,40 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
rayQueue.offer(this); rayQueue.offer(this);
return; return;
} }
if (snap != SubChunkSnapshot.EMPTY) { double t_exit_voxel = Math.min(tMaxX, Math.min(tMaxY, tMaxZ));
Block block = snap.getBlock(x & 15, y & 15, z & 15); double segmentLenInVoxel = t_exit_voxel - this.currentRayPosition;
double segmentLenForProcessing;
boolean stopAfterThisSegment = false;
if (this.currentRayPosition + segmentLenInVoxel > radius - PROCESSING_EPSILON) {
segmentLenForProcessing = Math.max(0.0, radius - this.currentRayPosition);
stopAfterThisSegment = true;
} else {
segmentLenForProcessing = segmentLenInVoxel;
}
if (snap != SubChunkSnapshot.EMPTY && segmentLenForProcessing > PROCESSING_EPSILON) {
Block block = snap.getBlock(x & 0xF, y & 0xF, z & 0xF);
if (block != Blocks.air) { if (block != Blocks.air) {
float res = getNukeResistance(block); float resistance = getNukeResistance(block);
float resistanceCutoff = 2_000_000F; if (resistance >= 2_000_000F) { // cutoff
if (res >= resistanceCutoff) break; energy = 0;
double distToBlock = Math.sqrt(dxBlock * dxBlock + dyBlock * dyBlock + dzBlock * dzBlock); } else {
double effectiveDist = Math.max(distToBlock, 0.01); double energyLossFactor = getEnergyLossFactor(resistance);
energy -= (float) (Math.pow(res + 1.0, 3.0 * (effectiveDist / radius)) - 1.0); energy -= (float) (energyLossFactor * segmentLenForProcessing);
if (energy > 0) { if (energy > 0) {
ConcurrentBitSet bs = destructionMap.computeIfAbsent(ck.pos, posKey -> new ConcurrentBitSet()); ConcurrentBitSet bs = destructionMap.computeIfAbsent(
bs.set(((255 - y) << 8) | ((x & 15) << 4) | (z & 15)); ck.pos,
} else break; posKey -> new ConcurrentBitSet()
);
int bitIndex = ((WORLD_HEIGHT - 1 - y) << 8) | ((x & 0xF) << 4) | (z & 0xF);
bs.set(bitIndex);
}
}
} }
} }
this.currentRayPosition = t_exit_voxel;
if (energy <= 0 || stopAfterThisSegment || this.currentRayPosition >= radius - PROCESSING_EPSILON) break;
if (tMaxX < tMaxY) { if (tMaxX < tMaxY) {
if (tMaxX < tMaxZ) { if (tMaxX < tMaxZ) {
@ -494,5 +516,18 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
} }
latch.countDown(); latch.countDown();
} }
private double getEnergyLossFactor(float resistance) {
double dxBlockToCenter = (this.x + 0.5) - explosionX;
double dyBlockToCenter = (this.y + 0.5) - explosionY;
double dzBlockToCenter = (this.z + 0.5) - explosionZ;
double distToBlockCenterSq = dxBlockToCenter * dxBlockToCenter +
dyBlockToCenter * dyBlockToCenter +
dzBlockToCenter * dzBlockToCenter;
double distToBlockCenter = Math.sqrt(distToBlockCenterSq);
double effectiveDist = Math.max(distToBlockCenter, MIN_EFFECTIVE_DIST_FOR_ENERGY_CALC);
return (Math.pow(resistance + 1.0, 3.0 * (effectiveDist / radius)) - 1.0);
}
} }
} }