/* * Copyright (c) 2018 Jitse Boonstra */ package net.jitse.npclib.nms.v1_8_R3; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import net.jitse.npclib.NPCLib; import net.jitse.npclib.api.skin.Skin; import net.jitse.npclib.api.state.NPCAnimation; import net.jitse.npclib.api.state.NPCSlot; import net.jitse.npclib.hologram.Hologram; import net.jitse.npclib.internal.MinecraftVersion; import net.jitse.npclib.internal.NPCBase; import net.jitse.npclib.nms.v1_8_R3.packets.*; import net.minecraft.server.v1_8_R3.*; import org.bukkit.Bukkit; import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer; import org.bukkit.craftbukkit.v1_8_R3.inventory.CraftItemStack; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import java.util.List; /** * @author Jitse Boonstra */ public class NPC_v1_8_R3 extends NPCBase { private PacketPlayOutNamedEntitySpawn packetPlayOutNamedEntitySpawn; private PacketPlayOutScoreboardTeam packetPlayOutScoreboardTeamRegister; private PacketPlayOutPlayerInfo packetPlayOutPlayerInfoAdd, packetPlayOutPlayerInfoRemove; private PacketPlayOutEntityHeadRotation packetPlayOutEntityHeadRotation; private PacketPlayOutEntityDestroy packetPlayOutEntityDestroy; public NPC_v1_8_R3(NPCLib instance, List lines) { super(instance, lines); } @Override public Hologram getPlayerHologram(Player player) { Hologram holo = super.getPlayerHologram(player); if (holo == null){ holo = new Hologram(MinecraftVersion.V1_8_R3, location.clone().add(0, 0.5, 0), getPlayerLines(player)); } super.textDisplayHolograms.put(player.getUniqueId(), holo); return holo; } @Override public void createPackets() { Bukkit.getOnlinePlayers().forEach(this::createPackets); } @Override public void createPackets(Player player) { PacketPlayOutPlayerInfoWrapper packetPlayOutPlayerInfoWrapper = new PacketPlayOutPlayerInfoWrapper(); // Packets for spawning the NPC: this.packetPlayOutScoreboardTeamRegister = new PacketPlayOutScoreboardTeamWrapper() .createRegisterTeam(name); // First packet to send. this.packetPlayOutPlayerInfoAdd = packetPlayOutPlayerInfoWrapper .create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, gameProfile, name); // Second packet to send. this.packetPlayOutNamedEntitySpawn = new PacketPlayOutNamedEntitySpawnWrapper() .create(uuid, location, entityId); // Third packet to send. this.packetPlayOutEntityHeadRotation = new PacketPlayOutEntityHeadRotationWrapper() .create(location, entityId); // Fourth packet to send. this.packetPlayOutPlayerInfoRemove = packetPlayOutPlayerInfoWrapper .create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.REMOVE_PLAYER, gameProfile, name); // Fifth packet to send (delayed). // Packet for destroying the NPC: this.packetPlayOutEntityDestroy = new PacketPlayOutEntityDestroy(entityId); // First packet to send. } @Override public void sendShowPackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; if (hasTeamRegistered.add(player.getUniqueId())) playerConnection.sendPacket(packetPlayOutScoreboardTeamRegister); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); playerConnection.sendPacket(packetPlayOutEntityHeadRotation); getPlayerHologram(player).show(player); // Removing the player info after 10 seconds. Bukkit.getScheduler().runTaskLater(instance.getPlugin(), () -> playerConnection.sendPacket(packetPlayOutPlayerInfoRemove), 200); } @Override public void sendHidePackets(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); hologram.hide(player); } @Override public void sendMetadataPacket(Player player) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadataWrapper().create(activeStates, entityId); playerConnection.sendPacket(packet); } @Override public void sendEquipmentPacket(Player player, NPCSlot slot, boolean auto) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; if (slot == NPCSlot.OFFHAND) { if (!auto) { throw new UnsupportedOperationException("Offhand is not supported on servers below 1.9"); } return; } ItemStack item = getItem(slot); PacketPlayOutEntityEquipment packet = new PacketPlayOutEntityEquipment(entityId, slot.getSlot(), CraftItemStack.asNMSCopy(item)); playerConnection.sendPacket(packet); } @Override public void sendAnimationPacket(Player player, NPCAnimation animation) { if(animation == NPCAnimation.SWING_OFFHAND) { throw new IllegalArgumentException("Offhand Swing Animations are only available on 1.9 and up."); } PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; PacketPlayOutAnimation packet = new PacketPlayOutAnimationWrapper().create(animation, entityId); playerConnection.sendPacket(packet); } @Override public void updateSkin(Skin skin) { GameProfile newProfile = new GameProfile(uuid, name); newProfile.getProperties().get("textures").clear(); newProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); this.packetPlayOutPlayerInfoAdd = new PacketPlayOutPlayerInfoWrapper().create(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, newProfile, name); for (Player player : Bukkit.getOnlinePlayers()) { PlayerConnection playerConnection = ((CraftPlayer) player).getHandle().playerConnection; playerConnection.sendPacket(packetPlayOutPlayerInfoRemove); playerConnection.sendPacket(packetPlayOutEntityDestroy); playerConnection.sendPacket(packetPlayOutPlayerInfoAdd); playerConnection.sendPacket(packetPlayOutNamedEntitySpawn); } } }