package me.yaruma.fightsystem.utils; import com.comphenix.protocol.PacketType; import com.comphenix.protocol.ProtocolLibrary; import com.comphenix.protocol.events.PacketAdapter; import com.comphenix.protocol.events.PacketContainer; import com.comphenix.protocol.events.PacketEvent; import com.comphenix.protocol.reflect.StructureModifier; import com.comphenix.protocol.wrappers.BlockPosition; import com.comphenix.protocol.wrappers.ChunkCoordIntPair; import com.comphenix.protocol.wrappers.MultiBlockChangeInfo; import com.comphenix.protocol.wrappers.WrappedBlockData; import com.comphenix.protocol.wrappers.nbt.NbtCompound; import com.comphenix.protocol.wrappers.nbt.NbtFactory; import com.google.common.primitives.Bytes; import me.yaruma.fightsystem.FightSystem; import me.yaruma.fightsystem.fight.Fight; import me.yaruma.fightsystem.fight.FightTeam; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.List; public class TechHider { private static int arenaMinX; private static int arenaMaxX; private static int arenaMinZ; private static int arenaMaxZ; private static int blueMinX; private static int blueMaxX; private static int blueMinZ; private static int blueMaxZ; private static int redMinX; private static int redMaxX; private static int redMinZ; private static int redMaxZ; private static int obfuscateShift4; private static Material obfuscateMaterial; public static void init(){ arenaMinX = Config.ArenaMinX / 16 - (Config.ArenaMinX % 16 < 0 ? 1 : 0); arenaMinZ = Config.ArenaMinZ / 16 - (Config.ArenaMinZ % 16 < 0 ? 1 : 0); arenaMaxX = Config.ArenaMaxX / 16 + (Config.ArenaMaxX % 16 > 0 ? 1 : 0); arenaMaxZ = Config.ArenaMaxZ / 16 + (Config.ArenaMaxZ % 16 > 0 ? 1 : 0); blueMinX = Config.TeamBlueCornerX / 16 - (Config.TeamBlueCornerX % 16 < 0 ? 1 : 0); blueMinZ = Config.TeamBlueCornerZ / 16 - (Config.TeamBlueCornerZ % 16 < 0 ? 1 : 0); int max = Config.TeamBlueCornerX + Config.SchemsizeX; blueMaxX = max / 16 + (max % 16 > 0 ? 1 : 0); max = Config.TeamBlueCornerZ + Config.SchemsizeZ; blueMaxZ = max / 16 + (max % 16 > 0 ? 1 : 0); redMinX = Config.TeamRedCornerX / 16 - (Config.TeamRedCornerX % 16 < 0 ? 1 : 0); redMinZ = Config.TeamRedCornerZ / 16 - (Config.TeamRedCornerZ % 16 < 0 ? 1 : 0); max = Config.TeamRedCornerX + Config.SchemsizeX; redMaxX = max / 16 + (max % 16 > 0 ? 1 : 0); max = Config.TeamRedCornerZ + Config.SchemsizeZ; redMaxZ = max / 16 + (max % 16 > 0 ? 1 : 0); obfuscateShift4 = Config.ObfuscateWith << 4; //noinspection deprecation obfuscateMaterial = Material.getMaterial(Config.ObfuscateWith); ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.MAP_CHUNK) { @Override public void onPacketSending(PacketEvent e) { PacketContainer packet = e.getPacket(); StructureModifier ints = packet.getIntegers(); StructureModifier byteArray = packet.getByteArrays(); StructureModifier list = packet.getSpecificModifier(List.class); List nmsTags = list.read(0); int chunkX = ints.read(0); int chunkZ = ints.read(1); Player p = e.getPlayer(); if(bypass(p, chunkX, chunkZ)) return; boolean changed = false; for(int i = nmsTags.size() - 1; i >= 0; i--){ NbtCompound nbt = NbtFactory.fromNMSCompound(nmsTags.get(i)); if(Config.HiddenBlockEntities.contains(nbt.getString("id"))){ nmsTags.remove(i); changed = true; } } if(changed){ list.write(0, nmsTags); } changed = false; byte [] data = byteArray.read(0); List newData = new ArrayList<>(Bytes.asList(data)); int i = 0; while(i < newData.size()){ byte bitsPerBlock = newData.get(i++); if(bitsPerBlock < 4) bitsPerBlock = 4; else if(bitsPerBlock > 8){ bitsPerBlock = 13; i++; } if(bitsPerBlock != 13){ int paletteLength = readVarInt(Bytes.toArray(newData), i); i += readVarIntLength(Bytes.toArray(newData), i); for(int actPaletteId = 0; actPaletteId < paletteLength; actPaletteId++){ int actPalette = readVarInt(Bytes.toArray(newData), i); int actPaletteLength = readVarIntLength(Bytes.toArray(newData), i); int blockId = actPalette >> 4; if(Config.HiddenBlocks.contains(blockId)){ byte[] a = writeVarInt(obfuscateShift4); for(int j = 0; j < actPaletteLength; j++){ newData.remove(i); } for(byte b : a){ newData.add(i++, b); } changed = true; }else{ i += actPaletteLength; } } int dataArrayLength = readVarInt(Bytes.toArray(newData), i); i += readVarIntLength(Bytes.toArray(newData), i); i += dataArrayLength * 8; }else{ System.out.println("Chunk with global palette!"); int dataArrayLength = readVarInt(Bytes.toArray(newData), i); i += readVarIntLength(Bytes.toArray(newData), i); int arrayEnd = dataArrayLength * 8 + i; int bitsOver = 8; //9 bits (id) + 4 bits (metadata) final int globalMask = 0x000001FF; final byte replacement = 0x01; while(i < arrayEnd){ int blockId = (newData.get(i++) & (globalMask >> 9 - bitsOver)) << 9-bitsOver; blockId += newData.get(i) >> bitsOver-1; if(Config.HiddenBlocks.contains(blockId)){ System.out.println("Hidden Block found!"); } bitsOver -= 5; // 13-8 if(bitsOver < 1){ i++; bitsOver += 8; } } //i += dataArrayLength * 8; } i += 4096; //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048 } if(changed){ byteArray.write(0, Bytes.toArray(newData)); } } }); ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.BLOCK_CHANGE) { @SuppressWarnings("deprecation") @Override public void onPacketSending(PacketEvent e) { PacketContainer packet = e.getPacket(); StructureModifier blockStructure = packet.getBlockData(); BlockPosition pos = packet.getBlockPositionModifier().read(0); Player p = e.getPlayer(); if(bypass(p, pos.getX() / 16, pos.getZ() / 16)) return; WrappedBlockData block = blockStructure.read(0); if(Config.HiddenBlocks.contains(block.getType().getId())){ block.setType(obfuscateMaterial); blockStructure.write(0, block); } } }); ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.MULTI_BLOCK_CHANGE) { @SuppressWarnings("deprecation") @Override public void onPacketSending(PacketEvent e) { PacketContainer packet = e.getPacket(); StructureModifier blockStructure = packet.getMultiBlockChangeInfoArrays(); MultiBlockChangeInfo[] changes = blockStructure.read(0); Player p = e.getPlayer(); ChunkCoordIntPair pos = changes[0].getChunk(); if(bypass(p, pos.getChunkX(), pos.getChunkZ())) return; boolean changed = false; for(MultiBlockChangeInfo mbci : changes){ WrappedBlockData block = mbci.getData(); if(Config.HiddenBlocks.contains(block.getType().getId())){ changed = true; block.setType(obfuscateMaterial); mbci.setData(block); } } if(changed){ blockStructure.write(0, changes); } } }); ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.BLOCK_ACTION) { @Override public void onPacketSending(PacketEvent e) { PacketContainer packet = e.getPacket(); BlockPosition pos = packet.getBlockPositionModifier().read(0); Player p = e.getPlayer(); if(bypass(p, pos.getX() / 16, pos.getZ() / 16)) return; e.setCancelled(true); } }); ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.USE_ITEM) { @Override public void onPacketReceiving(PacketEvent e) { Player p = e.getPlayer(); if(p.getGameMode() == GameMode.SPECTATOR){ e.setCancelled(true); } } }); ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.USE_ENTITY) { @Override public void onPacketReceiving(PacketEvent e) { Player p = e.getPlayer(); if(p.getGameMode() == GameMode.SPECTATOR){ e.setCancelled(true); } } }); } private static boolean bypass(Player p, int chunkX, int chunkZ){ if( ! (arenaMinX <= chunkX && chunkX <= arenaMaxX && arenaMinZ <= chunkZ && chunkZ <= arenaMaxZ)){ //Außerhalb der Arena return true; } FightTeam ft = Fight.getPlayerTeam(p); if(ft == null){ return false; }else if(ft == Fight.getBlueTeam()){ return Config.Entern || ! (redMinX <= chunkX && chunkX <= redMaxX && redMinZ <= chunkZ && chunkZ <= redMaxZ); }else{ return Config.Entern || ! (blueMinX <= chunkX && chunkX <= blueMaxX && blueMinZ <= chunkZ && chunkZ <= blueMaxZ); } } private static int readVarInt(byte[] array, int startPos) { int numRead = 0; int result = 0; byte read; do { read = array[startPos + numRead]; int value = (read & 0b01111111); result |= (value << (7 * numRead)); numRead++; if (numRead > 5) { break; } } while ((read & 0b10000000) != 0); return result; } private static int readVarIntLength(byte[] array, int startPos) { int numRead = 0; byte read; do { read = array[startPos + numRead]; numRead++; if (numRead > 5) { break; } } while ((read & 0b10000000) != 0); return numRead; } private static byte[] writeVarInt(int value) { ArrayList buffer = new ArrayList<>(); do { byte temp = (byte)(value & 0b01111111); // Note: >>> means that the sign bit is shifted with the rest of the number rather than being left alone value >>>= 7; if (value != 0) { temp |= 0b10000000; } buffer.add(temp); } while (value != 0); return Bytes.toArray(buffer); } }