Search in sources :

Example 1 with BitStorageWriter

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);
}
Also used : IntSupplier(java.util.function.IntSupplier) BitStorageReader(com.destroystokyo.paper.antixray.BitStorageReader) ChunkBlocks(com.vanillage.raytraceantixray.data.ChunkBlocks) BlockState(net.minecraft.world.level.block.state.BlockState) BitStorageWriter(com.destroystokyo.paper.antixray.BitStorageWriter) ServerLevel(net.minecraft.server.level.ServerLevel) Level(net.minecraft.world.level.Level) BlockPos(net.minecraft.core.BlockPos)

Aggregations

BitStorageReader (com.destroystokyo.paper.antixray.BitStorageReader)1 BitStorageWriter (com.destroystokyo.paper.antixray.BitStorageWriter)1 ChunkBlocks (com.vanillage.raytraceantixray.data.ChunkBlocks)1 IntSupplier (java.util.function.IntSupplier)1 BlockPos (net.minecraft.core.BlockPos)1 ServerLevel (net.minecraft.server.level.ServerLevel)1 Level (net.minecraft.world.level.Level)1 BlockState (net.minecraft.world.level.block.state.BlockState)1