0001-Add-custom-per-block-replacement.patch
Raw
From 9ef96155077f5830f6f2e3ea3605a6795438418f Mon Sep 17 00:00:00 2001
From: stonar96 <[email protected]>
Date: Thu, 2 Feb 2023 15:35:24 +0100
Subject: [PATCH] Add custom per block replacement
diff --git a/RayTraceAntiXray/src/main/java/com/vanillage/raytraceantixray/antixray/ChunkPacketBlockControllerAntiXray.java b/RayTraceAntiXray/src/main/java/com/vanillage/raytraceantixray/antixray/ChunkPacketBlockControllerAntiXray.java
index b3cd0ff..bc7d9f1 100644
--- a/RayTraceAntiXray/src/main/java/com/vanillage/raytraceantixray/antixray/ChunkPacketBlockControllerAntiXray.java
+++ b/RayTraceAntiXray/src/main/java/com/vanillage/raytraceantixray/antixray/ChunkPacketBlockControllerAntiXray.java
@@ -58,8 +58,8 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
private final int[] presetBlockStateBitsNetherrackGlobal;
private final int[] presetBlockStateBitsEndStoneGlobal;
public final boolean[] solidGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()];
- private final boolean[] obfuscateGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()];
- private final boolean[] traceGlobal;
+ private final int[] obfuscateGlobal = new int[Block.BLOCK_STATE_REGISTRY.size()];
+ private final int[] traceGlobal;
private final LevelChunkSection[] emptyNearbyChunkSections = {EMPTY_SECTION, EMPTY_SECTION, EMPTY_SECTION, EMPTY_SECTION};
public final boolean rayTraceThirdPerson;
public final double rayTraceDistance;
@@ -76,9 +76,9 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
this.rayTraceThirdPerson = rayTraceThirdPerson;
this.rayTraceDistance = rayTraceDistance;
this.maxRayTraceBlockCountPerChunk = maxRayTraceBlockCountPerChunk;
- List<String> toObfuscate;
+ List<String> toObfuscate = paperWorldConfig.hiddenBlocks;
- if (engineMode == EngineMode.HIDE) {
+ /*if (engineMode == EngineMode.HIDE) {
toObfuscate = paperWorldConfig.hiddenBlocks;
presetBlockStates = null;
presetBlockStatesFull = null;
@@ -124,16 +124,57 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
presetBlockStateBitsDeepslateGlobal = null;
presetBlockStateBitsNetherrackGlobal = null;
presetBlockStateBitsEndStoneGlobal = null;
+ }*/
+
+ List<BlockState> presetBlockStateList = new LinkedList<>();
+ BlockState defaultBlockState;
+
+ switch (level.getWorld().getEnvironment()) {
+ case NETHER:
+ defaultBlockState = Blocks.NETHERRACK.defaultBlockState();
+ break;
+ case THE_END:
+ defaultBlockState = Blocks.END_STONE.defaultBlockState();
+ break;
+ default:
+ defaultBlockState = Blocks.STONE.defaultBlockState();
}
+ // -1 means false (don't obfuscate).
+ Arrays.fill(obfuscateGlobal, -1);
+
for (String id : toObfuscate) {
- Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(id)).orElse(null);
+ String fromToIdSeparator = "->";
+ int fromToIdSeparatorIndex = id.lastIndexOf(fromToIdSeparator);
+ String fromId = fromToIdSeparatorIndex >= 0 ? id.substring(0, fromToIdSeparatorIndex) : id;
+ Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(fromId)).orElse(null);
// Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void
if (block != null && !block.defaultBlockState().isAir()) {
+ BlockState toBlockState = null;
+
+ if (fromToIdSeparatorIndex >= 0) {
+ Block toBlock = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(id.substring(fromToIdSeparatorIndex + fromToIdSeparator.length()))).orElse(null);
+
+ if (toBlock != null && !(toBlock instanceof EntityBlock)) {
+ toBlockState = toBlock.defaultBlockState();
+ }
+ }
+
+ if (toBlockState == null) {
+ toBlockState = defaultBlockState;
+ }
+
+ int presetBlockStateListIndex = presetBlockStateList.indexOf(toBlockState);
+
+ if (presetBlockStateListIndex < 0) {
+ presetBlockStateListIndex = presetBlockStateList.size();
+ presetBlockStateList.add(toBlockState);
+ }
+
// Replace all block states of a specified block
for (BlockState blockState : block.getStateDefinition().getPossibleStates()) {
- obfuscateGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] = true;
+ obfuscateGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] = presetBlockStateListIndex;
}
}
}
@@ -141,22 +182,69 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (toTrace == null) {
traceGlobal = obfuscateGlobal;
} else {
- traceGlobal = new boolean[Block.BLOCK_STATE_REGISTRY.size()];
+ traceGlobal = new int[Block.BLOCK_STATE_REGISTRY.size()];
+ // -1 means false (don't obfuscate).
+ Arrays.fill(traceGlobal, -1);
for (String id : toTrace) {
- Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(id)).orElse(null);
+ String fromToIdSeparator = "->";
+ int fromToIdSeparatorIndex = id.lastIndexOf(fromToIdSeparator);
+ String fromId = fromToIdSeparatorIndex >= 0 ? id.substring(0, fromToIdSeparatorIndex) : id;
+ Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(fromId)).orElse(null);
// Don't obfuscate air because air causes unnecessary block updates and causes block updates to fail in the void
if (block != null && !block.defaultBlockState().isAir()) {
+ BlockState toBlockState = null;
+
+ if (fromToIdSeparatorIndex >= 0) {
+ Block toBlock = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(id.substring(fromToIdSeparatorIndex + fromToIdSeparator.length()))).orElse(null);
+
+ if (toBlock != null && !(toBlock instanceof EntityBlock)) {
+ toBlockState = toBlock.defaultBlockState();
+ }
+ }
+
+ if (toBlockState == null) {
+ toBlockState = defaultBlockState;
+ }
+
+ int presetBlockStateListIndex = presetBlockStateList.indexOf(toBlockState);
+
+ if (presetBlockStateListIndex < 0) {
+ presetBlockStateListIndex = presetBlockStateList.size();
+ presetBlockStateList.add(toBlockState);
+ }
+
// Replace all block states of a specified block
for (BlockState blockState : block.getStateDefinition().getPossibleStates()) {
- traceGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] = true;
- obfuscateGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] = true;
+ traceGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] = presetBlockStateListIndex;
+ obfuscateGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] = presetBlockStateListIndex;
}
}
}
}
+ if (presetBlockStateList.isEmpty()) {
+ presetBlockStateList.add(defaultBlockState);
+ }
+
+ presetBlockStates = presetBlockStateList.toArray(new BlockState[0]);
+ presetBlockStatesFull = presetBlockStates;
+ presetBlockStatesStone = null;
+ presetBlockStatesDeepslate = null;
+ presetBlockStatesNetherrack = null;
+ presetBlockStatesEndStone = null;
+ presetBlockStateBitsGlobal = new int[presetBlockStatesFull.length];
+
+ for (int i = 0; i < presetBlockStatesFull.length; i++) {
+ presetBlockStateBitsGlobal[i] = GLOBAL_BLOCKSTATE_PALETTE.idFor(presetBlockStatesFull[i]);
+ }
+
+ presetBlockStateBitsStoneGlobal = null;
+ presetBlockStateBitsDeepslateGlobal = null;
+ presetBlockStateBitsNetherrackGlobal = null;
+ presetBlockStateBitsEndStoneGlobal = null;
+
EmptyLevelChunk emptyChunk = new EmptyLevelChunk(level, new ChunkPos(0, 0), MinecraftServer.getServer().registryAccess().registryOrThrow(Registries.BIOME).getHolderOrThrow(Biomes.PLAINS));
BlockPos zeroPos = new BlockPos(0, 0, 0);
@@ -175,14 +263,14 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
}
private int getPresetBlockStatesFullLength() {
- return engineMode == EngineMode.HIDE ? 1 : presetBlockStatesFull.length;
+ return presetBlockStatesFull.length;
}
@Override
public BlockState[] getPresetBlockStates(Level level, ChunkPos chunkPos, int bottomBlockY) {
// Return the block states to be added to the paletted containers so that they can be used for obfuscation
if (bottomBlockY < maxBlockHeight) {
- if (engineMode == EngineMode.HIDE) {
+ /*if (engineMode == EngineMode.HIDE) {
switch (level.getWorld().getEnvironment()) {
case NETHER:
return presetBlockStatesNetherrack;
@@ -191,7 +279,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
default:
return bottomBlockY < 0 ? presetBlockStatesDeepslate : presetBlockStatesStone;
}
- }
+ }*/
return presetBlockStates;
}
@@ -235,22 +323,24 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
// If an ExecutorService with multiple threads is used, ThreadLocal must be used here
private final ThreadLocal<int[]> presetBlockStateBits = ThreadLocal.withInitial(() -> new int[getPresetBlockStatesFullLength()]);
private static final ThreadLocal<boolean[]> SOLID = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]);
- private static final ThreadLocal<boolean[]> OBFUSCATE = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]);
- private static final ThreadLocal<boolean[]> TRACE = ThreadLocal.withInitial(() -> new boolean[Block.BLOCK_STATE_REGISTRY.size()]);
+ private static final ThreadLocal<int[]> OBFUSCATE = ThreadLocal.withInitial(() -> new int[Block.BLOCK_STATE_REGISTRY.size()]);
+ private static final ThreadLocal<int[]> TRACE = ThreadLocal.withInitial(() -> new int[Block.BLOCK_STATE_REGISTRY.size()]);
// These boolean arrays represent chunk layers, true means don't obfuscate, false means obfuscate
private static final ThreadLocal<boolean[][]> CURRENT = ThreadLocal.withInitial(() -> new boolean[16][16]);
private static final ThreadLocal<boolean[][]> NEXT = ThreadLocal.withInitial(() -> new boolean[16][16]);
private static final ThreadLocal<boolean[][]> NEXT_NEXT = ThreadLocal.withInitial(() -> new boolean[16][16]);
+ private static final ThreadLocal<int[][]> OBFUSCATE_CACHE = ThreadLocal.withInitial(() -> new int[16][16]);
private static final ThreadLocal<boolean[][]> TRACE_CACHE = ThreadLocal.withInitial(() -> new boolean[16][16]);
public void obfuscate(ChunkPacketInfoAntiXray chunkPacketInfoAntiXray) {
int[] presetBlockStateBits = this.presetBlockStateBits.get();
boolean[] solid = SOLID.get();
- boolean[] obfuscate = OBFUSCATE.get();
- boolean[] trace = traceGlobal == obfuscateGlobal ? obfuscate : TRACE.get();
+ int[] obfuscate = OBFUSCATE.get();
+ int[] trace = traceGlobal == obfuscateGlobal ? obfuscate : TRACE.get();
boolean[][] current = CURRENT.get();
boolean[][] next = NEXT.get();
boolean[][] nextNext = NEXT_NEXT.get();
+ int[][] obfuscateCache = OBFUSCATE_CACHE.get();
boolean[][] traceCache = TRACE_CACHE.get();
// bitStorageReader, bitStorageWriter and nearbyChunkSections could also be reused (with ThreadLocal if necessary) but it's not worth it
BitStorageReader bitStorageReader = new BitStorageReader();
@@ -260,8 +350,8 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
Level level = chunk.getLevel();
int maxChunkSectionIndex = Math.min((maxBlockHeight >> 4) - chunk.getMinSection(), chunk.getSectionsCount()) - 1;
boolean[] solidTemp = null;
- boolean[] obfuscateTemp = null;
- boolean[] traceTemp = null;
+ int[] obfuscateTemp = null;
+ int[] traceTemp = null;
bitStorageReader.setBuffer(chunkPacketInfoAntiXray.getBuffer());
bitStorageWriter.setBuffer(chunkPacketInfoAntiXray.getBuffer());
int numberOfBlocks = presetBlockStateBits.length;
@@ -290,7 +380,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
int[] presetBlockStateBitsTemp;
if (chunkPacketInfoAntiXray.getPalette(chunkSectionIndex) instanceof GlobalPalette) {
- if (engineMode == EngineMode.HIDE) {
+ /*if (engineMode == EngineMode.HIDE) {
switch (level.getWorld().getEnvironment()) {
case NETHER:
presetBlockStateBitsTemp = presetBlockStateBitsNetherrackGlobal;
@@ -301,9 +391,9 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
default:
presetBlockStateBitsTemp = chunkSectionIndex + chunk.getMinSection() < 0 ? presetBlockStateBitsDeepslateGlobal : presetBlockStateBitsStoneGlobal;
}
- } else {
+ } else {*/
presetBlockStateBitsTemp = presetBlockStateBitsGlobal;
- }
+ //}
} else {
// If it's presetBlockStates, use this.presetBlockStatesFull instead
BlockState[] presetBlockStatesFull = chunkPacketInfoAntiXray.getPresetValues(chunkSectionIndex) == presetBlockStates ? this.presetBlockStatesFull : chunkPacketInfoAntiXray.getPresetValues(chunkSectionIndex);
@@ -340,7 +430,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
// Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section
bitStorageWriter.setBits(0);
- obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, -1, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, traceCache, emptyNearbyChunkSections, random, blocks);
+ obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, -1, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, obfuscateCache, traceCache, emptyNearbyChunkSections, random, blocks);
}
bitStorageWriter.setBits(chunkPacketInfoAntiXray.getBits(chunkSectionIndex));
@@ -355,7 +445,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
current = next;
next = nextNext;
nextNext = temp;
- obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, y, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, traceCache, nearbyChunkSections, random, blocks);
+ obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, y, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, obfuscateCache, traceCache, nearbyChunkSections, random, blocks);
}
// Check if the chunk section above doesn't need obfuscation
@@ -378,7 +468,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
// There is nothing to read anymore
bitStorageReader.setBits(0);
solid[0] = true;
- obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, 15, bitStorageReader, bitStorageWriter, solid, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, traceCache, nearbyChunkSections, random, blocks);
+ obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, 15, bitStorageReader, bitStorageWriter, solid, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, obfuscateCache, traceCache, nearbyChunkSections, random, blocks);
} else {
// If not, initialize the reader and other stuff for the chunk section above to obfuscate the upper layer of the current chunk section
bitStorageReader.setBits(chunkPacketInfoAntiXray.getBits(chunkSectionIndex + 1));
@@ -390,7 +480,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
current = next;
next = nextNext;
nextNext = temp;
- obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, 15, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, traceCache, nearbyChunkSections, random, blocks);
+ obfuscateLayer(chunk.getPos(), chunk.getMinSection(), chunkSectionIndex, 15, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, obfuscateCache, traceCache, nearbyChunkSections, random, blocks);
}
bitStorageWriter.flush();
@@ -404,7 +494,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
chunkPacketInfoAntiXray.getChunkPacket().setReady(true);
}
- private void obfuscateLayer(ChunkPos chunkPos, int minSection, int chunkSectionIndex, int y, BitStorageReader bitStorageReader, BitStorageWriter bitStorageWriter, boolean[] solid, boolean[] obfuscate, boolean[] trace, int[] presetBlockStateBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, boolean[][] traceCache, LevelChunkSection[] nearbyChunkSections, IntSupplier random, Collection<? super BlockPos> blocks) {
+ private void obfuscateLayer(ChunkPos chunkPos, int minSection, int chunkSectionIndex, int y, BitStorageReader bitStorageReader, BitStorageWriter bitStorageWriter, boolean[] solid, int[] obfuscate, int[] trace, int[] presetBlockStateBits, boolean[][] current, boolean[][] next, boolean[][] nextNext, int[][] obfuscateCache, boolean[][] traceCache, LevelChunkSection[] nearbyChunkSections, IntSupplier random, Collection<? super BlockPos> blocks) {
int minX = chunkPos.getMinBlockX();
int minZ = chunkPos.getMinBlockZ();
int realY = (chunkSectionIndex + minSection << 4) + y;
@@ -413,7 +503,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[0][0] = !solid[bits]) {
if (traceCache[0][0] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][0]]); // Exposed to air
blocks.add(new BlockPos(minX + 0, realY, minZ + 0));
} else {
bitStorageWriter.skip();
@@ -424,23 +514,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[0][0] || isTransparent(nearbyChunkSections[2], 0, y, 15) || isTransparent(nearbyChunkSections[0], 15, y, 0)) {
if (traceCache[0][0] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][0]]); // Exposed to air
blocks.add(new BlockPos(minX + 0, realY, minZ + 0));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][0]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ int obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[0][0] = obfuscateValue;
traceCache[0][0] = true;
} else {
traceCache[0][0] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[0][0] = true;
+ } else {
+ obfuscateCache[0][0] = obfuscateValue;
}
}
@@ -450,7 +546,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[0][x] = !solid[bits]) {
if (traceCache[0][x] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][x]]); // Exposed to air
blocks.add(new BlockPos(minX + x, realY, minZ + 0));
} else {
bitStorageWriter.skip();
@@ -462,23 +558,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[0][x] || isTransparent(nearbyChunkSections[2], x, y, 15)) {
if (traceCache[0][x] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][x]]); // Exposed to air
blocks.add(new BlockPos(minX + x, realY, minZ + 0));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][x]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[0][x] = obfuscateValue;
traceCache[0][x] = true;
} else {
traceCache[0][x] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[0][x] = true;
+ } else {
+ obfuscateCache[0][x] = obfuscateValue;
}
}
}
@@ -488,7 +590,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[0][15] = !solid[bits]) {
if (traceCache[0][15] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][15]]); // Exposed to air
blocks.add(new BlockPos(minX + 15, realY, minZ + 0));
} else {
bitStorageWriter.skip();
@@ -499,23 +601,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[0][15] || isTransparent(nearbyChunkSections[2], 15, y, 15) || isTransparent(nearbyChunkSections[1], 0, y, 0)) {
if (traceCache[0][15] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][15]]); // Exposed to air
blocks.add(new BlockPos(minX + 15, realY, minZ + 0));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[0][15]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[0][15] = obfuscateValue;
traceCache[0][15] = true;
} else {
traceCache[0][15] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[0][15] = true;
+ } else {
+ obfuscateCache[0][15] = obfuscateValue;
}
}
@@ -526,7 +634,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[z][0] = !solid[bits]) {
if (traceCache[z][0] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][0]]); // Exposed to air
blocks.add(new BlockPos(minX + 0, realY, minZ + z));
} else {
bitStorageWriter.skip();
@@ -538,23 +646,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[z][0] || isTransparent(nearbyChunkSections[0], 15, y, z)) {
if (traceCache[z][0] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][0]]); // Exposed to air
blocks.add(new BlockPos(minX + 0, realY, minZ + z));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][0]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[z][0] = obfuscateValue;
traceCache[z][0] = true;
} else {
traceCache[z][0] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[z][0] = true;
+ } else {
+ obfuscateCache[z][0] = obfuscateValue;
}
}
@@ -564,7 +678,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[z][x] = !solid[bits]) {
if (traceCache[z][x] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][x]]); // Exposed to air
blocks.add(new BlockPos(minX + x, realY, minZ + z));
} else {
bitStorageWriter.skip();
@@ -577,23 +691,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[z][x]) {
if (traceCache[z][x] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][x]]); // Exposed to air
blocks.add(new BlockPos(minX + x, realY, minZ + z));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][x]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[z][x] = obfuscateValue;
traceCache[z][x] = true;
} else {
traceCache[z][x] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[z][x] = true;
+ } else {
+ obfuscateCache[z][x] = obfuscateValue;
}
}
}
@@ -603,7 +723,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[z][15] = !solid[bits]) {
if (traceCache[z][15] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][15]]); // Exposed to air
blocks.add(new BlockPos(minX + 15, realY, minZ + z));
} else {
bitStorageWriter.skip();
@@ -615,23 +735,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[z][15] || isTransparent(nearbyChunkSections[1], 0, y, z)) {
if (traceCache[z][15] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][15]]); // Exposed to air
blocks.add(new BlockPos(minX + 15, realY, minZ + z));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[z][15]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[z][15] = obfuscateValue;
traceCache[z][15] = true;
} else {
traceCache[z][15] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[z][15] = true;
+ } else {
+ obfuscateCache[z][15] = obfuscateValue;
}
}
}
@@ -641,7 +767,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[15][0] = !solid[bits]) {
if (traceCache[15][0] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][0]]); // Exposed to air
blocks.add(new BlockPos(minX + 0, realY, minZ + 15));
} else {
bitStorageWriter.skip();
@@ -652,23 +778,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[15][0] || isTransparent(nearbyChunkSections[3], 0, y, 0) || isTransparent(nearbyChunkSections[0], 15, y, 15)) {
if (traceCache[15][0] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][0]]); // Exposed to air
blocks.add(new BlockPos(minX + 0, realY, minZ + 15));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][0]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[15][0] = obfuscateValue;
traceCache[15][0] = true;
} else {
traceCache[15][0] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[15][0] = true;
+ } else {
+ obfuscateCache[15][0] = obfuscateValue;
}
}
@@ -678,7 +810,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[15][x] = !solid[bits]) {
if (traceCache[15][x] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][x]]); // Exposed to air
blocks.add(new BlockPos(minX + x, realY, minZ + 15));
} else {
bitStorageWriter.skip();
@@ -690,23 +822,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[15][x] || isTransparent(nearbyChunkSections[3], x, y, 0)) {
if (traceCache[15][x] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][x]]); // Exposed to air
blocks.add(new BlockPos(minX + x, realY, minZ + 15));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][x]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[15][x] = obfuscateValue;
traceCache[15][x] = true;
} else {
traceCache[15][x] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[15][x] = true;
+ } else {
+ obfuscateCache[15][x] = obfuscateValue;
}
}
}
@@ -716,7 +854,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
if (nextNext[15][15] = !solid[bits]) {
if (traceCache[15][15] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][15]]); // Exposed to air
blocks.add(new BlockPos(minX + 15, realY, minZ + 15));
} else {
bitStorageWriter.skip();
@@ -727,23 +865,29 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
} else {
if (current[15][15] || isTransparent(nearbyChunkSections[3], 15, y, 0) || isTransparent(nearbyChunkSections[1], 0, y, 15)) {
if (traceCache[15][15] && blocks.size() < maxRayTraceBlockCountPerChunk) {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][15]]); // Exposed to air
blocks.add(new BlockPos(minX + 15, realY, minZ + 15));
} else {
bitStorageWriter.skip();
}
} else {
- bitStorageWriter.write(presetBlockStateBits[random.getAsInt()]); // Not exposed to air
+ bitStorageWriter.write(presetBlockStateBits[obfuscateCache[15][15]]); // Not exposed to air
}
}
- if (trace[bits]) {
+ obfuscateValue = trace[bits];
+
+ if (obfuscateValue != -1) {
+ obfuscateCache[15][15] = obfuscateValue;
traceCache[15][15] = true;
} else {
traceCache[15][15] = false;
+ obfuscateValue = obfuscate[bits];
- if (!obfuscate[bits]) {
+ if (obfuscateValue == -1) {
next[15][15] = true;
+ } else {
+ obfuscateCache[15][15] = obfuscateValue;
}
}
}
@@ -782,6 +926,25 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
return temp;
}
+ private int[] readPalette(Palette<BlockState> palette, int[] temp, int[] global) {
+ if (palette instanceof GlobalPalette) {
+ return global;
+ }
+
+ try {
+ for (int i = 0; i < palette.getSize(); i++) {
+ temp[i] = global[GLOBAL_BLOCKSTATE_PALETTE.idFor(palette.valueFor(i))];
+ }
+ } catch (MissingPaletteEntryException e) {
+ // Race condition / visibility issue / no happens-before relationship
+ // We don't care because we at least see the state as it was when the chunk packet was created
+ // Internal implementation details of PalettedContainer, LinearPalette, HashMapPalette, CrudeIncrementalIntIdentityHashBiMap, ... guarantee us that no (other) exceptions will occur until we have all the data that we need here
+ // Since all palettes have a fixed initial maximum size and there is no internal restructuring and no values are removed from palettes, we are also guaranteed to see the data
+ }
+
+ return temp;
+ }
+
@Override
public void onBlockChange(Level level, BlockPos blockPos, BlockState newBlockState, BlockState oldBlockState, int flags, int maxUpdateDepth) {
if (oldBlockState != null && solidGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(oldBlockState)] && !solidGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(newBlockState)] && blockPos.getY() <= maxBlockHeightUpdatePosition) {
@@ -838,7 +1001,7 @@ public final class ChunkPacketBlockControllerAntiXray extends ChunkPacketBlockCo
public void updateBlock(Level level, BlockPos blockPos) {
BlockState blockState = level.getBlockStateIfLoaded(blockPos);
- if (blockState != null && obfuscateGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)]) {
+ if (blockState != null && obfuscateGlobal[GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] != -1) {
((ServerLevel) level).getChunkSource().blockChanged(blockPos);
}
}