2018-04-26 13:52:49 +02:00
/ *
* Copyright ( c ) 2018 Jitse Boonstra
* /
package net.jitse.npclib.listeners ;
2019-08-03 13:47:12 +02:00
import net.jitse.npclib.NPCLib ;
2019-10-21 09:49:23 +02:00
import net.jitse.npclib.internal.NPCBase ;
2019-08-03 13:47:12 +02:00
import net.jitse.npclib.internal.NPCManager ;
2018-04-26 13:52:49 +02:00
import org.bukkit.Bukkit ;
2019-09-22 21:09:48 +02:00
import org.bukkit.Location ;
2018-04-26 13:52:49 +02:00
import org.bukkit.World ;
import org.bukkit.entity.Player ;
import org.bukkit.event.EventHandler ;
2019-09-22 21:18:53 +02:00
import org.bukkit.event.EventPriority ;
2018-04-26 13:52:49 +02:00
import org.bukkit.event.Listener ;
2020-04-15 20:10:03 +02:00
import org.bukkit.event.entity.PlayerDeathEvent ;
2019-09-22 21:18:53 +02:00
import org.bukkit.event.player.* ;
2020-04-15 20:10:03 +02:00
import org.bukkit.scheduler.BukkitRunnable ;
2018-04-26 13:52:49 +02:00
/ * *
* @author Jitse Boonstra
* /
public class PlayerListener implements Listener {
2019-08-03 13:47:12 +02:00
private final NPCLib instance ;
public PlayerListener ( NPCLib instance ) {
this . instance = instance ;
}
2018-04-26 13:52:49 +02:00
@EventHandler
public void onPlayerQuit ( PlayerQuitEvent event ) {
2019-09-22 21:18:53 +02:00
onPlayerLeave ( event . getPlayer ( ) ) ;
}
@EventHandler ( ignoreCancelled = true , priority = EventPriority . MONITOR )
public void onPlayerKick ( PlayerKickEvent event ) {
onPlayerLeave ( event . getPlayer ( ) ) ;
}
private void onPlayerLeave ( Player player ) {
2019-10-21 09:49:23 +02:00
for ( NPCBase npc : NPCManager . getAllNPCs ( ) )
2019-09-26 00:02:37 +02:00
npc . onLogout ( player ) ;
2018-04-26 13:52:49 +02:00
}
2020-04-15 20:10:03 +02:00
@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 ) ;
}
}
2018-04-26 13:52:49 +02:00
@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.
2019-10-21 09:49:23 +02:00
for ( NPCBase npc : NPCManager . getAllNPCs ( ) ) {
2019-09-22 21:09:48 +02:00
if ( npc . getWorld ( ) . equals ( from ) ) {
2018-04-26 13:52:49 +02:00
if ( ! npc . getAutoHidden ( ) . contains ( player . getUniqueId ( ) ) ) {
npc . getAutoHidden ( ) . add ( player . getUniqueId ( ) ) ;
2019-09-26 00:02:37 +02:00
npc . hide ( player , true ) ;
2018-04-26 13:52:49 +02:00
}
}
}
}
@EventHandler
public void onPlayerMove ( PlayerMoveEvent event ) {
2019-09-22 21:09:48 +02:00
Location from = event . getFrom ( ) ;
Location to = event . getTo ( ) ;
2020-04-11 19:57:12 +02:00
// 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 ( )
2019-09-22 21:09:48 +02:00
| | 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.
2018-04-26 13:52:49 +02:00
}
@EventHandler
public void onPlayerTeleport ( PlayerTeleportEvent event ) {
handleMove ( event . getPlayer ( ) ) ;
}
private void handleMove ( Player player ) {
2020-04-15 20:10:03 +02:00
Location location = player . getLocation ( ) ;
2019-10-21 09:49:23 +02:00
for ( NPCBase npc : NPCManager . getAllNPCs ( ) ) {
2018-04-26 13:52:49 +02:00
if ( ! npc . getShown ( ) . contains ( player . getUniqueId ( ) ) ) {
continue ; // NPC was never supposed to be shown to the player.
}
2020-04-15 20:10:03 +02:00
if ( ! npc . getWorld ( ) . equals ( location . getWorld ( ) ) ) {
2018-04-26 13:52:49 +02:00
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).
2019-08-03 13:47:12 +02:00
double hideDistance = instance . getAutoHideDistance ( ) ;
2020-04-15 20:10:03 +02:00
double distanceSquared = location . distanceSquared ( npc . getLocation ( ) ) ;
2019-09-22 21:09:48 +02:00
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.
2018-04-26 13:52:49 +02:00
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 ( ) ) ;
2018-05-07 10:14:55 +02:00
npc . show ( player , true ) ;
2018-04-26 13:52:49 +02:00
}
} else {
// Check if the player and NPC are out of range to sendHidePackets it.
if ( ! inRange ) {
npc . getAutoHidden ( ) . add ( player . getUniqueId ( ) ) ;
2019-09-26 00:02:37 +02:00
npc . hide ( player , true ) ;
2018-04-26 13:52:49 +02:00
}
}
}
}
}