Search in sources :

Example 1 with ChunkBlocks

use of com.vanillage.raytraceantixray.data.ChunkBlocks 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)

Example 2 with ChunkBlocks

use of com.vanillage.raytraceantixray.data.ChunkBlocks in project RayTraceAntiXray by stonar96.

the class PacketListener method onPacketSending.

@Override
public void onPacketSending(PacketEvent event) {
    if (event.getPacketType() == PacketType.Play.Server.MAP_CHUNK) {
        PlayerData playerData = plugin.getPlayerData().get(event.getPlayer().getUniqueId());
        ChunkBlocks chunkBlocks = plugin.getPacketChunkBlocksCache().get(event.getPacket().getHandle());
        if (chunkBlocks == null) {
            Location location = event.getPlayer().getEyeLocation();
            if (!location.getWorld().equals(playerData.getLocations().get(0).getWorld())) {
                playerData = new PlayerData(plugin.getLocations(event.getPlayer(), location));
                plugin.getPlayerData().put(event.getPlayer().getUniqueId(), playerData);
            }
            // Not enabled in this world.
            return;
        }
        LevelChunk chunk = chunkBlocks.getChunk();
        if (chunk == null) {
            return;
        }
        if (!chunk.getLevel().getWorld().equals(playerData.getLocations().get(0).getWorld())) {
            Location location = event.getPlayer().getEyeLocation();
            if (!chunk.getLevel().getWorld().equals(location.getWorld())) {
                // The packet can be ignored.
                return;
            }
            playerData = new PlayerData(plugin.getLocations(event.getPlayer(), location));
            plugin.getPlayerData().put(event.getPlayer().getUniqueId(), playerData);
        }
        playerData.getChunks().put(chunk.getPos(), chunkBlocks);
    } else if (event.getPacketType() == PacketType.Play.Server.UNLOAD_CHUNK) {
        StructureModifier<Integer> integers = event.getPacket().getIntegers();
        plugin.getPlayerData().get(event.getPlayer().getUniqueId()).getChunks().remove(new ChunkPos(integers.read(0), integers.read(1)));
    }
}
Also used : LevelChunk(net.minecraft.world.level.chunk.LevelChunk) StructureModifier(com.comphenix.protocol.reflect.StructureModifier) ChunkBlocks(com.vanillage.raytraceantixray.data.ChunkBlocks) ChunkPos(net.minecraft.world.level.ChunkPos) PlayerData(com.vanillage.raytraceantixray.data.PlayerData) Location(org.bukkit.Location)

Example 3 with ChunkBlocks

use of com.vanillage.raytraceantixray.data.ChunkBlocks in project RayTraceAntiXray by stonar96.

the class RayTraceRunnable method run.

