Advertisement
Guest User

Untitled

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