Added some missing features to 2.7.0.

Note that this supercedes the previous increment commit.
This commit is contained in:
Kristian S. Stangeland 2013-09-02 02:42:18 +02:00
parent 1b5463651f
commit 37766d3ecf
3 changed files with 106 additions and 29 deletions

View File

@ -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.
* <p>
* 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 <i>includeTracker</i> 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.

View File

@ -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

View File

@ -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<Player> 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);
}
/**