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);
}
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)));
}
}
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();
}
}
}
}
}
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;
}
Aggregations