Advertisement
Guest User

Untitled

a guest
Feb 22nd, 2023
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 43.84 KB | None | 0 0
  1. import com.mojang.authlib.GameProfile;
  2. import com.mojang.authlib.properties.Property;
  3. import com.mojang.datafixers.util.Pair;
  4. import io.netty.buffer.Unpooled;
  5. import io.netty.channel.ChannelHandlerContext;
  6. import io.netty.channel.ChannelInboundHandlerAdapter;
  7. import io.netty.channel.ChannelPipeline;
  8. import net.minecraft.EnumChatFormat;
  9. import net.minecraft.core.BlockPosition;
  10. import net.minecraft.nbt.NBTTagCompound;
  11. import net.minecraft.network.PacketDataSerializer;
  12. import net.minecraft.network.chat.IChatBaseComponent;
  13. import net.minecraft.network.protocol.Packet;
  14. import net.minecraft.network.protocol.game.*;
  15. import net.minecraft.network.syncher.DataWatcher;
  16. import net.minecraft.network.syncher.DataWatcherObject;
  17. import net.minecraft.network.syncher.DataWatcherRegistry;
  18. import net.minecraft.network.syncher.DataWatcherSerializer;
  19. import net.minecraft.world.EnumHand;
  20. import net.minecraft.world.entity.Entity;
  21. import net.minecraft.world.entity.EntityPose;
  22. import net.minecraft.world.entity.EntityTypes;
  23. import net.minecraft.world.entity.EnumItemSlot;
  24. import net.minecraft.world.entity.animal.EntityParrot;
  25. import net.minecraft.world.item.ItemStack;
  26. import net.minecraft.world.level.EnumGamemode;
  27. import net.minecraft.world.scores.Scoreboard;
  28. import net.minecraft.world.scores.ScoreboardTeam;
  29. import net.minecraft.world.scores.ScoreboardTeamBase;
  30. import org.bukkit.Bukkit;
  31. import org.bukkit.Location;
  32. import org.bukkit.World;
  33. import org.bukkit.craftbukkit.v1_19_R2.CraftServer;
  34. import org.bukkit.craftbukkit.v1_19_R2.CraftWorld;
  35. import org.bukkit.craftbukkit.v1_19_R2.entity.CraftParrot;
  36. import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer;
  37. import org.bukkit.craftbukkit.v1_19_R2.inventory.CraftItemStack;
  38. import org.bukkit.craftbukkit.v1_19_R2.util.CraftChatMessage;
  39. import org.bukkit.entity.Parrot;
  40. import org.bukkit.entity.Player;
  41. import org.bukkit.event.EventHandler;
  42. import org.bukkit.event.EventPriority;
  43. import org.bukkit.event.Listener;
  44. import org.bukkit.event.player.PlayerJoinEvent;
  45. import org.bukkit.plugin.Plugin;
  46. import org.json.simple.JSONArray;
  47. import org.json.simple.JSONObject;
  48. import org.json.simple.parser.JSONParser;
  49.  
  50. import java.lang.reflect.Field;
  51. import java.lang.reflect.Method;
  52. import java.net.HttpURLConnection;
  53. import java.net.URI;
  54. import java.net.http.HttpClient;
  55. import java.net.http.HttpRequest;
  56. import java.net.http.HttpResponse;
  57. import java.time.Duration;
  58. import java.util.*;
  59. import java.util.concurrent.atomic.AtomicInteger;
  60. import java.util.function.Consumer;
  61.  
  62. public class NPC {
  63.  
  64.     private static AtomicInteger atomicInteger;
  65.  
  66.     private final int entityID;
  67.     private final Location location;
  68.     private GameProfile profile;
  69.     private MetaData metadata = new MetaData();
  70.  
  71.     static {
  72.         try {
  73.             Field field = Entity.class.getDeclaredField("c");
  74.             field.setAccessible(true);
  75.             atomicInteger = (AtomicInteger) field.get(null);
  76.         } catch (NoSuchFieldException | IllegalAccessException e) {
  77.             e.printStackTrace();
  78.         }
  79.     }
  80.  
  81.     public NPC(UUID uuid, Location location, String displayName) {
  82.         this.entityID = atomicInteger.incrementAndGet();
  83.         this.profile = new GameProfile(uuid, displayName);
  84.         this.location = location;
  85.     }
  86.  
  87.     public NPC(Location location, String displayName) {
  88.         this(UUID.randomUUID(), location, displayName);
  89.     }
  90.  
  91.     public void spawnNPC(Collection<? extends Player> receivers) {
  92.         receivers.forEach(this::spawnNPC);
  93.     }
  94.  
  95.     public void spawnNPC(Player receiver) {
  96.         this.addToTabList(receiver);
  97.         this.sendPacket(receiver, this.getEntitySpawnPacket());
  98.         this.updateMetadata(receiver);
  99.     }
  100.  
  101.     public void destroyNPC(Collection<? extends Player> receivers) {
  102.         receivers.forEach(this::destroyNPC);
  103.     }
  104.  
  105.     public void destroyNPC(Player receiver) {
  106.         this.sendPacket(receiver, this.getPlayerInfoPacket(PlayerInfo.REMOVE_PLAYER));
  107.         this.sendPacket(receiver, this.getEntityDestroyPacket());
  108.     }
  109.  
  110.     public void reloadNPC(Collection<? extends Player> receivers) {
  111.         receivers.forEach(this::reloadNPC);
  112.     }
  113.  
  114.     public void reloadNPC(Player receiver) {
  115.         this.destroyNPC(receiver);
  116.         this.spawnNPC(receiver);
  117.     }
  118.  
  119.     public void teleportNPC(Collection<? extends Player> receivers, Location location, boolean onGround) {
  120.         receivers.forEach(receiver -> this.teleportNPC(receiver, location, onGround));
  121.     }
  122.  
  123.     public void teleportNPC(Player receiver, Location location, boolean onGround) {
  124.         this.location.setX(location.getX());
  125.         this.location.setY(location.getY());
  126.         this.location.setZ(location.getZ());
  127.         this.location.setPitch(location.getPitch());
  128.         this.location.setYaw(location.getYaw());
  129.         this.rotateHead(receiver, location.getPitch(), location.getYaw(), true);
  130.         this.sendPacket(receiver, this.getEntityTeleportPacket(onGround));
  131.     }
  132.  
  133.     public void updateMetadata(Collection<? extends Player> receivers) {
  134.         receivers.forEach(this::updateMetadata);
  135.     }
  136.  
  137.     public void updateMetadata(Player receiver) {
  138.         this.sendPacket(receiver, this.getEntityMetadataPacket());
  139.     }
  140.  
  141.     public void updateGameMode(Collection<? extends Player> receivers) {
  142.         receivers.forEach(this::updateGameMode);
  143.     }
  144.  
  145.     public void updateGameMode(Player receiver) {
  146.         this.sendPacket(receiver, this.getPlayerInfoPacket(PlayerInfo.UPDATE_GAME_MODE));
  147.     }
  148.  
  149.     public void setPing(Collection<? extends Player> receivers, Ping ping) {
  150.         receivers.forEach(receiver -> this.setPing(receiver, ping));
  151.     }
  152.  
  153.     public void setPing(Player receiver, Ping ping) {
  154.         this.sendPacket(receiver, this.getUpdatePlayerInfoPacket(PlayerInfo.UPDATE_LATENCY, ping));
  155.     }
  156.  
  157.     public void setGameMode(Collection<? extends Player> receivers, GameMode gameMode) {
  158.         receivers.forEach(receiver -> this.setGameMode(receiver, gameMode));
  159.     }
  160.  
  161.     public void setGameMode(Player receiver, GameMode gameMode) {
  162.         this.sendPacket(receiver, this.getUpdatePlayerInfoPacket(PlayerInfo.UPDATE_GAME_MODE, gameMode));
  163.     }
  164.  
  165.     public void setTabListName(Collection<? extends Player> receivers, String displayName) {
  166.         receivers.forEach(receiver -> this.setTabListName(receiver, displayName));
  167.     }
  168.  
  169.     public void setTabListName(Player receiver, String displayName) {
  170.         this.sendPacket(receiver, this.getUpdatePlayerInfoPacket(PlayerInfo.UPDATE_DISPLAY_NAME, displayName));
  171.     }
  172.  
  173.     public void removeFromTabList(Collection<? extends Player> receivers) {
  174.         receivers.forEach(this::removeFromTabList);
  175.     }
  176.  
  177.     public void removeFromTabList(Player receiver) {
  178.         this.sendPacket(receiver, this.getPlayerInfoPacket(PlayerInfo.REMOVE_PLAYER));
  179.     }
  180.  
  181.     public void addToTabList(Collection<? extends Player> receivers) {
  182.         receivers.forEach(this::addToTabList);
  183.     }
  184.  
  185.     public void addToTabList(Player receiver) {
  186.         this.sendPacket(receiver, this.getPlayerInfoPacket(PlayerInfo.ADD_PLAYER));
  187.     }
  188.  
  189.     public void playAnimation(Collection<? extends Player> receivers, Animation animation) {
  190.         receivers.forEach(receiver -> this.playAnimation(receiver, animation));
  191.     }
  192.  
  193.     public void playAnimation(Player receiver, Animation animation) {
  194.         this.sendPacket(receiver, this.getEntityAnimationPacket(animation));
  195.     }
  196.  
  197.     public void lookAtPlayer(Collection<? extends Player> receivers, Player target) {
  198.         receivers.forEach(receiver -> this.lookAtPlayer(receiver, target));
  199.     }
  200.  
  201.     public void lookAtPlayer(Player receiver, Player target) {
  202.         this.lookAtPoint(receiver, target.getEyeLocation());
  203.     }
  204.  
  205.     public void lookAtPoint(Collection<? extends Player> receivers, Location location) {
  206.         receivers.forEach(receiver -> this.lookAtPoint(receiver, location));
  207.     }
  208.  
  209.     public void lookAtPoint(Player receiver, Location location) {
  210.         Location eyeLocation = this.getEyeLocation();
  211.         float yaw = (float) Math.toDegrees(Math.atan2(location.getZ() - eyeLocation.getZ(), location.getX() - eyeLocation.getX())) - 90;
  212.         yaw = (float) (yaw + Math.ceil(-yaw / 360) * 360);
  213.         float deltaXZ = (float) Math.sqrt(Math.pow(eyeLocation.getX() - location.getX(), 2) + Math.pow(eyeLocation.getZ() - location.getZ(), 2));
  214.         float pitch = (float) Math.toDegrees(Math.atan2(deltaXZ, location.getY() - eyeLocation.getY())) - 90;
  215.         pitch = (float) (pitch + Math.ceil(-pitch / 360) * 360);
  216.         this.rotateHead(receiver, pitch, yaw, true);
  217.     }
  218.  
  219.     public void rotateHead(Collection<? extends Player> receivers, float pitch, float yaw, boolean body) {
  220.         receivers.forEach(receiver -> this.rotateHead(receiver, pitch, yaw, body));
  221.     }
  222.  
  223.     public void rotateHead(Player receiver, float pitch, float yaw, boolean body) {
  224.         this.location.setPitch(pitch);
  225.         this.location.setYaw(yaw);
  226.         if(body) this.sendPacket(receiver, this.getEntityLookPacket());
  227.         this.sendPacket(receiver, this.getEntityHeadRotatePacket());
  228.     }
  229.  
  230.     public void setEquipment(Collection<? extends Player> receivers, ItemSlot slot, org.bukkit.inventory.ItemStack itemStack) {
  231.         receivers.forEach(receiver -> this.setEquipment(receiver, slot, itemStack));
  232.     }
  233.  
  234.     public void setEquipment(Player receiver, ItemSlot slot, org.bukkit.inventory.ItemStack itemStack) {
  235.         this.sendPacket(receiver, this.getEntityEquipmentPacket(slot.getNMSItemSlot(), CraftItemStack.asNMSCopy(itemStack)));
  236.     }
  237.  
  238.     public void setPassenger(Collection<? extends Player> receivers, int... entityIDs) {
  239.         receivers.forEach(receiver -> this.setPassenger(receiver, entityIDs));
  240.     }
  241.  
  242.     public void setPassenger(Player receiver, int... entityIDs) {
  243.         this.sendPacket(receiver, getEntityAttachPacket(entityIDs));
  244.     }
  245.  
  246.     public void setLeash(Player receiver, org.bukkit.entity.Entity entity) {
  247.         this.sendPacket(receiver, getAttachEntityPacket(entity));
  248.     }
  249.  
  250.     public void setLeash(Collection<? extends Player> receivers, org.bukkit.entity.Entity entity) {
  251.         receivers.forEach(p->this.setLeash(p, entity));
  252.     }
  253.  
  254.     public void moveRelative(Player receiver, double relX, double relY, double relZ, boolean onGround) {
  255.         this.sendPacket(receiver, getEntityMovePacket(relX, relY, relZ, onGround));
  256.     }
  257.  
  258.     public void moveRelative(Collection<? extends Player> receivers, double relX, double relY, double relZ, boolean onGround) {
  259.         receivers.forEach(p->this.moveRelative(p, relX, relY, relZ, onGround));
  260.     }
  261.  
  262.     public BukkitCompletable<NPC> setSkinByUsername(Plugin plugin, String username) {
  263.         return BukkitCompletable.supplyASync(plugin, ()->{
  264.             this.setSkin(NPC.SkinTextures.getByUsername(plugin, username).getSync());
  265.             return NPC.this;
  266.         });
  267.     }
  268.  
  269.     public BukkitCompletable<NPC> setSkinByCachedUsername(Plugin plugin, String username) {
  270.         return BukkitCompletable.supplyASync(plugin, ()->{
  271.             final SkinTextures skin = SkinTextures.getByCachedUsername(plugin, username).getSync();
  272.             this.setSkin(skin);
  273.             return NPC.this;
  274.         });
  275.     }
  276.  
  277.     public BukkitCompletable<NPC> setSkinByUUID(Plugin plugin, UUID uuid) {
  278.         return BukkitCompletable.supplyASync(plugin, ()->{
  279.             this.setSkin(NPC.SkinTextures.getByUUID(plugin, uuid).getSync());
  280.             return NPC.this;
  281.         });
  282.     }
  283.  
  284.     private void sendPacket(Player receiver, Packet<?> packet) {
  285.         ((CraftPlayer) (receiver)).getHandle().b.a(packet);
  286.     }
  287.  
  288.     public void setTeamFeatures(Player receiver, TeamFeatures teamFeatures) {
  289.         ScoreboardTeam team = new ScoreboardTeam(new Scoreboard(), this.profile.getName());
  290.         team.a(teamFeatures.nameTagVisible() ? ScoreboardTeamBase.EnumNameTagVisibility.a : ScoreboardTeamBase.EnumNameTagVisibility.b);
  291.         team.a(teamFeatures.glowColor().getNMSColor());
  292.         team.a(teamFeatures.collision() ? ScoreboardTeamBase.EnumTeamPush.a : ScoreboardTeamBase.EnumTeamPush.b);
  293.         PacketPlayOutScoreboardTeam createPacket = PacketPlayOutScoreboardTeam.a(team, true);
  294.         PacketPlayOutScoreboardTeam joinPacket = PacketPlayOutScoreboardTeam.a(team, this.profile.getName(), PacketPlayOutScoreboardTeam.a.a);
  295.         this.sendPacket(receiver, createPacket);
  296.         this.sendPacket(receiver, joinPacket);
  297.     }
  298.  
  299.     public NBTTagCompound createParrot(Consumer<Parrot> callback, World world) {
  300.         EntityParrot entityParrot = new EntityParrot(EntityTypes.ap, ((CraftWorld) world).getHandle());
  301.         CraftParrot parrot = new CraftParrot((CraftServer) Bukkit.getServer(), entityParrot);
  302.         callback.accept(parrot);
  303.         NBTTagCompound nbtTagCompound = new NBTTagCompound();
  304.         entityParrot.d(nbtTagCompound);
  305.         return nbtTagCompound;
  306.     }
  307.  
  308.     public void setParrotLeftShoulder(Consumer<Parrot> callback, World world) {
  309.         this.metadata.setLeftShoulder(this.createParrot(callback, world));
  310.     }
  311.  
  312.     public void setParrotRightShoulder(Consumer<Parrot> callback, World world) {
  313.         this.metadata.setRightShoulder(this.createParrot(callback, world));
  314.     }
  315.  
  316.     public int getEntityID() {
  317.         return entityID;
  318.     }
  319.  
  320.     public GameProfile getProfile() {
  321.         return profile;
  322.     }
  323.  
  324.     public MetaData getMetadata() {
  325.         return metadata;
  326.     }
  327.  
  328.     public Location getLocation() {
  329.         return location;
  330.     }
  331.  
  332.     public Location getEyeLocation() {
  333.         return this.location.clone().add(0, EntityTypes.bo.n().b * 0.85F, 0);
  334.     }
  335.  
  336.     public MetaData getMetaData() {
  337.         return this.metadata;
  338.     }
  339.  
  340.     public void setMetaData(MetaData metaData) {
  341.         this.metadata = metaData;
  342.     }
  343.  
  344.     public void setSkin(SkinTextures skinTextures) {
  345.         this.profile.getProperties().put("textures", new Property("textures", skinTextures.getTexture(), skinTextures.getSignature()));
  346.     }
  347.  
  348.     public void setDisplayName(String displayName) {
  349.         GameProfile swapProfile = new GameProfile(this.profile.getId(), displayName);
  350.         swapProfile.getProperties().putAll(this.profile.getProperties());
  351.         this.profile = swapProfile;
  352.     }
  353.  
  354.     public void registerListener(NPCListener listener) {
  355.         if (EventManager.isInitialized()) {
  356.             EventManager.INSTANCE.listenNPC(this, listener);
  357.         }
  358.     }
  359.  
  360.     public void unregisterListener() {
  361.         if (EventManager.isInitialized()) {
  362.             EventManager.INSTANCE.unlistenNPC(this);
  363.         }
  364.     }
  365.  
  366.     private PacketPlayOutMount getEntityAttachPacket(int[] entityIDs) {
  367.         return this.createDataSerializer(data -> {
  368.             data.d(this.entityID);
  369.             data.a(entityIDs);
  370.             return new PacketPlayOutMount(data);
  371.         });
  372.     }
  373.  
  374.     private PacketPlayOutEntity.PacketPlayOutEntityLook getEntityLookPacket() {
  375.         return new PacketPlayOutEntity.PacketPlayOutEntityLook(this.entityID, (byte) ((int) (this.location.getYaw() * 256.0F / 360.0F)), (byte) ((int) (this.location.getPitch() * 256.0F / 360.0F)), true);
  376.     }
  377.  
  378.     private PacketPlayOutEntityHeadRotation getEntityHeadRotatePacket() {
  379.         return this.createDataSerializer(data -> {
  380.             data.d(this.entityID);
  381.             data.writeByte((byte) ((int) (this.location.getYaw() * 256.0F / 360.0F)));
  382.             return new PacketPlayOutEntityHeadRotation(data);
  383.         });
  384.     }
  385.  
  386.     private PacketPlayOutEntityTeleport getEntityTeleportPacket(boolean onGround) {
  387.         return this.createDataSerializer(data -> {
  388.             data.d(this.entityID);
  389.             data.writeDouble(this.location.getX());
  390.             data.writeDouble(this.location.getY());
  391.             data.writeDouble(this.location.getZ());
  392.             data.writeByte((byte) ((int) (this.location.getYaw() * 256.0F / 360.0F)));
  393.             data.writeByte((byte) ((int) (this.location.getPitch() * 256.0F / 360.0F)));
  394.             data.writeBoolean(onGround);
  395.             return new PacketPlayOutEntityTeleport(data);
  396.         });
  397.     }
  398.  
  399.     private PacketPlayOutEntity.PacketPlayOutRelEntityMove getEntityMovePacket(double x, double y, double z, boolean onGround) {
  400.         return new PacketPlayOutEntity.PacketPlayOutRelEntityMove(this.entityID, (short)(x * 4096), (short)(y * 4096), (short)(z * 4096), onGround);
  401.     }
  402.  
  403.     private PacketPlayOutAttachEntity getAttachEntityPacket(org.bukkit.entity.Entity entity) {
  404.         return createDataSerializer(data -> {
  405.             data.writeInt(entity.getEntityId());
  406.             data.writeInt(this.entityID);
  407.             return new PacketPlayOutAttachEntity(data);
  408.         });
  409.     }
  410.  
  411.     private PacketPlayOutEntityEquipment getEntityEquipmentPacket(EnumItemSlot slot, ItemStack itemStack) {
  412.         return new PacketPlayOutEntityEquipment(this.entityID, Arrays.asList(new Pair<>(slot, itemStack)));
  413.     }
  414.  
  415.     private PacketPlayOutAnimation getEntityAnimationPacket(Animation animation) {
  416.         return this.createDataSerializer((data) -> {
  417.             data.d(this.entityID);
  418.             data.writeByte((byte) animation.getType());
  419.             return new PacketPlayOutAnimation(data);
  420.         });
  421.     }
  422.  
  423.     private PacketPlayOutEntityDestroy getEntityDestroyPacket() {
  424.         return new PacketPlayOutEntityDestroy(this.entityID);
  425.     }
  426.  
  427.     private PacketPlayOutEntityMetadata getEntityMetadataPacket() {
  428.         return this.createDataSerializer((data) -> {
  429.             data.d(this.entityID);
  430.             for(DataWatcher.Item item : this.metadata.getList())
  431.             {
  432.                 item.a(data);
  433.             }
  434.             data.writeByte(255);
  435.             return new PacketPlayOutEntityMetadata(data);
  436.         });
  437.     }
  438.  
  439.     private PacketPlayOutNamedEntitySpawn getEntitySpawnPacket() {
  440.         return this.createDataSerializer((data) -> {
  441.             data.d(this.entityID);
  442.             data.a(this.profile.getId());
  443.             data.writeDouble(this.location.getX());
  444.             data.writeDouble(this.location.getY());
  445.             data.writeDouble(this.location.getZ());
  446.             data.writeByte((byte) ((int) (this.location.getYaw() * 256.0F / 360.0F)));
  447.             data.writeByte((byte) ((int) (this.location.getPitch() * 256.0F / 360.0F)));
  448.             return new PacketPlayOutNamedEntitySpawn(data);
  449.         });
  450.     }
  451.  
  452.     private ClientboundPlayerInfoUpdatePacket getUpdatePlayerInfoPacket(PlayerInfo playerInfo, Object obj) {
  453.         return this.createDataSerializer((data) -> {
  454.             ClientboundPlayerInfoUpdatePacket.a action = playerInfo.getNMSAction();
  455.             ClientboundPlayerInfoUpdatePacket.b playerInfoData;
  456.  
  457.             if (playerInfo == PlayerInfo.UPDATE_LATENCY) {
  458.                 playerInfoData = new ClientboundPlayerInfoUpdatePacket.b(this.profile.getId(), this.profile, false, ((Ping) obj).getMilliseconds(), null, null, null);
  459.             } else if (playerInfo == PlayerInfo.UPDATE_GAME_MODE) {
  460.                 playerInfoData = new ClientboundPlayerInfoUpdatePacket.b(this.profile.getId(), this.profile, false, 0, ((GameMode) obj).getNMSGameMode(), null, null);
  461.             } else if (playerInfo == PlayerInfo.UPDATE_DISPLAY_NAME) {
  462.                 playerInfoData = new ClientboundPlayerInfoUpdatePacket.b(this.profile.getId(), this.profile, false, 0, null, CraftChatMessage.fromString(((String) obj))[0], null);
  463.             } else {
  464.                 throw new NullPointerException();
  465.             }
  466.  
  467.             List<ClientboundPlayerInfoUpdatePacket.b> list = List.of(playerInfoData);
  468.             Method method = playerInfo.getNMSAction().getDeclaringClass().getDeclaredMethod("a", PacketDataSerializer.class, ClientboundPlayerInfoUpdatePacket.b.class);
  469.             method.setAccessible(true);
  470.             data.a(playerInfo.getNMSAction());
  471.             data.a(list, (PacketDataSerializer.b<ClientboundPlayerInfoUpdatePacket.b>) (a, b) -> this.unsafe(() -> method.invoke(action, a, b)));
  472.             return new ClientboundPlayerInfoUpdatePacket(data);
  473.         });
  474.     }
  475.  
  476.     private ClientboundPlayerInfoUpdatePacket getPlayerInfoPacket(PlayerInfo playerInfo) {
  477.         return this.createDataSerializer((data) -> {
  478.             ClientboundPlayerInfoUpdatePacket.a action = playerInfo.getNMSAction();
  479.             ClientboundPlayerInfoUpdatePacket.b playerInfoData = new ClientboundPlayerInfoUpdatePacket.b(this.profile.getId(), this.profile, false, Ping.FIVE_BARS.getMilliseconds(), GameMode.CREATIVE.getNMSGameMode(), CraftChatMessage.fromString(this.getProfile().getName())[0], null);
  480.             List<ClientboundPlayerInfoUpdatePacket.b> list = List.of(playerInfoData);
  481.             data.a(playerInfo.getNMSAction());
  482.             Method method = playerInfo.getNMSAction().getDeclaringClass().getDeclaredMethod("a", PacketDataSerializer.class, ClientboundPlayerInfoUpdatePacket.b.class);
  483.             method.setAccessible(true);
  484.             data.a(list, (PacketDataSerializer.b<ClientboundPlayerInfoUpdatePacket.b>) (a, b) -> this.unsafe(() -> method.invoke(action, a, b)));
  485.             return new ClientboundPlayerInfoUpdatePacket(data);
  486.         });
  487.     }
  488.  
  489.     public static void initEventHandler(Plugin plugin) {
  490.         EventManager.init(plugin);
  491.     }
  492.  
  493.     public enum EntityState implements EnumUtil.Maskable<EntityState> {
  494.  
  495.         DEFAULT(0x00),
  496.         ON_FIRE(0x01),
  497.         @Deprecated CROUCHING(0x02),
  498.         @Deprecated UNUSED(0x04),
  499.         SPRINTING(0x08),
  500.         SWIMMING(0x10),
  501.         INVISIBLE(0x20),
  502.         GLOWING(0x40),
  503.         FLYING(0x80);
  504.  
  505.         private final int mask;
  506.  
  507.         EntityState(int mask) {
  508.             this.mask = mask;
  509.         }
  510.  
  511.         public int getMask() {
  512.             return mask;
  513.         }
  514.     }
  515.  
  516.     public enum SkinStatus implements EnumUtil.Maskable<SkinStatus> {
  517.  
  518.         CAPE_ENABLED(0x01),
  519.         JACKET_ENABLED(0x02),
  520.         LEFT_SLEEVE_ENABLED(0x04),
  521.         RIGHT_SLEEVE_ENABLED(0x08),
  522.         LEFT_PANTS_LEG_ENABLED(0x10),
  523.         RIGHT_PANTS_LEG_ENABLED(0x20),
  524.         HAT_ENABLED(0x40),
  525.         @Deprecated UNUSED(0x80);
  526.  
  527.         private static final SkinStatus[] ALL = {CAPE_ENABLED, JACKET_ENABLED, LEFT_SLEEVE_ENABLED, RIGHT_SLEEVE_ENABLED, LEFT_PANTS_LEG_ENABLED, RIGHT_PANTS_LEG_ENABLED, HAT_ENABLED};
  528.         private final int mask;
  529.  
  530.         SkinStatus(int mask) {
  531.             this.mask = mask;
  532.         }
  533.  
  534.         public int getMask() {
  535.             return mask;
  536.         }
  537.     }
  538.  
  539.     public enum Pose implements EnumUtil.Identifiable<EntityPose> {
  540.  
  541.         STANDING(EntityPose.a),
  542.         FALL_FLYING(EntityPose.b),
  543.         SLEEPING(EntityPose.c),
  544.         SWIMMING(EntityPose.d),
  545.         SPIN_ATTACK(EntityPose.e),
  546.         CROUCHING(EntityPose.f),
  547.         LONG_JUMPING(EntityPose.g),
  548.         DYING(EntityPose.h),
  549.         CROAKING(EntityPose.i),
  550.         ROARING(EntityPose.j),
  551.         SNIFFING(EntityPose.k),
  552.         EMERGING(EntityPose.l),
  553.         DIGGING(EntityPose.m);
  554.  
  555.         private final EntityPose nmsPose;
  556.  
  557.         Pose(EntityPose nmsPose) {
  558.             this.nmsPose = nmsPose;
  559.         }
  560.  
  561.         public EntityPose getID() {
  562.             return nmsPose;
  563.         }
  564.  
  565.     }
  566.  
  567.     public enum HandStatus implements EnumUtil.Maskable<HandStatus> {
  568.  
  569.         MAIN_HAND(0x00),
  570.         HAND_ACTIVE(0x01),
  571.         OFF_HAND(0x02),
  572.         RIPTIDE_SPIN_ATTACK(0x04);
  573.  
  574.         private final int mask;
  575.  
  576.         HandStatus(int mask) {
  577.             this.mask = mask;
  578.         }
  579.  
  580.         public int getMask() {
  581.             return mask;
  582.         }
  583.     }
  584.  
  585.     public enum Hand implements EnumUtil.BiIdentifiable<EnumHand, Integer> {
  586.  
  587.         OFF_HAND(EnumHand.b, 1),
  588.         MAIN_HAND(EnumHand.a, 0);
  589.  
  590.         private final EnumHand id;
  591.         private final int type;
  592.  
  593.         Hand(EnumHand id, int type) {
  594.             this.id = id;
  595.             this.type = type;
  596.         }
  597.  
  598.         public Integer getSecondID() {
  599.             return type;
  600.         }
  601.  
  602.         public EnumHand getID() {
  603.             return id;
  604.         }
  605.  
  606.     }
  607.  
  608.     public enum InteractType implements EnumUtil.Identifiable<String> {
  609.  
  610.         RIGHT_CLICK("INTERACT"),
  611.         LEFT_CLICK("ATTACK"),
  612.         RIGHT_CLICK_AT("INTERACT_AT");
  613.  
  614.         private final String id;
  615.  
  616.         InteractType(String id) {
  617.             this.id = id;
  618.         }
  619.  
  620.         public String getID() {
  621.             return id;
  622.         }
  623.     }
  624.  
  625.     public enum PlayerInfo {
  626.  
  627.         ADD_PLAYER(ClientboundPlayerInfoUpdatePacket.a.a),
  628.         UPDATE_GAME_MODE(ClientboundPlayerInfoUpdatePacket.a.b),
  629.         UPDATE_LATENCY(ClientboundPlayerInfoUpdatePacket.a.c),
  630.         UPDATE_DISPLAY_NAME(ClientboundPlayerInfoUpdatePacket.a.d),
  631.         REMOVE_PLAYER(ClientboundPlayerInfoUpdatePacket.a.e);
  632.  
  633.         private final ClientboundPlayerInfoUpdatePacket.a nmsAction;
  634.  
  635.         PlayerInfo(ClientboundPlayerInfoUpdatePacket.a nmsAction) {
  636.             this.nmsAction = nmsAction;
  637.         }
  638.  
  639.         public ClientboundPlayerInfoUpdatePacket.a getNMSAction() {
  640.             return nmsAction;
  641.         }
  642.     }
  643.  
  644.     public enum Ping {
  645.  
  646.         NO_CONNECTION(-1),
  647.         ONE_BAR(1000),
  648.         TWO_BARS(999),
  649.         THREE_BARS(599),
  650.         FOUR_BARS(299),
  651.         FIVE_BARS(149);
  652.  
  653.         private final int milliseconds;
  654.  
  655.         Ping(int milliseconds) {
  656.             this.milliseconds = milliseconds;
  657.         }
  658.  
  659.         public int getMilliseconds() {
  660.             return milliseconds;
  661.         }
  662.     }
  663.  
  664.     public enum ItemSlot {
  665.  
  666.         MAIN_HAND(EnumItemSlot.a),
  667.         OFF_HAND(EnumItemSlot.b),
  668.         BOOTS(EnumItemSlot.c),
  669.         LEGGINGS(EnumItemSlot.d),
  670.         CHESTPLATE(EnumItemSlot.e),
  671.         HELMET(EnumItemSlot.f);
  672.  
  673.         private final EnumItemSlot nmsItemSlot;
  674.  
  675.         ItemSlot(EnumItemSlot nmsItemSlot) {
  676.             this.nmsItemSlot = nmsItemSlot;
  677.         }
  678.  
  679.         public EnumItemSlot getNMSItemSlot() {
  680.             return nmsItemSlot;
  681.         }
  682.     }
  683.  
  684.     public enum GlowColor {
  685.  
  686.         BLACK(EnumChatFormat.a),
  687.         DARK_BLUE(EnumChatFormat.b),
  688.         DARK_GREEN(EnumChatFormat.c),
  689.         DARK_AQUA(EnumChatFormat.d),
  690.         DARK_RED(EnumChatFormat.e),
  691.         DARK_PURPLE(EnumChatFormat.f),
  692.         GOLD(EnumChatFormat.g),
  693.         GRAY(EnumChatFormat.h),
  694.         DARK_GRAY(EnumChatFormat.i),
  695.         BLUE(EnumChatFormat.j),
  696.         GREEN(EnumChatFormat.k),
  697.         AQUA(EnumChatFormat.l),
  698.         RED(EnumChatFormat.m),
  699.         LIGHT_PURPLE(EnumChatFormat.n),
  700.         YELLOW(EnumChatFormat.o),
  701.         WHITE(EnumChatFormat.p),
  702.         NONE(EnumChatFormat.v);
  703.  
  704.         private final EnumChatFormat nmsColor;
  705.  
  706.         GlowColor(EnumChatFormat nmsColor) {
  707.             this.nmsColor = nmsColor;
  708.         }
  709.  
  710.         public EnumChatFormat getNMSColor() {
  711.             return nmsColor;
  712.         }
  713.     }
  714.  
  715.     public enum GameMode {
  716.  
  717.         SURVIVAL(EnumGamemode.a),
  718.         CREATIVE(EnumGamemode.b),
  719.         ADVENTURE(EnumGamemode.c),
  720.         SPECTATOR(EnumGamemode.d);
  721.  
  722.         private final EnumGamemode nmsGameMode;
  723.  
  724.         GameMode(EnumGamemode nmsGameMode) {
  725.             this.nmsGameMode = nmsGameMode;
  726.         }
  727.  
  728.         public EnumGamemode getNMSGameMode() {
  729.             return nmsGameMode;
  730.         }
  731.     }
  732.  
  733.     public enum Animation {
  734.  
  735.         SWING_MAIN_HAND(0),
  736.         TAKE_DAMAGE(1),
  737.         LEAVE_BED(2),
  738.         SWING_OFFHAND(3),
  739.         CRITICAL_EFFECT(4),
  740.         MAGIC_CRITICAL_EFFECT(5);
  741.  
  742.         private final int type;
  743.  
  744.         Animation(int type) {
  745.             this.type = type;
  746.         }
  747.  
  748.         public int getType() {
  749.             return type;
  750.         }
  751.  
  752.     }
  753.  
  754.     public class MetaData {
  755.  
  756.         //Entity metadata
  757.         private final DataWatcher.Item<Byte> entityState = a(0, (byte) EnumUtil.createMask(EntityState.DEFAULT));
  758.         private final DataWatcher.Item<Integer> airTicks = a(1, 300);
  759.         private final DataWatcher.Item<Optional<IChatBaseComponent>> customName = a(2, Optional.empty(), DataWatcherRegistry.g);
  760.         private final DataWatcher.Item<Boolean> customNameVisible = a(3, false);
  761.         private final DataWatcher.Item<Boolean> silent = a(4, false);
  762.         private final DataWatcher.Item<Boolean> noGravity = a(5, false);
  763.         private final DataWatcher.Item<EntityPose> pose = a(6, Pose.STANDING.getID());
  764.         private final DataWatcher.Item<Integer> frozenTicks = a(7, 0); //shaking at tick 140
  765.  
  766.         //LivingEntity metadata
  767.         private final DataWatcher.Item<Byte> handStatus = a(8, (byte) EnumUtil.createMask(HandStatus.MAIN_HAND));
  768.         private final DataWatcher.Item<Float> health = a(9, 1.0F);
  769.         private final DataWatcher.Item<Integer> potionEffectColor = a(10, 0);
  770.         private final DataWatcher.Item<Boolean> isPotionEffectAmbient = a(11, false);
  771.         private final DataWatcher.Item<Integer> arrowsInEntity = a(12, 0);
  772.         private final DataWatcher.Item<Integer> beeStingers = a(13, 0);
  773.         private final DataWatcher.Item<Optional<BlockPosition>> sleepingBedLocation = a(14, Optional.empty(), DataWatcherRegistry.n);
  774.  
  775.         //Player metadata
  776.         private final DataWatcher.Item<Float> additionalHearts = a(15, 0.0F);
  777.         private final DataWatcher.Item<Integer> score = a(16, 0);
  778.         private final DataWatcher.Item<Byte> skinStatus = a(17, (byte) EnumUtil.createMask(SkinStatus.ALL));
  779.         private final DataWatcher.Item<Byte> hand = a(18, (byte) ((int) Hand.MAIN_HAND.getSecondID()));
  780.         private final DataWatcher.Item<NBTTagCompound> leftShoulder = a(19, new NBTTagCompound());
  781.         private final DataWatcher.Item<NBTTagCompound> rightShoulder = a(20, new NBTTagCompound());
  782.  
  783.         private final List<DataWatcher.Item<?>> list;
  784.  
  785.         public MetaData() {
  786.             this.list = new ArrayList<>(Arrays.asList(
  787.                     this.entityState,
  788.                     this.airTicks,
  789.                     this.customName,
  790.                     this.customNameVisible,
  791.                     this.silent,
  792.                     this.noGravity,
  793.                     this.pose,
  794.                     this.frozenTicks,
  795.                     this.handStatus,
  796.                     this.health,
  797.                     this.potionEffectColor,
  798.                     this.isPotionEffectAmbient,
  799.                     this.arrowsInEntity,
  800.                     this.beeStingers,
  801.                     this.sleepingBedLocation,
  802.                     this.additionalHearts,
  803.                     this.score,
  804.                     this.skinStatus,
  805.                     this.hand,
  806.                     this.leftShoulder,
  807.                     this.rightShoulder));
  808.         }
  809.  
  810.         public List<EntityState> getEntityState() {
  811.             return EnumUtil.fromMask(entityState.b(), EntityState.class);
  812.         }
  813.  
  814.         public Integer getAirTicks() {
  815.             return airTicks.b();
  816.         }
  817.  
  818.         public Optional<IChatBaseComponent> getCustomName() {
  819.             return customName.b();
  820.         }
  821.  
  822.         public Boolean isCustomNameVisible() {
  823.             return customNameVisible.b();
  824.         }
  825.  
  826.         public Boolean isSilent() {
  827.             return silent.b();
  828.         }
  829.  
  830.         public Boolean hasNoGravity() {
  831.             return noGravity.b();
  832.         }
  833.  
  834.         public Pose getPose() {
  835.             return EnumUtil.getByID(this.pose.b(), Pose.class);
  836.         }
  837.  
  838.         public Integer getFrozenTicks() {
  839.             return frozenTicks.b();
  840.         }
  841.  
  842.         public List<HandStatus> getHandStatus() {
  843.             return EnumUtil.fromMask(handStatus.b(), HandStatus.class);
  844.         }
  845.  
  846.         public Float getHealth() {
  847.             return health.b();
  848.         }
  849.  
  850.         public Integer getPotionEffectColor() {
  851.             return potionEffectColor.b();
  852.         }
  853.  
  854.         public Boolean isPotionEffectAmbient() {
  855.             return isPotionEffectAmbient.b();
  856.         }
  857.  
  858.         public Integer getArrowsInEntity() {
  859.             return arrowsInEntity.b();
  860.         }
  861.  
  862.         public Integer getBeeStingers() {
  863.             return beeStingers.b();
  864.         }
  865.  
  866.         public Optional<BlockPosition> getSleepingBedLocation() {
  867.             return sleepingBedLocation.b();
  868.         }
  869.  
  870.         public Float getAdditionalHearts() {
  871.             return additionalHearts.b();
  872.         }
  873.  
  874.         public Integer getScore() {
  875.             return score.b();
  876.         }
  877.  
  878.         public List<SkinStatus> getSkinStatus() {
  879.             return EnumUtil.fromMask(skinStatus.b(), SkinStatus.class);
  880.         }
  881.  
  882.         public Hand getHand() {
  883.             return EnumUtil.getBySecondID((int) hand.b(), Hand.class);
  884.         }
  885.  
  886.         public NBTTagCompound getLeftShoulder() {
  887.             return leftShoulder.b();
  888.         }
  889.  
  890.         public NBTTagCompound getRightShoulder() {
  891.             return rightShoulder.b();
  892.         }
  893.  
  894.         public void setEntityState(EntityState... entityState) {
  895.             this.entityState.a((byte) EnumUtil.createMask(entityState));
  896.         }
  897.  
  898.         public void setAirTicks(Integer airTicks) {
  899.             this.airTicks.a(airTicks);
  900.         }
  901.  
  902.         public void setCustomName(String customName) {
  903.             this.customName.a(Optional.ofNullable(IChatBaseComponent.a(customName)));
  904.         }
  905.  
  906.         public void setCustomNameVisible(Boolean customNameVisible) {
  907.             this.customNameVisible.a(customNameVisible);
  908.         }
  909.  
  910.         public void setSilent(Boolean silent) {
  911.             this.silent.a(silent);
  912.         }
  913.  
  914.         public void setNoGravity(Boolean gravity) {
  915.             this.noGravity.a(gravity);
  916.         }
  917.  
  918.         public void setPose(Pose pose) {
  919.             this.pose.a(pose.getID());
  920.         }
  921.  
  922.         public void setFrozenTicks(Integer frozenTicks) {
  923.             this.frozenTicks.a(frozenTicks);
  924.         }
  925.  
  926.         public void setShaking(boolean shaking) {
  927.             this.setFrozenTicks(shaking ? 140 : 0);
  928.         }
  929.  
  930.         public void setHandStatus(HandStatus handStatus) {
  931.             this.handStatus.a((byte) EnumUtil.createMask(handStatus));
  932.         }
  933.  
  934.         public void setHealth(Float health) {
  935.             this.health.a(health);
  936.         }
  937.  
  938.         public void setPotionEffectColor(Integer potionEffectColor) {
  939.             this.potionEffectColor.a(potionEffectColor);
  940.         }
  941.  
  942.         public void setIsPotionEffectAmbient(Boolean isPotionEffectAmbient) {
  943.             this.isPotionEffectAmbient.a(isPotionEffectAmbient);
  944.         }
  945.  
  946.         public void setArrowsInEntity(Integer arrowsInEntity) {
  947.             this.arrowsInEntity.a(arrowsInEntity);
  948.         }
  949.  
  950.         public void setBeeStingers(Integer beeStingers) {
  951.             this.beeStingers.a(beeStingers);
  952.         }
  953.  
  954.         public void setSleepingBedLocation(BlockPosition sleepingBedLocation) {
  955.             this.sleepingBedLocation.a(Optional.ofNullable(sleepingBedLocation));
  956.         }
  957.  
  958.         public void setAdditionalHearts(Float additionalHearts) {
  959.             this.additionalHearts.a(additionalHearts);
  960.         }
  961.  
  962.         public void setScore(Integer score) {
  963.             this.score.a(score);
  964.         }
  965.  
  966.         public void setSkinStatus(SkinStatus... skinStatus) {
  967.             this.skinStatus.a((byte) EnumUtil.createMask(skinStatus));
  968.         }
  969.  
  970.         public void setHand(Hand hand) {
  971.             this.hand.a((byte) ((int) hand.getSecondID()));
  972.         }
  973.  
  974.         public void setLeftShoulder(NBTTagCompound leftShoulder) {
  975.             this.leftShoulder.a(leftShoulder);
  976.         }
  977.  
  978.         public void setRightShoulder(NBTTagCompound rightShoulder) {
  979.             this.rightShoulder.a(rightShoulder);
  980.         }
  981.  
  982.         public List<DataWatcher.Item<?>> getList() {
  983.             return list;
  984.         }
  985.  
  986.         private static <T> DataWatcher.Item<T> a(int index, T value) {
  987.             DataWatcherSerializer<?> serializer = null;
  988.  
  989.             if (value instanceof Byte) {
  990.                 serializer = DataWatcherRegistry.a;
  991.             } else if (value instanceof Float) {
  992.                 serializer = DataWatcherRegistry.c;
  993.             } else if (value instanceof Integer) {
  994.                 serializer = DataWatcherRegistry.b;
  995.             } else if (value instanceof String) {
  996.                 serializer = DataWatcherRegistry.d;
  997.             } else if (value instanceof Boolean) {
  998.                 serializer = DataWatcherRegistry.i;
  999.             } else if (value instanceof NBTTagCompound) {
  1000.                 serializer = DataWatcherRegistry.q;
  1001.             } else if (value instanceof BlockPosition) {
  1002.                 serializer = DataWatcherRegistry.m;
  1003.             } else if (value instanceof IChatBaseComponent) {
  1004.                 serializer = DataWatcherRegistry.e;
  1005.             } else if (value instanceof EntityPose) {
  1006.                 serializer = DataWatcherRegistry.t;
  1007.             }
  1008.             return a(index, value, (DataWatcherSerializer<T>) serializer);
  1009.         }
  1010.  
  1011.         private static <T> DataWatcher.Item<T> a(int index, T value, DataWatcherSerializer<T> serializer) {
  1012.             return new DataWatcher.Item<T>(new DataWatcherObject<T>(index, serializer), value);
  1013.         }
  1014.  
  1015.     }
  1016.  
  1017.     public static class EnumUtil {
  1018.  
  1019.         private interface Maskable<M> {
  1020.             int getMask();
  1021.         }
  1022.  
  1023.         private interface Identifiable<I> {
  1024.  
  1025.             I getID();
  1026.  
  1027.         }
  1028.  
  1029.         private interface BiIdentifiable<I, J> extends Identifiable<I> {
  1030.  
  1031.             J getSecondID();
  1032.         }
  1033.  
  1034.         @SafeVarargs
  1035.         private static <M> int createMask(Maskable<M>... maskables) {
  1036.             int mask = 0;
  1037.             for (Maskable<M> m : maskables) {
  1038.                 mask |= m.getMask();
  1039.             }
  1040.             return mask;
  1041.         }
  1042.  
  1043.         private static <M extends Maskable<M>> List<M> fromMask(int mask, Class<M> enumClass) {
  1044.             List<M> list = new ArrayList<M>();
  1045.             for (M maskable : enumClass.getEnumConstants()) {
  1046.                 if ((maskable.getMask() & mask) != 0) {
  1047.                     list.add(maskable);
  1048.                 }
  1049.             }
  1050.             return list;
  1051.         }
  1052.  
  1053.         private static <I, M extends Identifiable<I>> M getByID(I id, Class<M> enumClass) {
  1054.             for (M identifiable : enumClass.getEnumConstants()) {
  1055.                 if (id == identifiable.getID()) {
  1056.                     return identifiable;
  1057.                 }
  1058.             }
  1059.             return null;
  1060.         }
  1061.  
  1062.         private static <I, J, M extends BiIdentifiable<I, J>> M getBySecondID(J id, Class<M> enumClass) {
  1063.             for (M identifiable : enumClass.getEnumConstants()) {
  1064.                 if (id == identifiable.getID()) {
  1065.                     return identifiable;
  1066.                 }
  1067.             }
  1068.             return null;
  1069.         }
  1070.     }
  1071.  
  1072.     public static class SkinTextures {
  1073.  
  1074.         private static final String TEXTURE_URL = "https://mc-heads.net/minecraft/profile/%s/signed";
  1075.         private static final String UUID_URL = "https://api.mojang.com/profiles/minecraft";
  1076.  
  1077.         private final String texture;
  1078.         private final String signature;
  1079.  
  1080.         public SkinTextures(String textures, String signature) {
  1081.             this.texture = textures;
  1082.             this.signature = signature;
  1083.         }
  1084.  
  1085.         public String getTexture() {
  1086.             return texture;
  1087.         }
  1088.  
  1089.         public String getSignature() {
  1090.             return signature;
  1091.         }
  1092.  
  1093.         public static BukkitCompletable<SkinTextures> getByUsername(Plugin plugin, String username) {
  1094.             return BukkitCompletable.supplyASync(plugin, ()->{
  1095.                 JSONArray array = new JSONArray();
  1096.                 array.add(username);
  1097.                 UUID uuid = null;
  1098.                 HttpRequest request = HttpRequest.newBuilder(new URI(UUID_URL))
  1099.                         .setHeader("Content-Type", "application/json")
  1100.                         .POST(HttpRequest.BodyPublishers.ofString(array.toString()))
  1101.                         .timeout(Duration.ofSeconds(5))
  1102.                         .build();
  1103.                 HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
  1104.                 if (response.statusCode() == HttpURLConnection.HTTP_OK) {
  1105.                     JSONArray uuidArray = (JSONArray) new JSONParser().parse(response.body());
  1106.                     if (uuidArray.size() > 0) {
  1107.                         String uuidStr = (String) ((JSONObject) uuidArray.get(0)).get("id");
  1108.                         uuid = UUID.fromString(uuidStr.replaceAll("(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})", "$1-$2-$3-$4-$5"));
  1109.                     }
  1110.                 }
  1111.                 if (uuid == null) throw new NullPointerException("uuid is null");
  1112.                 return getByUUID(plugin, uuid).getSync();
  1113.             });
  1114.         }
  1115.  
  1116.         public static BukkitCompletable<SkinTextures> getByUUID(Plugin plugin, UUID uuid) {
  1117.             return BukkitCompletable.supplyASync(plugin, ()->{
  1118.                 SkinTextures result = null;
  1119.                 HttpRequest request = HttpRequest.newBuilder(new URI(String.format(TEXTURE_URL, uuid.toString().replace("-", ""))))
  1120.                         .timeout(Duration.ofSeconds(5))
  1121.                         .GET()
  1122.                         .build();
  1123.                 HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
  1124.                 if (response.statusCode() == HttpURLConnection.HTTP_OK) {
  1125.                     JSONArray properties = (JSONArray) ((JSONObject) new JSONParser().parse(response.body())).get("properties");
  1126.                     for (int t = 0; t < properties.size(); t++) {
  1127.                         JSONObject obj = (JSONObject) properties.get(t);
  1128.                         if (obj.containsKey("name") && obj.get("name").equals("textures")) {
  1129.                             result = new SkinTextures((String) obj.get("value"), (String) obj.get("signature"));
  1130.                         }
  1131.                     }
  1132.                 }
  1133.                 return result;
  1134.             });
  1135.         }
  1136.  
  1137.         public static BukkitCompletable<SkinTextures> getByCachedUsername(Plugin plugin, String username) {
  1138.             return BukkitCompletable.supplyASync(plugin, ()->{
  1139.                 SkinTextures result = null;
  1140.                 HttpRequest request = HttpRequest.newBuilder(new URI(String.format(TEXTURE_URL, username)))
  1141.                         .timeout(Duration.ofSeconds(5))
  1142.                         .GET()
  1143.                         .build();
  1144.                 HttpResponse<String> response = HttpClient.newHttpClient().send(request, HttpResponse.BodyHandlers.ofString());
  1145.                 if (response.statusCode() == HttpURLConnection.HTTP_OK) {
  1146.                     JSONArray properties = (JSONArray) ((JSONObject) new JSONParser().parse(response.body())).get("properties");
  1147.                     for(Object property : properties)
  1148.                     {
  1149.                         JSONObject obj = (JSONObject) property;
  1150.                         if(obj.containsKey("name") && obj.get("name").equals("textures"))
  1151.                         {
  1152.                             result = new SkinTextures((String) obj.get("value"), (String) obj.get("signature"));
  1153.                         }
  1154.                     }
  1155.                 }
  1156.                 return result;
  1157.             });
  1158.         }
  1159.     }
  1160.  
  1161.     public static class BukkitCompletable<T> {
  1162.  
  1163.         private final Plugin plugin;
  1164.         private final UnsafeSupplier<T> runnable;
  1165.         private Consumer<Throwable> errorHandler;
  1166.         private Consumer<T> callbackHandler;
  1167.         private Runnable emptyCallbackHandler;
  1168.  
  1169.         private BukkitCompletable(Plugin plugin, UnsafeSupplier<T> runnable) {
  1170.             this.plugin = plugin;
  1171.             this.runnable = runnable;
  1172.         }
  1173.  
  1174.         public static <T> BukkitCompletable<T> supplyASync(Plugin plugin, UnsafeSupplier<T> runnable) {
  1175.             return new BukkitCompletable<T>(plugin, runnable);
  1176.         }
  1177.  
  1178.         public BukkitCompletable<T> onFinish(Consumer<T> callbackHandler) {
  1179.             this.callbackHandler = callbackHandler;
  1180.             return this;
  1181.         }
  1182.  
  1183.         public BukkitCompletable<T> onEmptyFinish(Runnable emptyCallbackHandler) {
  1184.             this.emptyCallbackHandler = emptyCallbackHandler;
  1185.             return this;
  1186.         }
  1187.  
  1188.         public BukkitCompletable<T> onException(Consumer<Throwable> errorHandler) {
  1189.             this.errorHandler = errorHandler;
  1190.             return this;
  1191.         }
  1192.  
  1193.         public void getSafe() {
  1194.             this.get(true);
  1195.         }
  1196.  
  1197.         public void getUnsafe() {
  1198.             this.get(false);
  1199.         }
  1200.  
  1201.         public T getSync() throws Exception {
  1202.             return runnable.get();
  1203.         }
  1204.  
  1205.         private void get(boolean safe) {
  1206.             async(plugin, ()->{
  1207.                 try {
  1208.                     T t = this.runnable.get();
  1209.                     if(!(this.callbackHandler == null && this.emptyCallbackHandler == null)) {
  1210.                         if(safe) {
  1211.                             sync(plugin, () -> {
  1212.                                 if (callbackHandler != null) this.callbackHandler.accept(t);
  1213.                                 if (emptyCallbackHandler != null) this.emptyCallbackHandler.run();
  1214.                             });
  1215.                         } else {
  1216.                             if(callbackHandler != null) this.callbackHandler.accept(t);
  1217.                             if(emptyCallbackHandler != null) this.emptyCallbackHandler.run();
  1218.                         }
  1219.                     }
  1220.                 } catch (Throwable e) {
  1221.                     if(this.errorHandler != null) {
  1222.                         if(safe) sync(plugin, ()->this.errorHandler.accept(e));
  1223.                         else this.errorHandler.accept(e);
  1224.                     }
  1225.                 }
  1226.             });
  1227.         }
  1228.     }
  1229.  
  1230.     private static class EventManager implements Listener {
  1231.  
  1232.         private static final String CHANNEL_NAME = "npc_manager";
  1233.         private static EventManager INSTANCE;
  1234.  
  1235.         private final Plugin plugin;
  1236.         private final Map<Integer, NPCListener> listenerMap = new HashMap<>();
  1237.  
  1238.         private EventManager(Plugin plugin) {
  1239.             this.plugin = plugin;
  1240.             Bukkit.getPluginManager().registerEvents(this, plugin);
  1241.             Bukkit.getOnlinePlayers().forEach(this::unregisterPlayer);
  1242.             Bukkit.getOnlinePlayers().forEach(this::registerPlayer);
  1243.         }
  1244.  
  1245.         private void listenNPC(NPC npc, NPCListener listener) {
  1246.             if (listenerMap.containsKey(npc.getEntityID()))
  1247.                 throw new UnsupportedOperationException("cannot register same npc twice");
  1248.             this.listenerMap.put(npc.getEntityID(), listener);
  1249.         }
  1250.  
  1251.         private void unlistenNPC(NPC npc) {
  1252.             if (!listenerMap.containsKey(npc.getEntityID())) throw new NullPointerException("listener does not exist");
  1253.             this.listenerMap.remove(npc.getEntityID());
  1254.         }
  1255.  
  1256.         private void unregisterPlayer(Player player) {
  1257.             ChannelPipeline pipeline = ((CraftPlayer) player).getHandle().b.b.m.pipeline();
  1258.             if(pipeline.names().contains(CHANNEL_NAME)) {
  1259.                 pipeline.remove(CHANNEL_NAME);
  1260.             }
  1261.         }
  1262.  
  1263.         private void registerPlayer(Player player) {
  1264.             ChannelPipeline pipeline = ((CraftPlayer) player).getHandle().b.b.m.pipeline();
  1265.             if(!pipeline.names().contains(CHANNEL_NAME)) {
  1266.                 pipeline.addBefore("packet_handler", CHANNEL_NAME, new PlayerInboundHandlerAdapter(player));
  1267.             }
  1268.         }
  1269.  
  1270.         @EventHandler(priority = EventPriority.LOWEST)
  1271.         public void onPlayerJoinEvent(PlayerJoinEvent e) {
  1272.             this.registerPlayer(e.getPlayer());
  1273.         }
  1274.  
  1275.         public static boolean isInitialized() {
  1276.             return INSTANCE != null;
  1277.         }
  1278.  
  1279.         public static void init(Plugin plugin) {
  1280.             if(INSTANCE != null) INSTANCE.listenerMap.clear();
  1281.             INSTANCE = new EventManager(plugin);
  1282.         }
  1283.  
  1284.         private class PlayerInboundHandlerAdapter extends ChannelInboundHandlerAdapter {
  1285.  
  1286.             private final Player player;
  1287.  
  1288.             public PlayerInboundHandlerAdapter(Player player) {
  1289.                 this.player = player;
  1290.             }
  1291.  
  1292.             @Override
  1293.             public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
  1294.                 super.channelRead(ctx, msg);
  1295.                 try {
  1296.                     if (msg instanceof PacketPlayInUseEntity packet) {
  1297.                         Field entityIdField = packet.getClass().getDeclaredField("a");
  1298.                         entityIdField.setAccessible(true);
  1299.                         int entityId = (int) entityIdField.get(packet);
  1300.                         final NPCListener listener = listenerMap.getOrDefault(entityId, null);
  1301.                         if (listener != null) {
  1302.                             Field typeField = packet.getClass().getDeclaredField("b");
  1303.                             typeField.setAccessible(true);
  1304.                             Object type = typeField.get(packet);
  1305.                             Method typeMethod = type.getClass().getDeclaredMethod("a");
  1306.                             typeMethod.setAccessible(true);
  1307.                             InteractType interactType = EnumUtil.getByID(((Enum) typeMethod.invoke(type)).name(), InteractType.class);
  1308.                             Hand hand = Hand.MAIN_HAND;
  1309.                             if (interactType != InteractType.RIGHT_CLICK_AT) {
  1310.                                 if (interactType == InteractType.RIGHT_CLICK) {
  1311.                                     Field handField = type.getClass().getDeclaredField("a");
  1312.                                     handField.setAccessible(true);
  1313.                                     hand = EnumUtil.getByID((EnumHand) handField.get(type), Hand.class);
  1314.                                 }
  1315.                                 boolean sneaking = packet.b();
  1316.                                 final NPCInteractEvent event = new NPCInteractEvent(this.player, interactType, hand, sneaking);
  1317.                                 Bukkit.getScheduler().runTask(plugin, () -> listener.accept(event));
  1318.                             }
  1319.                         }
  1320.                     }
  1321.                 } catch (Exception e) {
  1322.                     e.printStackTrace();
  1323.                 }
  1324.                 ;
  1325.             }
  1326.         }
  1327.     }
  1328.  
  1329.     public record TeamFeatures(boolean nameTagVisible, boolean collision, GlowColor glowColor) {}
  1330.  
  1331.     public record NPCInteractEvent(Player player, InteractType interactType, Hand hand, boolean sneaking) {
  1332.     }
  1333.  
  1334.     public static void sync(Plugin plugin, Runnable runnable) {
  1335.         Bukkit.getScheduler().runTask(plugin, runnable);
  1336.     }
  1337.  
  1338.     public static void async(Plugin plugin, Runnable runnable) {
  1339.         Bukkit.getScheduler().runTaskAsynchronously(plugin, runnable);
  1340.     }
  1341.  
  1342.     public static void sleep(int milliseconds) {
  1343.         try {
  1344.             Thread.sleep(milliseconds);
  1345.         } catch (InterruptedException e) {}
  1346.     }
  1347.  
  1348.     private static void unsafe(UnsafeRunnable run) {
  1349.         try {
  1350.             run.run();
  1351.         } catch (Exception e) {
  1352.             e.printStackTrace();
  1353.         }
  1354.     }
  1355.  
  1356.     private static <T> T createDataSerializer(UnsafeFunction<PacketDataSerializer, T> callback) {
  1357.         PacketDataSerializer data = new PacketDataSerializer(Unpooled.buffer());
  1358.         T result = null;
  1359.         try {
  1360.             result = callback.apply(data);
  1361.         } catch (Exception e) {
  1362.             e.printStackTrace();
  1363.         } finally {
  1364.             data.release();
  1365.         }
  1366.         return result;
  1367.     }
  1368.  
  1369.     @FunctionalInterface
  1370.     private interface UnsafeSupplier<T> {
  1371.         T get() throws Exception;
  1372.     }
  1373.  
  1374.     @FunctionalInterface
  1375.     private interface UnsafeRunnable {
  1376.         void run() throws Exception;
  1377.     }
  1378.  
  1379.     @FunctionalInterface
  1380.     private interface UnsafeFunction<K, T> {
  1381.         T apply(K k) throws Exception;
  1382.     }
  1383.  
  1384.     @FunctionalInterface
  1385.     public interface NPCListener extends Consumer<NPCInteractEvent> {
  1386.     }
  1387. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement