diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java index ef0bbad8..a4b635d3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/other/NoClipCommand.java @@ -27,11 +27,9 @@ import de.steamwar.bausystem.linkage.LinkageType; import de.steamwar.bausystem.linkage.Linked; import de.steamwar.bausystem.utils.ProtocolAPI; import de.steamwar.command.SWCommand; +import de.steamwar.core.Core; import de.steamwar.core.VersionedRunnable; import lombok.Getter; -import net.minecraft.server.v1_15_R1.EnumGamemode; -import net.minecraft.server.v1_15_R1.IChatBaseComponent; -import net.minecraft.server.v1_15_R1.PacketPlayOutPlayerInfo; import org.bukkit.GameMode; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; import org.bukkit.entity.Player; @@ -42,19 +40,28 @@ import org.bukkit.event.player.PlayerGameModeChangeEvent; import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.event.player.PlayerToggleFlightEvent; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.function.BiFunction; @Linked(LinkageType.COMMAND) @Linked(LinkageType.LISTENER) public class NoClipCommand extends SWCommand implements Listener { - public static final Class playerInfo = Reflection.getClass("{nms}.PacketPlayOutPlayerInfo"); - private static final Reflection.FieldAccessor playerInfoAction = Reflection.getField(playerInfo, PacketPlayOutPlayerInfo.EnumPlayerInfoAction.class, 0); - private static final Reflection.FieldAccessor playerInfoDataList = Reflection.getField(playerInfo, "b", List.class); + 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 final Class gameStateChange = Reflection.getClass("{nms}.PacketPlayOutGameStateChange"); private static final Reflection.FieldAccessor integerFieldAccessor = Reflection.getField(gameStateChange, int.class, 0); @@ -106,14 +113,6 @@ public class NoClipCommand extends SWCommand implements Listener { ((CraftPlayer) player).getHandle().abilities.mayBuild = true; ((CraftPlayer) player).getHandle().abilities.canInstantlyBuild = true; - Object playerInfoObject = Reflection.newInstance(playerInfo); - playerInfoAction.set(playerInfoObject, PacketPlayOutPlayerInfo.EnumPlayerInfoAction.UPDATE_GAME_MODE); - PacketPlayOutPlayerInfo packetPlayOutPlayerInfo = (PacketPlayOutPlayerInfo) playerInfoObject; - - List playerInfoData = new ArrayList<>(); - playerInfoData.add(packetPlayOutPlayerInfo.new PlayerInfoData(new GameProfile(player.getUniqueId(), player.getName()), 1, EnumGamemode.SPECTATOR, IChatBaseComponent.ChatSerializer.b(player.getDisplayName()))); - playerInfoDataList.set(playerInfoObject, playerInfoData); - Object gameStateChangeObject = Reflection.newInstance(gameStateChange); integerFieldAccessor.set(gameStateChangeObject, 3); floatFieldAccessor.set(gameStateChangeObject, 1F); @@ -121,7 +120,7 @@ public class NoClipCommand extends SWCommand implements Listener { NOCLIPS.add(player); BauSystem.MESSAGE.send("OTHER_NOCLIP_SLOT_INFO", player); ProtocolAPI.tinyProtocol.sendPacket(player, gameStateChangeObject); - ProtocolAPI.tinyProtocol.sendPacket(player, playerInfoObject); + pseudoSpectator(player, false); } } @@ -157,4 +156,15 @@ public class NoClipCommand extends SWCommand implements Listener { event.setCancelled(true); } } + + public static void pseudoSpectator(Player player, boolean enable) { + 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; + } } \ No newline at end of file