use of com.destroystokyo.paper.antixray.BitStorageWriter in project RayTraceAntiXray by stonar96.
the class ChunkPacketBlockControllerAntiXray method obfuscate.
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();
boolean[][] current = CURRENT.get();
boolean[][] next = NEXT.get();
boolean[][] nextNext = NEXT_NEXT.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();
BitStorageWriter bitStorageWriter = new BitStorageWriter();
LevelChunkSection[] nearbyChunkSections = new LevelChunkSection[4];
LevelChunk chunk = chunkPacketInfoAntiXray.getChunk();
Level level = chunk.getLevel();
int maxChunkSectionIndex = Math.min((maxBlockHeight >> 4) - chunk.getMinSection(), chunk.getSectionsCount() - 1);
boolean[] solidTemp = null;
boolean[] obfuscateTemp = null;
boolean[] traceTemp = null;
bitStorageReader.setBuffer(chunkPacketInfoAntiXray.getBuffer());
bitStorageWriter.setBuffer(chunkPacketInfoAntiXray.getBuffer());
int numberOfBlocks = presetBlockStateBits.length;
// Keep the lambda expressions as simple as possible. They are used very frequently.
IntSupplier random = numberOfBlocks == 1 ? (() -> 0) : new IntSupplier() {
private int state;
{
while ((state = ThreadLocalRandom.current().nextInt()) == 0) ;
}
@Override
public int getAsInt() {
// https://en.wikipedia.org/wiki/Xorshift
state ^= state << 13;
state ^= state >>> 17;
state ^= state << 5;
// https://www.pcg-random.org/posts/bounded-rands.html
return (int) ((Integer.toUnsignedLong(state) * numberOfBlocks) >>> 32);
}
};
Collection<BlockPos> blocks = new HashSet<>();
for (int chunkSectionIndex = 0; chunkSectionIndex <= maxChunkSectionIndex; chunkSectionIndex++) {
if (chunkPacketInfoAntiXray.isWritten(chunkSectionIndex) && chunkPacketInfoAntiXray.getPresetValues(chunkSectionIndex) != null) {
int[] presetBlockStateBitsTemp;
if (chunkPacketInfoAntiXray.getPalette(chunkSectionIndex) instanceof GlobalPalette) {
if (engineMode == EngineMode.HIDE) {
switch(level.getWorld().getEnvironment()) {
case NETHER:
presetBlockStateBitsTemp = presetBlockStateBitsNetherrackGlobal;
break;
case THE_END:
presetBlockStateBitsTemp = presetBlockStateBitsEndStoneGlobal;
break;
default:
presetBlockStateBitsTemp = presetBlockStateBitsStoneGlobal;
}
} else {
presetBlockStateBitsTemp = presetBlockStateBitsGlobal;
}
} else {
// If it's presetBlockStates, use this.presetBlockStatesFull instead
BlockState[] presetBlockStatesFull = chunkPacketInfoAntiXray.getPresetValues(chunkSectionIndex) == presetBlockStates ? this.presetBlockStatesFull : chunkPacketInfoAntiXray.getPresetValues(chunkSectionIndex);
presetBlockStateBitsTemp = presetBlockStateBits;
for (int i = 0; i < presetBlockStateBitsTemp.length; i++) {
// This is thread safe because we only request IDs that are guaranteed to be in the palette and are visible
// For more details see the comments in the readPalette method
presetBlockStateBitsTemp[i] = chunkPacketInfoAntiXray.getPalette(chunkSectionIndex).idFor(presetBlockStatesFull[i]);
}
}
bitStorageWriter.setIndex(chunkPacketInfoAntiXray.getIndex(chunkSectionIndex));
// Check if the chunk section below was not obfuscated
if (chunkSectionIndex == 0 || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex - 1) || chunkPacketInfoAntiXray.getPresetValues(chunkSectionIndex - 1) == null) {
// If so, initialize some stuff
bitStorageReader.setBits(chunkPacketInfoAntiXray.getBits(chunkSectionIndex));
bitStorageReader.setIndex(chunkPacketInfoAntiXray.getIndex(chunkSectionIndex));
solidTemp = readPalette(chunkPacketInfoAntiXray.getPalette(chunkSectionIndex), solid, solidGlobal);
obfuscateTemp = readPalette(chunkPacketInfoAntiXray.getPalette(chunkSectionIndex), obfuscate, obfuscateGlobal);
traceTemp = trace == obfuscate ? obfuscateTemp : readPalette(chunkPacketInfoAntiXray.getPalette(chunkSectionIndex), trace, traceGlobal);
// Read the blocks of the upper layer of the chunk section below if it exists
LevelChunkSection belowChunkSection = null;
boolean skipFirstLayer = chunkSectionIndex == 0 || (belowChunkSection = chunk.getSections()[chunkSectionIndex - 1]) == EMPTY_SECTION;
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
current[z][x] = true;
next[z][x] = skipFirstLayer || isTransparent(belowChunkSection, x, 15, z);
traceCache[z][x] = false;
}
}
// Abuse the obfuscateLayer method to read the blocks of the first layer of the current chunk section
bitStorageWriter.setBits(0);
obfuscateLayer(chunk.getMinSection(), chunkSectionIndex, -1, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, traceCache, emptyNearbyChunkSections, random, blocks);
}
bitStorageWriter.setBits(chunkPacketInfoAntiXray.getBits(chunkSectionIndex));
nearbyChunkSections[0] = chunkPacketInfoAntiXray.getNearbyChunks()[0] == null ? EMPTY_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[0].getSections()[chunkSectionIndex];
nearbyChunkSections[1] = chunkPacketInfoAntiXray.getNearbyChunks()[1] == null ? EMPTY_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[1].getSections()[chunkSectionIndex];
nearbyChunkSections[2] = chunkPacketInfoAntiXray.getNearbyChunks()[2] == null ? EMPTY_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[2].getSections()[chunkSectionIndex];
nearbyChunkSections[3] = chunkPacketInfoAntiXray.getNearbyChunks()[3] == null ? EMPTY_SECTION : chunkPacketInfoAntiXray.getNearbyChunks()[3].getSections()[chunkSectionIndex];
// Obfuscate all layers of the current chunk section except the upper one
for (int y = 0; y < 15; y++) {
boolean[][] temp = current;
current = next;
next = nextNext;
nextNext = temp;
obfuscateLayer(chunk.getMinSection(), chunkSectionIndex, y, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, traceCache, nearbyChunkSections, random, blocks);
}
// Check if the chunk section above doesn't need obfuscation
if (chunkSectionIndex == maxChunkSectionIndex || !chunkPacketInfoAntiXray.isWritten(chunkSectionIndex + 1) || chunkPacketInfoAntiXray.getPresetValues(chunkSectionIndex + 1) == null) {
// If so, obfuscate the upper layer of the current chunk section by reading blocks of the first layer from the chunk section above if it exists
LevelChunkSection aboveChunkSection = chunkSectionIndex == chunk.getSectionsCount() - 1 ? EMPTY_SECTION : chunk.getSections()[chunkSectionIndex + 1];
boolean[][] temp = current;
current = next;
next = nextNext;
nextNext = temp;
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
if (aboveChunkSection == EMPTY_SECTION || isTransparent(aboveChunkSection, x, 0, z)) {
current[z][x] = true;
}
}
}
// There is nothing to read anymore
bitStorageReader.setBits(0);
solid[0] = true;
obfuscateLayer(chunk.getMinSection(), chunkSectionIndex, 15, bitStorageReader, bitStorageWriter, solid, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, 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));
bitStorageReader.setIndex(chunkPacketInfoAntiXray.getIndex(chunkSectionIndex + 1));
solidTemp = readPalette(chunkPacketInfoAntiXray.getPalette(chunkSectionIndex + 1), solid, solidGlobal);
obfuscateTemp = readPalette(chunkPacketInfoAntiXray.getPalette(chunkSectionIndex + 1), obfuscate, obfuscateGlobal);
traceTemp = trace == obfuscate ? obfuscateTemp : readPalette(chunkPacketInfoAntiXray.getPalette(chunkSectionIndex + 1), trace, traceGlobal);
boolean[][] temp = current;
current = next;
next = nextNext;
nextNext = temp;
obfuscateLayer(chunk.getMinSection(), chunkSectionIndex, 15, bitStorageReader, bitStorageWriter, solidTemp, obfuscateTemp, traceTemp, presetBlockStateBitsTemp, current, next, nextNext, traceCache, nearbyChunkSections, random, blocks);
}
bitStorageWriter.flush();
}
}
if (plugin.isRunning()) {
plugin.getPacketChunkBlocksCache().put(chunkPacketInfoAntiXray.getChunkPacket(), new ChunkBlocks(chunkPacketInfoAntiXray.getChunk(), blocks));
}
chunkPacketInfoAntiXray.getChunkPacket().setReady(true);
}
Aggregations