TechHider refactoring, simple Blocktagging

This commit is contained in:
Lixfel
2024-12-21 16:53:49 +01:00
parent 1b47700c19
commit 793fc31b5c
16 changed files with 269 additions and 208 deletions
@@ -27,9 +27,7 @@ import net.minecraft.core.SectionPosition;
import net.minecraft.network.protocol.game.PacketPlayOutBlockChange;
import net.minecraft.network.protocol.game.PacketPlayOutMultiBlockChange;
import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.block.data.BlockData;
import java.util.ArrayList;
import java.util.List;
@@ -38,20 +36,13 @@ public class HullHiderWrapper18 implements HullHiderWrapper {
private static final Reflection.MethodInvoker getState = Reflection.getTypedMethod(Reflection.getClass("{obc}.block.data.CraftBlockData"), "getState", IBlockData.class);
@Override
public Object generateBlockChangePacket(List<Hull.IntVector> changes) {
List<Object> blockdata = new ArrayList<>(changes.size());
Object[] blockdata = new Object[changes.size()];
for(int i = 0; i < blockdata.length; i++) {
Hull.IntVector change = changes.get(i);
blockdata[i] = getState.invoke(Config.world.getBlockData(change.getX(), change.getY(), change.getZ()));
}
changes.removeIf(change -> {
BlockData data = Config.world.getBlockData(change.getX(), change.getY(), change.getZ());
boolean unchanged = data.getMaterial() == Config.ObfuscateWith || Config.HiddenBlocks.contains(data.getMaterial());
if(!unchanged)
blockdata.add(getState.invoke(data));
return unchanged;
});
if(changes.isEmpty())
return null;
return generateBlockChangePacket(changes, blockdata.toArray());
return generateBlockChangePacket(changes, blockdata);
}
private Object generateBlockChangePacket(List<Hull.IntVector> changes, Object[] blockdata) {
@@ -21,7 +21,6 @@ package de.steamwar.fightsystem.utils;
import com.comphenix.tinyprotocol.Reflection;
import de.steamwar.fightsystem.Config;
import org.bukkit.Material;
import java.util.List;
@@ -31,14 +30,6 @@ public class HullHiderWrapper8 implements HullHiderWrapper {
private static final Reflection.MethodInvoker getHandle = Reflection.getMethod("{obc}.CraftChunk", "getHandle");
@Override
public Object generateBlockChangePacket(List<Hull.IntVector> changes) {
changes.removeIf(change -> {
Material material = Config.world.getBlockAt(change.getX(), change.getY(), change.getZ()).getType();
return material == Config.ObfuscateWith || Config.HiddenBlocks.contains(material);
});
if(changes.isEmpty())
return null;
Hull.IntVector chunk = changes.get(0);
chunk = new Hull.IntVector(chunk.getX() >> 4, chunk.getY() >> 4, chunk.getZ() >> 4);
int xOffset = 16*chunk.getX();
@@ -187,9 +187,6 @@ public class Hull {
for (Map.Entry<IntVector, List<IntVector>> entry : sectionWise.entrySet()) {
Object packet = HullHiderWrapper.impl.generateBlockChangePacket(entry.getValue());
if(packet == null)
continue;
players.forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
}
}
@@ -112,7 +112,9 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati
public TechHider.State check(Player player, int x, int y, int z) {
if(hiddenRegion.computeIfAbsent(player, this::getHiddenRegion).inRegion(x, y, z)) {
if(FightSystem.getHullHider().isBlockHidden(player, x, y, z)) {
return TechHider.State.HIDE;
long pattern = player.getUniqueId().getLeastSignificantBits();
int id = ((y&3) << 4) + ((z&3) << 2) + (x&3);
return (pattern & (1L << id)) == 0 ? TechHider.State.HIDE : TechHider.State.HIDE_AIR;
} else {
return TechHider.State.CHECK;
}
@@ -19,24 +19,26 @@
package de.steamwar.techhider;
import io.netty.buffer.ByteBuf;
import java.util.Collections;
import java.util.Set;
public class ChunkHider14 extends ChunkHider9 {
@Override
protected void dataHider(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, boolean skip, boolean blockPrecise) {
out.writeShort(in.readShort()); // Block count
byte bitsPerBlock = in.readByte();
out.writeByte(bitsPerBlock);
protected void dataHider(SectionHider section) {
section.copyBlockCount();
section.copyBitsPerBlock();
if(bitsPerBlock < 9) {
obfuscationTarget = ChunkHider.processPalette(obfuscationTarget, obfuscate, in, out);
obfuscate = Collections.emptySet();
boolean hasPalette = section.getBitsPerBlock() < 9;
if(hasPalette)
section.processPalette();
if(section.isSkipSection()) {
section.skipDataArray();
} else {
if(hasPalette && !section.blockPrecise()) {
section.skipDataArray();
return;
}
processDataArray(section);
}
processDataArray(locationEvaluator, obfuscationTarget, obfuscate, in, out, bitsPerBlock, skip || (!blockPrecise && bitsPerBlock < 9));
}
}
@@ -20,31 +20,34 @@
package de.steamwar.techhider;
import com.comphenix.tinyprotocol.Reflection;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.function.UnaryOperator;
public class ProtocolWrapper14 extends ProtocolWrapper8 {
@Override
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
UnaryOperator<Object> blockBreakCloner = ProtocolUtils.shallowCloneGenerator(blockBreakPacket);
Reflection.FieldAccessor<?> blockBreakPosition = Reflection.getField(blockBreakPacket, TechHider.blockPosition, 0);
Reflection.FieldAccessor<?> blockBreakBlockData = Reflection.getField(blockBreakPacket, TechHider.iBlockData, 0);
return (p, packet) -> {
switch (locationEvaluator.checkBlockPos(p, blockBreakPosition.get(packet))) {
switch (techHider.getLocationEvaluator().checkBlockPos(p, blockBreakPosition.get(packet))) {
case SKIP:
return packet;
case CHECK:
if(!TechHider.iBlockDataHidden(obfuscate, blockBreakBlockData.get(packet)))
if(!techHider.iBlockDataHidden(blockBreakBlockData.get(packet)))
return packet;
case HIDE:
packet = blockBreakCloner.apply(packet);
blockBreakBlockData.set(packet, techHider.getObfuscationTarget());
return packet;
case HIDE_AIR:
default:
packet = blockBreakCloner.apply(packet);
blockBreakBlockData.set(packet, obfuscationTarget);
blockBreakBlockData.set(packet, TechHider.AIR);
return packet;
}
};
@@ -31,7 +31,6 @@ import net.minecraft.util.SimpleBitStorage;
import net.minecraft.world.level.block.entity.TileEntityTypes;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
@@ -55,26 +54,27 @@ public class ChunkHider18 implements ChunkHider {
private static final Reflection.FieldAccessor<List> tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0);
@Override
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities) {
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
return (p, packet) -> {
int chunkX = chunkXField.get(packet);
int chunkZ = chunkZField.get(packet);
if (locationEvaluator.skipChunk(p, chunkX, chunkZ))
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
return packet;
packet = chunkPacketCloner.apply(packet);
Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet));
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
tileEntities.set(dataWrapper, ((List<?>)tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList()));
ByteBuf in = Unpooled.wrappedBuffer(dataField.get(dataWrapper));
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
int xOffset = 16*chunkX;
int zOffset = 16*chunkZ;
for(int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) {
int finalYOffset = yOffset;
int chunkY = yOffset/16;
dataHider((x, y, z) -> locationEvaluator.check(p, x+xOffset, y+finalYOffset, z+zOffset), obfuscationTarget, obfuscate, in, out, locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ), locationEvaluator.blockPrecise(p, chunkX, chunkY, chunkZ));
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset/16, chunkZ);
section.copyBlockCount();
blocks(section);
biomes(section);
}
out.writeBytes(in); // MC appends a 0 byte at the end if there is a full chunk, idk why
@@ -96,70 +96,57 @@ public class ChunkHider18 implements ChunkHider {
return !hiddenBlockEntities.contains((String) getName.invoke(getKey.invoke(tileEntityTypes, entityType.get(tile))));
}
private void dataHider(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, boolean skip, boolean blockPrecise) {
out.writeShort(in.readShort()); // Block count
private void blocks(SectionHider section) {
section.copyBitsPerBlock();
containerWalker(in, out, 15, obfuscationTarget, skip ? Collections.emptySet() : obfuscate, (paletteTarget, dataArrayLength, bitsPerBlock) -> {
Set<Integer> palettedObfuscate;
if(bitsPerBlock < 15) {
palettedObfuscate = Collections.emptySet();
} else {
paletteTarget = obfuscationTarget;
palettedObfuscate = obfuscate;
}
boolean singletonPalette = section.getBitsPerBlock() == 0;
if(singletonPalette) {
int value = ProtocolUtils.readVarInt(section.getIn());
ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value);
}else if(section.getBitsPerBlock() < 15) {
section.processPalette();
}
if(skip || dataArrayLength == 0 || (!blockPrecise && bitsPerBlock < 15)) {
out.writeBytes(in, dataArrayLength*8);
return;
}
if(section.isSkipSection() || singletonPalette || (!section.blockPrecise() && section.isPaletted())) {
section.skipDataArray();
return;
}
long[] array = new long[dataArrayLength];
for(int i = 0; i < dataArrayLength; i++)
array[i] = in.readLong();
SimpleBitStorage values = new SimpleBitStorage(bitsPerBlock, 4096, array);
SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readDataArray());
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int pos = (((y * 16) + z) * 16) + x;
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int pos = (((y * 16) + z) * 16) + x;
switch (locationEvaluator.test(x, y, z)) {
case SKIP:
switch (section.test(x, y, z)) {
case SKIP:
break;
case CHECK:
if(!section.getObfuscate().contains(values.a(pos)))
break;
case CHECK:
if(!palettedObfuscate.contains(values.a(pos)))
break;
default:
values.b(pos, paletteTarget);
}
case HIDE:
values.b(pos, section.getTarget());
break;
case HIDE_AIR:
default:
values.b(pos, section.getAir());
}
}
}
for (long l : values.a())
out.writeLong(l);
});
containerWalker(in, out, 6, 0, Collections.emptySet(), (paletteTarget, dataArrayLength, bitsPerBlock) -> out.writeBytes(in, dataArrayLength * 8)); // Biomes
}
private void containerWalker(ByteBuf in, ByteBuf out, int globalPalette, int obfuscationTarget, Set<Integer> obfuscate, TriConsumer<Integer, Integer, Byte> dataArray) {
byte bitsPerBlock = in.readByte();
out.writeByte(bitsPerBlock);
//blockId -> obfuscate.contains(blockId) ? obfuscationTarget : blockId
if(bitsPerBlock == 0) {
int value = ProtocolUtils.readVarInt(in);
ProtocolUtils.writeVarInt(out, obfuscate.contains(value) ? obfuscationTarget : value);
}else if(bitsPerBlock < globalPalette) {
obfuscationTarget = ChunkHider.processPalette(obfuscationTarget, obfuscate, in, out);
}
int dataArrayLength = ProtocolUtils.readVarInt(in);
ProtocolUtils.writeVarInt(out, dataArrayLength);
dataArray.accept(obfuscationTarget, dataArrayLength, bitsPerBlock);
section.writeDataArray(values.a());
}
private interface TriConsumer<X, Y, Z> {
void accept(X x, Y y, Z z);
private void biomes(SectionHider section) {
section.copyBitsPerBlock();
boolean singletonPalette = section.getBitsPerBlock() == 0;
if(singletonPalette)
section.copyVarInt();
else if(section.getBitsPerBlock() < 6)
section.skipPalette();
section.skipDataArray();
}
}
@@ -25,11 +25,9 @@ import net.minecraft.network.protocol.game.PacketPlayOutBlockBreak;
import net.minecraft.world.level.block.entity.TileEntitySign;
import net.minecraft.world.level.block.entity.TileEntityTypes;
import net.minecraft.world.level.block.state.IBlockData;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.ArrayList;
import java.util.Set;
import java.util.function.BiFunction;
public class ProtocolWrapper18 implements ProtocolWrapper {
@@ -38,8 +36,9 @@ public class ProtocolWrapper18 implements ProtocolWrapper {
private static final Reflection.FieldAccessor<short[]> multiBlockChangePos = Reflection.getField(TechHider.multiBlockChangePacket, short[].class, 0);
private static final Reflection.FieldAccessor<IBlockData[]> multiBlockChangeBlocks = Reflection.getField(TechHider.multiBlockChangePacket, IBlockData[].class, 0);
@Override
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider) {
return (p, packet) -> {
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
Object chunkCoords = multiBlockChangeChunk.get(packet);
int chunkX = TechHider.blockPositionX.get(chunkCoords);
int chunkY = TechHider.blockPositionY.get(chunkCoords);
@@ -62,7 +61,7 @@ public class ProtocolWrapper18 implements ProtocolWrapper {
break;
case CHECK:
poss.add(pos);
blocks.add(TechHider.iBlockDataHidden(obfuscate, block) ? (IBlockData) obfuscationTarget : block);
blocks.add(techHider.iBlockDataHidden(block) ? (IBlockData) techHider.getObfuscationTarget() : block);
break;
default:
break;
@@ -90,17 +89,20 @@ public class ProtocolWrapper18 implements ProtocolWrapper {
}
@Override
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
return (p, packet) -> {
PacketPlayOutBlockBreak breakPacket = (PacketPlayOutBlockBreak) packet;
switch (locationEvaluator.checkBlockPos(p, breakPacket.b())) {
switch (techHider.getLocationEvaluator().checkBlockPos(p, breakPacket.b())) {
case SKIP:
return packet;
case CHECK:
if(!TechHider.iBlockDataHidden(obfuscate, breakPacket.c()))
if(!techHider.iBlockDataHidden(breakPacket.c()))
return packet;
case HIDE:
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) techHider.getObfuscationTarget(), breakPacket.d(), breakPacket.a());
case HIDE_AIR:
default:
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) obfuscationTarget, breakPacket.d(), breakPacket.a());
return new PacketPlayOutBlockBreak(breakPacket.b(), (IBlockData) TechHider.AIR, breakPacket.d(), breakPacket.a());
}
};
}
@@ -19,16 +19,14 @@
package de.steamwar.techhider;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.function.BiFunction;
public class ProtocolWrapper19 extends ProtocolWrapper18 {
@Override
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
return null;
}
}
@@ -22,7 +22,6 @@ package de.steamwar.techhider;
import com.comphenix.tinyprotocol.Reflection;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.function.BiFunction;
public class ChunkHider8 implements ChunkHider {
@@ -34,7 +33,7 @@ public class ChunkHider8 implements ChunkHider {
}
@Override
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities) {
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
return (player, packet) -> packet;
}
}
@@ -20,12 +20,10 @@
package de.steamwar.techhider;
import com.comphenix.tinyprotocol.Reflection;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Set;
import java.util.function.BiFunction;
public class ProtocolWrapper8 implements ProtocolWrapper {
@@ -40,8 +38,9 @@ public class ProtocolWrapper8 implements ProtocolWrapper {
private static final Class<?> multiBlockChangeInfoArray = Reflection.getClass("[L{nms}.PacketPlayOutMultiBlockChange$MultiBlockChangeInfo;");
private static final Reflection.FieldAccessor<?> multiBlockChangeInfos = Reflection.getField(TechHider.multiBlockChangePacket, multiBlockChangeInfoArray, 0);
@Override
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator) {
public BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider) {
return (p, packet) -> {
TechHider.LocationEvaluator locationEvaluator = techHider.getLocationEvaluator();
Object chunkCoords = multiBlockChangeChunk.get(packet);
int chunkX = chunkCoordinateX.get(chunkCoords);
int chunkZ = chunkCoordinateZ.get(chunkCoords);
@@ -58,7 +57,7 @@ public class ProtocolWrapper8 implements ProtocolWrapper {
blockChangeInfos.add(mbci);
break;
case CHECK:
blockChangeInfos.add(TechHider.iBlockDataHidden(obfuscate, multiBlockChangeInfoBlock.get(mbci)) ? multiBlockChangeInfoConstructor.invoke(packet, pos, obfuscationTarget) : mbci);
blockChangeInfos.add(techHider.iBlockDataHidden(multiBlockChangeInfoBlock.get(mbci)) ? multiBlockChangeInfoConstructor.invoke(packet, pos, techHider.getObfuscationTarget()) : mbci);
break;
default:
break;
@@ -80,7 +79,7 @@ public class ProtocolWrapper8 implements ProtocolWrapper {
}
@Override
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator bypass) {
public BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider) {
return null;
}
}
@@ -24,7 +24,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.function.BiFunction;
@@ -45,20 +44,19 @@ public class ChunkHider9 extends ChunkHider8 {
private static final Reflection.MethodInvoker nbtTagGetString = Reflection.getTypedMethod(nbtTagCompound, null, String.class, String.class);
@Override
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities) {
public BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider) {
return (p, packet) -> {
int chunkX = mapChunkX.get(packet);
int chunkZ = mapChunkZ.get(packet);
if (locationEvaluator.skipChunk(p, chunkX, chunkZ))
if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ))
return packet;
packet = mapChunkCloner.apply(packet);
Set<String> hiddenBlockEntities = techHider.getHiddenBlockEntities();
mapChunkBlockEntities.set(packet, ((List<?>)mapChunkBlockEntities.get(packet)).stream().filter(
nbttag -> !hiddenBlockEntities.contains((String) nbtTagGetString.invoke(nbttag, "id"))
).collect(Collectors.toList()));
int xOffset = 16*chunkX;
int zOffset = 16*chunkZ;
int primaryBitMask = mapChunkBitMask.get(packet);
ByteBuf in = Unpooled.wrappedBuffer(mapChunkData.get(packet));
ByteBuf out = Unpooled.buffer(in.readableBytes() + 64);
@@ -66,8 +64,8 @@ public class ChunkHider9 extends ChunkHider8 {
if(((1 << chunkY) & primaryBitMask) == 0)
continue;
int yOffset = 16*chunkY;
dataHider((x, y, z) -> locationEvaluator.check(p, x+xOffset, y+yOffset, z+zOffset), obfuscationTarget, obfuscate, in, out, locationEvaluator.skipChunkSection(p, chunkX, chunkY, chunkZ), locationEvaluator.blockPrecise(p, chunkX, chunkY, chunkZ));
SectionHider section = new SectionHider(p, techHider, in, out, chunkX, chunkY, chunkZ);
dataHider(section);
}
byte[] data = new byte[out.readableBytes()];
out.readBytes(data);
@@ -77,51 +75,45 @@ public class ChunkHider9 extends ChunkHider8 {
};
}
protected void dataHider(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, boolean skip, boolean blockPrecise) {
byte bitsPerBlock = in.readByte();
out.writeByte(bitsPerBlock);
protected void dataHider(SectionHider section) {
section.copyBitsPerBlock();
section.processPalette();
int paletteTarget = ChunkHider.processPalette(obfuscationTarget, skip ? Collections.emptySet() : obfuscate, in, out);
if(bitsPerBlock < 13) {
obfuscationTarget = paletteTarget;
obfuscate = Collections.emptySet();
if(section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) { //section.getBitsPerBlock() < 9
section.skipDataArray();
} else {
processDataArray(section);
}
processDataArray(locationEvaluator, obfuscationTarget, obfuscate, in, out, bitsPerBlock, skip || (!blockPrecise && bitsPerBlock < 9));
out.writeBytes(in, 4096); //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
section.getOut().writeBytes(section.getIn(), 4096); //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048
}
protected void processDataArray(PosEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out, int bitsPerBlock, boolean skip) {
int dataArrayLength = ProtocolUtils.readVarInt(in);
ProtocolUtils.writeVarInt(out, dataArrayLength);
protected void processDataArray(SectionHider section) {
VariableValueArray values = new VariableValueArray(section.getBitsPerBlock(), section.readDataArray());
if(skip) {
out.writeBytes(in, dataArrayLength*8);
return;
}
VariableValueArray values = new VariableValueArray(bitsPerBlock, dataArrayLength, in);
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int pos = (((y * 16) + z) * 16) + x;
switch (locationEvaluator.test(x, y, z)) {
switch (section.test(x, y, z)) {
case SKIP:
break;
case CHECK:
if(!obfuscate.contains(values.get(pos)))
if(!section.getObfuscate().contains(values.get(pos)))
break;
case HIDE:
values.set(pos, section.getTarget());
break;
case HIDE_AIR:
default:
values.set(pos, obfuscationTarget);
values.set(pos, section.getAir());
}
}
}
}
for(long l : values.backing)
out.writeLong(l);
section.writeDataArray(values.backing);
}
private static class VariableValueArray {
@@ -129,13 +121,10 @@ public class ChunkHider9 extends ChunkHider8 {
private final int bitsPerValue;
private final long valueMask;
public VariableValueArray(int bitsPerEntry, int dataArrayLength, ByteBuf in) {
public VariableValueArray(int bitsPerEntry, long[] dataArray) {
this.bitsPerValue = bitsPerEntry;
this.valueMask = (1L << this.bitsPerValue) - 1;
this.backing = new long[dataArrayLength];
for(int i = 0; i < dataArrayLength; i++)
backing[i] = in.readLong();
this.backing = dataArray;
}
public int get(int index) {
@@ -22,8 +22,10 @@ package de.steamwar.techhider;
import de.steamwar.core.Core;
import de.steamwar.core.VersionDependent;
import io.netty.buffer.ByteBuf;
import lombok.Getter;
import org.bukkit.entity.Player;
import java.util.Collections;
import java.util.Set;
import java.util.function.BiFunction;
@@ -31,29 +33,124 @@ public interface ChunkHider {
ChunkHider impl = VersionDependent.getVersionImpl(Core.getInstance());
Class<?> mapChunkPacket();
BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set<Integer> obfuscate, Set<String> hiddenBlockEntities);
BiFunction<Player, Object, Object> chunkHiderGenerator(TechHider techHider);
static int processPalette(int obfuscationTarget, Set<Integer> obfuscate, ByteBuf in, ByteBuf out) {
int paletteLength = ProtocolUtils.readVarInt(in);
ProtocolUtils.writeVarInt(out, paletteLength);
@Getter
class SectionHider {
private final Player player;
private final TechHider techHider;
private final ByteBuf in;
private final ByteBuf out;
int paletteTarget = 0;
private final int chunkX;
private final int chunkY;
private final int chunkZ;
private final int offsetX;
private final int offsetY;
private final int offsetZ;
for(int i = 0; i < paletteLength; i++) {
int entry = ProtocolUtils.readVarInt(in);
if(obfuscate.contains(entry))
entry = obfuscationTarget;
private final boolean skipSection;
if(entry == obfuscationTarget)
paletteTarget = i;
private boolean paletted;
private int bitsPerBlock;
private int air;
private int target;
private Set<Integer> obfuscate;
ProtocolUtils.writeVarInt(out, entry);
public SectionHider(Player player, TechHider techHider, ByteBuf in, ByteBuf out, int chunkX, int chunkY, int chunkZ) {
this.player = player;
this.techHider = techHider;
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();
}
return paletteTarget;
}
public boolean blockPrecise() {
return techHider.getLocationEvaluator().blockPrecise(player, chunkX, chunkY, chunkZ);
}
interface PosEvaluator {
TechHider.State test(int x, int y, int z);
public TechHider.State test(int x, int y, int z) {
return techHider.getLocationEvaluator().check(player, offsetX+x, offsetY+y, offsetZ+z);
}
public void copyBlockCount() {
out.writeShort(in.readShort());
}
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() {
if(skipSection) {
skipPalette();
return;
}
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);
}
obfuscate = Collections.emptySet();
}
public void skipDataArray() {
int dataArrayLength = copyVarInt();
out.writeBytes(in, dataArrayLength*8);
}
public long[] readDataArray() {
long[] array = new long[copyVarInt()];
for(int i = 0; i < array.length; i++)
array[i] = in.readLong();
return array;
}
public void writeDataArray(long[] array) {
for(long l : array)
out.writeLong(l);
}
}
}
@@ -20,10 +20,8 @@
package de.steamwar.techhider;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import com.google.common.primitives.Bytes;
import io.netty.buffer.ByteBuf;
import org.bukkit.Bukkit;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -37,10 +35,6 @@ import java.util.function.UnaryOperator;
public class ProtocolUtils {
private ProtocolUtils() {}
public static void broadcastPacket(Object packet) {
Bukkit.getOnlinePlayers().forEach(player -> TinyProtocol.instance.sendPacket(player, packet));
}
@Deprecated
public static BiFunction<Object, UnaryOperator<Object>, Object> arrayCloneGenerator(Class<?> elementClass) {
return (array, worker) -> {
@@ -21,10 +21,8 @@ package de.steamwar.techhider;
import de.steamwar.core.Core;
import de.steamwar.core.VersionDependent;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import java.util.Set;
import java.util.function.BiFunction;
public interface ProtocolWrapper {
@@ -33,7 +31,7 @@ public interface ProtocolWrapper {
boolean unfilteredTileEntityDataAction(Object packet);
BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator);
BiFunction<Player, Object, Object> blockBreakHiderGenerator(Class<?> blockBreakPacket, TechHider techHider);
BiFunction<Player, Object, Object> multiBlockChangeGenerator(Object obfuscationTarget, Set<Material> obfuscate, TechHider.LocationEvaluator locationEvaluator);
BiFunction<Player, Object, Object> multiBlockChangeGenerator(TechHider techHider);
}
@@ -22,6 +22,7 @@ package de.steamwar.techhider;
import com.comphenix.tinyprotocol.Reflection;
import com.comphenix.tinyprotocol.TinyProtocol;
import de.steamwar.core.Core;
import lombok.Getter;
import org.bukkit.GameMode;
import org.bukkit.Material;
import org.bukkit.entity.Player;
@@ -49,34 +50,44 @@ public class TechHider {
private static final Reflection.MethodInvoker getBlockByBlockData = Reflection.getTypedMethod(iBlockData, null, block);
private static final Reflection.MethodInvoker getMaterialByBlock = Reflection.getTypedMethod(craftMagicNumbers, "getMaterial", Material.class, block);
public static boolean iBlockDataHidden(Set<Material> obfuscate, Object iBlockData) {
public boolean iBlockDataHidden(Object iBlockData) {
return obfuscate.contains((Material) getMaterialByBlock.invoke(null, getBlockByBlockData.invoke(iBlockData)));
}
private final Map<Class<?>, BiFunction<Player, Object, Object>> techhiders = new HashMap<>();
private final LocationEvaluator locationEvaluator;
private final Object obfuscationTarget;
private final Set<Material> obfuscate;
public static final Object AIR = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, Material.AIR));
public static final int AIR_ID = BlockIds.impl.materialToId(Material.AIR);
@Deprecated
public TechHider(BypassEvaluator bypass, Material obfuscationTarget, Set<Material> obfuscate, Set<String> hiddenBlockEntities) {
this((LocationEvaluator) (player, x, z) -> bypass.bypass(player, ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z)), obfuscationTarget, obfuscate, hiddenBlockEntities);
}
private final Map<Class<?>, BiFunction<Player, Object, Object>> techhiders = new HashMap<>();
@Getter
private final LocationEvaluator locationEvaluator;
@Getter
private final Object obfuscationTarget;
@Getter
private final int obfuscationTargetId;
@Getter
private final Set<Material> obfuscate;
@Getter
private final Set<Integer> obfuscateIds;
@Getter
private final Set<String> hiddenBlockEntities;
public TechHider(LocationEvaluator locationEvaluator, Material obfuscationTarget, Set<Material> obfuscate, Set<String> hiddenBlockEntities) {
this.locationEvaluator = locationEvaluator;
this.obfuscate = obfuscate;
this.obfuscateIds = obfuscate.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet());
this.hiddenBlockEntities = hiddenBlockEntities;
this.obfuscationTarget = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, obfuscationTarget));
this.obfuscationTargetId = BlockIds.impl.materialToId(obfuscationTarget);
techhiders.put(blockActionPacket, this::blockActionHider);
techhiders.put(blockChangePacket, this::blockChangeHider);
techhiders.put(tileEntityDataPacket, this::tileEntityDataHider);
techhiders.put(multiBlockChangePacket, ProtocolWrapper.impl.multiBlockChangeGenerator(this.obfuscationTarget, obfuscate, locationEvaluator));
techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(locationEvaluator, BlockIds.impl.materialToId(obfuscationTarget), obfuscate.stream().flatMap(m -> BlockIds.impl.materialToAllIds(m).stream()).collect(Collectors.toSet()), hiddenBlockEntities));
techhiders.put(multiBlockChangePacket, ProtocolWrapper.impl.multiBlockChangeGenerator(this));
techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(this));
if(Core.getVersion() > 12 && Core.getVersion() < 19) {
Class<?> blockBreakClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutBlockBreak");
techhiders.put(blockBreakClass, ProtocolWrapper.impl.blockBreakHiderGenerator(blockBreakClass, this.obfuscationTarget, obfuscate, locationEvaluator));
techhiders.put(blockBreakClass, ProtocolWrapper.impl.blockBreakHiderGenerator(blockBreakClass, this));
}
if(Core.getVersion() > 8){
@@ -106,12 +117,17 @@ public class TechHider {
case SKIP:
return packet;
case CHECK:
if(!iBlockDataHidden(obfuscate, blockChangeBlockData.get(packet)))
if(!iBlockDataHidden(blockChangeBlockData.get(packet)))
return packet;
default:
case HIDE:
packet = blockChangeCloner.apply(packet);
blockChangeBlockData.set(packet, obfuscationTarget);
return packet;
case HIDE_AIR:
default:
packet = blockChangeCloner.apply(packet);
blockChangeBlockData.set(packet, AIR);
return packet;
}
}
@@ -137,15 +153,11 @@ public class TechHider {
}
}
@Deprecated
public interface BypassEvaluator {
boolean bypass(Player p, int chunkX, int chunkZ);
}
public enum State {
SKIP,
CHECK,
HIDE
HIDE,
HIDE_AIR
}
public interface LocationEvaluator {