/* * Copyright (c) 2018 Jitse Boonstra */ package net.jitse.npclib.api; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import net.jitse.npclib.NPCManager; import net.jitse.npclib.events.NPCDestroyEvent; import net.jitse.npclib.events.NPCSpawnEvent; import net.jitse.npclib.events.trigger.TriggerType; import net.jitse.npclib.skin.Skin; import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.java.JavaPlugin; import java.util.*; /** * @author Jitse Boonstra */ public abstract class NPC { protected final UUID uuid = UUID.randomUUID(); protected final String name = uuid.toString().replace("-", "").substring(0, 10); protected final int entityId = (int) Math.ceil(Math.random() * 100000) + 100000; private final Set shown = new HashSet<>(); private final Set autoHidden = new HashSet<>(); protected final double autoHideDistance; protected final Skin skin; protected final List lines; protected JavaPlugin plugin; protected GameProfile gameProfile; protected Location location; public NPC(JavaPlugin plugin, Skin skin, double autoHideDistance, List lines) { this.plugin = plugin; this.skin = skin; this.autoHideDistance = autoHideDistance; this.lines = (lines == null ? Collections.emptyList() : lines); NPCManager.add(this); } protected GameProfile generateGameProfile(UUID uuid, String name) { GameProfile gameProfile = new GameProfile(uuid, name); if (skin != null) { gameProfile.getProperties().put("textures", new Property("textures", skin.getValue(), skin.getSignature())); } return gameProfile; } public void destroy() { NPCManager.remove(this); // Destroy NPC for every player that is still seeing it. for (UUID uuid : shown) { if (autoHidden.contains(uuid)) { continue; } hide(Bukkit.getPlayer(uuid), true); } } public Set getShown() { return shown; } public Set getAutoHidden() { return autoHidden; } public Location getLocation() { return location; } public double getAutoHideDistance() { return autoHideDistance; } public int getEntityId() { return entityId; } public boolean isActuallyShown(Player player) { return shown.contains(player.getUniqueId()) && !autoHidden.contains(player.getUniqueId()); } // Generate packets. public abstract void create(Location location); public void show(Player player) { show(player, false); } public void show(Player player, boolean auto) { NPCSpawnEvent event = new NPCSpawnEvent(this, player, auto ? TriggerType.AUTOMATIC : TriggerType.MANUAL); plugin.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return; } if (auto) { sendShowPackets(player); } else { if (shown.contains(player.getUniqueId())) { throw new RuntimeException("Cannot call show method twice."); } shown.add(player.getUniqueId()); if (player.getLocation().distance(location) <= autoHideDistance) { sendShowPackets(player); } else { if (!autoHidden.contains(player.getUniqueId())) { autoHidden.add(player.getUniqueId()); } } } } // Internal method. protected abstract void sendShowPackets(Player player); public void hide(Player player) { hide(player, false); } public void hide(Player player, boolean auto) { NPCDestroyEvent event = new NPCDestroyEvent(this, player, auto ? TriggerType.AUTOMATIC : TriggerType.MANUAL); plugin.getServer().getPluginManager().callEvent(event); if (event.isCancelled()) { return; } if (auto) { sendHidePackets(player); } else { if (!shown.contains(player.getUniqueId())) { throw new RuntimeException("Cannot call hide method without calling NPC#show."); } shown.remove(player.getUniqueId()); if (player.getWorld().equals(location.getWorld()) && player.getLocation().distance(location) <= autoHideDistance) { sendHidePackets(player); } else { if (autoHidden.contains(player.getUniqueId())) { autoHidden.remove(player.getUniqueId()); } } } } // Internal method. protected abstract void sendHidePackets(Player player); }