diff --git a/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/HullHiderWrapper18.java b/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/HullHiderWrapper18.java index 8f81cf95..af5f83a1 100644 --- a/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/HullHiderWrapper18.java +++ b/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/HullHiderWrapper18.java @@ -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 changes) { - List 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 changes, Object[] blockdata) { diff --git a/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/HullHiderWrapper8.java b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/HullHiderWrapper8.java index 524842e6..af56e404 100644 --- a/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/HullHiderWrapper8.java +++ b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/HullHiderWrapper8.java @@ -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 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(); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java index 5c4bd32c..a67c6d5d 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/Hull.java @@ -187,9 +187,6 @@ public class Hull { for (Map.Entry> entry : sectionWise.entrySet()) { Object packet = HullHiderWrapper.impl.generateBlockChangePacket(entry.getValue()); - if(packet == null) - continue; - players.forEach(player -> TinyProtocol.instance.sendPacket(player, packet)); } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index 9e97afa2..68781d46 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -30,12 +30,23 @@ import de.steamwar.fightsystem.fight.FightTeam; import de.steamwar.fightsystem.states.FightState; import de.steamwar.fightsystem.states.StateDependent; import de.steamwar.fightsystem.states.StateDependentListener; +import de.steamwar.sql.SteamwarUser; import de.steamwar.techhider.TechHider; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerQuitEvent; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; +import javax.crypto.spec.SecretKeySpec; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; import java.util.concurrent.ConcurrentHashMap; public class TechHiderWrapper extends StateDependent implements TechHider.LocationEvaluator, Listener { @@ -43,12 +54,21 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati public static final boolean ENABLED = !Config.OnlyPublicSchematics && !Config.test() && Config.TechhiderActive; private final ConcurrentHashMap hiddenRegion = new ConcurrentHashMap<>(); + private final ConcurrentHashMap patterns = new ConcurrentHashMap<>(); private final TechHider techHider; + private final Cipher cipher; public TechHiderWrapper() { super(ENABLED, FightState.Schem); techHider = new TechHider(this, Config.ObfuscateWith, Config.HiddenBlocks, Config.HiddenBlockEntities); + try { + cipher = Cipher.getInstance("AES_256/CFB/NoPadding"); + cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(Files.readAllBytes(new File(System.getProperty("user.home"), "hullhider.key").toPath()), "AES")); + } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IOException e) { + throw new SecurityException(e); + } + new StateDependentListener(ENABLED, FightState.Schem, this); register(); } @@ -112,7 +132,8 @@ 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; + int id = ((y&3) << 4) + ((z&3) << 2) + (x&3); + return (patterns.computeIfAbsent(player, this::getPattern) & (1L << id)) == 0 ? TechHider.State.HIDE_AIR : TechHider.State.HIDE; } else { return TechHider.State.CHECK; } @@ -121,6 +142,35 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati } } + public long getPattern(Player player) { + long pattern = SteamwarUser.get(player.getUniqueId()).getId(); + + byte[] bytes = new byte[]{ + (byte) (pattern & 0xFF), + (byte) ((pattern >>> 8) & 0xFF), + (byte) ((pattern >>> 16) & 0xFF), + (byte) ((pattern >>> 24) & 0xFF) + }; + + try { + bytes = cipher.doFinal(bytes); + } catch (IllegalBlockSizeException | BadPaddingException e) { + throw new SecurityException(e); + } + + pattern = bytes[0] & 0xFFL | + ((bytes[1] & 0xFFL) << 8) | + ((bytes[2] & 0xFFL) << 16) | + ((bytes[3] & 0xFFL) << 24); + + /* XXXO OOOX + * XXXO OOOX + * XXOX OOXO + * OOXX XXOO */ + pattern |= 0b1110_1110_1101_0011___0001_0001_0010_1100___0000_0000_0000_0000___0000_0000_0000_0000L; + return pattern; + } + @Override public boolean blockPrecise(Player player, int chunkX, int chunkY, int chunkZ) { return FightSystem.getHullHider().blockPrecise(player, chunkX, chunkY, chunkZ); diff --git a/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ChunkHider14.java b/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ChunkHider14.java index 9a2d50e8..a9a37e1b 100644 --- a/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ChunkHider14.java +++ b/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ChunkHider14.java @@ -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 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)); } } diff --git a/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ProtocolWrapper14.java b/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ProtocolWrapper14.java index 76b4d9f8..ea98d273 100644 --- a/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ProtocolWrapper14.java +++ b/SpigotCore/SpigotCore_14/src/de/steamwar/techhider/ProtocolWrapper14.java @@ -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 blockBreakHiderGenerator(Class blockBreakPacket, Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator locationEvaluator) { + public BiFunction blockBreakHiderGenerator(Class blockBreakPacket, TechHider techHider) { UnaryOperator 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; } }; diff --git a/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ChunkHider18.java b/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ChunkHider18.java index 774cf2d7..16cecb9b 100644 --- a/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ChunkHider18.java +++ b/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ChunkHider18.java @@ -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 tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0); @Override - public BiFunction chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set obfuscate, Set hiddenBlockEntities) { + public BiFunction 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 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 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 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 obfuscate, TriConsumer 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 { - 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(); } } diff --git a/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ProtocolWrapper18.java b/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ProtocolWrapper18.java index d314c2d3..9fef09fd 100644 --- a/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ProtocolWrapper18.java +++ b/SpigotCore/SpigotCore_18/src/de/steamwar/techhider/ProtocolWrapper18.java @@ -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 multiBlockChangePos = Reflection.getField(TechHider.multiBlockChangePacket, short[].class, 0); private static final Reflection.FieldAccessor multiBlockChangeBlocks = Reflection.getField(TechHider.multiBlockChangePacket, IBlockData[].class, 0); @Override - public BiFunction multiBlockChangeGenerator(Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator locationEvaluator) { + public BiFunction 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 blockBreakHiderGenerator(Class blockBreakPacket, Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator locationEvaluator) { + public BiFunction 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()); } }; } diff --git a/SpigotCore/SpigotCore_19/src/de/steamwar/techhider/ProtocolWrapper19.java b/SpigotCore/SpigotCore_19/src/de/steamwar/techhider/ProtocolWrapper19.java index 38ac90cd..7909b0fd 100644 --- a/SpigotCore/SpigotCore_19/src/de/steamwar/techhider/ProtocolWrapper19.java +++ b/SpigotCore/SpigotCore_19/src/de/steamwar/techhider/ProtocolWrapper19.java @@ -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 blockBreakHiderGenerator(Class blockBreakPacket, Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator locationEvaluator) { + public BiFunction blockBreakHiderGenerator(Class blockBreakPacket, TechHider techHider) { return null; } } diff --git a/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ChunkHider8.java b/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ChunkHider8.java index b7da81e1..50adcaa3 100644 --- a/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ChunkHider8.java +++ b/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ChunkHider8.java @@ -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 chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set obfuscate, Set hiddenBlockEntities) { + public BiFunction chunkHiderGenerator(TechHider techHider) { return (player, packet) -> packet; } } diff --git a/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ProtocolWrapper8.java b/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ProtocolWrapper8.java index ba307d0d..b0de38c8 100644 --- a/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ProtocolWrapper8.java +++ b/SpigotCore/SpigotCore_8/src/de/steamwar/techhider/ProtocolWrapper8.java @@ -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 multiBlockChangeGenerator(Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator locationEvaluator) { + public BiFunction 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 blockBreakHiderGenerator(Class blockBreakPacket, Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator bypass) { + public BiFunction blockBreakHiderGenerator(Class blockBreakPacket, TechHider techHider) { return null; } } diff --git a/SpigotCore/SpigotCore_9/src/de/steamwar/techhider/ChunkHider9.java b/SpigotCore/SpigotCore_9/src/de/steamwar/techhider/ChunkHider9.java index 59e279f5..89f6570f 100644 --- a/SpigotCore/SpigotCore_9/src/de/steamwar/techhider/ChunkHider9.java +++ b/SpigotCore/SpigotCore_9/src/de/steamwar/techhider/ChunkHider9.java @@ -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 chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set obfuscate, Set hiddenBlockEntities) { + public BiFunction 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 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 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 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) { diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java index 0a392450..a74feb42 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java @@ -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 chunkHiderGenerator(TechHider.LocationEvaluator locationEvaluator, int obfuscationTarget, Set obfuscate, Set hiddenBlockEntities); + BiFunction chunkHiderGenerator(TechHider techHider); - static int processPalette(int obfuscationTarget, Set 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 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); + } } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java index 43bf0435..fe7bc707 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java @@ -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> arrayCloneGenerator(Class elementClass) { return (array, worker) -> { diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolWrapper.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolWrapper.java index 489e11b7..aab486c4 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolWrapper.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolWrapper.java @@ -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 blockBreakHiderGenerator(Class blockBreakPacket, Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator locationEvaluator); + BiFunction blockBreakHiderGenerator(Class blockBreakPacket, TechHider techHider); - BiFunction multiBlockChangeGenerator(Object obfuscationTarget, Set obfuscate, TechHider.LocationEvaluator locationEvaluator); + BiFunction multiBlockChangeGenerator(TechHider techHider); } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java index 24fbb27a..9f3ccf90 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java @@ -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 obfuscate, Object iBlockData) { + public boolean iBlockDataHidden(Object iBlockData) { return obfuscate.contains((Material) getMaterialByBlock.invoke(null, getBlockByBlockData.invoke(iBlockData))); } - private final Map, BiFunction> techhiders = new HashMap<>(); - private final LocationEvaluator locationEvaluator; - private final Object obfuscationTarget; - private final Set 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 obfuscate, Set hiddenBlockEntities) { - this((LocationEvaluator) (player, x, z) -> bypass.bypass(player, ProtocolUtils.posToChunk(x), ProtocolUtils.posToChunk(z)), obfuscationTarget, obfuscate, hiddenBlockEntities); - } + private final Map, BiFunction> techhiders = new HashMap<>(); + @Getter + private final LocationEvaluator locationEvaluator; + @Getter + private final Object obfuscationTarget; + @Getter + private final int obfuscationTargetId; + @Getter + private final Set obfuscate; + @Getter + private final Set obfuscateIds; + @Getter + private final Set hiddenBlockEntities; public TechHider(LocationEvaluator locationEvaluator, Material obfuscationTarget, Set obfuscate, Set 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 {