296 lines
No EOL
15 KiB
Java
296 lines
No EOL
15 KiB
Java
package de.cliffbreak.varo.managers;
|
|
|
|
import java.io.IOException;
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.UUID;
|
|
|
|
import com.mojang.authlib.GameProfile;
|
|
import com.mojang.authlib.properties.Property;
|
|
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.Sound;
|
|
import org.bukkit.World;
|
|
import org.bukkit.craftbukkit.v1_15_R1.CraftServer;
|
|
import org.bukkit.craftbukkit.v1_15_R1.CraftWorld;
|
|
import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer;
|
|
import org.bukkit.craftbukkit.v1_15_R1.inventory.CraftItemStack;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
|
|
import org.bukkit.inventory.ItemStack;
|
|
import org.bukkit.inventory.PlayerInventory;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
import org.bukkit.scoreboard.Team;
|
|
import org.json.simple.JSONArray;
|
|
import org.json.simple.JSONObject;
|
|
import org.json.simple.JSONValue;
|
|
import org.json.simple.parser.ParseException;
|
|
|
|
import de.cliffbreak.varo.Varo;
|
|
import de.cliffbreak.varo.utils.ImprovedOfflinePlayer;
|
|
import de.cliffbreak.varo.utils.WebUtils;
|
|
import net.minecraft.server.v1_15_R1.DataWatcherObject;
|
|
import net.minecraft.server.v1_15_R1.DataWatcherRegistry;
|
|
import net.minecraft.server.v1_15_R1.EntityPlayer;
|
|
import net.minecraft.server.v1_15_R1.EnumItemSlot;
|
|
import net.minecraft.server.v1_15_R1.MinecraftServer;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityDestroy;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityEquipment;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityHeadRotation;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityMetadata;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutEntityStatus;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutNamedEntitySpawn;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutPlayerInfo;
|
|
import net.minecraft.server.v1_15_R1.PacketPlayOutPlayerInfo.EnumPlayerInfoAction;
|
|
import net.minecraft.server.v1_15_R1.PlayerConnection;
|
|
import net.minecraft.server.v1_15_R1.PlayerInteractManager;
|
|
import net.minecraft.server.v1_15_R1.WorldServer;
|
|
|
|
public class NPCManager {
|
|
|
|
private final Varo plugin;
|
|
private final ArrayList<EntityPlayer> npcs = new ArrayList<EntityPlayer>();
|
|
private final ArrayList<Integer> isDying = new ArrayList<Integer>();
|
|
private final HashMap<UUID, PlayerInventory> inventories = new HashMap<UUID, PlayerInventory>();
|
|
|
|
public NPCManager(final Varo plugin) {
|
|
this.plugin = plugin;
|
|
addAllClones();
|
|
}
|
|
|
|
public void createClone(final Player player) {
|
|
final Location location = player.getLocation();
|
|
final MinecraftServer nmsServer = ((CraftServer) Bukkit.getServer()).getServer();
|
|
final WorldServer nmsWorld = ((CraftWorld) player.getWorld()).getHandle();
|
|
final GameProfile gameProfile = new GameProfile(player.getUniqueId(), player.getName());
|
|
inventories.put(player.getUniqueId(), player.getInventory());
|
|
try {
|
|
final String result = WebUtils.GET("https://sessionserver.mojang.com/session/minecraft/profile/"
|
|
+ player.getUniqueId().toString().replace("-", "") + "?unsigned=false");
|
|
final JSONObject resultObject = (JSONObject) JSONValue.parseWithException(result);
|
|
final JSONObject properties = (JSONObject) ((JSONArray) resultObject.get("properties")).get(0);
|
|
|
|
gameProfile.getProperties().put("textures", new Property("textures", properties.get("value").toString(),
|
|
properties.get("signature").toString()));
|
|
} catch (IOException | ParseException e) {
|
|
this.plugin.getLogger().info(e.getMessage());
|
|
}
|
|
final PlayerInteractManager playerInteractManager = new PlayerInteractManager(nmsWorld);
|
|
final EntityPlayer npc = new EntityPlayer(nmsServer, nmsWorld, gameProfile, playerInteractManager);
|
|
|
|
npc.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
npc.setHealth((float) player.getHealth());
|
|
npcs.add(npc);
|
|
|
|
for (final Player connectionPlayer : Bukkit.getOnlinePlayers()) {
|
|
final PlayerConnection connection = ((CraftPlayer) connectionPlayer).getHandle().playerConnection;
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, npc));
|
|
}
|
|
}.runTaskLater(this.plugin, 20);
|
|
connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc));
|
|
connection.sendPacket(
|
|
new PacketPlayOutEntityHeadRotation(npc, (byte) ((location.getYaw() * 256.0F) / 360.0F)));
|
|
npc.getDataWatcher().set(new DataWatcherObject<>(16, DataWatcherRegistry.a),
|
|
(byte) this.plugin.getPlayerCache().getSkinParts(player.getUniqueId().toString().replace("-", "")));
|
|
npc.getDataWatcher().set(new DataWatcherObject<>(17, DataWatcherRegistry.a),
|
|
this.plugin.getPlayerCache().getMainHandAsByte(player.getUniqueId().toString().replace("-", "")));
|
|
connection.sendPacket(new PacketPlayOutEntityMetadata(npc.getId(), npc.getDataWatcher(), true));
|
|
sendEquipmentPackets(connection, npc.getId(), player.getInventory());
|
|
}
|
|
}
|
|
|
|
public void createOfflineClone(final UUID uuid, final String name) {
|
|
final String compressedUuid = uuid.toString().replace("-", "");
|
|
final Location location = this.plugin.getPlayerCache().getPlayerLocationCache(compressedUuid);
|
|
final MinecraftServer nmsServer = ((CraftServer) Bukkit.getServer()).getServer();
|
|
final WorldServer nmsWorld = ((CraftWorld) location.getWorld()).getHandle();
|
|
final GameProfile gameProfile = new GameProfile(uuid, name);
|
|
|
|
ImprovedOfflinePlayer iop = new ImprovedOfflinePlayer(uuid.toString());
|
|
iop.getInventoryItems();
|
|
|
|
// final Inventory inventory = this.plugin.getPlayerCache().getInventory(compressedUuid);
|
|
// for (ItemStack item : inventory.getContents()) {
|
|
// System.out.println(item);
|
|
// }
|
|
|
|
// inventories.put(uuid, inventory);
|
|
try {
|
|
final String result = WebUtils.GET(
|
|
"https://sessionserver.mojang.com/session/minecraft/profile/" + compressedUuid + "?unsigned=false");
|
|
final JSONObject resultObject = (JSONObject) JSONValue.parseWithException(result);
|
|
final JSONObject properties = (JSONObject) ((JSONArray) resultObject.get("properties")).get(0);
|
|
|
|
gameProfile.getProperties().put("textures", new Property("textures", properties.get("value").toString(),
|
|
properties.get("signature").toString()));
|
|
} catch (IOException | ParseException e) {
|
|
this.plugin.getLogger().info(e.getMessage());
|
|
}
|
|
|
|
final PlayerInteractManager playerInteractManager = new PlayerInteractManager(nmsWorld);
|
|
final EntityPlayer npc = new EntityPlayer(nmsServer, nmsWorld, gameProfile, playerInteractManager);
|
|
|
|
npc.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
|
// npc.setHealth(this.plugin.getPlayerCache().getHealth(compressedUuid));
|
|
// npcs.add(npc);
|
|
|
|
// for (final Player connectionPlayer : Bukkit.getOnlinePlayers()) {
|
|
// final PlayerConnection connection = ((CraftPlayer) connectionPlayer).getHandle().playerConnection;
|
|
// new BukkitRunnable() {
|
|
// @Override
|
|
// public void run() {
|
|
// connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, npc));
|
|
// }
|
|
// }.runTaskLater(this.plugin, 20);
|
|
// connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc));
|
|
// connection.sendPacket(
|
|
// new PacketPlayOutEntityHeadRotation(npc, (byte) ((location.getYaw() * 256.0F) / 360.0F)));
|
|
// npc.getDataWatcher().set(new DataWatcherObject<>(16, DataWatcherRegistry.a),
|
|
// (byte) this.plugin.getPlayerCache().getSkinParts(compressedUuid));
|
|
// npc.getDataWatcher().set(new DataWatcherObject<>(17, DataWatcherRegistry.a),
|
|
// this.plugin.getPlayerCache().getMainHandAsByte(compressedUuid));
|
|
// connection.sendPacket(new PacketPlayOutEntityMetadata(npc.getId(), npc.getDataWatcher(), true));
|
|
// // sendEquipmentPackets(connection, npc.getId(), inventory);
|
|
// }
|
|
}
|
|
|
|
private void sendEquipmentPackets(final PlayerConnection connection, final int id,
|
|
final PlayerInventory inventory) {
|
|
connection.sendPacket(new PacketPlayOutEntityEquipment(id, EnumItemSlot.MAINHAND,
|
|
CraftItemStack.asNMSCopy(inventory.getItemInMainHand())));
|
|
connection.sendPacket(new PacketPlayOutEntityEquipment(id, EnumItemSlot.OFFHAND,
|
|
CraftItemStack.asNMSCopy(inventory.getItemInOffHand())));
|
|
connection.sendPacket(new PacketPlayOutEntityEquipment(id, EnumItemSlot.FEET,
|
|
CraftItemStack.asNMSCopy(inventory.getBoots())));
|
|
connection.sendPacket(new PacketPlayOutEntityEquipment(id, EnumItemSlot.LEGS,
|
|
CraftItemStack.asNMSCopy(inventory.getLeggings())));
|
|
connection.sendPacket(new PacketPlayOutEntityEquipment(id, EnumItemSlot.CHEST,
|
|
CraftItemStack.asNMSCopy(inventory.getChestplate())));
|
|
connection.sendPacket(new PacketPlayOutEntityEquipment(id, EnumItemSlot.HEAD,
|
|
CraftItemStack.asNMSCopy(inventory.getHelmet())));
|
|
}
|
|
|
|
public void syncClones(final Player player) {
|
|
for (final EntityPlayer npc : this.npcs) {
|
|
final PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection;
|
|
connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.ADD_PLAYER, npc));
|
|
connection.sendPacket(new PacketPlayOutNamedEntitySpawn(npc));
|
|
connection.sendPacket(new PacketPlayOutEntityHeadRotation(npc, (byte) ((npc.yaw * 256.0F) / 360.0F)));
|
|
npc.getDataWatcher().set(new DataWatcherObject<>(16, DataWatcherRegistry.a),
|
|
(byte) this.plugin.getPlayerCache().getSkinParts(player.getUniqueId().toString().replace("-", "")));
|
|
npc.getDataWatcher().set(new DataWatcherObject<>(17, DataWatcherRegistry.a),
|
|
this.plugin.getPlayerCache().getMainHandAsByte(player.getUniqueId().toString().replace("-", "")));
|
|
connection.sendPacket(new PacketPlayOutEntityMetadata(npc.getId(), npc.getDataWatcher(), true));
|
|
sendEquipmentPackets(connection, npc.getId(), this.inventories.get(npc.getUniqueID()));
|
|
}
|
|
}
|
|
|
|
public boolean isNPC(final int id) {
|
|
for (final EntityPlayer npc : this.npcs) {
|
|
if (npc.getId() == id)
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public void addDamage(final Player damager, final int id, final double damage, final boolean isCritical) {
|
|
for (final EntityPlayer npc : this.npcs) {
|
|
if (npc.getId() == id) {
|
|
npc.setHealth((float) (npc.getHealth() - damage));
|
|
|
|
final World world = npc.getWorld().getWorld();
|
|
final Location loc = new Location(world, npc.locX(), npc.locY(), npc.locZ());
|
|
if (npc.getHealth() > 0.0F) {
|
|
for (final Player connectionPlayer : Bukkit.getOnlinePlayers()) {
|
|
final PlayerConnection connection = ((CraftPlayer) connectionPlayer)
|
|
.getHandle().playerConnection;
|
|
connection.sendPacket(new PacketPlayOutEntityStatus(npc, (byte) 2)); // Send HURT (2) Animation
|
|
}
|
|
world.playSound(loc, Sound.ENTITY_PLAYER_HURT, 1.0F, 1.0F);
|
|
world.playSound(loc, Sound.ENTITY_PLAYER_ATTACK_STRONG, 1.0F, 1.0F);
|
|
if (isCritical)
|
|
world.playSound(loc, Sound.ENTITY_PLAYER_ATTACK_CRIT, 1.0F, 1.0F);
|
|
} else {
|
|
if (this.isDying.contains(npc.getId())) {
|
|
return;
|
|
}
|
|
this.isDying.add(npc.getId());
|
|
// Send Death Animation Packet
|
|
for (final Player connectionPlayer : Bukkit.getOnlinePlayers()) {
|
|
final PlayerConnection connection = ((CraftPlayer) connectionPlayer)
|
|
.getHandle().playerConnection;
|
|
connection.sendPacket(new PacketPlayOutEntityMetadata(npc.getId(), npc.getDataWatcher(), true));
|
|
}
|
|
if (isCritical)
|
|
world.playSound(loc, Sound.ENTITY_PLAYER_ATTACK_CRIT, 1.0F, 1.0F);
|
|
world.playSound(loc, Sound.ENTITY_PLAYER_DEATH, 1.0F, 1.0F);
|
|
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
for (final ItemStack item : inventories.get(npc.getUniqueID())) {
|
|
if (item != null)
|
|
world.dropItem(loc, item);
|
|
}
|
|
|
|
}
|
|
}.runTask(this.plugin); // Run Task in sync to be thread safe
|
|
|
|
this.plugin.getBanUtils().addBan(npc.getUniqueID());
|
|
|
|
Bukkit.broadcastMessage(this.plugin.getMessageUtils()
|
|
.getDeathMessage(npc.getBukkitEntity().getPlayer(), damager, DamageCause.CUSTOM));
|
|
this.plugin.getDatabase().addKill(damager.getUniqueId().toString().replace("-", ""),
|
|
npc.getUniqueID().toString().replace("-", ""));
|
|
this.plugin.getDiscordBot().broadcastMessage("Der Spieler <@!" + this.plugin.getTeamManager()
|
|
.getDiscordIdByUuid(npc.getUniqueID().toString().replace("-", "")) + "> ist gestorben.");
|
|
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
removeClone(npc.getUniqueID());
|
|
}
|
|
}.runTaskLater(this.plugin, 20);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
private void addAllClones() {
|
|
final ArrayList<Team> teams = this.plugin.getTeamManager().getTeams();
|
|
for (final Team team : teams) {
|
|
for (String player : team.getEntries()) {
|
|
UUID uuid = this.plugin.getTeamManager().getUuidFromPlayerName(player);
|
|
this.createOfflineClone(uuid, player);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void removeClone(final UUID uuid) {
|
|
for (int i = 0; i < this.npcs.size(); i++) {
|
|
final EntityPlayer npc = this.npcs.get(i);
|
|
if (npc.getUniqueID().equals(uuid)) {
|
|
final WorldServer nmsWorld = npc.getWorldServer();
|
|
|
|
for (final Player connectionPlayer : Bukkit.getOnlinePlayers()) {
|
|
final PlayerConnection connection = ((CraftPlayer) connectionPlayer).getHandle().playerConnection;
|
|
connection.sendPacket(new PacketPlayOutEntityDestroy(npc.getId()));
|
|
// connection.sendPacket(new PacketPlayOutPlayerInfo(EnumPlayerInfoAction.REMOVE_PLAYER, npc));
|
|
}
|
|
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
nmsWorld.removeEntity(npc);
|
|
npcs.remove(npc);
|
|
}
|
|
}.runTask(this.plugin);
|
|
}
|
|
}
|
|
}
|
|
} |