From 37766d3ecf4311d15253cb4ce4b49cef23fc02cf Mon Sep 17 00:00:00 2001 From: "Kristian S. Stangeland" Date: Mon, 2 Sep 2013 02:42:18 +0200 Subject: [PATCH] Added some missing features to 2.7.0. Note that this supercedes the previous increment commit. --- .../comphenix/protocol/ProtocolManager.java | 16 ++++- .../injector/DelayedPacketManager.java | 59 +++++++++++------- .../injector/PacketFilterManager.java | 60 ++++++++++++++++++- 3 files changed, 106 insertions(+), 29 deletions(-) diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java index c5a30c4c..e009b589 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/ProtocolManager.java @@ -21,6 +21,7 @@ import java.lang.reflect.InvocationTargetException; import java.util.List; import java.util.Set; +import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -83,12 +84,21 @@ public interface ProtocolManager extends PacketStream { * Broadcast a packet to every player that is recieving information about a given entity. *

* This is usually every player in the same world within an observable distance. If the entity is a - * player, its naturally excluded. + * player, it will only be included if includeTracker is TRUE. * @param packet - the packet to broadcast. - * @param tracker - the entity tracker. + * @param entity - the entity whose trackers we will inform. + * @param includeTracker - whether or not to also transmit the packet to the entity, if it is a tracker. * @throws FieldAccessException If we were unable to send the packet due to reflection problems. */ - public void broadcastServerPacket(PacketContainer packet, Entity tracker); + public void broadcastServerPacket(PacketContainer packet, Entity entity, boolean includeTracker); + + /** + * Broadcast a packet to every player within the given maximum observer distance. + * @param packet - the packet to broadcast. + * @param origin - the origin to consider when calculating the distance to each observer. + * @param maxObserverDistance - the maximum distance to the origin. + */ + public void broadcastServerPacket(PacketContainer packet, Location origin, int maxObserverDistance); /** * Retrieves a list of every registered packet listener. diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/DelayedPacketManager.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/DelayedPacketManager.java index 07ad0396..c00a003b 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/DelayedPacketManager.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/DelayedPacketManager.java @@ -7,6 +7,7 @@ import java.util.List; import java.util.Set; import javax.annotation.Nonnull; +import org.bukkit.Location; import org.bukkit.World; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; @@ -162,20 +163,6 @@ public class DelayedPacketManager implements ProtocolManager, InternalManager { }; } - private Runnable queuedBroadcastServerPacket(final PacketContainer packet, final Entity tracker) { - return new Runnable() { - @Override - public void run() { - // Invoke the correct version - if (tracker != null) { - delegate.broadcastServerPacket(packet, tracker); - } else { - delegate.broadcastServerPacket(packet); - } - } - }; - } - @Override public void setPlayerHook(PlayerInjectHooks playerHook) { this.hook = playerHook; @@ -225,19 +212,45 @@ public class DelayedPacketManager implements ProtocolManager, InternalManager { } @Override - public void broadcastServerPacket(PacketContainer packet, Entity tracker) { - if (delegate != null) - delegate.broadcastServerPacket(packet, tracker); - else - queuedActions.add(queuedBroadcastServerPacket(packet, tracker)); + public void broadcastServerPacket(final PacketContainer packet, final Entity entity, final boolean includeTracker) { + if (delegate != null) { + delegate.broadcastServerPacket(packet, entity, includeTracker); + } else { + queuedActions.add(new Runnable() { + @Override + public void run() { + delegate.broadcastServerPacket(packet, entity, includeTracker); + } + }); + } } @Override - public void broadcastServerPacket(PacketContainer packet) { - if (delegate != null) + public void broadcastServerPacket(final PacketContainer packet, final Location origin, final int maxObserverDistance) { + if (delegate != null) { + delegate.broadcastServerPacket(packet, origin, maxObserverDistance); + } else { + queuedActions.add(new Runnable() { + @Override + public void run() { + delegate.broadcastServerPacket(packet, origin, maxObserverDistance); + } + }); + } + } + + @Override + public void broadcastServerPacket(final PacketContainer packet) { + if (delegate != null) { delegate.broadcastServerPacket(packet); - else - queuedActions.add(queuedBroadcastServerPacket(packet, null)); + } else { + queuedActions.add(new Runnable() { + @Override + public void run() { + delegate.broadcastServerPacket(packet); + } + }); + } } @Override diff --git a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java index d31fb9ae..2037df9f 100644 --- a/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java +++ b/ProtocolLib/src/main/java/com/comphenix/protocol/injector/PacketFilterManager.java @@ -33,6 +33,7 @@ import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; +import org.bukkit.Location; import org.bukkit.Server; import org.bukkit.World; import org.bukkit.entity.Entity; @@ -182,6 +183,9 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok // Plugin verifier private PluginVerifier pluginVerifier; + // Whether or not Location.distance(Location) exists - we assume this is the case + private boolean hasRecycleDistance = true; + // The current Minecraft version private MinecraftVersion minecraftVersion; @@ -626,10 +630,60 @@ public final class PacketFilterManager implements ProtocolManager, ListenerInvok } @Override - public void broadcastServerPacket(PacketContainer packet, Entity tracker) { + public void broadcastServerPacket(PacketContainer packet, Entity entity, boolean includeTracker) { Preconditions.checkNotNull(packet, "packet cannot be NULL."); - Preconditions.checkNotNull(tracker, "tracker cannot be NULL."); - broadcastServerPacket(packet, getEntityTrackers(tracker)); + Preconditions.checkNotNull(entity, "entity cannot be NULL."); + List trackers = getEntityTrackers(entity); + + // Only add it if it's a player + if (includeTracker && entity instanceof Player) { + trackers.add((Player) entity); + } + broadcastServerPacket(packet, trackers); + } + + @Override + public void broadcastServerPacket(PacketContainer packet, Location origin, int maxObserverDistance) { + try { + // Square the maximum too + int maxDistance = maxObserverDistance * maxObserverDistance; + + World world = origin.getWorld(); + Location recycle = origin.clone(); + + // Only broadcast the packet to nearby players + for (Player player : server.getOnlinePlayers()) { + if (world.equals(player.getWorld()) && + getDistanceSquared(origin, recycle, player) <= maxDistance) { + + sendServerPacket(player, packet); + } + } + + } catch (InvocationTargetException e) { + throw new FieldAccessException("Unable to send server packet.", e); + } + } + + /** + * Retrieve the squared distance between a location and a player. + * @param origin - the origin location. + * @param recycle - a location object to be recycled, if supported. + * @param player - the player. + * @return The squared distance between the player and the origin, + */ + private double getDistanceSquared(Location origin, Location recycle, Player player) { + if (hasRecycleDistance) { + try { + return player.getLocation(recycle).distanceSquared(origin); + } catch (Error e) { + // Damn it + hasRecycleDistance = false; + } + } + + // The fallback method + return player.getLocation().distanceSquared(origin); } /**