Disguises are now removed 30 ticks after death, and by sending entity remove packets

This commit is contained in:
libraryaddict 2014-04-04 18:54:40 +13:00
parent 3709db548a
commit f3b3c15685
2 changed files with 52 additions and 11 deletions

View File

@ -179,11 +179,17 @@ public abstract class Disguise {
final TargetedDisguise disguise = (TargetedDisguise) this; final TargetedDisguise disguise = (TargetedDisguise) this;
// A scheduler to clean up any unused disguises. // A scheduler to clean up any unused disguises.
velocityRunnable = new BukkitRunnable() { velocityRunnable = new BukkitRunnable() {
private int deadTicks = 0;
private int refreshDisguise = 0; private int refreshDisguise = 0;
public void run() { public void run() {
// If entity is no longer valid. Remove it. // If entity is no longer valid. Remove it.
if (!getEntity().isValid()) { if (!getEntity().isValid()) {
// If it has been dead for 30+ ticks
// This is to ensure that this disguise isn't removed while clients think its the real entity
// The delay is because if it sends the destroy entity packets straight away, then it means no death animation
// This is probably still a problem for wither and enderdragon deaths.
if (deadTicks++ > 30) {
if (getEntity() instanceof Player ? if (getEntity() instanceof Player ?
@ -199,7 +205,9 @@ public abstract class Disguise {
watcher = getWatcher().clone(disguise); watcher = getWatcher().clone(disguise);
cancel(); cancel();
} }
}
} else { } else {
deadTicks = 0;
// If the disguise type is tnt, we need to resend the entity packet else it will turn invisible // If the disguise type is tnt, we need to resend the entity packet else it will turn invisible
if (getType() == DisguiseType.PRIMED_TNT || getType() == DisguiseType.FIREWORK) { if (getType() == DisguiseType.PRIMED_TNT || getType() == DisguiseType.FIREWORK) {
refreshDisguise++; refreshDisguise++;
@ -400,7 +408,11 @@ public abstract class Disguise {
} }
// Better refresh the entity to undisguise it // Better refresh the entity to undisguise it
if (getEntity().isValid()) {
DisguiseUtilities.refreshTrackers((TargetedDisguise) this); DisguiseUtilities.refreshTrackers((TargetedDisguise) this);
} else {
DisguiseUtilities.destroyEntity((TargetedDisguise) this);
}
} }
} else { } else {
// Loop through the disguises because it could be used with a unknown entity id. // Loop through the disguises because it could be used with a unknown entity id.

View File

@ -142,6 +142,35 @@ public class DisguiseUtilities {
} }
} }
/**
* @param Sends
* entity removal packets, as this disguise was removed
*/
public static void destroyEntity(TargetedDisguise disguise) {
try {
Object world = ReflectionManager.getWorld(disguise.getEntity().getWorld());
Object tracker = world.getClass().getField("tracker").get(world);
Object trackedEntities = tracker.getClass().getField("trackedEntities").get(tracker);
Object entityTrackerEntry = trackedEntities.getClass().getMethod("get", int.class)
.invoke(trackedEntities, disguise.getEntity().getEntityId());
if (entityTrackerEntry != null) {
HashSet trackedPlayers = (HashSet) entityTrackerEntry.getClass().getField("trackedPlayers")
.get(entityTrackerEntry);
HashSet cloned = (HashSet) trackedPlayers.clone();
PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);
destroyPacket.getIntegerArrays().write(0, new int[] { disguise.getEntity().getEntityId() });
for (Object p : cloned) {
Player player = (Player) ReflectionManager.getBukkitEntity(p);
if (disguise.canSee(player.getName())) {
ProtocolLibrary.getProtocolManager().sendServerPacket(player, destroyPacket);
}
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
public static void doBoundingBox(TargetedDisguise disguise) { public static void doBoundingBox(TargetedDisguise disguise) {
// TODO Slimes // TODO Slimes
Entity entity = disguise.getEntity(); Entity entity = disguise.getEntity();