This commit is contained in:
mlbv 2025-06-12 16:48:37 +08:00
parent 105f44a36a
commit a9567d986b
4 changed files with 81 additions and 51 deletions

View File

@ -3,7 +3,7 @@ package com.hbm.explosion;
import com.hbm.config.BombConfig;
import com.hbm.interfaces.IExplosionRay;
import com.hbm.main.MainRegistry;
import com.hbm.util.ChunkKey;
import com.hbm.util.SubChunkKey;
import com.hbm.util.ConcurrentBitSet;
import com.hbm.util.SubChunkSnapshot;
import net.minecraft.block.Block;
@ -41,10 +41,10 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
private final ConcurrentMap<ChunkCoordIntPair, ConcurrentBitSet> destructionMap;
private final ConcurrentMap<ChunkCoordIntPair, ChunkDamageAccumulator> accumulatedDamageMap;
private final ConcurrentMap<ChunkKey, SubChunkSnapshot> snapshots;
private final ConcurrentMap<SubChunkKey, SubChunkSnapshot> snapshots;
private final BlockingQueue<RayTask> rayQueue;
private final BlockingQueue<ChunkKey> cacheQueue;
private final BlockingQueue<SubChunkKey> cacheQueue;
private final ExecutorService pool;
private final CountDownLatch latch;
private final Thread latchWatcherThread;
@ -115,7 +115,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
final long deadline = System.nanoTime() + (timeBudgetMs * 1_000_000L);
while (System.nanoTime() < deadline) {
ChunkKey ck = cacheQueue.poll();
SubChunkKey ck = cacheQueue.poll();
if (ck == null) break;
snapshots.computeIfAbsent(ck, k -> SubChunkSnapshot.getSnapshot(world, k, BombConfig.chunkloading));
}
@ -188,7 +188,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
if (bs.isEmpty()) {
destructionMap.remove(cp);
for (int sy = 0; sy < (WORLD_HEIGHT >> 4); sy++) {
snapshots.remove(new ChunkKey(cp, sy));
snapshots.remove(new SubChunkKey(cp, sy));
}
it.remove();
}
@ -293,7 +293,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
continue;
}
ChunkKey snapshotKey = new ChunkKey(cp, subY);
SubChunkKey snapshotKey = new SubChunkKey(cp, subY);
SubChunkSnapshot snap = snapshots.get(snapshotKey);
Block originalBlock;
@ -440,7 +440,7 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
if (y < 0 || y >= WORLD_HEIGHT) break;
if (currentRayPosition >= radius - PROCESSING_EPSILON) break;
ChunkKey ck = new ChunkKey(x >> 4, z >> 4, y >> 4);
SubChunkKey ck = new SubChunkKey(x >> 4, z >> 4, y >> 4);
SubChunkSnapshot snap = snapshots.get(ck);
if (snap == null) {
@ -473,14 +473,14 @@ public class ExplosionNukeRayParallelized implements IExplosionRay {
if (damageDealt > 0) {
int bitIndex = ((WORLD_HEIGHT - 1 - y) << 8) | ((x & 0xF) << 4) | (z & 0xF);
if (BombConfig.explosionAlgorithm == 2) {
ChunkCoordIntPair chunkPos = ck.pos;
ChunkCoordIntPair chunkPos = ck.getPos();
ChunkDamageAccumulator chunkAccumulator =
accumulatedDamageMap.computeIfAbsent(chunkPos, k -> new ChunkDamageAccumulator());
chunkAccumulator.addDamage(bitIndex, damageDealt);
} else {
if (energy > 0) {
ConcurrentBitSet bs = destructionMap.computeIfAbsent(
ck.pos,
ck.getPos(),
posKey -> new ConcurrentBitSet(BITSET_SIZE)
);
bs.set(bitIndex);

View File

@ -1,37 +0,0 @@
package com.hbm.util;
import net.minecraft.world.ChunkCoordIntPair;
import java.util.Objects;
/**
* Unique identifier for sub-chunks.
* @author mlbv
*/
public class ChunkKey {
public final ChunkCoordIntPair pos;
public final int subY;
public ChunkKey(int cx, int cz, int sy) {
this.pos = new ChunkCoordIntPair(cx, cz);
this.subY = sy;
}
public ChunkKey(ChunkCoordIntPair pos, int sy) {
this.pos = pos;
this.subY = sy;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof ChunkKey)) return false;
ChunkKey k = (ChunkKey) o;
return subY == k.subY && pos.equals(k.pos);
}
@Override
public int hashCode() {
return Objects.hash(pos.chunkXPos, pos.chunkZPos, subY);
}
}

View File

@ -0,0 +1,67 @@
package com.hbm.util;
import net.minecraft.world.ChunkCoordIntPair;
/**
* Unique identifier for sub-chunks.
* @author mlbv
*/
public class SubChunkKey {
private int chunkXPos;
private int chunkZPos;
private int subY;
private int hash;
public SubChunkKey() {
this(0, 0, 0);
}
public SubChunkKey(int cx, int cz, int sy) {
this.update(cx, cz, sy);
}
public SubChunkKey(ChunkCoordIntPair pos, int sy) {
this.update(pos.chunkXPos, pos.chunkZPos, sy);
}
public SubChunkKey update(int cx, int cz, int sy) {
this.chunkXPos = cx;
this.chunkZPos = cz;
this.subY = sy;
int result = subY;
result = 31 * result + cx;
result = 31 * result + cz;
this.hash = result;
return this;
}
@Override
public final int hashCode() {
return this.hash;
}
@Override
public final boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof SubChunkKey)) return false;
SubChunkKey k = (SubChunkKey) o;
return this.subY == k.subY && this.chunkXPos == k.chunkXPos && this.chunkZPos == k.chunkZPos;
}
public int getSubY() {
return subY;
}
public int getChunkXPos() {
return chunkXPos;
}
public int getChunkZPos() {
return chunkZPos;
}
public ChunkCoordIntPair getPos() {
return new ChunkCoordIntPair(this.chunkXPos, this.chunkZPos);
}
}

