forked from SteamWar/SteamWar
Finish initial implementation of logic
This commit is contained in:
@@ -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);
|
||||
|
||||
for(int i = 0; i < palletLength; i++) {
|
||||
int palletEntry = ProtocolUtils.readVarInt(oldData);
|
||||
ProtocolUtils.writeVarInt(newData, palletEntry);
|
||||
}
|
||||
|
||||
long[] rawData = readSectionDataFromBuffer(oldData, bitsPerBiome, BIOMES_PER_SECTION);
|
||||
for(long rawDataSegment : rawData ) {
|
||||
newData.writeLong(rawDataSegment);
|
||||
}
|
||||
}
|
||||
else {
|
||||
long[] rawData = readSectionDataFromBuffer(oldData, bitsPerBiome, BIOMES_PER_SECTION);
|
||||
for(long rawDataSegment : rawData ) {
|
||||
newData.writeLong(rawDataSegment);
|
||||
}
|
||||
}
|
||||
|
||||
@Getter
|
||||
class SectionHider {
|
||||
private final Player player;
|
||||
private final ByteBuf in;
|
||||
private final ByteBuf out;
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user