diff --git a/FightSystem_14/src/de/steamwar/fightsystem/utils/FlatteningWrapper14.java b/FightSystem_14/src/de/steamwar/fightsystem/utils/FlatteningWrapper14.java index dc3ed90..7f79995 100644 --- a/FightSystem_14/src/de/steamwar/fightsystem/utils/FlatteningWrapper14.java +++ b/FightSystem_14/src/de/steamwar/fightsystem/utils/FlatteningWrapper14.java @@ -19,12 +19,15 @@ package de.steamwar.fightsystem.utils; +import com.comphenix.tinyprotocol.Reflection; +import de.steamwar.fightsystem.record.REntity; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.block.data.Waterlogged; +import org.bukkit.entity.EntityType; import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.BlockDataMeta; @@ -108,4 +111,29 @@ public class FlatteningWrapper14 implements FlatteningWrapper.IFlatteningWrapper public boolean checkPistonMoving(Block block) { return block.getType() == Material.MOVING_PISTON; } + + @Override + public void setNamedSpawnPacketDataWatcher(Object packet) { + // field not present + } + + private static final Class entityTypes = Reflection.getClass("{nms}.EntityTypes"); + private static final Reflection.FieldAccessor spawnType = Reflection.getField(REntity.spawnPacket, entityTypes, 0); + private static final Object tnt = Reflection.getField(entityTypes, "TNT", entityTypes).get(null); + private static final Object arrow = Reflection.getField(entityTypes, "ARROW", entityTypes).get(null); + private static final Object fireball = Reflection.getField(entityTypes, "FIREBALL", entityTypes).get(null); + @Override + public void setSpawnPacketType(Object packet, EntityType type) { + switch(type) { + case PRIMED_TNT: + spawnType.set(packet, tnt); + break; + case ARROW: + spawnType.set(packet, arrow); + break; + case FIREBALL: + spawnType.set(packet, fireball); + break; + } + } } diff --git a/FightSystem_14/src/de/steamwar/fightsystem/utils/TechHider14.java b/FightSystem_14/src/de/steamwar/fightsystem/utils/TechHider14.java index 78100f1..a391a50 100644 --- a/FightSystem_14/src/de/steamwar/fightsystem/utils/TechHider14.java +++ b/FightSystem_14/src/de/steamwar/fightsystem/utils/TechHider14.java @@ -19,76 +19,27 @@ package de.steamwar.fightsystem.utils; -import com.comphenix.protocol.PacketType; -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.nbt.NbtBase; -import com.comphenix.protocol.wrappers.nbt.NbtCompound; -import de.steamwar.fightsystem.Config; -import de.steamwar.fightsystem.FightSystem; import io.netty.buffer.ByteBuf; import io.netty.buffer.UnpooledByteBufAllocator; -import org.bukkit.entity.Player; import java.nio.ByteBuffer; import java.nio.LongBuffer; -import java.util.List; import java.util.Set; +import java.util.function.BiFunction; -import static de.steamwar.fightsystem.utils.TechHider.bypass; - -public class TechHider14 extends PacketAdapter { +public class TechHider14 implements BiFunction { private final Set hiddenBlockIds = BlockIdWrapper.impl.getHiddenBlockIds(); private final int obfuscateWith = BlockIdWrapper.impl.getObfuscateWith(); - public TechHider14(){ - super(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; - - packet = packet.shallowClone(); - e.setPacket(packet); - StructureModifier>> list = packet.getListNbtModifier(); - List> nmsTags = list.read(0); - boolean changed = false; - for(int i = nmsTags.size() - 1; i >= 0; i--){ - NbtBase nbtBase = nmsTags.get(i); - assert nbtBase instanceof NbtCompound; - NbtCompound nbt = (NbtCompound) nbtBase; - if(Config.HiddenBlockEntities.contains(nbt.getString("id"))){ - nmsTags.remove(i); - changed = true; - } - } - if(changed){ - list.write(0, nmsTags); - } - - changed = false; - StructureModifier byteArray = packet.getByteArrays(); - int primaryBitMask = ints.read(2); - byte[] data = byteArray.read(0); + public byte[] apply(byte[] data, Integer primaryBitMask) { ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100); int i = 0; - //int chunkY = 0; while(primaryBitMask != 0){ while((primaryBitMask & 1) == 0){ primaryBitMask >>= 1; - //chunkY++; } buffer.writeBytes(data, i, 2); // Block count @@ -107,7 +58,6 @@ public class TechHider14 extends PacketAdapter { if(hiddenBlockIds.contains(blockId)){ buffer.writeBytes(TechHider.writeVarInt(obfuscateWith)); - changed = true; }else{ buffer.writeBytes(data, i, actPaletteLength); } @@ -132,7 +82,6 @@ public class TechHider14 extends PacketAdapter { for(int pos = 0; pos < 4096; pos++){ if(hiddenBlockIds.contains(values.get(pos))){ - changed = true; values.set(pos, obfuscateWith); } } @@ -144,15 +93,12 @@ public class TechHider14 extends PacketAdapter { } primaryBitMask >>= 1; - //chunkY++; } buffer.writeBytes(data, i, data.length - i); // MC appends a 0 byte at the end if there is a full chunk, idk why - if(changed){ - data = new byte[buffer.readableBytes()]; - buffer.readBytes(data); - byteArray.write(0, data); - } + data = new byte[buffer.readableBytes()]; + buffer.readBytes(data); + return data; } private static final class VariableValueArray { diff --git a/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java b/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java index 723e2f0..e338878 100644 --- a/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java +++ b/FightSystem_8/src/de/steamwar/fightsystem/utils/BlockIdWrapper8.java @@ -54,6 +54,6 @@ public class BlockIdWrapper8 implements BlockIdWrapper.IBlockIdWrapper { @Override public Object getPose(boolean sneaking) { - return null; + return Byte.valueOf((byte)(sneaking ? 2 : 0)); } } diff --git a/FightSystem_8/src/de/steamwar/fightsystem/utils/BountifulWrapper8.java b/FightSystem_8/src/de/steamwar/fightsystem/utils/BountifulWrapper8.java index 50ff9ea..c5b5801 100644 --- a/FightSystem_8/src/de/steamwar/fightsystem/utils/BountifulWrapper8.java +++ b/FightSystem_8/src/de/steamwar/fightsystem/utils/BountifulWrapper8.java @@ -19,12 +19,14 @@ package de.steamwar.fightsystem.utils; -import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.fightsystem.listener.Recording; import de.steamwar.fightsystem.record.GlobalRecorder; +import de.steamwar.fightsystem.record.REntity; import net.md_5.bungee.api.chat.BaseComponent; import net.minecraft.server.v1_8_R3.ChatComponentText; import net.minecraft.server.v1_8_R3.PacketPlayOutChat; +import net.royawesome.jlibnoise.MathHelper; import org.bukkit.Effect; import org.bukkit.Location; import org.bukkit.Material; @@ -34,9 +36,19 @@ import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.bukkit.scoreboard.Team; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + public class BountifulWrapper8 implements BountifulWrapper.IBountifulWrapper { + @Override - public boolean bowInHand(EnumWrappers.Hand hand, Player p) { + public boolean mainHand(Object packet) { + return true; + } + + @Override + public boolean bowInHand(boolean mainHand, Player p) { return p.getInventory().getItemInHand().getType() == Material.BOW; } @@ -86,4 +98,63 @@ public class BountifulWrapper8 implements BountifulWrapper.IBountifulWrapper { public void spawnParticle(World world, String particleName, double x, double y, double z) { world.playEffect(new Location(world, x, y, z), Effect.valueOf(particleName), 1); } + + @Override + public Object getDataWatcherObject(int index, Class type) { + return index; + } + + private static final Class watchableObject = Reflection.getClass("{nms}.DataWatcher$WatchableObject"); + private static final Reflection.ConstructorInvoker watchableObjectConstructor = Reflection.getConstructor(watchableObject, int.class, int.class, Object.class); + private static final Map, Integer> watchableDatatypes = new HashMap<>(); + static { + watchableDatatypes.put(byte.class, 0); + watchableDatatypes.put(short.class, 1); + watchableDatatypes.put(int.class, 2); + watchableDatatypes.put(float.class, 3); + watchableDatatypes.put(String.class, 4); + } + + @Override + public Object getDataWatcherItem(Object dwo, Object value) { + return watchableObjectConstructor.invoke(watchableDatatypes.get(value.getClass()), dwo, value); + } + + private static final Reflection.FieldAccessor teleportX = Reflection.getField(REntity.teleportPacket, int.class, 1); + private static final Reflection.FieldAccessor teleportY = Reflection.getField(REntity.teleportPacket, int.class, 2); + private static final Reflection.FieldAccessor teleportZ = Reflection.getField(REntity.teleportPacket, int.class, 3); + @Override + public void setTeleportPacketPosition(Object packet, double x, double y, double z) { + teleportX.set(packet, MathHelper.floor(x * 32)); + teleportY.set(packet, MathHelper.floor(y * 32)); + teleportZ.set(packet, MathHelper.floor(z * 32)); + } + + @Override + public void setSpawnPacketUUID(Object packet, UUID uuid) { + // field not present + } + + private static final Reflection.FieldAccessor equipmentSlot = Reflection.getField(REntity.equipmentPacket, int.class, 1); + @Override + public void setEquipmentPacketSlot(Object packet, String slot) { + switch(slot){ + case "HEAD": + equipmentSlot.set(packet, 4); + break; + case "CHEST": + equipmentSlot.set(packet, 3); + break; + case "LEGS": + equipmentSlot.set(packet, 2); + break; + case "FEET": + equipmentSlot.set(packet, 1); + break; + case "MAINHAND": + case "OFFHAND": + default: + equipmentSlot.set(packet, 0); + } + } } diff --git a/FightSystem_8/src/de/steamwar/fightsystem/utils/FlatteningWrapper8.java b/FightSystem_8/src/de/steamwar/fightsystem/utils/FlatteningWrapper8.java index 5782625..b4a9fd3 100644 --- a/FightSystem_8/src/de/steamwar/fightsystem/utils/FlatteningWrapper8.java +++ b/FightSystem_8/src/de/steamwar/fightsystem/utils/FlatteningWrapper8.java @@ -19,10 +19,14 @@ package de.steamwar.fightsystem.utils; +import com.comphenix.tinyprotocol.Reflection; +import de.steamwar.core.Core; +import de.steamwar.fightsystem.record.REntity; import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.entity.EntityType; import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -86,4 +90,29 @@ public class FlatteningWrapper8 implements FlatteningWrapper.IFlatteningWrapper public boolean checkPistonMoving(Block block) { return block.getType() == Material.PISTON_MOVING_PIECE; } + + private static final Class dataWatcher = Reflection.getClass("{nms}.DataWatcher"); + private static final Reflection.FieldAccessor namedSpawnDataWatcher = Reflection.getField(REntity.namedSpawnPacket, dataWatcher, 0); + private static final Class entity = Reflection.getClass("{nms}.Entity"); + private static final Reflection.ConstructorInvoker dataWatcherConstructor = Reflection.getConstructor(dataWatcher, entity); + @Override + public void setNamedSpawnPacketDataWatcher(Object packet) { + namedSpawnDataWatcher.set(packet, dataWatcherConstructor.invoke((Object) null)); + } + + private static final Reflection.FieldAccessor spawnType = Reflection.getField(REntity.spawnPacket, int.class, Core.getVersion() > 8 ? 6 : 9); + @Override + public void setSpawnPacketType(Object packet, EntityType type) { + switch(type) { + case PRIMED_TNT: + spawnType.set(packet, 50); + break; + case ARROW: + spawnType.set(packet, 60); + break; + case FIREBALL: + spawnType.set(packet, 63); + break; + } + } } diff --git a/FightSystem_8/src/de/steamwar/fightsystem/utils/TechHider8.java b/FightSystem_8/src/de/steamwar/fightsystem/utils/TechHider8.java index 3a8e4f6..39aaecc 100644 --- a/FightSystem_8/src/de/steamwar/fightsystem/utils/TechHider8.java +++ b/FightSystem_8/src/de/steamwar/fightsystem/utils/TechHider8.java @@ -19,19 +19,13 @@ package de.steamwar.fightsystem.utils; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.events.PacketAdapter; -import com.comphenix.protocol.events.PacketEvent; -import de.steamwar.fightsystem.FightSystem; +import java.util.function.BiFunction; -public class TechHider8 extends PacketAdapter { - - public TechHider8() { - super(FightSystem.getPlugin(), PacketType.Play.Server.MAP_CHUNK); - } +public class TechHider8 implements BiFunction { @Override - public void onPacketSending(PacketEvent e) { - // no implementation availible + public byte[] apply(byte[] data, Integer primaryBitMask) { + // No implementation availible + return data; } } diff --git a/FightSystem_9/src/de/steamwar/fightsystem/utils/BountifulWrapper9.java b/FightSystem_9/src/de/steamwar/fightsystem/utils/BountifulWrapper9.java index 12312f9..dc7dbee 100644 --- a/FightSystem_9/src/de/steamwar/fightsystem/utils/BountifulWrapper9.java +++ b/FightSystem_9/src/de/steamwar/fightsystem/utils/BountifulWrapper9.java @@ -19,9 +19,10 @@ package de.steamwar.fightsystem.utils; -import com.comphenix.protocol.wrappers.EnumWrappers; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.fightsystem.listener.Recording; import de.steamwar.fightsystem.record.GlobalRecorder; +import de.steamwar.fightsystem.record.REntity; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.Material; @@ -37,11 +38,24 @@ import org.bukkit.event.player.PlayerPickupArrowEvent; import org.bukkit.event.player.PlayerSwapHandItemsEvent; import org.bukkit.scoreboard.Team; +import java.lang.reflect.Field; +import java.lang.reflect.ParameterizedType; +import java.util.UUID; + public class BountifulWrapper9 implements BountifulWrapper.IBountifulWrapper { + + private static final Class enumHand = Reflection.getClass("{nms}.EnumHand"); + private static final Object mainHand = enumHand.getEnumConstants()[0]; + private static final Reflection.FieldAccessor blockPlaceHand = Reflection.getField(Recording.blockPlacePacket, enumHand, 0); + @Override - public boolean bowInHand(EnumWrappers.Hand hand, Player p) { - return (hand == EnumWrappers.Hand.MAIN_HAND && p.getInventory().getItemInMainHand().getType() == Material.BOW) || - (hand == EnumWrappers.Hand.OFF_HAND && p.getInventory().getItemInOffHand().getType() == Material.BOW); + public boolean mainHand(Object packet) { + return blockPlaceHand.get(packet) == mainHand; + } + + @Override + public boolean bowInHand(boolean mainHand, Player p) { + return (mainHand ? p.getInventory().getItemInMainHand() : p.getInventory().getItemInOffHand()).getType() == Material.BOW; } @Override @@ -110,4 +124,73 @@ public class BountifulWrapper9 implements BountifulWrapper.IBountifulWrapper { public void spawnParticle(World world, String particleName, double x, double y, double z) { world.spawnParticle(Particle.valueOf(particleName), x, y, z, 1); } + + + private static final Class dataWatcherObject = Reflection.getClass("{nms}.DataWatcherObject"); + private static final Class dataWatcherRegistry = Reflection.getClass("{nms}.DataWatcherRegistry"); + private static final Class dataWatcherSerializer = Reflection.getClass("{nms}.DataWatcherSerializer"); + private static final Reflection.ConstructorInvoker dataWatcherObjectConstructor = Reflection.getConstructor(dataWatcherObject, int.class, dataWatcherSerializer); + @Override + public Object getDataWatcherObject(int index, Class type) { + for(Field field : dataWatcherRegistry.getFields()) { + if(dataWatcherSerializer.isAssignableFrom(field.getType()) && type.equals(((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0])) { + try { + return dataWatcherObjectConstructor.invoke(index, field.get(null)); + } catch (IllegalAccessException e) { + throw new SecurityException("Could not get field", e); + } + } + } + throw new SecurityException("Could not find Serializer for " + type.getName()); + } + + private static final Class item = Reflection.getClass("{nms}.DataWatcher$Item"); + private static final Reflection.ConstructorInvoker itemConstructor = Reflection.getConstructor(item, dataWatcherObject, Object.class); + @Override + public Object getDataWatcherItem(Object dwo, Object value) { + return itemConstructor.invoke(dwo, value); + } + + private static final Reflection.FieldAccessor teleportX = Reflection.getField(REntity.teleportPacket, double.class, 0); + private static final Reflection.FieldAccessor teleportY = Reflection.getField(REntity.teleportPacket, double.class, 1); + private static final Reflection.FieldAccessor teleportZ = Reflection.getField(REntity.teleportPacket, double.class, 2); + @Override + public void setTeleportPacketPosition(Object packet, double x, double y, double z) { + teleportX.set(packet, x); + teleportY.set(packet, y); + teleportZ.set(packet, z); + } + + private static final Reflection.FieldAccessor spawnUUID = Reflection.getField(REntity.spawnPacket, UUID.class, 0); + @Override + public void setSpawnPacketUUID(Object packet, UUID uuid) { + spawnUUID.set(packet, uuid); + } + + private static final Class enumItemSlot = Reflection.getClass("{nms}.EnumItemSlot"); + private static final Reflection.FieldAccessor equipmentSlot = Reflection.getField(REntity.equipmentPacket, enumItemSlot, 0); + private static final Object[] itemSlots = enumItemSlot.getEnumConstants(); + @Override + public void setEquipmentPacketSlot(Object packet, String slot) { + switch(slot){ + case "HEAD": + equipmentSlot.set(packet, itemSlots[5]); + break; + case "CHEST": + equipmentSlot.set(packet, itemSlots[4]); + break; + case "LEGS": + equipmentSlot.set(packet, itemSlots[3]); + break; + case "FEET": + equipmentSlot.set(packet, itemSlots[2]); + break; + case "OFFHAND": + equipmentSlot.set(packet, itemSlots[1]); + break; + case "MAINHAND": + default: + equipmentSlot.set(packet, itemSlots[0]); + } + } } diff --git a/FightSystem_12/src/de/steamwar/fightsystem/utils/TechHider12.java b/FightSystem_9/src/de/steamwar/fightsystem/utils/TechHider9.java similarity index 57% rename from FightSystem_12/src/de/steamwar/fightsystem/utils/TechHider12.java rename to FightSystem_9/src/de/steamwar/fightsystem/utils/TechHider9.java index f554505..e1f6bef 100644 --- a/FightSystem_12/src/de/steamwar/fightsystem/utils/TechHider12.java +++ b/FightSystem_9/src/de/steamwar/fightsystem/utils/TechHider9.java @@ -1,7 +1,7 @@ -/* +/* This file is a part of the SteamWar software. - - Copyright (C) 2020 SteamWar.de-Serverteam + + Copyright (C) 2021 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 @@ -15,68 +15,25 @@ 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.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.nbt.NbtBase; -import com.comphenix.protocol.wrappers.nbt.NbtCompound; -import de.steamwar.fightsystem.Config; -import de.steamwar.fightsystem.FightSystem; import io.netty.buffer.ByteBuf; import io.netty.buffer.UnpooledByteBufAllocator; import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import java.util.List; import java.util.Set; +import java.util.function.BiFunction; import java.util.logging.Level; -import static de.steamwar.fightsystem.utils.TechHider.bypass; - -public class TechHider12 extends PacketAdapter { +public class TechHider9 implements BiFunction { private final Set hiddenBlockIds = BlockIdWrapper.impl.getHiddenBlockIds(); private final int obfuscateWith = BlockIdWrapper.impl.getObfuscateWith(); - public TechHider12() { - super(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; - - packet = packet.shallowClone(); - e.setPacket(packet); - StructureModifier>> list = packet.getListNbtModifier(); - List> nmsTags = list.read(0); - boolean changed = false; - for(int i = nmsTags.size() - 1; i >= 0; i--){ - NbtCompound nbt = (NbtCompound)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 = packet.getByteArrays(); - byte [] data = byteArray.read(0); + public byte[] apply(byte[] data, Integer primaryBitMask) { ByteBuf buffer = UnpooledByteBufAllocator.DEFAULT.directBuffer(data.length + 100); int i = 0; @@ -96,7 +53,6 @@ public class TechHider12 extends PacketAdapter { if(hiddenBlockIds.contains(entry)){ entry = obfuscateWith; - changed = true; } buffer.writeBytes(TechHider.writeVarInt(entry)); } @@ -115,10 +71,8 @@ public class TechHider12 extends PacketAdapter { i += 4096; //Skylight (Not in Nether/End!!!) 2048 + Blocklight 2048 } - if(changed){ - data = new byte[buffer.readableBytes()]; - buffer.readBytes(data); - byteArray.write(0, data); - } + data = new byte[buffer.readableBytes()]; + buffer.readBytes(data); + return data; } } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index 12c713d..8c977c4 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -140,6 +140,8 @@ public class FightSystem extends JavaPlugin { getLogger().log(Level.SEVERE, "Failed to replace commands", e); } + REntity.initWatchers(); + if(Config.mode == ArenaMode.EVENT) { setPreSchemState(); }else if(Config.mode == ArenaMode.CHECK){ diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java b/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java index c00c9ba..80129fb 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/fight/Fight.java @@ -19,26 +19,21 @@ package de.steamwar.fightsystem.fight; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.EnumWrappers; -import com.comphenix.protocol.wrappers.PlayerInfoData; -import com.comphenix.protocol.wrappers.WrappedChatComponent; -import com.comphenix.protocol.wrappers.WrappedGameProfile; +import com.comphenix.tinyprotocol.Reflection; +import com.mojang.authlib.GameProfile; +import de.steamwar.core.Core; import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.record.GlobalRecorder; +import de.steamwar.fightsystem.utils.ProtocolAPI; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Sound; import org.bukkit.entity.Player; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; -import java.util.logging.Level; public class Fight { private Fight(){} @@ -105,6 +100,7 @@ public class Fight { return null; } + @SuppressWarnings("deprecation") public static void setPlayerGamemode(Player player, GameMode gameMode) { player.setGameMode(gameMode); @@ -134,17 +130,30 @@ public class Fight { } } + private static final Class playerInfoPacket = Reflection.getClass("{nms}.PacketPlayOutPlayerInfo"); + private static final Reflection.ConstructorInvoker playerInfoConstructor = Reflection.getConstructor(playerInfoPacket); + private static final Class playerInfoActionClass = Reflection.getClass("{nms}.PacketPlayOutPlayerInfo$EnumPlayerInfoAction"); + public static final Object addPlayer = playerInfoActionClass.getEnumConstants()[0]; + private static final Reflection.FieldAccessor playerInfoAction = Reflection.getField(playerInfoPacket, playerInfoActionClass, 0); + private static final Object updateGamemode = playerInfoActionClass.getEnumConstants()[1]; + public static final Object removePlayer = playerInfoActionClass.getEnumConstants()[4]; + private static final Reflection.FieldAccessor playerInfoData = Reflection.getField(playerInfoPacket, List.class, 0); + private static final Class playerInfoDataClass = Reflection.getClass("{nms}.PacketPlayOutPlayerInfo$PlayerInfoData"); + private static final Class enumGamemode = Reflection.getClass(Core.getVersion() > 9 ? "{nms}.EnumGamemode" : "{nms}.WorldSettings$EnumGamemode"); + public static final Object creative = enumGamemode.getEnumConstants()[2]; + private static final Object spectator = enumGamemode.getEnumConstants()[4]; + private static final Class iChatBaseComponent = Reflection.getClass("{nms}.IChatBaseComponent"); + + private static final Reflection.ConstructorInvoker playerInfoDataConstructor = Reflection.getConstructor(playerInfoDataClass, playerInfoPacket, GameProfile.class, int.class, enumGamemode, iChatBaseComponent); public static void pseudoSpectator(Player player, boolean enable) { - PacketContainer gm1packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); - gm1packet.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.UPDATE_GAME_MODE); - List playerInfoActions = new ArrayList<>(); - playerInfoActions.add(new PlayerInfoData(WrappedGameProfile.fromPlayer(player), 1, enable ? EnumWrappers.NativeGameMode.CREATIVE : EnumWrappers.NativeGameMode.SPECTATOR, WrappedChatComponent.fromText(player.getDisplayName()))); - gm1packet.getPlayerInfoDataLists().write(0, playerInfoActions); - try { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, gm1packet); - } catch (InvocationTargetException e) { - Bukkit.getLogger().log(Level.SEVERE, "Invocation target exception", e); - } + ProtocolAPI.tinyProtocol.sendPacket(player, playerInfoPacket(updateGamemode, new GameProfile(player.getUniqueId(), player.getName()), enable ? creative : spectator)); + } + + public static Object playerInfoPacket(Object action, GameProfile profile, Object mode) { + Object packet = playerInfoConstructor.invoke(); + playerInfoAction.set(packet, action); + playerInfoData.set(packet, Collections.singletonList(playerInfoDataConstructor.invoke(packet, profile, 0, mode, null))); + return packet; } public static int getMaxRank(){ diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java b/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java index 94d8182..1a69667 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/listener/Recording.java @@ -19,12 +19,7 @@ package de.steamwar.fightsystem.listener; -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.wrappers.EnumWrappers; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.fight.Fight; @@ -37,6 +32,7 @@ import de.steamwar.fightsystem.states.StateDependentListener; import de.steamwar.fightsystem.states.StateDependentTask; import de.steamwar.fightsystem.utils.BountifulWrapper; import de.steamwar.fightsystem.utils.FlatteningWrapper; +import de.steamwar.fightsystem.utils.ProtocolAPI; import de.steamwar.fightsystem.utils.SWSound; import org.bukkit.Bukkit; import org.bukkit.Location; @@ -62,28 +58,6 @@ public class Recording implements Listener { private static final int AIR = 0; private static final Random random = new Random(); private static final World world = Bukkit.getWorlds().get(0); - private static final PacketAdapter BOW_PACKET_PROCESSOR = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.BLOCK_PLACE) { - @Override - public void onPacketReceiving(PacketEvent event) { - PacketContainer packet = event.getPacket(); - EnumWrappers.Hand hand = packet.getHands().read(0); - Player p = event.getPlayer(); - - if(!BountifulWrapper.impl.bowInHand(hand, p)) - return; - - GlobalRecorder.getInstance().bowSpan(p, true, hand != EnumWrappers.Hand.MAIN_HAND); - } - }; - private static final PacketAdapter BOW_PACKET_DEDRAW_PROCESSOR = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.BLOCK_DIG) { - @Override - public void onPacketReceiving(PacketEvent e) { - PacketContainer packetDig = e.getPacket(); - if(packetDig.getPlayerDigTypes().read(0) == EnumWrappers.PlayerDigType.RELEASE_USE_ITEM) { - GlobalRecorder.getInstance().bowSpan(e.getPlayer(), false, false); - } - } - }; public static ItemStack disarmNull(ItemStack stack){ if(stack == null) @@ -118,14 +92,14 @@ public class Recording implements Listener { new StateDependent(ArenaMode.AntiReplay, FightState.Ingame) { @Override public void enable() { - ProtocolLibrary.getProtocolManager().addPacketListener(BOW_PACKET_PROCESSOR); - ProtocolLibrary.getProtocolManager().addPacketListener(BOW_PACKET_DEDRAW_PROCESSOR); + ProtocolAPI.setIncomingHandler(blockPlacePacket, Recording.this::blockPlace); + ProtocolAPI.setIncomingHandler(blockDigPacket, Recording.this::blockDig); } @Override public void disable() { - ProtocolLibrary.getProtocolManager().removePacketListener(BOW_PACKET_PROCESSOR); - ProtocolLibrary.getProtocolManager().removePacketListener(BOW_PACKET_DEDRAW_PROCESSOR); + ProtocolAPI.removeIncomingHandler(blockPlacePacket); + ProtocolAPI.removeIncomingHandler(blockDigPacket); } }.register(); new StateDependentTask(ArenaMode.AntiReplay, FightState.All, () -> { @@ -141,6 +115,24 @@ public class Recording implements Listener { }, 1, 1); } + private static final Class blockDigPacket = Reflection.getClass("{nms}.PacketPlayInBlockDig"); + private static final Class playerDigType = blockDigPacket.getDeclaredClasses()[0]; + private static final Reflection.FieldAccessor blockDigType = Reflection.getField(blockDigPacket, playerDigType, 0); + private static final Object releaseUseItem = playerDigType.getEnumConstants()[5]; + private Object blockDig(Player p, Object packet) { + if(blockDigType.get(packet) == releaseUseItem) + GlobalRecorder.getInstance().bowSpan(p, false, false); + return packet; + } + + public static final Class blockPlacePacket = Reflection.getClass("{nms}.PacketPlayInBlockPlace"); + private Object blockPlace(Player p, Object packet) { + boolean mainHand = BountifulWrapper.impl.mainHand(packet); + if(BountifulWrapper.impl.bowInHand(mainHand, p)) + GlobalRecorder.getInstance().bowSpan(p, true, !mainHand); + return packet; + } + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) public void onPlayerMove(PlayerMoveEvent e){ if(isNotSent(e.getPlayer())) @@ -223,7 +215,7 @@ public class Recording implements Listener { Location loc = e.getLocation(); GlobalRecorder.getInstance().entityDespawns(e.getEntity()); GlobalRecorder.getInstance().particle(loc.getX(), loc.getY(), loc.getZ(), "EXPLOSION_HUGE"); - GlobalRecorder.getInstance().sound(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), SWSound.ENTITY_GENERIC_EXPLODE, EnumWrappers.SoundCategory.BLOCKS.name(), 4.0F, (1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F) * 0.7F); + GlobalRecorder.getInstance().sound(loc.getBlockX(), loc.getBlockY(), loc.getBlockZ(), SWSound.ENTITY_GENERIC_EXPLODE, "BLOCKS", 4.0F, (1.0F + (random.nextFloat() - random.nextFloat()) * 0.2F) * 0.7F); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/record/REntity.java b/FightSystem_Core/src/de/steamwar/fightsystem/record/REntity.java index 880b41d..c0e70e1 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/record/REntity.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/record/REntity.java @@ -19,18 +19,16 @@ package de.steamwar.fightsystem.record; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.reflect.StructureModifier; -import com.comphenix.protocol.wrappers.*; +import com.comphenix.tinyprotocol.Reflection; import com.mojang.authlib.GameProfile; import de.steamwar.core.Core; +import de.steamwar.fightsystem.fight.Fight; import de.steamwar.fightsystem.listener.FightScoreboard; import de.steamwar.fightsystem.utils.BlockIdWrapper; +import de.steamwar.fightsystem.utils.BountifulWrapper; +import de.steamwar.fightsystem.utils.FlatteningWrapper; +import de.steamwar.fightsystem.utils.ProtocolAPI; import de.steamwar.sql.SteamwarUser; -import net.royawesome.jlibnoise.MathHelper; -import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.EntityType; @@ -39,9 +37,7 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.scoreboard.NameTagVisibility; import org.bukkit.scoreboard.Team; -import java.lang.reflect.InvocationTargetException; import java.util.*; -import java.util.logging.Level; public class REntity { @@ -51,43 +47,48 @@ public class REntity { return entities.get(internalId); } + private static Object entityStatusWatcher; + private static Object sneakingDataWatcher; + private static Object bowDrawnWatcher; + public static void initWatchers() { + // not during to prevent cyclic class init. + entityStatusWatcher = BountifulWrapper.impl.getDataWatcherObject(0, Byte.class); + sneakingDataWatcher = BountifulWrapper.impl.getDataWatcherObject(Core.getVersion() > 12 ? 6 : 0, BlockIdWrapper.impl.getPose(true).getClass()); + bowDrawnWatcher = BountifulWrapper.impl.getDataWatcherObject(Core.getVersion() > 12 ? 7 : 6, Byte.class); + } + + public static void tickFire() { entities.forEach((integer, entity) -> { if(entity.fireTick > 0) { entity.fireTick--; if(entity.fireTick == 0) { - ProtocolLibrary.getProtocolManager().broadcastServerPacket(entity.getDataWatcherPacket(0, (byte)0)); + ProtocolAPI.broadcastPacket(entity.getDataWatcherPacket(entityStatusWatcher, (byte)0)); } } }); } public static void playerJoins(Player player) { - try{ - for(REntity entity : entities.values()){ - if(entity.entityType == EntityType.PLAYER){ - ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getPlayerInfoPacket()); - ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getNamedSpawnPacket()); - for (Map.Entry entry : entity.itemSlots.entrySet()) { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getEquipmentPacket(entry.getKey(), entry.getValue())); - } - }else{ - ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getSpawnEntityPacket()); - } - //ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getTeleportPacket()); Sollte nicht nötig sein? - if(entity.fireTick != 0) { - ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getDataWatcherPacket(0, (byte) 1)); - } - if(entity.sneaks) { - if(Core.getVersion() > 12){ - ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getDataWatcherPacket(6, BlockIdWrapper.impl.getPose(true))); - }else{ - ProtocolLibrary.getProtocolManager().sendServerPacket(player, entity.getDataWatcherPacket(0, (byte) 2)); - } + for(REntity entity : entities.values()){ + if(entity.entityType == EntityType.PLAYER){ + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getPlayerInfoPacket()); + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getNamedSpawnPacket()); + for (Map.Entry entry : entity.itemSlots.entrySet()) { + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getEquipmentPacket(entry.getKey(), entry.getValue())); } + }else{ + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getSpawnEntityPacket()); + } + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getTeleportPacket()); + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getHeadRotationPacket()); + + if(entity.fireTick != 0) { + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getDataWatcherPacket(entityStatusWatcher, (byte) 1)); + } + if(entity.sneaks) { + ProtocolAPI.tinyProtocol.sendPacket(player, entity.getDataWatcherPacket(sneakingDataWatcher, BlockIdWrapper.impl.getPose(true))); } - }catch(InvocationTargetException e){ - Bukkit.getLogger().log(Level.SEVERE, "Could not sync player", e); } } @@ -114,7 +115,7 @@ public class REntity { private final int entityId; private final UUID uuid; private final EntityType entityType; - private final PlayerInfoData playerInfoData; + private final String name; private final Map itemSlots = new HashMap<>(); private double locX; @@ -133,23 +134,23 @@ public class REntity { SteamwarUser user = SteamwarUser.get(userId); this.uuid = user.getUUID(); - this.playerInfoData = new PlayerInfoData(WrappedGameProfile.fromHandle(new GameProfile(uuid, user.getUserName())), 0, EnumWrappers.NativeGameMode.SURVIVAL, WrappedChatComponent.fromText(user.getUserName())); + this.name = user.getUserName(); entities.put(internalId, this); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getPlayerInfoPacket()); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getNamedSpawnPacket()); - team.addEntry(user.getUserName()); + ProtocolAPI.broadcastPacket(getPlayerInfoPacket()); + ProtocolAPI.broadcastPacket(getNamedSpawnPacket()); + team.addEntry(name); } public REntity(int internalId, EntityType entityType){ this.internalId = internalId; this.entityType = entityType; this.entityId = entityCount--; - this.playerInfoData = null; + this.name = null; this.uuid = new UUID(random.nextLong() & -61441L | 16384L, random.nextLong() & 4611686018427387903L | -9223372036854775808L); entities.put(internalId, this); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getSpawnEntityPacket()); + ProtocolAPI.broadcastPacket(getSpawnEntityPacket()); } public void move(double locX, double locY, double locZ, float pitch, float yaw, byte headYaw){ @@ -159,43 +160,50 @@ public class REntity { this.yaw = (byte)((int)(yaw * 256.0F / 360.0F)); this.pitch = (byte)((int)(pitch * 256.0F / 360.0F)); this.headYaw = headYaw; - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getTeleportPacket()); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getHeadRotationPacket()); + ProtocolAPI.broadcastPacket(getTeleportPacket()); + ProtocolAPI.broadcastPacket(getHeadRotationPacket()); } + private static final Class animationPacket = Reflection.getClass("{nms}.PacketPlayOutAnimation"); + private static final Reflection.ConstructorInvoker animationConstructor = Reflection.getConstructor(animationPacket); + private static final Reflection.FieldAccessor animationEntity = Reflection.getField(animationPacket, int.class, 0); + private static final Reflection.FieldAccessor animationAnimation = Reflection.getField(animationPacket, int.class, 1); public void animation(byte animation) { - PacketContainer animationPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ANIMATION); - StructureModifier ints = animationPacket.getIntegers(); - ints.write(0, entityId); - ints.write(1, (int) animation); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(animationPacket); + Object packet = animationConstructor.invoke(); + animationEntity.set(packet, entityId); + animationAnimation.set(packet, (int) animation); + ProtocolAPI.broadcastPacket(packet); } + private static final Class velocityPacket = Reflection.getClass("{nms}.PacketPlayOutEntityVelocity"); + private static final Reflection.ConstructorInvoker velocityConstructor = Reflection.getConstructor(velocityPacket); + private static final Reflection.FieldAccessor velocityEntity = Reflection.getField(velocityPacket, int.class, 0); + private static final Reflection.FieldAccessor velocityX = Reflection.getField(velocityPacket, int.class, 1); + private static final Reflection.FieldAccessor velocityY = Reflection.getField(velocityPacket, int.class, 2); + private static final Reflection.FieldAccessor velocityZ = Reflection.getField(velocityPacket, int.class, 3); public void setVelocity(double dX, double dY, double dZ) { - PacketContainer velocityPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_VELOCITY); - StructureModifier ints = velocityPacket.getIntegers(); - ints.write(0, entityId); - ints.write(1, calcVelocity(dX)); - ints.write(2, calcVelocity(dY)); - ints.write(3, calcVelocity(dZ)); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(velocityPacket); + Object packet = velocityConstructor.invoke(); + velocityEntity.set(packet, entityId); + velocityX.set(packet, calcVelocity(dX)); + velocityY.set(packet, calcVelocity(dY)); + velocityZ.set(packet, calcVelocity(dZ)); + ProtocolAPI.broadcastPacket(packet); } + private static final Class statusPacket = Reflection.getClass("{nms}.PacketPlayOutEntityStatus"); + private static final Reflection.ConstructorInvoker statusConstructor = Reflection.getConstructor(statusPacket); + private static final Reflection.FieldAccessor statusEntity = Reflection.getField(statusPacket, int.class, 0); + private static final Reflection.FieldAccessor statusStatus = Reflection.getField(statusPacket, byte.class, 0); public void damage() { - PacketContainer statusPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_STATUS); - statusPacket.getIntegers().write(0, entityId); - statusPacket.getBytes().write(0, (byte) 2); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(statusPacket); + Object packet = statusConstructor.invoke(); + statusEntity.set(packet, entityId); + statusStatus.set(packet, (byte) 2); + ProtocolAPI.broadcastPacket(packet); } public void sneak(boolean sneaking) { sneaks = sneaking; - - if(Core.getVersion() > 12){ - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDataWatcherPacket(6, BlockIdWrapper.impl.getPose(sneaking))); - }else{ - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDataWatcherPacket(0, sneaking ? (byte) 2 : (byte) 0)); - } + ProtocolAPI.broadcastPacket(getDataWatcherPacket(sneakingDataWatcher, BlockIdWrapper.impl.getPose(sneaking))); } public void setOnFire(boolean perma) { @@ -205,14 +213,14 @@ public class REntity { fireTick = -1; } - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDataWatcherPacket(0, (byte) 1)); + ProtocolAPI.broadcastPacket(getDataWatcherPacket(entityStatusWatcher, (byte) 1)); } public void setBowDrawn(boolean drawn, boolean offHand) { if(Core.getVersion() > 8){ - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDataWatcherPacket(Core.getVersion() > 12 ? 7 : 6, (byte) ((drawn ? 1 : 0) + (offHand ? 2 : 0)))); + ProtocolAPI.broadcastPacket(getDataWatcherPacket(bowDrawnWatcher, (byte) ((drawn ? 1 : 0) + (offHand ? 2 : 0)))); }else{ - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getDataWatcherPacket(0, (byte)0x10)); + ProtocolAPI.broadcastPacket(getDataWatcherPacket(entityStatusWatcher, (byte)0x10)); } } @@ -222,7 +230,7 @@ public class REntity { stack.addUnsafeEnchantment(Enchantment.DURABILITY, 1); itemSlots.put(slot, stack); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(getEquipmentPacket(slot, stack)); + ProtocolAPI.broadcastPacket(getEquipmentPacket(slot, stack)); } public void die(){ @@ -230,144 +238,99 @@ public class REntity { entities.remove(internalId); } + private static final Class destroyPacket = Reflection.getClass("{nms}.PacketPlayOutEntityDestroy"); + private static final Reflection.ConstructorInvoker destroyConstructor = Reflection.getConstructor(destroyPacket); + private static final Reflection.FieldAccessor destroyEntities = Reflection.getField(destroyPacket, int[].class, 0); private void broadcastDeath(){ if(entityType == EntityType.PLAYER){ - PacketContainer infoPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); - infoPacket.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.REMOVE_PLAYER); - infoPacket.getPlayerInfoDataLists().write(0, Collections.singletonList(playerInfoData)); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(infoPacket); - team.removeEntry(playerInfoData.getProfile().getName()); + ProtocolAPI.broadcastPacket(Fight.playerInfoPacket(Fight.removePlayer, new GameProfile(uuid, name), Fight.creative)); + team.removeEntry(name); } - PacketContainer destroyPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_DESTROY); - destroyPacket.getIntegerArrays().write(0, new int[]{entityId}); - ProtocolLibrary.getProtocolManager().broadcastServerPacket(destroyPacket); + Object packet = destroyConstructor.invoke(); + destroyEntities.set(packet, new int[]{entityId}); + ProtocolAPI.broadcastPacket(packet); } private int calcVelocity(double value) { return (int)(Math.max(-3.9, Math.min(value, 3.9)) * 8000); } - private void fillPositioningPacket(PacketContainer packet, StructureModifier ints){ - ints.write(0, entityId); - if(Core.getVersion() > 8){ - StructureModifier doubles = packet.getDoubles(); - doubles.write(0, locX); - doubles.write(1, locY); - doubles.write(2, locZ); - }else{ - ints.write(1, MathHelper.floor(locX * 32)); - ints.write(2, MathHelper.floor(locY * 32)); - ints.write(3, MathHelper.floor(locZ * 32)); - } + private static final Class metadataPacket = Reflection.getClass("{nms}.PacketPlayOutEntityMetadata"); + private static final Reflection.ConstructorInvoker metadataConstructor = Reflection.getConstructor(metadataPacket); + private static final Reflection.FieldAccessor metadataEntity = Reflection.getField(metadataPacket, int.class, 0); + private static final Reflection.FieldAccessor metadataMetadata = Reflection.getField(metadataPacket, List.class, 0); + private Object getDataWatcherPacket(Object dataWatcherObject, Object value) { + Object packet = metadataConstructor.invoke(); + metadataEntity.set(packet, entityId); + metadataMetadata.set(packet, Collections.singletonList(BountifulWrapper.impl.getDataWatcherItem(dataWatcherObject, value))); + return packet; } - private void fillByteRotation(PacketContainer packet){ - StructureModifier bytes = packet.getBytes(); - bytes.write(0, yaw); - bytes.write(1, pitch); + public static final Class teleportPacket = Reflection.getClass("{nms}.PacketPlayOutEntityTeleport"); + private static final Reflection.ConstructorInvoker teleportConstructor = Reflection.getConstructor(teleportPacket); + private static final Reflection.FieldAccessor teleportEntity = Reflection.getField(teleportPacket, int.class, 0); + private static final Reflection.FieldAccessor teleportYaw = Reflection.getField(teleportPacket, byte.class, 0); + private static final Reflection.FieldAccessor teleportPitch = Reflection.getField(teleportPacket, byte.class, 1); + private Object getTeleportPacket(){ + Object packet = teleportConstructor.invoke(); + teleportEntity.set(packet, entityId); + BountifulWrapper.impl.setTeleportPacketPosition(packet, locX, locY, locZ); + teleportYaw.set(packet, yaw); + teleportPitch.set(packet, pitch); + return packet; } - private PacketContainer getDataWatcherPacket(int index, Object value) { - PacketContainer metadataPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_METADATA); - metadataPacket.getIntegers().write(0, entityId); - WrappedWatchableObject watchable = new WrappedWatchableObject(new WrappedDataWatcher.WrappedDataWatcherObject(index, WrappedDataWatcher.Registry.get(value.getClass())), value); - watchable.setDirtyState(true); - metadataPacket.getWatchableCollectionModifier().write(0, Collections.singletonList(watchable)); - return metadataPacket; + private static final Class headRotationPacket = Reflection.getClass("{nms}.PacketPlayOutEntityHeadRotation"); + private static final Reflection.ConstructorInvoker headRotationConstructor = Reflection.getConstructor(headRotationPacket); + private static final Reflection.FieldAccessor headRotationEntity = Reflection.getField(headRotationPacket, int.class, 0); + private static final Reflection.FieldAccessor headRotationYaw = Reflection.getField(headRotationPacket, byte.class, 0); + private Object getHeadRotationPacket(){ + Object packet = headRotationConstructor.invoke(); + headRotationEntity.set(packet, entityId); + headRotationYaw.set(packet, headYaw); + return packet; } - private PacketContainer getTeleportPacket(){ - PacketContainer teleportPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_TELEPORT); - fillPositioningPacket(teleportPacket, teleportPacket.getIntegers()); - fillByteRotation(teleportPacket); - return teleportPacket; + public static final Class spawnPacket = Reflection.getClass("{nms}.PacketPlayOutSpawnEntity"); + private static final Reflection.ConstructorInvoker spawnConstructor = Reflection.getConstructor(spawnPacket); + private static final Reflection.FieldAccessor spawnEntity = Reflection.getField(spawnPacket, int.class, 0); + private Object getSpawnEntityPacket(){ + Object packet = spawnConstructor.invoke(); + spawnEntity.set(packet, entityId); + BountifulWrapper.impl.setSpawnPacketUUID(packet, uuid); + FlatteningWrapper.impl.setSpawnPacketType(packet, entityType); + return packet; } - private PacketContainer getHeadRotationPacket(){ - PacketContainer headRotation = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_HEAD_ROTATION); - headRotation.getIntegers().write(0, entityId); - headRotation.getBytes().write(0, headYaw); - return headRotation; + public static final Class equipmentPacket = Reflection.getClass("{nms}.PacketPlayOutEntityEquipment"); + private static final Reflection.ConstructorInvoker equipmentConstructor = Reflection.getConstructor(equipmentPacket); + private static final Reflection.FieldAccessor equipmentEntity = Reflection.getField(equipmentPacket, int.class, 0); + private static final Class itemStack = Reflection.getClass("{nms}.ItemStack"); + private static final Reflection.FieldAccessor equipmentStack = Reflection.getField(equipmentPacket, itemStack, 0); + private static final Class craftItemStack = Reflection.getClass("{obc}.inventory.CraftItemStack"); + private static final Reflection.MethodInvoker asNMSCopy = Reflection.getTypedMethod(craftItemStack, "asNMSCopy", itemStack, ItemStack.class); + private Object getEquipmentPacket(String slot, ItemStack stack){ + Object packet = equipmentConstructor.invoke(); + equipmentEntity.set(packet, entityId); + BountifulWrapper.impl.setEquipmentPacketSlot(packet, slot); + equipmentStack.set(packet, asNMSCopy.invoke(null, stack)); + return packet; } - private PacketContainer getSpawnEntityPacket(){ - PacketContainer spawnPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.SPAWN_ENTITY); - StructureModifier ints = spawnPacket.getIntegers(); - fillPositioningPacket(spawnPacket, ints); - spawnPacket.getUUIDs().write(0, uuid); - if(Core.getVersion() > 8){ - spawnPacket.getUUIDs().write(0, uuid); - ints.write(1, 0); // dX - ints.write(2, 0); // dY - ints.write(3, 0); // dZ - } - ints.write(4, (int)pitch); - ints.write(5, (int)yaw); - if(Core.getVersion() > 12){ - spawnPacket.getEntityTypeModifier().write(0, entityType); - }else{ - switch(entityType){ - case PRIMED_TNT: - ints.write(6, 50); - break; - case ARROW: - ints.write(6, 60); - break; - case FIREBALL: - ints.write(6, 63); - break; - } - } - return spawnPacket; + private Object getPlayerInfoPacket(){ + return Fight.playerInfoPacket(Fight.addPlayer, new GameProfile(uuid, name), Fight.creative); } - private PacketContainer getEquipmentPacket(String slot, ItemStack stack){ - PacketContainer equipmentPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_EQUIPMENT); - StructureModifier ints = equipmentPacket.getIntegers(); - ints.write(0, entityId); - if(Core.getVersion() == 8){ - switch(slot){ - case "MAINHAND": - case "OFFHAND": - ints.write(1, 0); - break; - case "HEAD": - ints.write(1, 4); - break; - case "CHEST": - ints.write(1, 3); - break; - case "LEGS": - ints.write(1, 2); - break; - case "FEET": - default: - ints.write(1, 1); - } - }else{ - equipmentPacket.getItemSlots().write(0, EnumWrappers.ItemSlot.valueOf(slot)); - } - equipmentPacket.getItemModifier().write(0, stack); - return equipmentPacket; - } - - private PacketContainer getPlayerInfoPacket(){ - PacketContainer infoPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.PLAYER_INFO); - infoPacket.getPlayerInfoAction().write(0, EnumWrappers.PlayerInfoAction.ADD_PLAYER); - infoPacket.getPlayerInfoDataLists().write(0, Collections.singletonList(playerInfoData)); - return infoPacket; - } - - private PacketContainer getNamedSpawnPacket(){ - PacketContainer namedSpawnPacket = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.NAMED_ENTITY_SPAWN); - StructureModifier ints = namedSpawnPacket.getIntegers(); - fillPositioningPacket(namedSpawnPacket, ints); - namedSpawnPacket.getUUIDs().write(0, uuid); - fillByteRotation(namedSpawnPacket); - if(Core.getVersion() < 13){ - namedSpawnPacket.getDataWatcherModifier().write(0, new WrappedDataWatcher()); - } - return namedSpawnPacket; + public static final Class namedSpawnPacket = Reflection.getClass("{nms}.PacketPlayOutNamedEntitySpawn"); + private static final Reflection.ConstructorInvoker namedSpawnConstructor = Reflection.getConstructor(namedSpawnPacket); + private static final Reflection.FieldAccessor namedSpawnEntity = Reflection.getField(namedSpawnPacket, int.class, 0); + private static final Reflection.FieldAccessor namedSpawnUUID = Reflection.getField(namedSpawnPacket, UUID.class, 0); + private Object getNamedSpawnPacket(){ + Object packet = namedSpawnConstructor.invoke(); + namedSpawnEntity.set(packet, entityId); + namedSpawnUUID.set(packet, uuid); + FlatteningWrapper.impl.setNamedSpawnPacketDataWatcher(packet); + return packet; } } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/utils/BountifulWrapper.java b/FightSystem_Core/src/de/steamwar/fightsystem/utils/BountifulWrapper.java index 261c83f..2fa5cba 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/utils/BountifulWrapper.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/utils/BountifulWrapper.java @@ -19,7 +19,6 @@ package de.steamwar.fightsystem.utils; -import com.comphenix.protocol.wrappers.EnumWrappers; import de.steamwar.fightsystem.VersionDependent; import net.md_5.bungee.api.chat.BaseComponent; import org.bukkit.World; @@ -27,13 +26,16 @@ import org.bukkit.entity.Player; import org.bukkit.event.Listener; import org.bukkit.scoreboard.Team; +import java.util.UUID; + public class BountifulWrapper { private BountifulWrapper() {} public static final IBountifulWrapper impl = VersionDependent.getVersionImpl(BountifulWrapper.class.getName()); public interface IBountifulWrapper { - boolean bowInHand(EnumWrappers.Hand hand, Player p); + boolean mainHand(Object packet); + boolean bowInHand(boolean mainHand, Player p); void toActionbar(Player player, BaseComponent... components); void toChat(Player player, BaseComponent... components); @@ -49,5 +51,11 @@ public class BountifulWrapper { Listener newHandSwapRecorder(); void spawnParticle(World world, String particleName, double x, double y, double z); + + Object getDataWatcherObject(int index, Class type); + Object getDataWatcherItem(Object dataWatcherObject, Object value); + void setTeleportPacketPosition(Object packet, double x, double y, double z); + void setSpawnPacketUUID(Object packet, UUID uuid); + void setEquipmentPacketSlot(Object packet, String slot); } } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/utils/FlatteningWrapper.java b/FightSystem_Core/src/de/steamwar/fightsystem/utils/FlatteningWrapper.java index a3b09e2..c20412e 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/utils/FlatteningWrapper.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/utils/FlatteningWrapper.java @@ -24,6 +24,7 @@ import org.bukkit.DyeColor; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.entity.EntityType; import org.bukkit.event.block.BlockPhysicsEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -49,5 +50,8 @@ public class FlatteningWrapper { void forceLoadChunk(World world, int cX, int cZ); boolean checkPistonMoving(Block block); + + void setNamedSpawnPacketDataWatcher(Object packet); + void setSpawnPacketType(Object packet, EntityType type); } } diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/utils/ProtocolAPI.java b/FightSystem_Core/src/de/steamwar/fightsystem/utils/ProtocolAPI.java new file mode 100644 index 0000000..05c5f3f --- /dev/null +++ b/FightSystem_Core/src/de/steamwar/fightsystem/utils/ProtocolAPI.java @@ -0,0 +1,138 @@ +/* + This file is a part of the SteamWar software. + + Copyright (C) 2021 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.tinyprotocol.TinyProtocol; +import de.steamwar.fightsystem.FightSystem; +import io.netty.channel.Channel; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.UnaryOperator; + +public class ProtocolAPI { + private ProtocolAPI() {} + + private static final Map, BiFunction> outgoingHandler = new HashMap<>(); + private static final Map, BiFunction> incomingHandler = new HashMap<>(); + + public static final TinyProtocol tinyProtocol = new TinyProtocol(FightSystem.getPlugin()) { + @Override + public Object onPacketOutAsync(Player receiver, Channel channel, Object packet) { + BiFunction handler = outgoingHandler.get(packet.getClass()); + if(handler == null) + return packet; + return handler.apply(receiver, packet); + } + + @Override + public Object onPacketInAsync(Player sender, Channel channel, Object packet) { + BiFunction handler = incomingHandler.get(packet.getClass()); + if(handler == null) + return packet; + return handler.apply(sender, packet); + } + }; + + public static void setOutgoingHandler(Class packetClass, BiFunction handler) { + outgoingHandler.put(packetClass, handler); + } + + public static void removeOutgoingHandler(Class packetClass) { + outgoingHandler.remove(packetClass); + } + + public static void setIncomingHandler(Class packetClass, BiFunction handler) { + incomingHandler.put(packetClass, handler); + } + + public static void removeIncomingHandler(Class packetClass) { + incomingHandler.remove(packetClass); + } + + public static void broadcastPacket(Object packet) { + Bukkit.getOnlinePlayers().stream().map(tinyProtocol::getChannel).filter(tinyProtocol::hasInjected).forEach(channel -> tinyProtocol.sendPacket(channel, packet)); + } + + public static BiFunction, Object> arrayCloneGenerator(Class elementClass) { + return (array, worker) -> { + int length = Array.getLength(array); + Object result = Array.newInstance(elementClass, length); + + for(int i = 0; i < length; i++) + Array.set(result, i, worker.apply(Array.get(array, i))); + + return result; + }; + } + + public static UnaryOperator shallowCloneGenerator(Class clazz) { + BiConsumer filler = shallowFill(clazz); + + return source -> { + Object clone; + try { + clone = clazz.newInstance(); + } catch (InstantiationException | IllegalAccessException e) { + throw new IllegalStateException("Could not clone " + clazz.getName(), e); + } + filler.accept(source, clone); + return clone; + }; + } + + private static BiConsumer shallowFill(Class clazz) { + if(clazz == null) + return (source, clone) -> {}; + + BiConsumer superFiller = shallowFill(clazz.getSuperclass()); + + Field[] fds = clazz.getDeclaredFields(); + List fields = new ArrayList<>(); + for(Field field : fds) { + if (Modifier.isStatic(field.getModifiers())) + continue; + + field.setAccessible(true); + fields.add(field); + } + + return (source, clone) -> { + superFiller.accept(source, clone); + try { + for(Field field : fields) { + field.set(clone, field.get(source)); + } + } catch (IllegalAccessException e) { + throw new IllegalStateException("Could not set field", e); + } + + }; + } +} diff --git a/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHider.java b/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHider.java index f0b0f5c..8b79648 100644 --- a/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHider.java +++ b/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHider.java @@ -19,21 +19,10 @@ package de.steamwar.fightsystem.utils; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -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.tinyprotocol.Reflection; import com.google.common.primitives.Bytes; import de.steamwar.core.Core; import de.steamwar.core.events.ChunkListener; -import de.steamwar.fightsystem.ArenaMode; import de.steamwar.fightsystem.Config; import de.steamwar.fightsystem.FightSystem; import de.steamwar.fightsystem.VersionDependent; @@ -47,206 +36,186 @@ import org.bukkit.Material; import org.bukkit.entity.Player; import java.util.*; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; public class TechHider extends StateDependent { + private static final Class blockPosition = Reflection.getClass("{nms}.BlockPosition"); + private static final Class baseBlockPosition = Reflection.getClass("{nms}.BaseBlockPosition"); + private static final Reflection.FieldAccessor blockPositionX = Reflection.getField(baseBlockPosition, int.class, 0); + private static final Reflection.FieldAccessor blockPositionZ = Reflection.getField(baseBlockPosition, int.class, 2); + + private static final Class iBlockData = Reflection.getClass("{nms}.IBlockData"); + private static final Class block = Reflection.getClass("{nms}.Block"); + private static final Reflection.MethodInvoker getBlockByBlockData = Reflection.getTypedMethod(iBlockData, "getBlock", block); + private static final Reflection.MethodInvoker getBlockDataByBlock = Reflection.getTypedMethod(block, "getBlockData", iBlockData); + + private static final Class craftMagicNumbers = Reflection.getClass("{obc}.util.CraftMagicNumbers"); + private static final Reflection.MethodInvoker getMaterialByBlock = Reflection.getTypedMethod(craftMagicNumbers, "getMaterial", Material.class, block); + private static final Reflection.MethodInvoker getBlockByMaterial = Reflection.getTypedMethod(craftMagicNumbers, "getBlock", block, Material.class); + public static final boolean ENABLED = !Config.OnlyPublicSchematics && !Config.test() && Config.TechhiderActive; - private final ProtocolManager protocolManager = ProtocolLibrary.getProtocolManager(); - private final Map packetCache = new HashMap<>(); - private final Material obfuscateMaterial; - private final PacketAdapter chunkHider; - private final int threadMultiplier; + private final Object obfuscateIBlockData = getBlockDataByBlock.invoke(getBlockByMaterial.invoke(null, Material.getMaterial(Config.ObfuscateWith.toUpperCase()))); + private final Map, BiFunction> techhiders = new HashMap<>(); + private final BiFunction chunkDataHider; public TechHider(){ super(ENABLED, FightState.Schem); - obfuscateMaterial = Material.getMaterial(Config.ObfuscateWith.toUpperCase()); - chunkHider = VersionDependent.getVersionImpl(TechHider.class.getName()); + chunkDataHider = VersionDependent.getVersionImpl(TechHider.class.getName()); - if(Config.mode == ArenaMode.EVENT) - threadMultiplier = 4; - else - threadMultiplier = 1; - - Bukkit.getScheduler().runTaskTimer(FightSystem.getPlugin(), packetCache::clear, 1, 1); + techhiders.put(blockActionPacket, this::blockActionHider); + techhiders.put(blockChangePacket, this::blockChangeHider); + techhiders.put(tileEntityDataPacket, this::tileEntityDataHider); + techhiders.put(multiBlockChangePacket, this::multiBlockChangeHider); + if(Core.getVersion() > 8) { + techhiders.put(mapChunkPacket, this::mapChunkHider); + } + if(Core.getVersion() > 12) { + Class blockBreakClass = Reflection.getClass("{nms}.PacketPlayOutBlockBreak"); + techhiders.put(blockBreakClass, blockBreakHiderGenerator(blockBreakClass)); + } if(Core.getVersion() > 8){ - protocolManager.addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.USE_ITEM) { - @Override - public void onPacketReceiving(PacketEvent e) { - Player p = e.getPlayer(); - - if(p == null || p.getGameMode() == GameMode.SPECTATOR) - e.setCancelled(true); - } - }); + ProtocolAPI.setIncomingHandler(Reflection.getClass("{nms}.PacketPlayInUseItem"), (p, packet) -> p.getGameMode() == GameMode.SPECTATOR ? null : packet); } - protocolManager.addPacketListener(new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Client.USE_ENTITY) { - @Override - public void onPacketReceiving(PacketEvent e) { - Player p = e.getPlayer(); + ProtocolAPI.setIncomingHandler(Reflection.getClass("{nms}.PacketPlayInUseEntity"), (p, packet) -> p.getGameMode() == GameMode.SPECTATOR ? null : packet); - if(p.getGameMode() == GameMode.SPECTATOR) - e.setCancelled(true); - } - }); register(); } @Override public void enable() { - protocolManager.addPacketListener(blockHider); - protocolManager.addPacketListener(multiBlockHider); - protocolManager.addPacketListener(blockActionHider); - protocolManager.getAsynchronousManager().registerAsyncHandler(chunkHider).start(threadMultiplier * 4); - if(Core.getVersion() > 8) { - protocolManager.addPacketListener(updateBlockEntity); - } - if(Core.getVersion() > 12) { - protocolManager.addPacketListener(blockBreakHider); - } + techhiders.forEach(ProtocolAPI::setOutgoingHandler); } @Override public void disable() { - protocolManager.removePacketListener(blockHider); - protocolManager.removePacketListener(multiBlockHider); - protocolManager.removePacketListener(blockActionHider); - protocolManager.getAsynchronousManager().unregisterAsyncHandler(chunkHider); - if(Core.getVersion() > 8) { - protocolManager.removePacketListener(updateBlockEntity); - } - if(Core.getVersion() > 12) { - protocolManager.removePacketListener(blockBreakHider); - } + techhiders.keySet().forEach(ProtocolAPI::removeOutgoingHandler); } - private final PacketAdapter multiBlockHider = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.MULTI_BLOCK_CHANGE) { - @Override - public void onPacketSending(PacketEvent e) { - PacketContainer packet = e.getPacket(); + private static final Class nbtTagCompound = Reflection.getClass("{nms}.NBTTagCompound"); + private static final Reflection.MethodInvoker nbtTagGetString = Reflection.getTypedMethod(nbtTagCompound, "getString", String.class, String.class); - 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(); - if(Config.HiddenBlocks.contains(block.getType().name().toLowerCase())){ - changed = true; - block.setType(obfuscateMaterial); - mbci.setData(block); - } - } - - if(changed){ - blockStructure.write(0, changes); - } + private static final Class mapChunkPacket = Reflection.getClass("{nms}.PacketPlayOutMapChunk"); + private static final UnaryOperator mapChunkCloner = ProtocolAPI.shallowCloneGenerator(mapChunkPacket); + private static final Reflection.FieldAccessor mapChunkX = Reflection.getField(mapChunkPacket, int.class, 0); + private static final Reflection.FieldAccessor mapChunkZ = Reflection.getField(mapChunkPacket, int.class, 1); + private static final Reflection.FieldAccessor mapChunkBitMask; + private static final Reflection.FieldAccessor mapChunkBlockEntities; + private static final Reflection.FieldAccessor mapChunkData; + static { + if(Core.getVersion() > 8) { + mapChunkBitMask = Reflection.getField(mapChunkPacket, int.class, 2); + mapChunkBlockEntities = Reflection.getField(mapChunkPacket, List.class, 0); + mapChunkData = Reflection.getField(mapChunkPacket, byte[].class, 0); + }else { + mapChunkBitMask = null; + mapChunkBlockEntities = null; + mapChunkData = null; } - }; + } + private Object mapChunkHider(Player p, Object packet) { + if(bypass(p, mapChunkX.get(packet), mapChunkZ.get(packet))) + return packet; - private final PacketAdapter blockHider = 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); + packet = mapChunkCloner.apply(packet); + mapChunkBlockEntities.set(packet, ((List)mapChunkBlockEntities.get(packet)).stream().filter( + nbttag -> Config.HiddenBlockEntities.contains((String) nbtTagGetString.invoke(nbttag, "id")) + ).collect(Collectors.toList())); - Player p = e.getPlayer(); - if(bypass(p, posToChunk(pos.getX()), posToChunk(pos.getZ()))) - return; + byte[] data = chunkDataHider.apply(mapChunkData.get(packet), mapChunkBitMask.get(packet)); + mapChunkData.set(packet, data); - PacketContainer cached = packetCache.get(packet); - if(cached != null){ - e.setPacket(cached); - return; - } + return packet; + } - cached = packet.deepClone(); - packetCache.put(packet, cached); - e.setPacket(cached); - StructureModifier blockStructure = cached.getBlockData(); - WrappedBlockData block = blockStructure.read(0); - if(Config.HiddenBlocks.contains(block.getType().name().toLowerCase())){ - block.setType(obfuscateMaterial); - blockStructure.write(0, block); - } + private static final Class multiBlockChangePacket = Reflection.getClass("{nms}.PacketPlayOutMultiBlockChange"); + private static final UnaryOperator multiBlockChangeCloner = ProtocolAPI.shallowCloneGenerator(multiBlockChangePacket); + private static final Class chunkCoordinateIntPair = Reflection.getClass("{nms}.ChunkCoordIntPair"); + private static final Reflection.FieldAccessor multiBlockChangeChunk = Reflection.getField(multiBlockChangePacket, chunkCoordinateIntPair, 0); + private static final Reflection.FieldAccessor chunkCoordinateX = Reflection.getField(chunkCoordinateIntPair, int.class, 0); + private static final Reflection.FieldAccessor chunkCoordinateZ = Reflection.getField(chunkCoordinateIntPair, int.class, 1); + private static final Class multiBlockChangeInfo = Reflection.getClass("{nms}.PacketPlayOutMultiBlockChange$MultiBlockChangeInfo"); + private static final Reflection.ConstructorInvoker multiBlockChangeInfoConstructor = Reflection.getConstructor(multiBlockChangeInfo, multiBlockChangePacket, short.class, iBlockData); + private static final BiFunction, Object> multiBlockChangeInfoArrayCloner = ProtocolAPI.arrayCloneGenerator(multiBlockChangeInfo); + private static final Reflection.FieldAccessor multiBlockChangeInfoBlock = Reflection.getField(multiBlockChangeInfo, iBlockData, 0); + private static final Reflection.FieldAccessor multiBlockChangeInfoPos = Reflection.getField(multiBlockChangeInfo, short.class, 0); + private static final Class multiBlockChangeInfoArray = Reflection.getClass("[L{nms}.PacketPlayOutMultiBlockChange$MultiBlockChangeInfo;"); + private static final Reflection.FieldAccessor multiBlockChangeInfos = Reflection.getField(multiBlockChangePacket, multiBlockChangeInfoArray, 0); + private Object multiBlockChangeHider(Player p, Object packet) { + Object chunkCoords = multiBlockChangeChunk.get(packet); + if(bypass(p, chunkCoordinateX.get(chunkCoords), chunkCoordinateZ.get(chunkCoords))) + return packet; + + Object modpacket = multiBlockChangeCloner.apply(packet); + multiBlockChangeInfos.set(modpacket, multiBlockChangeInfoArrayCloner.apply(multiBlockChangeInfos.get(modpacket), mbci -> { + if(Config.HiddenBlocks.contains(getMaterialByIBlockData(multiBlockChangeInfoBlock.get(mbci)).name().toLowerCase())) + return multiBlockChangeInfoConstructor.invoke(modpacket, multiBlockChangeInfoPos.get(mbci), obfuscateIBlockData); + return mbci; + })); + return modpacket; + } + + private static final Class blockChangePacket = Reflection.getClass("{nms}.PacketPlayOutBlockChange"); + private static final Function blockChangeCloner = ProtocolAPI.shallowCloneGenerator(blockChangePacket); + private static final Reflection.FieldAccessor blockChangePosition = Reflection.getField(blockChangePacket, blockPosition, 0); + private static final Reflection.FieldAccessor blockChangeBlockData = Reflection.getField(blockChangePacket, iBlockData, 0); + private Object blockChangeHider(Player p, Object packet) { + Object pos = blockChangePosition.get(packet); + if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos)))) + return packet; + + if(Config.HiddenBlocks.contains(getMaterialByIBlockData(blockChangeBlockData.get(packet)).name().toLowerCase())){ + packet = blockChangeCloner.apply(packet); + blockChangeBlockData.set(packet, obfuscateIBlockData); } - }; + return packet; + } - private final PacketAdapter blockActionHider = 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); + private static final Class blockActionPacket = Reflection.getClass("{nms}.PacketPlayOutBlockAction"); + private static final Reflection.FieldAccessor blockActionPosition = Reflection.getField(blockActionPacket, blockPosition, 0); + private Object blockActionHider(Player p, Object packet) { + Object pos = blockActionPosition.get(packet); + if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos)))) + return packet; + return null; + } - Player p = e.getPlayer(); - if(bypass(p, posToChunk(pos.getX()), posToChunk(pos.getZ()))) - return; + private BiFunction blockBreakHiderGenerator(Class blockBreakPacket){ + UnaryOperator blockBreakCloner = ProtocolAPI.shallowCloneGenerator(blockBreakPacket); + Reflection.FieldAccessor blockBreakPosition = Reflection.getField(blockBreakPacket, blockPosition, 0); + Reflection.FieldAccessor blockBreakBlockData = Reflection.getField(blockBreakPacket, iBlockData, 0); - e.setCancelled(true); - } - }; + return (p, packet) -> { + Object pos = blockBreakPosition.get(packet); + if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos)))) + return packet; - private final PacketAdapter blockBreakHider = new PacketAdapter(FightSystem.getPlugin(), PacketType.Play.Server.BLOCK_BREAK) { - @Override - public void onPacketSending(PacketEvent e) { - PacketContainer packet = e.getPacket(); - BlockPosition pos = packet.getBlockPositionModifier().read(0); - - Player p = e.getPlayer(); - if(bypass(p, posToChunk(pos.getX()), posToChunk(pos.getZ()))) - return; - - - PacketContainer cached = packetCache.get(packet); - if(cached != null){ - e.setPacket(cached); - return; + if(Config.HiddenBlocks.contains(getMaterialByIBlockData(blockBreakBlockData.get(packet)).name().toLowerCase())){ + packet = blockBreakCloner.apply(packet); + blockBreakBlockData.set(packet, obfuscateIBlockData); } + return packet; + }; + } - cached = packet.deepClone(); - packetCache.put(packet, cached); - e.setPacket(cached); - StructureModifier blockStructure = cached.getBlockData(); - WrappedBlockData block = blockStructure.read(0); - if(Config.HiddenBlocks.contains(block.getType().name().toLowerCase())){ - block.setType(obfuscateMaterial); - blockStructure.write(0, block); - } - } - }; + private static final Class tileEntityDataPacket = Reflection.getClass("{nms}.PacketPlayOutTileEntityData"); + private static final Reflection.FieldAccessor tileEntityDataPosition = Reflection.getField(tileEntityDataPacket, blockPosition, 0); + private static final Reflection.FieldAccessor tileEntityDataAction = Reflection.getField(tileEntityDataPacket, int.class, 0); + private Object tileEntityDataHider(Player p, Object packet) { + Object pos = tileEntityDataPosition.get(packet); + if(bypass(p, posToChunk(blockPositionX.get(pos)), posToChunk(blockPositionZ.get(pos)))) + return packet; - private final PacketAdapter updateBlockEntity = 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, posToChunk(pos.getX()), posToChunk(pos.getZ()))) - return; - - // 9 == Set sign text - if(packet.getIntegers().read(0) != 9) - return; - - event.setCancelled(true); - } - }; + if(tileEntityDataAction.get(packet) != 9) + return packet; + return null; + } public static List prepareChunkReload(Player p, boolean hide){ if(!ENABLED) @@ -284,6 +253,10 @@ public class TechHider extends StateDependent { } } + private static Material getMaterialByIBlockData(Object iBlockData) { + return (Material) getMaterialByBlock.invoke(null, getBlockByBlockData.invoke(iBlockData)); + } + private static int posToChunk(int c){ int chunk = c / 16; if(c<0) diff --git a/FightSystem_Core/src/plugin.yml b/FightSystem_Core/src/plugin.yml index 88fbbec..066b5aa 100644 --- a/FightSystem_Core/src/plugin.yml +++ b/FightSystem_Core/src/plugin.yml @@ -4,7 +4,7 @@ authors: - Yaruma3341 - Lixfel main: de.steamwar.fightsystem.FightSystem -depend: [SpigotCore, WorldEdit, ProtocolLib] +depend: [SpigotCore, WorldEdit] api-version: "1.13" commands: diff --git a/pom.xml b/pom.xml index da93e94..99c8b1b 100644 --- a/pom.xml +++ b/pom.xml @@ -68,13 +68,6 @@ system ${main.basedir}/lib/SpigotCore.jar - - steamwar - ProtocolLib - 1.0 - system - ${main.basedir}/lib/ProtocolLib.jar -