333 lines
12 KiB
Java
333 lines
12 KiB
Java
package net.minecraft.server;
|
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Sets;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.Iterator;
|
|
import java.util.Set;
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
/**
|
|
* Akarin Changes Note
|
|
* 1) Add lock for entries set operations (safety issue)
|
|
*/
|
|
public class EntityTracker {
|
|
|
|
private static final Logger a = LogManager.getLogger();
|
|
private final WorldServer world;
|
|
private final Set<EntityTrackerEntry> c = Sets.newHashSet();
|
|
public final ReentrantLock entriesLock = new ReentrantLock(); // Akarin - add lock
|
|
public final IntHashMap<EntityTrackerEntry> trackedEntities = new IntHashMap();
|
|
private int e;
|
|
|
|
public EntityTracker(WorldServer worldserver) {
|
|
this.world = worldserver;
|
|
this.e = PlayerChunkMap.getFurthestViewableBlock(worldserver.spigotConfig.viewDistance); // Spigot
|
|
}
|
|
|
|
public static long a(double d0) {
|
|
return MathHelper.d(d0 * 4096.0D);
|
|
}
|
|
|
|
public void track(Entity entity) {
|
|
if (entity instanceof EntityPlayer) {
|
|
this.addEntity(entity, 512, 2);
|
|
EntityPlayer entityplayer = (EntityPlayer) entity;
|
|
Iterator iterator = this.c.iterator();
|
|
entriesLock.lock(); // Akarin
|
|
|
|
while (iterator.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
|
|
|
|
if (entitytrackerentry.b() != entityplayer) {
|
|
entitytrackerentry.updatePlayer(entityplayer);
|
|
}
|
|
}
|
|
entriesLock.unlock(); // Akarin
|
|
} else if (entity instanceof EntityFishingHook) {
|
|
this.addEntity(entity, 64, 5, true);
|
|
} else if (entity instanceof EntityArrow) {
|
|
this.addEntity(entity, 64, 20, false);
|
|
} else if (entity instanceof EntitySmallFireball) {
|
|
this.addEntity(entity, 64, 10, false);
|
|
} else if (entity instanceof EntityFireball) {
|
|
this.addEntity(entity, 64, 10, true);
|
|
} else if (entity instanceof EntitySnowball) {
|
|
this.addEntity(entity, 64, 10, true);
|
|
} else if (entity instanceof EntityLlamaSpit) {
|
|
this.addEntity(entity, 64, 10, false);
|
|
} else if (entity instanceof EntityEnderPearl) {
|
|
this.addEntity(entity, 64, 10, true);
|
|
} else if (entity instanceof EntityEnderSignal) {
|
|
this.addEntity(entity, 64, 4, true);
|
|
} else if (entity instanceof EntityEgg) {
|
|
this.addEntity(entity, 64, 10, true);
|
|
} else if (entity instanceof EntityPotion) {
|
|
this.addEntity(entity, 64, 10, true);
|
|
} else if (entity instanceof EntityThrownExpBottle) {
|
|
this.addEntity(entity, 64, 10, true);
|
|
} else if (entity instanceof EntityFireworks) {
|
|
this.addEntity(entity, 64, 10, true);
|
|
} else if (entity instanceof EntityItem) {
|
|
this.addEntity(entity, 64, 20, true);
|
|
} else if (entity instanceof EntityMinecartAbstract) {
|
|
this.addEntity(entity, 80, 3, true);
|
|
} else if (entity instanceof EntityBoat) {
|
|
this.addEntity(entity, 80, 3, true);
|
|
} else if (entity instanceof EntitySquid) {
|
|
this.addEntity(entity, 64, 3, true);
|
|
} else if (entity instanceof EntityWither) {
|
|
this.addEntity(entity, 80, 3, false);
|
|
} else if (entity instanceof EntityShulkerBullet) {
|
|
this.addEntity(entity, 80, 3, true);
|
|
} else if (entity instanceof EntityBat) {
|
|
this.addEntity(entity, 80, 3, false);
|
|
} else if (entity instanceof EntityEnderDragon) {
|
|
this.addEntity(entity, 160, 3, true);
|
|
} else if (entity instanceof IAnimal) {
|
|
this.addEntity(entity, 80, 3, true);
|
|
} else if (entity instanceof EntityTNTPrimed) {
|
|
this.addEntity(entity, 160, 10, true);
|
|
} else if (entity instanceof EntityFallingBlock) {
|
|
this.addEntity(entity, 160, 20, true);
|
|
} else if (entity instanceof EntityHanging) {
|
|
this.addEntity(entity, 160, Integer.MAX_VALUE, false);
|
|
} else if (entity instanceof EntityArmorStand) {
|
|
this.addEntity(entity, 160, 3, true);
|
|
} else if (entity instanceof EntityExperienceOrb) {
|
|
this.addEntity(entity, 160, 20, true);
|
|
} else if (entity instanceof EntityAreaEffectCloud) {
|
|
this.addEntity(entity, 160, 10, true); // CraftBukkit
|
|
} else if (entity instanceof EntityEnderCrystal) {
|
|
this.addEntity(entity, 256, Integer.MAX_VALUE, false);
|
|
} else if (entity instanceof EntityEvokerFangs) {
|
|
this.addEntity(entity, 160, 2, false);
|
|
}
|
|
|
|
}
|
|
|
|
public void addEntity(Entity entity, int i, int j) {
|
|
this.addEntity(entity, i, j, false);
|
|
}
|
|
|
|
public void addEntity(Entity entity, int i, final int j, boolean flag) {
|
|
org.spigotmc.AsyncCatcher.catchOp( "entity track"); // Spigot
|
|
i = org.spigotmc.TrackingRange.getEntityTrackingRange(entity, i); // Spigot
|
|
try {
|
|
if (this.trackedEntities.b(entity.getId())) {
|
|
throw new IllegalStateException("Entity is already tracked!");
|
|
}
|
|
|
|
EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(entity, i, this.e, j, flag);
|
|
|
|
entriesLock.lock(); // Akarin
|
|
this.c.add(entitytrackerentry);
|
|
|
|
this.trackedEntities.a(entity.getId(), entitytrackerentry);
|
|
entitytrackerentry.scanPlayers(this.world.players);
|
|
entriesLock.unlock(); // Akarin
|
|
} catch (Throwable throwable) {
|
|
CrashReport crashreport = CrashReport.a(throwable, "Adding entity to track");
|
|
CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity To Track");
|
|
|
|
crashreportsystemdetails.a("Tracking range", i + " blocks");
|
|
final int finalI = i; // CraftBukkit - fix decompile error
|
|
crashreportsystemdetails.a("Update interval", new CrashReportCallable() {
|
|
public String a() throws Exception {
|
|
String s = "Once per " + finalI + " ticks"; // CraftBukkit
|
|
|
|
if (finalI == Integer.MAX_VALUE) { // CraftBukkit
|
|
s = "Maximum (" + s + ")";
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
@Override
|
|
public Object call() throws Exception {
|
|
return this.a();
|
|
}
|
|
});
|
|
entity.appendEntityCrashDetails(crashreportsystemdetails);
|
|
this.trackedEntities.get(entity.getId()).b().appendEntityCrashDetails(crashreport.a("Entity That Is Already Tracked"));
|
|
|
|
try {
|
|
throw new ReportedException(crashreport);
|
|
} catch (ReportedException reportedexception) {
|
|
EntityTracker.a.error("\"Silently\" catching entity tracking error.", reportedexception);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void untrackEntity(Entity entity) {
|
|
org.spigotmc.AsyncCatcher.catchOp( "entity untrack"); // Spigot
|
|
if (entity instanceof EntityPlayer) {
|
|
EntityPlayer entityplayer = (EntityPlayer) entity;
|
|
Iterator iterator = this.c.iterator();
|
|
entriesLock.lock(); // Akarin
|
|
|
|
while (iterator.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
|
|
|
|
entitytrackerentry.a(entityplayer);
|
|
}
|
|
entriesLock.unlock(); // Akarin
|
|
}
|
|
|
|
EntityTrackerEntry entitytrackerentry1 = this.trackedEntities.d(entity.getId());
|
|
|
|
if (entitytrackerentry1 != null) {
|
|
entriesLock.lock(); // Akarin
|
|
this.c.remove(entitytrackerentry1);
|
|
entitytrackerentry1.a();
|
|
entriesLock.unlock(); // Akarin
|
|
}
|
|
}
|
|
|
|
public void updatePlayers() {
|
|
ArrayList arraylist = Lists.newArrayList();
|
|
Iterator iterator = this.c.iterator();
|
|
world.timings.tracker1.startTiming(); // Spigot
|
|
entriesLock.lock(); // Akarin
|
|
while (iterator.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
|
|
|
|
entitytrackerentry.track(this.world.players);
|
|
if (entitytrackerentry.b) {
|
|
Entity entity = entitytrackerentry.b();
|
|
|
|
if (entity instanceof EntityPlayer) {
|
|
arraylist.add(entity);
|
|
}
|
|
}
|
|
}
|
|
world.timings.tracker1.stopTiming(); // Spigot
|
|
|
|
world.timings.tracker2.startTiming(); // Spigot
|
|
for (int i = 0; i < arraylist.size(); ++i) {
|
|
EntityPlayer entityplayer = (EntityPlayer) arraylist.get(i);
|
|
Iterator iterator1 = this.c.iterator();
|
|
|
|
while (iterator1.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry1 = (EntityTrackerEntry) iterator1.next();
|
|
|
|
if (entitytrackerentry1.b() != entityplayer) {
|
|
entitytrackerentry1.updatePlayer(entityplayer);
|
|
}
|
|
}
|
|
}
|
|
entriesLock.unlock(); // Akarin
|
|
world.timings.tracker2.stopTiming(); // Spigot
|
|
|
|
}
|
|
|
|
public void a(EntityPlayer entityplayer) {
|
|
Iterator iterator = this.c.iterator();
|
|
entriesLock.lock(); // Akarin
|
|
|
|
while (iterator.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
|
|
|
|
if (entitytrackerentry.b() == entityplayer) {
|
|
entitytrackerentry.scanPlayers(this.world.players);
|
|
} else {
|
|
entitytrackerentry.updatePlayer(entityplayer);
|
|
}
|
|
}
|
|
entriesLock.unlock(); // Akarin
|
|
}
|
|
|
|
public void a(Entity entity, Packet<?> packet) {
|
|
EntityTrackerEntry entitytrackerentry = this.trackedEntities.get(entity.getId());
|
|
|
|
if (entitytrackerentry != null) {
|
|
entitytrackerentry.broadcast(packet);
|
|
}
|
|
|
|
}
|
|
|
|
public void sendPacketToEntity(Entity entity, Packet<?> packet) {
|
|
EntityTrackerEntry entitytrackerentry = this.trackedEntities.get(entity.getId());
|
|
|
|
if (entitytrackerentry != null) {
|
|
entitytrackerentry.broadcastIncludingSelf(packet);
|
|
}
|
|
|
|
}
|
|
|
|
public void untrackPlayer(EntityPlayer entityplayer) {
|
|
Iterator iterator = this.c.iterator();
|
|
entriesLock.lock(); // Akarin
|
|
|
|
while (iterator.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
|
|
|
|
entitytrackerentry.clear(entityplayer);
|
|
}
|
|
entriesLock.unlock(); // Akarin
|
|
}
|
|
|
|
public void a(EntityPlayer entityplayer, Chunk chunk) {
|
|
ArrayList arraylist = Lists.newArrayList();
|
|
ArrayList arraylist1 = Lists.newArrayList();
|
|
Iterator iterator = this.c.iterator();
|
|
entriesLock.lock(); // Akarin
|
|
|
|
while (iterator.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
|
|
Entity entity = entitytrackerentry.b();
|
|
|
|
if (entity != entityplayer && entity.ab == chunk.locX && entity.ad == chunk.locZ) {
|
|
entitytrackerentry.updatePlayer(entityplayer);
|
|
if (entity instanceof EntityInsentient && ((EntityInsentient) entity).getLeashHolder() != null) {
|
|
arraylist.add(entity);
|
|
}
|
|
|
|
if (!entity.bF().isEmpty()) {
|
|
arraylist1.add(entity);
|
|
}
|
|
}
|
|
}
|
|
entriesLock.unlock(); // Akarin
|
|
|
|
Entity entity1;
|
|
|
|
if (!arraylist.isEmpty()) {
|
|
iterator = arraylist.iterator();
|
|
|
|
while (iterator.hasNext()) {
|
|
entity1 = (Entity) iterator.next();
|
|
entityplayer.playerConnection.sendPacket(new PacketPlayOutAttachEntity(entity1, ((EntityInsentient) entity1).getLeashHolder()));
|
|
}
|
|
}
|
|
|
|
if (!arraylist1.isEmpty()) {
|
|
iterator = arraylist1.iterator();
|
|
|
|
while (iterator.hasNext()) {
|
|
entity1 = (Entity) iterator.next();
|
|
entityplayer.playerConnection.sendPacket(new PacketPlayOutMount(entity1));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public void a(int i) {
|
|
this.e = (i - 1) * 16;
|
|
Iterator iterator = this.c.iterator();
|
|
entriesLock.lock(); // Akarin
|
|
|
|
while (iterator.hasNext()) {
|
|
EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next();
|
|
|
|
entitytrackerentry.a(this.e);
|
|
}
|
|
entriesLock.unlock(); // Akarin
|
|
}
|
|
}
|