@Override
public void run() {
    List<? extends Location> locations = playerData.getLocations();
    Location playerLocation = locations.get(0);
    ChunkPacketBlockController chunkPacketBlockController = ((CraftWorld) playerLocation.getWorld()).getHandle().chunkPacketBlockController;
    if (!(chunkPacketBlockController instanceof ChunkPacketBlockControllerAntiXray)) {
        return;
    }
    boolean[] solidGlobal = ((ChunkPacketBlockControllerAntiXray) chunkPacketBlockController).solidGlobal;
    double rayTraceDistance = Math.max(plugin.getConfig().getDouble("world-settings." + playerLocation.getWorld().getName() + ".anti-xray.ray-trace-distance", plugin.getConfig().getDouble("world-settings.default.anti-xray.ray-trace-distance")), 0.);
    Location temp = playerLocation.clone();
    temp.setX(playerLocation.getX() - rayTraceDistance);
    temp.setZ(playerLocation.getZ() - rayTraceDistance);
    int chunkXMin = temp.getBlockX() >> 4;
    int chunkZMin = temp.getBlockZ() >> 4;
    temp.setX(playerLocation.getX() + rayTraceDistance);
    temp.setZ(playerLocation.getZ() + rayTraceDistance);
    int chunkXMax = temp.getBlockX() >> 4;
    int chunkZMax = temp.getBlockZ() >> 4;
    double rayTraceDistanceSquared = rayTraceDistance * rayTraceDistance;
    for (Location location : locations) {
        Vector vector = location.toVector();
        Vector direction = location.getDirection();
        for (Entry<ChunkPos, ChunkBlocks> chunkEntry : playerData.getChunks().entrySet()) {
            ChunkBlocks chunkBlocks = chunkEntry.getValue();
            LevelChunk chunk = chunkBlocks.getChunk();
            if (chunk == null) {
                playerData.getChunks().remove(chunkEntry.getKey(), chunkBlocks);
                continue;
            }
            if (chunk.locX < chunkXMin || chunk.locX > chunkXMax || chunk.locZ < chunkZMin || chunk.locZ > chunkZMax) {
                continue;
            }
            Iterator<? extends BlockPos> iterator = chunkBlocks.getBlocks().iterator();
            while (iterator.hasNext()) {
                BlockPos block = iterator.next();
                block = new BlockPos((chunk.locX << 4) + block.getX(), block.getY(), (chunk.locZ << 4) + block.getZ());
                Vector blockCenter = new Vector(block.getX() + 0.5, block.getY() + 0.5, block.getZ() + 0.5);
                Vector difference = vector.clone().subtract(blockCenter);
                if (difference.lengthSquared() > rayTraceDistanceSquared || difference.dot(direction) > 0.) {
                    continue;
                }
                Iterator<BlockPos> blockIterator = new BlockIterator(blockCenter, vector);
                boolean update = true;
                while (blockIterator.hasNext()) {
                    BlockPos rayBlock = blockIterator.next();
                    ChunkPos chunkPos = new ChunkPos(rayBlock);
                    ChunkBlocks rayChunkBlocks = playerData.getChunks().get(chunkPos);
                    if (rayChunkBlocks == null) {
                        update = false;
                        break;
                    }
                    LevelChunk rayChunk = rayChunkBlocks.getChunk();
                    if (rayChunk == null) {
                        playerData.getChunks().remove(chunkPos, rayChunkBlocks);
                        update = false;
                        break;
                    }
                    int sectionY = rayBlock.getY() >> 4;
                    if (sectionY < rayChunk.getMinSection() || sectionY > rayChunk.getMaxSection() - 1) {
                        continue;
                    }
                    LevelChunkSection section = rayChunk.getSections()[sectionY - rayChunk.getMinSection()];
                    if (section == null || section.hasOnlyAir()) {
                        // Sections aren't null anymore.
                        continue;
                    }
                    BlockState blockState;
                    // section.getStates().acquire();
                    try {
                        blockState = section.getBlockState(rayBlock.getX() & 15, rayBlock.getY() & 15, rayBlock.getZ() & 15);
                    } catch (MissingPaletteEntryException e) {
                        blockState = Blocks.AIR.defaultBlockState();
                    }
                    if (solidGlobal[ChunkPacketBlockControllerAntiXray.GLOBAL_BLOCKSTATE_PALETTE.idFor(blockState)] && checkSurroundingBlocks(block.getX(), block.getY(), block.getZ(), rayBlock.getX(), rayBlock.getY(), rayBlock.getZ(), difference, section, chunkPos.x, sectionY, chunkPos.z, playerData, solidGlobal)) {
                        update = false;
                        break;
                    }
                }
                if (update) {
                    playerData.getResult().add(block);
                    iterator.remove();
                }
            }
        }
    }
}
Also used : BlockIterator(com.vanillage.raytraceantixray.util.BlockIterator) ChunkPacketBlockController(com.destroystokyo.paper.antixray.ChunkPacketBlockController) ChunkBlocks(com.vanillage.raytraceantixray.data.ChunkBlocks) ChunkPacketBlockControllerAntiXray(com.vanillage.raytraceantixray.antixray.ChunkPacketBlockControllerAntiXray) LevelChunk(net.minecraft.world.level.chunk.LevelChunk) BlockState(net.minecraft.world.level.block.state.BlockState) LevelChunkSection(net.minecraft.world.level.chunk.LevelChunkSection) MissingPaletteEntryException(net.minecraft.world.level.chunk.MissingPaletteEntryException) ChunkPos(net.minecraft.world.level.ChunkPos) BlockPos(net.minecraft.core.BlockPos) Vector(org.bukkit.util.Vector) Location(org.bukkit.Location)