View File

@ -34,19 +34,19 @@ public class SubChunkSnapshot {
* @param world
* The World instance from which to retrieve the chunk.
* @param key
* The ChunkKey identifying the sub-chunk.
* The SubChunkKey identifying the sub-chunk.
* @param allowGeneration
* Whether to generate chunks. If false, attempting to retrieve a snapshot of a chunk that does not exist will return {@link SubChunkSnapshot#EMPTY}.
* @return
* A SubChunkSnapshot containing the palette and block data for the sub-chunk,
* or {@link SubChunkSnapshot#EMPTY} if the region contains only air.
*/
public static SubChunkSnapshot getSnapshot(World world, ChunkKey key, boolean allowGeneration){
if (!world.getChunkProvider().chunkExists(key.pos.chunkXPos, key.pos.chunkZPos) && !allowGeneration) {
public static SubChunkSnapshot getSnapshot(World world, SubChunkKey key, boolean allowGeneration){
if (!world.getChunkProvider().chunkExists(key.getChunkXPos(), key.getChunkZPos()) && !allowGeneration) {
return SubChunkSnapshot.EMPTY;
}
Chunk chunk = world.getChunkProvider().provideChunk(key.pos.chunkXPos, key.pos.chunkZPos);
ExtendedBlockStorage ebs = chunk.getBlockStorageArray()[key.subY];
Chunk chunk = world.getChunkProvider().provideChunk(key.getChunkXPos(), key.getChunkZPos());
ExtendedBlockStorage ebs = chunk.getBlockStorageArray()[key.getSubY()];
if (ebs == null || ebs.isEmpty()) return SubChunkSnapshot.EMPTY;
short[] data = new short[16 * 16 * 16];