149 lines
5.8 KiB
Java
Executable File
149 lines
5.8 KiB
Java
Executable File
/*
|
|
* Copyright (c) 2018 Jitse Boonstra
|
|
*/
|
|
|
|
package net.jitse.npclib.listeners;
|
|
|
|
import net.jitse.npclib.NPCLib;
|
|
import net.jitse.npclib.internal.NPCBase;
|
|
import net.jitse.npclib.internal.NPCManager;
|
|
import org.bukkit.Bukkit;
|
|
import org.bukkit.Location;
|
|
import org.bukkit.World;
|
|
import org.bukkit.entity.Player;
|
|
import org.bukkit.event.EventHandler;
|
|
import org.bukkit.event.EventPriority;
|
|
import org.bukkit.event.Listener;
|
|
import org.bukkit.event.entity.PlayerDeathEvent;
|
|
import org.bukkit.event.player.*;
|
|
import org.bukkit.scheduler.BukkitRunnable;
|
|
|
|
/**
|
|
* @author Jitse Boonstra
|
|
*/
|
|
public class PlayerListener implements Listener {
|
|
|
|
private final NPCLib instance;
|
|
|
|
public PlayerListener(NPCLib instance) {
|
|
this.instance = instance;
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerQuit(PlayerQuitEvent event) {
|
|
onPlayerLeave(event.getPlayer());
|
|
}
|
|
|
|
@EventHandler(ignoreCancelled = true, priority = EventPriority.MONITOR)
|
|
public void onPlayerKick(PlayerKickEvent event) {
|
|
onPlayerLeave(event.getPlayer());
|
|
}
|
|
|
|
private void onPlayerLeave(Player player) {
|
|
for (NPCBase npc : NPCManager.getAllNPCs())
|
|
npc.onLogout(player);
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerDeath(PlayerDeathEvent event) {
|
|
// Need to auto hide the NPCs from the player, or else the system will think they can see the NPC on respawn.
|
|
Player player = event.getEntity();
|
|
for (NPCBase npc : NPCManager.getAllNPCs()) {
|
|
if (npc.getWorld().equals(player.getWorld())) {
|
|
if (!npc.getAutoHidden().contains(player.getUniqueId())) {
|
|
npc.getAutoHidden().add(player.getUniqueId());
|
|
npc.hide(player, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerRespawn(PlayerRespawnEvent event) {
|
|
// If the player dies in the server spawn world, the world change event isn't called (nor is the PlayerTeleportEvent).
|
|
Player player = event.getPlayer();
|
|
Location respawn = event.getRespawnLocation();
|
|
if (respawn.getWorld() != null && respawn.getWorld().equals(player.getWorld())) {
|
|
// Waiting until the player is moved to the new location or else it'll mess things up.
|
|
// I.e. if the player is at great distance from the NPC spawning, they won't be able to see it.
|
|
new BukkitRunnable() {
|
|
@Override
|
|
public void run() {
|
|
if (player.isOnline() && player.getLocation().equals(respawn)) {
|
|
handleMove(player);
|
|
this.cancel();
|
|
}
|
|
}
|
|
}.runTaskTimerAsynchronously(instance.getPlugin(), 0, 1);
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerChangedWorld(PlayerChangedWorldEvent event) {
|
|
Player player = event.getPlayer();
|
|
World from = event.getFrom();
|
|
|
|
// The PlayerTeleportEvent is call, and will handle visibility in the new world.
|
|
for (NPCBase npc : NPCManager.getAllNPCs()) {
|
|
if (npc.getWorld().equals(from)) {
|
|
if (!npc.getAutoHidden().contains(player.getUniqueId())) {
|
|
npc.getAutoHidden().add(player.getUniqueId());
|
|
npc.hide(player, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerMove(PlayerMoveEvent event) {
|
|
Location from = event.getFrom();
|
|
Location to = event.getTo();
|
|
// 11/4/20: Added pitch and yaw to the if statement. If the change in this is 10 or more degrees, check the movement.
|
|
if (to == null || (Math.abs(from.getPitch() - to.getPitch()) <= 10
|
|
|| Math.abs(from.getYaw() - to.getYaw()) <= 10
|
|
|| from.getBlockX() != to.getBlockX()
|
|
|| from.getBlockY() != to.getBlockY()
|
|
|| from.getBlockZ() != to.getBlockZ()))
|
|
handleMove(event.getPlayer()); // Verify the player changed which block they are on. Since PlayerMoveEvent is one of the most called events, this is worth it.
|
|
}
|
|
|
|
@EventHandler
|
|
public void onPlayerTeleport(PlayerTeleportEvent event) {
|
|
handleMove(event.getPlayer());
|
|
}
|
|
|
|
private void handleMove(Player player) {
|
|
Location location = player.getLocation();
|
|
for (NPCBase npc : NPCManager.getAllNPCs()) {
|
|
if (!npc.getShown().contains(player.getUniqueId())) {
|
|
continue; // NPC was never supposed to be shown to the player.
|
|
}
|
|
|
|
if (!npc.getWorld().equals(location.getWorld())) {
|
|
continue; // NPC is not in the same world.
|
|
}
|
|
|
|
// If Bukkit doesn't track the NPC entity anymore, bypass the hiding distance variable.
|
|
// This will cause issues otherwise (e.g. custom skin disappearing).
|
|
double hideDistance = instance.getAutoHideDistance();
|
|
double distanceSquared = location.distanceSquared(npc.getLocation());
|
|
|
|
int tempRange = Bukkit.getViewDistance() << 4;
|
|
boolean inRange = distanceSquared <= (hideDistance * hideDistance) && distanceSquared <= (tempRange * tempRange); // Avoids Math.pow due to how intensive it is. Could make a static utility function for it.
|
|
if (npc.getAutoHidden().contains(player.getUniqueId())) {
|
|
// Check if the player and NPC are within the range to sendShowPackets it again.
|
|
if (inRange) {
|
|
npc.getAutoHidden().remove(player.getUniqueId());
|
|
npc.show(player, true);
|
|
}
|
|
} else {
|
|
// Check if the player and NPC are out of range to sendHidePackets it.
|
|
if (!inRange) {
|
|
npc.getAutoHidden().add(player.getUniqueId());
|
|
npc.hide(player, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|