Example 4 with ChunkBlocks

use of com.vanillage.raytraceantixray.data.ChunkBlocks in project RayTraceAntiXray by stonar96.

the class RayTraceRunnable method getBlockData.

private BlockState getBlockData(int x, int y, int z, LevelChunkSection expectedSection, int expectedChunkX, int expectedSectionY, int expectedChunkZ, PlayerData playerData) {
    int chunkX = x >> 4;
    int sectionY = y >> 4;
    int chunkZ = z >> 4;
    if (expectedChunkX != chunkX || expectedSectionY != sectionY || expectedChunkZ != chunkZ) {
        ChunkPos chunkPos = new ChunkPos(chunkX, chunkZ);
        ChunkBlocks chunkBlocks = playerData.getChunks().get(chunkPos);
        if (chunkBlocks == null) {
            return null;
        }
        LevelChunk chunk = chunkBlocks.getChunk();
        if (chunk == null) {
            playerData.getChunks().remove(chunkPos, chunkBlocks);
            return null;
        }
        if (sectionY < chunk.getMinSection() || sectionY > chunk.getMaxSection() - 1) {
            return Blocks.AIR.defaultBlockState();
        }
        expectedSection = chunk.getSections()[sectionY - chunk.getMinSection()];
        if (expectedSection == null || expectedSection.hasOnlyAir()) {
            // Sections aren't null anymore.
            return Blocks.AIR.defaultBlockState();
        }
    }
    BlockState blockState;
    // expectedSection.getStates().acquire();
    try {
        blockState = expectedSection.getBlockState(x & 15, y & 15, z & 15);
    } catch (MissingPaletteEntryException e) {
        blockState = Blocks.AIR.defaultBlockState();
    }
    return blockState;
}
Also used : LevelChunk(net.minecraft.world.level.chunk.LevelChunk) BlockState(net.minecraft.world.level.block.state.BlockState) MissingPaletteEntryException(net.minecraft.world.level.chunk.MissingPaletteEntryException) ChunkPos(net.minecraft.world.level.ChunkPos) ChunkBlocks(com.vanillage.raytraceantixray.data.ChunkBlocks)

Aggregations

ChunkBlocks (com.vanillage.raytraceantixray.data.ChunkBlocks)4 ChunkPos (net.minecraft.world.level.ChunkPos)3 BlockState (net.minecraft.world.level.block.state.BlockState)3 LevelChunk (net.minecraft.world.level.chunk.LevelChunk)3 BlockPos (net.minecraft.core.BlockPos)2 MissingPaletteEntryException (net.minecraft.world.level.chunk.MissingPaletteEntryException)2 Location (org.bukkit.Location)2 StructureModifier (com.comphenix.protocol.reflect.StructureModifier)1 BitStorageReader (com.destroystokyo.paper.antixray.BitStorageReader)1 BitStorageWriter (com.destroystokyo.paper.antixray.BitStorageWriter)1 ChunkPacketBlockController (com.destroystokyo.paper.antixray.ChunkPacketBlockController)1 ChunkPacketBlockControllerAntiXray (com.vanillage.raytraceantixray.antixray.ChunkPacketBlockControllerAntiXray)1 PlayerData (com.vanillage.raytraceantixray.data.PlayerData)1 BlockIterator (com.vanillage.raytraceantixray.util.BlockIterator)1 IntSupplier (java.util.function.IntSupplier)1 ServerLevel (net.minecraft.server.level.ServerLevel)1 Level (net.minecraft.world.level.Level)1 LevelChunkSection (net.minecraft.world.level.chunk.LevelChunkSection)1 Vector (org.bukkit.util.Vector)1