package de.steamwar.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 de.steamwar.core.Core; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import io.netty.buffer.ByteBuf; import io.netty.buffer.UnpooledByteBufAllocator; import javafx.util.Pair; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.entity.Player; import java.util.*; import static de.steamwar.fightsystem.utils.ITechHider.bypass; public class TechHider { private TechHider(){} private static Map packetCache = new HashMap<>(); private static int arenaMinX; private static int arenaMaxX; private static int arenaMinZ; private static int arenaMaxZ; private static short obfuscateShift4; private static Material obfuscateMaterial; private static boolean running = false; private static int threadMultiplier = 1; public static void init(){ if(disabled()) return; arenaMinX = ITechHider.posToChunk(Config.ArenaMinX); arenaMinZ = ITechHider.posToChunk(Config.ArenaMinZ); arenaMaxX = ITechHider.posToChunk(Config.ArenaMaxX) + 1; arenaMaxZ = ITechHider.posToChunk(Config.ArenaMaxZ) + 1; obfuscateShift4 = (short)(Config.ObfuscateWith << 4); //noinspection deprecation obfuscateMaterial = Material.getMaterial(Config.ObfuscateWith); if(Config.event()) threadMultiplier = 4; if(Core.getVersion() > 8){ 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); } } }); } public static void start(){ if(running) return; running = true; if(disabled()) return; Bukkit.getScheduler().runTaskTimer(FightSystem.getPlugin(), packetCache::clear, 1, 1); switch(Core.getVersion()){ case 8: break; default: chunkHider(); multiBlockHider(); blockHider(); blockActionHider(); } } private static void chunkHider(){ ProtocolLibrary.getProtocolManager().getAsynchronousManager().registerAsyncHandler(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.MAP_CHUNK) { @Override public void onPacketSending(PacketEvent e) { PacketContainer packet = e.getPacket(); StructureModifier ints = packet.getIntegers(); int chunkX = ints.read(0); int chunkZ = ints.read(1); Player p = e.getPlayer(); if(bypass(p, chunkX, chunkZ)) return; PacketContainer cached = packetCache.get(packet); if(cached != null){ e.setPacket(cached); return; } cached = packet.deepClone(); packetCache.put(packet, cached); e.setPacket(cached); StructureModifier list = cached.getSpecificModifier(List.class); List nmsTags = list.read(0); 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; StructureModifier byteArray = cached.getByteArrays(); byte [] data = byteArray.read(0); ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100); int i = 0; while(i < data.length){ byte bitsPerBlock = data[i++]; buffer.writeByte(bitsPerBlock); if(bitsPerBlock < 4) bitsPerBlock = 4; else if(bitsPerBlock > 8){ bitsPerBlock = 13; buffer.writeByte(data[++i]); } if(bitsPerBlock != 13){ int paletteLength = ITechHider.readVarInt(data, i); int paletteLengthLength = ITechHider.readVarIntLength(data, i); buffer.writeBytes(data, i, paletteLengthLength); i += paletteLengthLength; for(int actPaletteId = 0; actPaletteId < paletteLength; actPaletteId++){ int actPalette = ITechHider.readVarInt(data, i); int actPaletteLength = ITechHider.readVarIntLength(data, i); int blockId = actPalette >> 4; if(Config.HiddenBlocks.contains(blockId)){ byte[] a = ITechHider.writeVarInt(obfuscateShift4); buffer.writeBytes(a); changed = true; }else{ buffer.writeBytes(data, i, actPaletteLength); } i += actPaletteLength; } int dataArrayLength = ITechHider.readVarInt(data, i); int dataArrayLengthLength = ITechHider.readVarIntLength(data, i); buffer.writeBytes(data, i, dataArrayLength * 8 + dataArrayLengthLength); i += dataArrayLengthLength; i += dataArrayLength * 8; }else{ int dataArrayLength = ITechHider.readVarInt(data, i); int dataArrayLengthLength = ITechHider.readVarIntLength(data, i); buffer.writeBytes(data, i, dataArrayLength*8 + dataArrayLengthLength); i += dataArrayLengthLength; i += dataArrayLength * 8; } buffer.writeBytes(data, i, 4096); i += 4096; //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048 } if(changed){ data = new byte[buffer.readableBytes()]; buffer.readBytes(data); byteArray.write(0, data); } } }).start(threadMultiplier * 4); } private static void multiBlockHider(){ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.MULTI_BLOCK_CHANGE) { @Override public void onPacketSending(PacketEvent e) { PacketContainer packet = e.getPacket(); Player p = e.getPlayer(); ChunkCoordIntPair pos = packet.getChunkCoordIntPairs().read(0); if(bypass(p, pos.getChunkX(), pos.getChunkZ())) return; PacketContainer cached = packetCache.get(packet); if(cached != null){ e.setPacket(cached); return; } cached = packet.shallowClone(); packetCache.put(packet, cached); e.setPacket(cached); StructureModifier blockStructure = cached.getMultiBlockChangeInfoArrays(); MultiBlockChangeInfo[] changes = blockStructure.read(0).clone(); boolean changed = false; for(MultiBlockChangeInfo mbci : changes){ WrappedBlockData block = mbci.getData(); //noinspection deprecation if(Config.HiddenBlocks.contains(block.getType().getId())){ changed = true; block.setType(obfuscateMaterial); mbci.setData(block); } } if(changed){ blockStructure.write(0, changes); } } }); } private static void blockHider(){ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.BLOCK_CHANGE) { @Override public void onPacketSending(PacketEvent e) { PacketContainer packet = e.getPacket(); BlockPosition pos = packet.getBlockPositionModifier().read(0); Player p = e.getPlayer(); if(bypass(p, ITechHider.posToChunk(pos.getX()), ITechHider.posToChunk(pos.getZ()))) return; PacketContainer cached = packetCache.get(packet); if(cached != null){ e.setPacket(cached); return; } cached = packet.deepClone(); packetCache.put(packet, cached); e.setPacket(cached); StructureModifier blockStructure = cached.getBlockData(); WrappedBlockData block = blockStructure.read(0); //noinspection deprecation if(Config.HiddenBlocks.contains(block.getType().getId())){ block.setType(obfuscateMaterial); blockStructure.write(0, block); } } }); } private static void blockActionHider(){ 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, ITechHider.posToChunk(pos.getX()), ITechHider.posToChunk(pos.getZ()))) return; e.setCancelled(true); } }); } public static List> prepareChunkReload(Player p){ if(disabled()) return Collections.emptyList(); List> chunksToReload = new ArrayList<>(); for(int x = arenaMinX; x <= arenaMaxX; x++) for(int z = arenaMinZ; z <= arenaMaxZ; z++) if(!bypass(p, x, z)) chunksToReload.add(new Pair<>(x, z)); return chunksToReload; } public static void reloadChunks(Player p, List> chunksToReload){ if(disabled()) return; Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { for(Pair chunk : chunksToReload){ if(bypass(p, chunk.getKey(), chunk.getValue())) reloadChunk(p, chunk); } }, 40); } private static void reloadChunk(Player p, Pair chunk){ switch(Core.getVersion()){ case 8: TechHider_8.reloadChunk(p, chunk); break; default: TechHider_12.reloadChunk(p, chunk); } } private static boolean disabled(){ return Config.OnlyPublicSchematics; } }