Finish initial implementation of logic
Pull Request Build / Build (pull_request) Failing after 56s

This commit is contained in:
D4rkr34lm
2026-05-19 22:47:22 +02:00
parent cf7a1ee086
commit 32a2cbb4dd
2 changed files with 56 additions and 154 deletions
@@ -56,11 +56,19 @@ public abstract class ChunkHider {
private final int SECTION_SPAN_SIZE = 16;
private final byte BIT_PER_BLOCK_INDIRECTION_LIMIT = 8;
private final int BLOCKS_PER_SECTION = 4096;
private final int BIOMES_PER_SECTION = 64;
private final byte BITS_PER_LONG = 64;
private long[] readSectionDataFromBuffer(ByteBuf dataSource, byte bitsPerEntry, int entryCount) {
private final int blockIdUsedForHiding;
public ChunkHider(Block blockUsedForObfuscation) {
blockIdUsedForHiding = Block.BLOCK_STATE_REGISTRY.getId(blockUsedForObfuscation.defaultBlockState());
}
private long[] readSectionDataFromBuffer(ByteBuf dataSource, short bitsPerEntry, int entryCount) {
int entriesPerLong = BITS_PER_LONG / bitsPerEntry;
int dataLengthAsLongCount = (entryCount + entriesPerLong - 1) / entriesPerLong;
@@ -73,7 +81,7 @@ public abstract class ChunkHider {
return dataArray;
}
public ClientboundLevelChunkWithLightPacket chunkHiderGenerator(Player player, ClientboundLevelChunkWithLightPacket packet) {
public ClientboundLevelChunkWithLightPacket processLevelChunkWithLightPacket(Player player, ClientboundLevelChunkWithLightPacket packet) {
int chunkX = packet.getX();
int chunkZ = packet.getZ();
ClientboundLevelChunkPacketData chunkData = packet.getChunkData();
@@ -85,15 +93,16 @@ public abstract class ChunkHider {
int worldMaxHeight = player.getWorld().getMaxHeight();
for (int yOffset = worldMinHeight; yOffset < worldMaxHeight; yOffset += SECTION_SPAN_SIZE) {
// TODO make configurable
int blockIdUsedForHiding = 121;
short blockCount = in.readShort();
byte bitsPerBlock = in.readByte();
if(bitsPerBlock == 0) {
int sectionBlockId = ProtocolUtils.readVarInt(in);
out.writeShort(blockCount);
out.writeByte(bitsPerBlock);
ProtocolUtils.writeVarInt(out, sectionBlockId);
}
else if (bitsPerBlock <= BIT_PER_BLOCK_INDIRECTION_LIMIT) {
int palletLength = ProtocolUtils.readVarInt(in);
@@ -205,6 +214,7 @@ public abstract class ChunkHider {
}
}
copyOverSectionBiomeData(in, out);
}
if (in.readableBytes() != 0) {
@@ -258,159 +268,34 @@ public abstract class ChunkHider {
}).toList();
}
private void biomes(SectionHider section) {
section.copyBitsPerBlock();
if (section.getBitsPerBlock() == 0) {
section.copyVarInt();
} else if (section.getBitsPerBlock() < 6) {
section.skipPalette();
section.skipNewDataArray(64);
} else {
// Direct (global) biome IDs no palette present
section.skipNewDataArray(64);
private void copyOverSectionBiomeData(ByteBuf oldData, ByteBuf newData){
short bitsPerBiome = oldData.readShort();
newData.writeShort(bitsPerBiome);
if(bitsPerBiome == 0) {
int sectionBiomeId = ProtocolUtils.readVarInt(oldData);
ProtocolUtils.writeVarInt(newData, sectionBiomeId);
}
}
else if(bitsPerBiome <= BIT_PER_BLOCK_INDIRECTION_LIMIT) {
int palletLength = ProtocolUtils.readVarInt(oldData);
ProtocolUtils.writeVarInt(newData, palletLength);
@Getter
class SectionHider {
private final Player player;
private final ByteBuf in;
private final ByteBuf out;
for(int i = 0; i < palletLength; i++) {
int palletEntry = ProtocolUtils.readVarInt(oldData);
ProtocolUtils.writeVarInt(newData, palletEntry);
}
private final int chunkX;
private final int chunkY;
private final int chunkZ;
private final int offsetX;
private final int offsetY;
private final int offsetZ;
private boolean paletted;
private int bitsPerBlock;
private int blockCount;
private int air;
private int target;
private Set<Integer> blockIdsToObfuscate;
private final int blockIdToObfuscateTo;
public SectionHider(Player player, ByteBuf in, ByteBuf out, int chunkX, int chunkY, int chunkZ) {
this.player = player;
this.in = in;
this.out = out;
this.chunkX = chunkX;
this.chunkY = chunkY;
this.chunkZ = chunkZ;
this.offsetX = 16 * chunkX;
this.offsetY = 16 * chunkY;
this.offsetZ = 16 * chunkZ;
this.skipSection = techHider.getLocationEvaluator().skipChunkSection(player, chunkX, chunkY, chunkZ);
this.paletted = false;
this.bitsPerBlock = 0;
this.air = TechHider.AIR_ID;
this.target = techHider.getObfuscationTargetId();
this.obfuscate = techHider.getObfuscateIds();
long[] rawData = readSectionDataFromBuffer(oldData, bitsPerBiome, BIOMES_PER_SECTION);
for(long rawDataSegment : rawData ) {
newData.writeLong(rawDataSegment);
}
}
public boolean blockPrecise() {
return techHider.getLocationEvaluator().blockPrecise(player, chunkX, chunkY, chunkZ);
}
public TechHider.State test(int x, int y, int z) {
return techHider.getLocationEvaluator().check(player, offsetX + x, offsetY + y, offsetZ + z);
}
public void copyBlockCount() {
this.blockCount = in.readShort();
out.writeShort(blockCount);
}
public void copyBitsPerBlock() {
bitsPerBlock = in.readByte();
out.writeByte(bitsPerBlock);
}
public int copyVarInt() {
int value = ProtocolUtils.readVarInt(in);
ProtocolUtils.writeVarInt(out, value);
return value;
}
public void skipPalette() {
int paletteLength = copyVarInt();
for (int i = 0; i < paletteLength; i++) {
copyVarInt();
else {
long[] rawData = readSectionDataFromBuffer(oldData, bitsPerBiome, BIOMES_PER_SECTION);
for(long rawDataSegment : rawData ) {
newData.writeLong(rawDataSegment);
}
}
public void processPalette() {
int paletteLength = copyVarInt();
if (paletteLength == 0) return;
paletted = true;
air = 0;
target = 0;
for (int i = 0; i < paletteLength; i++) {
int entry = ProtocolUtils.readVarInt(in);
if (obfuscate.contains(entry)) {
entry = techHider.getObfuscationTargetId();
}
if (entry == TechHider.AIR_ID) {
air = i;
} else if (entry == techHider.getObfuscationTargetId()) {
target = i;
}
ProtocolUtils.writeVarInt(out, entry);
}
blockIdsToObfuscate = Collections.emptySet();
}
public void skipDataArray() {
int dataArrayLength = copyVarInt();
out.writeBytes(in, dataArrayLength * 8);
}
public void skipNewDataArray(int entries) {
if (bitsPerBlock == 0) {
return;
}
char valuesPerLong = (char) (64 / bitsPerBlock);
int i1 = (entries + valuesPerLong - 1) / valuesPerLong;
out.writeBytes(in, i1 * Long.BYTES);
}
public long[] readDataArray() {
long[] array = new long[copyVarInt()];
for (int i = 0; i < array.length; i++) {
array[i] = in.readLong();
}
return array;
}
public long[] readNewDataArray(int entries) {
if (bitsPerBlock == 0) {
return new long[entries];
}
char valuesPerLong = (char) (64 / bitsPerBlock);
int i1 = (entries + valuesPerLong - 1) / valuesPerLong;
long[] array = new long[i1];
for (int i = 0; i < i1; i++) {
array[i] = in.readLong();
}
return array;
}
public void writeDataArray(long[] array) {
for (long l : array) {
out.writeLong(l);
}
}
}
}
@@ -186,12 +186,30 @@ public abstract class TechHider {
private final Block blockUsedForObfuscation;
private final BlockState blockStateUsedForObfuscation;
private ChunkHider chunkHider;
// TODO handle packet bundle
public TechHider(Plugin plugin, Block blockUsedForObfuscation) {
this.blockUsedForObfuscation = blockUsedForObfuscation;
this.blockStateUsedForObfuscation = blockUsedForObfuscation.defaultBlockState();
this.chunkHider = new ChunkHider(blockUsedForObfuscation) {
@Override
public boolean isPlayerPrivilegedToAccessBlock(Player p, int blockX, int blockY, int blockZ, Block block) {
return TechHider.this.isPlayerPrivilegedToAccessBlock(p, blockX, blockY, blockZ, block);
}
@Override
public boolean isPlayerPrivilegedToAccessBlockEntity(Player p, int blockX, int blockY, int blockZ, BlockEntityType<?> type) {
return TechHider.this.isPlayerPrivilegedToAccessBlocEntity(p, blockX, blockY, blockZ, type);
}
@Override
public boolean isPlayerPrivilegedToAccessPosition(Player p, int blockX, int blockY, int blockZ) {
return TechHider.this.isPlayerPrivilegedToAccessPosition(p, blockX, blockY, blockZ);
}
};
this.bypassingPackets = new HashSet<>(List.of(
// --- 5.1.x Login Protocol ---
ClientboundLoginDisconnectPacket.class, // 5.1.1 Disconnect
@@ -621,9 +639,8 @@ public abstract class TechHider {
}
}
private final ChunkHider chunkHider = new ChunkHider();
private ClientboundLevelChunkWithLightPacket processChunkWithLight(Player p, ClientboundLevelChunkWithLightPacket packet) {
return chunkHider.processLevelChunkWithLightPacket(p, blockEntitiesToHide, this::isPlayerPrivilegedToAccessBlockPos, blockToObfuscateTo, blockIdsToObfuscate, packet);
return chunkHider.processLevelChunkWithLightPacket(p, packet);
}
private Packet<? extends PacketListener> processContainerPacket(Player player, int containerId, Packet<? extends PacketListener> packet) {