Player move optimization.
This commit is contained in:
@@ -6,6 +6,7 @@ package net.jitse.npclib.api;
|
|||||||
|
|
||||||
import net.jitse.npclib.api.skin.Skin;
|
import net.jitse.npclib.api.skin.Skin;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
|
|
||||||
public interface NPC {
|
public interface NPC {
|
||||||
@@ -35,6 +36,13 @@ public interface NPC {
|
|||||||
*/
|
*/
|
||||||
Location getLocation();
|
Location getLocation();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the world the NPC is located in.
|
||||||
|
*
|
||||||
|
* @return The world the NPC is located in.
|
||||||
|
*/
|
||||||
|
World getWorld();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create all necessary packets for the NPC so it can be shown to players.
|
* Create all necessary packets for the NPC so it can be shown to players.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import net.jitse.npclib.api.events.NPCShowEvent;
|
|||||||
import net.jitse.npclib.api.skin.Skin;
|
import net.jitse.npclib.api.skin.Skin;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.Location;
|
import org.bukkit.Location;
|
||||||
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.util.Vector;
|
import org.bukkit.util.Vector;
|
||||||
|
|
||||||
@@ -104,6 +105,11 @@ public abstract class SimpleNPC implements NPC, PacketHandler {
|
|||||||
return location;
|
return location;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public World getWorld() {
|
||||||
|
return location != null ? location.getWorld() : null;
|
||||||
|
}
|
||||||
|
|
||||||
public int getEntityId() {
|
public int getEntityId() {
|
||||||
return entityId;
|
return entityId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,10 @@ import org.bukkit.Location;
|
|||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.HashSet;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Jitse Boonstra
|
* @author Jitse Boonstra
|
||||||
@@ -47,11 +50,12 @@ public class PacketListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean handleInteractPacket(Player player, Object packet) {
|
private boolean handleInteractPacket(Player player, Object packet) {
|
||||||
if (packetPlayInUseEntityClazz.isInstance(packet)) {
|
if (!packetPlayInUseEntityClazz.isInstance(packet))
|
||||||
|
return true; // We aren't handling the packet.
|
||||||
|
|
||||||
SimpleNPC npc = null;
|
SimpleNPC npc = null;
|
||||||
int packetEntityId = (int) entityIdField.get(packet);
|
int packetEntityId = (int) entityIdField.get(packet);
|
||||||
|
|
||||||
|
|
||||||
// Not using streams here is an intentional choice.
|
// Not using streams here is an intentional choice.
|
||||||
// Packet listeners is one of the few places where it is important to write optimized code.
|
// Packet listeners is one of the few places where it is important to write optimized code.
|
||||||
// Lambdas (And the stream api) create a massive amount of objects, especially if it isn't a static lambda.
|
// Lambdas (And the stream api) create a massive amount of objects, especially if it isn't a static lambda.
|
||||||
@@ -82,9 +86,6 @@ public class PacketListener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This would be a non-static lambda, and its usage matters, so we'll make it a full class.
|
// This would be a non-static lambda, and its usage matters, so we'll make it a full class.
|
||||||
private static final class TaskCallNpcInteractEvent implements Runnable {
|
private static final class TaskCallNpcInteractEvent implements Runnable {
|
||||||
private NPCInteractEvent eventToCall;
|
private NPCInteractEvent eventToCall;
|
||||||
@@ -102,7 +103,7 @@ public class PacketListener {
|
|||||||
Player player = eventToCall.getWhoClicked();
|
Player player = eventToCall.getWhoClicked();
|
||||||
this.listener.delay.remove(player.getUniqueId()); // Remove the NPC from the interact cooldown.
|
this.listener.delay.remove(player.getUniqueId()); // Remove the NPC from the interact cooldown.
|
||||||
|
|
||||||
if (!Objects.equals(playerLocation.getWorld(), eventToCall.getNPC().getLocation().getWorld()))
|
if (!Objects.equals(playerLocation.getWorld(), eventToCall.getNPC().getWorld()))
|
||||||
return; // If the NPC and player are not in the same world, abort!
|
return; // If the NPC and player are not in the same world, abort!
|
||||||
|
|
||||||
double distance = player.getLocation(playerLocation).distanceSquared(eventToCall.getNPC().getLocation());
|
double distance = player.getLocation(playerLocation).distanceSquared(eventToCall.getNPC().getLocation());
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import net.jitse.npclib.NPCLib;
|
|||||||
import net.jitse.npclib.internal.NPCManager;
|
import net.jitse.npclib.internal.NPCManager;
|
||||||
import net.jitse.npclib.internal.SimpleNPC;
|
import net.jitse.npclib.internal.SimpleNPC;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.Location;
|
||||||
import org.bukkit.World;
|
import org.bukkit.World;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.event.EventHandler;
|
import org.bukkit.event.EventHandler;
|
||||||
@@ -46,7 +47,7 @@ public class PlayerListener implements Listener {
|
|||||||
|
|
||||||
// The PlayerTeleportEvent is call, and will handle visibility in the new world.
|
// The PlayerTeleportEvent is call, and will handle visibility in the new world.
|
||||||
for (SimpleNPC npc : NPCManager.getAllNPCs()) {
|
for (SimpleNPC npc : NPCManager.getAllNPCs()) {
|
||||||
if (npc.getLocation().getWorld().equals(from)) {
|
if (npc.getWorld().equals(from)) {
|
||||||
if (!npc.getAutoHidden().contains(player.getUniqueId())) {
|
if (!npc.getAutoHidden().contains(player.getUniqueId())) {
|
||||||
npc.getAutoHidden().add(player.getUniqueId());
|
npc.getAutoHidden().add(player.getUniqueId());
|
||||||
npc.hide(player, true, false);
|
npc.hide(player, true, false);
|
||||||
@@ -57,7 +58,12 @@ public class PlayerListener implements Listener {
|
|||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void onPlayerMove(PlayerMoveEvent event) {
|
public void onPlayerMove(PlayerMoveEvent event) {
|
||||||
handleMove(event.getPlayer());
|
Location from = event.getFrom();
|
||||||
|
Location to = event.getTo();
|
||||||
|
if (to == null || (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
|
@EventHandler
|
||||||
@@ -72,7 +78,7 @@ public class PlayerListener implements Listener {
|
|||||||
continue; // NPC was never supposed to be shown to the player.
|
continue; // NPC was never supposed to be shown to the player.
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!npc.getLocation().getWorld().equals(world)) {
|
if (!npc.getWorld().equals(world)) {
|
||||||
continue; // NPC is not in the same world.
|
continue; // NPC is not in the same world.
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,8 +86,9 @@ public class PlayerListener implements Listener {
|
|||||||
// This will cause issues otherwise (e.g. custom skin disappearing).
|
// This will cause issues otherwise (e.g. custom skin disappearing).
|
||||||
double hideDistance = instance.getAutoHideDistance();
|
double hideDistance = instance.getAutoHideDistance();
|
||||||
double distanceSquared = player.getLocation().distanceSquared(npc.getLocation());
|
double distanceSquared = player.getLocation().distanceSquared(npc.getLocation());
|
||||||
boolean inRange = distanceSquared <= (Math.pow(hideDistance, 2))
|
|
||||||
&& distanceSquared <= (Math.pow(Bukkit.getViewDistance() << 4, 2));
|
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())) {
|
if (npc.getAutoHidden().contains(player.getUniqueId())) {
|
||||||
// Check if the player and NPC are within the range to sendShowPackets it again.
|
// Check if the player and NPC are within the range to sendShowPackets it again.
|
||||||
if (inRange) {
|
if (inRange) {
|
||||||
|
|||||||
Reference in New Issue
Block a user