/* This file is a part of the SteamWar software. Copyright (C) 2020 SteamWar.de-Serverteam This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see . */ 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 de.steamwar.core.Core; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.IFightSystem; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.entity.Player; import java.util.ArrayList; import java.util.Collections; import java.util.List; import static de.steamwar.fightsystem.utils.ITechHider.bypass; public class TechHider { private TechHider(){} private static boolean running = false; public static void init(){ if(disabled()) return; 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; blockActionHider(); blockHider(); multiBlockHider(); updateBlockEntity(); switch(Core.getVersion()){ case 15: TechHider_15.start(); break; case 14: TechHider_14.start(); break; case 10: case 9: case 8: break; default: TechHider_12.start(); } } private static void multiBlockHider(){ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(IFightSystem.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 = ITechHider.packetCache.get(packet); if(cached != null){ e.setPacket(cached); return; } cached = packet.shallowClone(); ITechHider.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(); if(Config.HiddenBlockTags.contains(block.getType().name())){ changed = true; block.setType(ITechHider.obfuscateMaterial); mbci.setData(block); } } if(changed){ blockStructure.write(0, changes); } } }); } private static void blockHider(){ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(IFightSystem.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 = ITechHider.packetCache.get(packet); if(cached != null){ e.setPacket(cached); return; } cached = packet.deepClone(); ITechHider.packetCache.put(packet, cached); e.setPacket(cached); StructureModifier blockStructure = cached.getBlockData(); WrappedBlockData block = blockStructure.read(0); if(Config.HiddenBlockTags.contains(block.getType().name())){ block.setType(ITechHider.obfuscateMaterial); blockStructure.write(0, block); } } }); } private static void blockActionHider(){ ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(IFightSystem.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); } }); } private static void updateBlockEntity(){ if(Core.getVersion() < 9) return; ProtocolLibrary.getProtocolManager().addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.TILE_ENTITY_DATA) { @Override public void onPacketSending(PacketEvent event) { PacketContainer packet = event.getPacket(); BlockPosition pos = packet.getBlockPositionModifier().read(0); Player p = event.getPlayer(); if(bypass(p, ITechHider.posToChunk(pos.getX()), ITechHider.posToChunk(pos.getZ()))) return; // 9 == Set sign text if(packet.getIntegers().read(0) != 9) return; event.setCancelled(true); } }); } public static List prepareChunkReload(Player p){ if(disabled()) return Collections.emptyList(); List chunksToReload = new ArrayList<>(); for(int x = ITechHider.arenaMinX; x <= ITechHider.arenaMaxX; x++) for(int z = ITechHider.arenaMinZ; z <= ITechHider.arenaMaxZ; z++) if(!bypass(p, x, z)) chunksToReload.add(new ITechHider.ChunkPos(x, z)); return chunksToReload; } public static void reloadChunks(Player p, List chunksToReload){ if(disabled()) return; Bukkit.getScheduler().runTaskLater(FightSystem.getPlugin(), () -> { for(ITechHider.ChunkPos chunk : chunksToReload){ if(bypass(p, chunk.x(), chunk.z())) reloadChunk(p, chunk); } }, 40); } private static void reloadChunk(Player p, ITechHider.ChunkPos chunk){ switch(Core.getVersion()){ case 15: TechHider_15.reloadChunk(p, chunk); break; case 14: TechHider_14.reloadChunk(p, chunk); break; case 10: TechHider_10.reloadChunk(p, chunk); break; case 9: TechHider_9.reloadChunk(p, chunk); break; case 8: TechHider_8.reloadChunk(p, chunk); break; default: TechHider_12.reloadChunk(p, chunk); } } private static boolean disabled(){ return Config.OnlyPublicSchematics || Config.test() || !Config.TechhiderActive; } }