diff --git a/eSpigot-Server/src/main/java/com/elevatemc/spigot/visuals/CannonTrackerEntry.java b/eSpigot-Server/src/main/java/com/elevatemc/spigot/visuals/CannonTrackerEntry.java deleted file mode 100644 index ed6a44d..0000000 --- a/eSpigot-Server/src/main/java/com/elevatemc/spigot/visuals/CannonTrackerEntry.java +++ /dev/null @@ -1,111 +0,0 @@ -package com.elevatemc.spigot.visuals; - -import net.minecraft.server.*; - -import java.util.List; - -/* - * This is a custom entity tracker made for the cannoning entities tnt and sand. - * The goal behind this is to reduce packets and logic without hiding entities. - * It may not completely replicate the original behavior, but it should make up - * for that with it's advantages. - * Source: IonSpigot - */ -public class CannonTrackerEntry extends EntityTrackerEntry { - - private boolean movingX; - private boolean movingY; - private boolean movingZ; - - private double updateX; - private double updateY; - private double updateZ; - - public CannonTrackerEntry(Entity entity, int i, int j, boolean flag) { - super(entity, i, j, flag); - this.movingX = entity.motX != 0.0; - this.movingY = true; - this.movingZ = entity.motZ != 0.0; - this.updateX = entity.locX; - this.updateY = entity.locY; - this.updateZ = entity.locZ; - } - - @Override - public void track(List list) { - boolean motionX = this.tracker.motX != 0.0; - boolean motionY = this.tracker.motY != 0.0; - boolean motionZ = this.tracker.motZ != 0.0; - - // This tracked entities motion has changed or an explosion has occurred, update it! - if (!this.tracker.ai && motionX == movingX && motionY == movingY && motionZ == movingZ) { - return; - } - - // This entity has moved 4 blocks since the last update, search for players - if (this.tracker.e(updateX, updateY, updateZ) > 16.0D) { - this.scanPlayers(list); - this.updateX = this.tracker.locX; - this.updateY = this.tracker.locY; - this.updateZ = this.tracker.locZ; - } - - // Update nearby players, only resynchronise when motion is updated - if (motionX || motionY || motionZ) { - this.broadcastUpdate(); - } - - // Keep what of which axis the entity is moving on - this.tracker.ai = false; - this.movingX = motionX; - this.movingY = motionY; - this.movingZ = motionZ; - } - - private void broadcastUpdate() { - DataWatcher datawatcher = this.tracker.getDataWatcher(); - - if (datawatcher.a()) { - this.broadcastIncludingSelf(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false)); - } - - // Only update location on movement - if (this.tracker.lastX != this.tracker.locX || this.tracker.lastY != this.tracker.locY || this.tracker.lastZ != this.tracker.locZ) { - this.broadcast(new PacketPlayOutEntityTeleport(this.tracker)); - } - - this.broadcast(new PacketPlayOutEntityVelocity(this.tracker)); - } - - @Override - public void updatePlayer(EntityPlayer entityplayer) { - // Check configurable distance as a cube then visible distance. - if (this.c(entityplayer) && this.tracker.h(entityplayer) < 4096.0D) { - if (this.trackedPlayers.contains(entityplayer) || (!this.e(entityplayer) && !this.tracker.attachedToPlayer)) { - return; - } - - entityplayer.removeQueue.remove(this.tracker.getId()); - - this.trackedPlayerMap.put(entityplayer, true); // Paper - Packet packet = this.c(); // IonSpigot - if (packet == null) return; // IonSpigot - If it's null don't update the client! - - entityplayer.playerConnection.sendPacket(packet); - - if (this.tracker.getCustomNameVisible()) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityMetadata(this.tracker.getId(), this.tracker.getDataWatcher(), true)); - } - - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityVelocity(this.tracker.getId(), this.tracker.motX, this.tracker.motY, this.tracker.motZ)); - - if (this.tracker.vehicle != null) { - entityplayer.playerConnection.sendPacket(new PacketPlayOutAttachEntity(0, this.tracker, this.tracker.vehicle)); - } - } else if (this.trackedPlayers.contains(entityplayer)) { - this.trackedPlayers.remove(entityplayer); - entityplayer.d(this.tracker); - } - } - -} \ No newline at end of file diff --git a/eSpigot-Server/src/main/java/net/minecraft/server/EntityPlayer.java b/eSpigot-Server/src/main/java/net/minecraft/server/EntityPlayer.java index 20afa3e..b3357c1 100644 --- a/eSpigot-Server/src/main/java/net/minecraft/server/EntityPlayer.java +++ b/eSpigot-Server/src/main/java/net/minecraft/server/EntityPlayer.java @@ -247,75 +247,54 @@ public class EntityPlayer extends EntityHuman implements ICrafting { } if (!this.chunkCoordIntPairQueue.isEmpty()) { - ArrayList chunkList = Lists.newArrayList(); - Iterator chunksToLoad = this.chunkCoordIntPairQueue.iterator(); - ArrayList tileEntities = Lists.newArrayList(); + ArrayList arraylist = Lists.newArrayList(); + Iterator iterator1 = this.chunkCoordIntPairQueue.iterator(); + ArrayList arraylist1 = Lists.newArrayList(); - Chunk chunk = null; + Chunk chunk; - while (chunksToLoad.hasNext() && chunkList.size() < this.world.spigotConfig.maxBulkChunk) { // Spigot - ChunkCoordIntPair chunkcoordintpair = chunksToLoad.next(); + while (iterator1.hasNext() && arraylist.size() < this.world.spigotConfig.maxBulkChunk) { // Spigot + ChunkCoordIntPair chunkcoordintpair = (ChunkCoordIntPair) iterator1.next(); if (chunkcoordintpair != null) { - if (this.world.isLoaded(chunkcoordintpair.x << 4, 0, chunkcoordintpair.z << 4)) {// [Nacho-0024] Do not create new BlockPosition when loading chunk + if (this.world.isLoaded(new BlockPosition(chunkcoordintpair.x << 4, 0, chunkcoordintpair.z << 4))) { chunk = this.world.getChunkAt(chunkcoordintpair.x, chunkcoordintpair.z); if (chunk.isReady()) { - chunkList.add(chunk); - tileEntities.addAll(chunk.tileEntities.values()); // CraftBukkit - Get tile entities directly from the chunk instead of the world - chunksToLoad.remove(); + arraylist.add(chunk); + arraylist1.addAll(chunk.tileEntities.values()); // CraftBukkit - Get tile entities directly from the chunk instead of the world + iterator1.remove(); } } } else { - chunksToLoad.remove(); + iterator1.remove(); } } - if (!chunkList.isEmpty()) { - if (chunkList.size() == 1) { - this.playerConnection.sendPacket(new PacketPlayOutMapChunk(chunkList.get(0), true, '\uffff')); + if (!arraylist.isEmpty()) { + if (arraylist.size() == 1) { + this.playerConnection.sendPacket(new PacketPlayOutMapChunk((Chunk) arraylist.get(0), true, '\uffff')); } else { - this.playerConnection.sendPacket(new PacketPlayOutMapChunkBulk(chunkList)); + this.playerConnection.sendPacket(new PacketPlayOutMapChunkBulk(arraylist)); } - Iterator tileEntitiesIterator = tileEntities.iterator(); + Iterator iterator2 = arraylist1.iterator(); - while (tileEntitiesIterator.hasNext()) { - TileEntity tileentity = tileEntitiesIterator.next(); + while (iterator2.hasNext()) { + TileEntity tileentity = (TileEntity) iterator2.next(); this.a(tileentity); } - // //Nacho - if there are a lot of entities, we end up scanning the WHOLE list of entities multiple times -// // Which isn't the best if we have 100 players doing that - // So instead of updating all entities by chunk, we update all entities at once with a hashset of chunks - // This means we don't have to pass over the list x chunks - // o(chunk * entityList) => o(entitylist) + iterator2 = arraylist.iterator(); -// Iterator chunkIterator = chunkList.iterator(); -// while (chunkIterator.hasNext()) -// { -// chunk = (Chunk) chunkIterator.next(); -// this.u().getTracker().a(this, chunk); -// } -// Nacho - end - - LongOpenHashSet chunkPosSet = new LongOpenHashSet(chunkList.size()); - for (Chunk newChunk : chunkList) - chunkPosSet.add(this.chunkToLong(newChunk.locX, newChunk.locZ)); - - Iterator trackerEntryIterator = this.u().getTracker().getEntityTrackerEntries(); - while (trackerEntryIterator.hasNext()) - { - EntityTrackerEntry entitytrackerentry = trackerEntryIterator.next(); - - if (entitytrackerentry.tracker != this && chunkPosSet.contains(this.chunkToLong(entitytrackerentry.tracker.ae, entitytrackerentry.tracker.ag))) - { - entitytrackerentry.updatePlayer(this); - } + while (iterator2.hasNext()) { + chunk = (Chunk) iterator2.next(); + this.u().getTracker().a(this, chunk); } } } + Entity entity = this.C(); if (entity != this) { diff --git a/eSpigot-Server/src/main/java/net/minecraft/server/EntityTracker.java b/eSpigot-Server/src/main/java/net/minecraft/server/EntityTracker.java index 62d23bc..17b4af0 100644 --- a/eSpigot-Server/src/main/java/net/minecraft/server/EntityTracker.java +++ b/eSpigot-Server/src/main/java/net/minecraft/server/EntityTracker.java @@ -1,34 +1,21 @@ package net.minecraft.server; -import com.elevatemc.spigot.config.eSpigotConfig; -import com.elevatemc.spigot.visuals.CannonTrackerEntry; import com.google.common.collect.Lists; import com.google.common.collect.Sets; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import java.util.ArrayList; import java.util.Iterator; -import java.util.List; import java.util.Set; import java.util.concurrent.Callable; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.bukkit.Bukkit; -import com.elevatemc.spigot.util.SynchronizedIntHashMap; -import com.elevatemc.spigot.util.task.Task; -import com.elevatemc.spigot.util.task.impl.ThreadTaskExecutor; - public class EntityTracker { - private static final Logger LOGGER = LogManager.getLogger(); - private static final ThreadTaskExecutor TASK_EXECUTOR = new ThreadTaskExecutor("EntityTracker"); - - static { - TASK_EXECUTOR.start(); - } - - private WorldServer world; - private Set c = Sets.newConcurrentHashSet(); // eSpigot - ConcurrentHashSet - public IntHashMap trackedEntities = new SynchronizedIntHashMap<>(); // eSpigot - Thread safe implementation of IntHashMap (SynchronizedIntHashMap) + private static final Logger a = LogManager.getLogger(); + private final WorldServer world; + private Set c = Sets.newConcurrentHashSet(); + public IntHashMap trackedEntities = new IntHashMap(); private int e; public EntityTracker(WorldServer worldserver) { @@ -39,6 +26,16 @@ public class EntityTracker { public void track(Entity entity) { if (entity instanceof EntityPlayer) { this.addEntity(entity, 512, 2); + EntityPlayer entityplayer = (EntityPlayer) entity; + Iterator iterator = this.c.iterator(); + + while (iterator.hasNext()) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); + + if (entitytrackerentry.tracker != entityplayer) { + entitytrackerentry.updatePlayerFor(entityplayer); + } + } } else if (entity instanceof EntityFishingHook) { this.addEntity(entity, 64, 5, true); } else if (entity instanceof EntityArrow) { @@ -98,204 +95,161 @@ public class EntityTracker { } 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 if (i > this.e) { i = this.e; } - if (this.trackedEntities.b(entity.getId())) { // IntHashMap already contains entity id - throw new IllegalStateException("Entity is already tracked!"); - } - - final int finalI = i; // CraftBukkit - fix decompile error - - EntityTrackerEntry entitytrackerentry = createTracker(entity, i, j, flag); // IonSpigot - - // We want to add them to these collections directly to ensure compatibility with plugins like Citizens - - this.c.add(entitytrackerentry); // Add entity to entity tracker entries set - this.trackedEntities.a(entity.getId(), entitytrackerentry); // Add entity to trackedEntities collection - - TASK_EXECUTOR.submit(executor -> { - try { - entitytrackerentry.scanPlayers(this.world.players); // Update all players in world, - // essentially the only method that would - // be heavy in this method is this method (EntityTrackerEntry#scanPlayers) - } catch (Throwable throwable) { - CrashReport crashreport = CrashReport.a(throwable, "Adding entity to track"); - CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity To Track"); - - crashreportsystemdetails.a("Tracking range", finalI + " blocks"); - crashreportsystemdetails.a("Update interval", new Callable() { - public String a() throws Exception { - String s = "Once per " + finalI + " ticks"; // CraftBukkit - - if (finalI == Integer.MAX_VALUE) { // CraftBukkit - s = "Maximum (" + s + ")"; - } - - return s; - } - - public Object call() throws Exception { - return this.a(); - } - }); - entity.appendEntityCrashDetails(crashreportsystemdetails); - CrashReportSystemDetails crashreportsystemdetails1 = crashreport.a("Entity That Is Already Tracked"); - - this.trackedEntities.get(entity.getId()).tracker.appendEntityCrashDetails(crashreportsystemdetails1); - - try { - throw new ReportedException(crashreport); - } catch (ReportedException reportedexception) { - EntityTracker.LOGGER.error("\"Silently\" catching entity tracking error.", reportedexception); - } + try { + if (this.trackedEntities.b(entity.getId())) { + throw new IllegalStateException("Entity is already tracked!"); } - }); - } - // IonSpigot start - private EntityTrackerEntry createTracker(Entity entity, int i, int j, boolean flag) { - if (entity.isCannoningEntity && eSpigotConfig.cannonTracker) { - return new CannonTrackerEntry(entity, i, j, flag); - } else { - return new EntityTrackerEntry(entity, i, j, flag); + EntityTrackerEntry entitytrackerentry = new EntityTrackerEntry(entity, i, j, flag); + + this.c.add(entitytrackerentry); + this.trackedEntities.a(entity.getId(), entitytrackerentry); + entitytrackerentry.scanPlayers(this.world.players); + } catch (Throwable throwable) { + CrashReport crashreport = CrashReport.a(throwable, "Adding entity to track"); + CrashReportSystemDetails crashreportsystemdetails = crashreport.a("Entity To Track"); + + crashreportsystemdetails.a("Tracking range", (Object) (i + " blocks")); + final int finalI = i; // CraftBukkit - fix decompile error + crashreportsystemdetails.a("Update interval", new Callable() { + public String a() throws Exception { + String s = "Once per " + finalI + " ticks"; // CraftBukkit + + if (finalI == Integer.MAX_VALUE) { // CraftBukkit + s = "Maximum (" + s + ")"; + } + + return s; + } + + public Object call() throws Exception { + return this.a(); + } + }); + entity.appendEntityCrashDetails(crashreportsystemdetails); + CrashReportSystemDetails crashreportsystemdetails1 = crashreport.a("Entity That Is Already Tracked"); + + ((EntityTrackerEntry) this.trackedEntities.get(entity.getId())).tracker.appendEntityCrashDetails(crashreportsystemdetails1); + + try { + throw new ReportedException(crashreport); + } catch (ReportedException reportedexception) { + EntityTracker.a.error("\"Silently\" catching entity tracking error.", reportedexception); + } } + } - // IonSpigot end public void untrackEntity(Entity entity) { - //org.spigotmc.AsyncCatcher.catchOp( "entity untrack"); // Spigot - boolean mainThread = Thread.currentThread() == MinecraftServer.getServer().primaryThread; - + org.spigotmc.AsyncCatcher.catchOp( "entity untrack"); // Spigot if (entity instanceof EntityPlayer) { EntityPlayer entityplayer = (EntityPlayer) entity; - // The best way to go around reducing load on this method is by fully doing the iteration asynchronously - // We honestly don't need to handle this asynchronously if the size of the entity tracker entry set - // Iterate through all entity tracker entries + Iterator iterator = this.c.iterator(); - if (this.c.size() < 20 || !mainThread) - for (EntityTrackerEntry entitytrackerentry : this.c) - entitytrackerentry.a(entityplayer); // Untrack entity - else { - TASK_EXECUTOR.submit(executor -> - {for(EntityTrackerEntry entityTrackerEntry : this.c){entityTrackerEntry.a(entityplayer);}}); + while (iterator.hasNext()) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); + + entitytrackerentry.a(entityplayer); } } - EntityTrackerEntry entitytrackerentry1 = this.trackedEntities.d(entity.getId()); + EntityTrackerEntry entitytrackerentry1 = (EntityTrackerEntry) this.trackedEntities.d(entity.getId()); if (entitytrackerentry1 != null) { this.c.remove(entitytrackerentry1); - TASK_EXECUTOR.submit(executor -> entitytrackerentry1.a()); + entitytrackerentry1.a(); } + } - private final Task updatePlayerTask = executor -> { - List pending = Lists.newArrayList(); - - // Iterate through all entitytracker entries - for (EntityTrackerEntry entitytrackerentry : this.c) { - entitytrackerentry.track(this.world.players); // Ensure you're tracking them - if (entitytrackerentry.n && entitytrackerentry.tracker instanceof EntityPlayer) { - pending.add(entitytrackerentry.tracker); - } - } - - for (Object o : pending) { - EntityPlayer entityplayer = (EntityPlayer) o; - - for (EntityTrackerEntry entitytrackerentry1 : this.c) { - if (entitytrackerentry1.tracker != entityplayer) { - entitytrackerentry1.updatePlayer(entityplayer); - } - } - } - }; - public void updatePlayers() { - if (Bukkit.isPrimaryThread()) - TASK_EXECUTOR.submit(updatePlayerTask); - else updatePlayerTask.onExecute(null); // It's already being ran async so no need to make sure it runs on a separate thread - } + ArrayList arraylist = Lists.newArrayList(); + Iterator iterator = this.c.iterator(); - // Force update - public void a(EntityPlayer entityplayer) { - boolean mainThread = Thread.currentThread() == MinecraftServer.getServer().primaryThread; + while (iterator.hasNext()) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); - Task task = executor -> { - for (EntityTrackerEntry entitytrackerentry : this.c) { - if (entitytrackerentry.tracker == entityplayer) { - entitytrackerentry.scanPlayers(this.world.players); - } else { - entitytrackerentry.updatePlayer(entityplayer); + entitytrackerentry.track(this.world.players); + if (entitytrackerentry.n && entitytrackerentry.tracker instanceof EntityPlayer) { + arraylist.add(entitytrackerentry.tracker); + } + } + + 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.tracker != entityplayer) { + entitytrackerentry1.updatePlayerFor(entityplayer); } } - }; + } - if (!mainThread) - task.onExecute(null); - else TASK_EXECUTOR.submit(task); } - public void a(Entity entity, Packet packet) { - // The packets being passed onto this method generally don't tend to make gameplay less smooth if it takes a 10L delay, so we can submit them to our TaskExecutor - Task task = executor -> { - EntityTrackerEntry entitytrackerentry = this.trackedEntities.get(entity.getId()); + public void a(EntityPlayer entityplayer) { + Iterator iterator = this.c.iterator(); - if (entitytrackerentry != null) { - entitytrackerentry.broadcast(packet); + while (iterator.hasNext()) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); + + if (entitytrackerentry.tracker == entityplayer) { + entitytrackerentry.scanPlayers(this.world.players); + } else { + entitytrackerentry.updatePlayerFor(entityplayer); } - }; + } - if (!Bukkit.isPrimaryThread()) - task.onExecute(null); - else TASK_EXECUTOR.submit(task); } - public void sendPacketToEntity(Entity entity, Packet packet) { /* Used for entity animations & entity status packets, same reasoning for async as EntityTracker#a(Entity, Packet) method */ - Task task = executor -> { - EntityTrackerEntry entitytrackerentry = this.trackedEntities.get(entity.getId()); + public void a(Entity entity, Packet packet) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) this.trackedEntities.get(entity.getId()); - if (entitytrackerentry != null) - entitytrackerentry.broadcastIncludingSelf(packet); - }; + if (entitytrackerentry != null) { + entitytrackerentry.broadcast(packet); + } + + } + + public void sendPacketToEntity(Entity entity, Packet packet) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) this.trackedEntities.get(entity.getId()); + + if (entitytrackerentry != null) { + entitytrackerentry.broadcastIncludingSelf(packet); + } - if (!Bukkit.isPrimaryThread()) - task.onExecute(null); - else TASK_EXECUTOR.submit(task); } public void untrackPlayer(EntityPlayer entityplayer) { - Task task = executor -> { - for (EntityTrackerEntry entitytrackerentry : this.c) - entitytrackerentry.clear(entityplayer); - }; + Iterator iterator = this.c.iterator(); - if (!Bukkit.isPrimaryThread()) - task.onExecute(null); - else TASK_EXECUTOR.submit(task); - } + while (iterator.hasNext()) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); + + entitytrackerentry.clear(entityplayer); + } - public Iterator getEntityTrackerEntries() - { - return this.c.iterator(); } public void a(EntityPlayer entityplayer, Chunk chunk) { - Task task = executor -> { - for (EntityTrackerEntry entitytrackerentry : this.c) { - if (entitytrackerentry.tracker != entityplayer - && entitytrackerentry.tracker.ae == chunk.locX - && entitytrackerentry.tracker.ag == chunk.locZ) { - entitytrackerentry.updatePlayer(entityplayer); - } - } - }; + Iterator iterator = this.c.iterator(); + + while (iterator.hasNext()) { + EntityTrackerEntry entitytrackerentry = (EntityTrackerEntry) iterator.next(); + + if (entitytrackerentry.tracker != entityplayer && entitytrackerentry.tracker.ae == chunk.locX && entitytrackerentry.tracker.ag == chunk.locZ) { + entitytrackerentry.updatePlayerFor(entityplayer); + } + } - if (!Bukkit.isPrimaryThread()) - task.onExecute(null); - else TASK_EXECUTOR.submit(task); } -} +} \ No newline at end of file diff --git a/eSpigot-Server/src/main/java/net/minecraft/server/EntityTrackerEntry.java b/eSpigot-Server/src/main/java/net/minecraft/server/EntityTrackerEntry.java index 8795b38..bed69c6 100644 --- a/eSpigot-Server/src/main/java/net/minecraft/server/EntityTrackerEntry.java +++ b/eSpigot-Server/src/main/java/net/minecraft/server/EntityTrackerEntry.java @@ -1,15 +1,14 @@ package net.minecraft.server; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerVelocityEvent; + import java.util.*; import java.util.concurrent.ConcurrentHashMap; -import com.elevatemc.spigot.config.eSpigotConfig; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - // CraftBukkit start -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerVelocityEvent; // CraftBukkit end public class EntityTrackerEntry { @@ -41,7 +40,7 @@ public class EntityTrackerEntry { // PaperSpigot start // Replace trackedPlayers Set with a Map. The value is true until the player receives // their first update (which is forced to have absolute coordinates), false afterward. - public java.util.Map trackedPlayerMap = new ConcurrentHashMap<>(); // eSpigot - ConcurrentHashMap + public java.util.Map trackedPlayerMap = new ConcurrentHashMap<>(); public Set trackedPlayers = trackedPlayerMap.keySet(); // PaperSpigot end @@ -60,7 +59,7 @@ public class EntityTrackerEntry { } public boolean equals(Object object) { - return object instanceof EntityTrackerEntry && ((EntityTrackerEntry) object).tracker.getId() == this.tracker.getId(); + return object instanceof EntityTrackerEntry ? ((EntityTrackerEntry) object).tracker.getId() == this.tracker.getId() : false; } public int hashCode() { @@ -83,16 +82,17 @@ public class EntityTrackerEntry { this.broadcast(new PacketPlayOutAttachEntity(0, this.tracker, this.tracker.vehicle)); } - if (this.tracker instanceof EntityItemFrame && this.m % 20 == 0) { // Paper + if (this.tracker instanceof EntityItemFrame /*&& this.m % 10 == 0*/) { // CraftBukkit - Moved below, should always enter this block EntityItemFrame entityitemframe = (EntityItemFrame) this.tracker; ItemStack itemstack = entityitemframe.getItem(); - if (itemstack != null && itemstack.getItem() instanceof ItemWorldMap) { // Paper - moved back up + if (this.m % 10 == 0 && itemstack != null && itemstack.getItem() instanceof ItemWorldMap) { // CraftBukkit - Moved this.m % 10 logic here so item frames do not enter the other blocks WorldMap worldmap = Items.FILLED_MAP.getSavedMap(itemstack, this.tracker.world); - // CraftBukkit + Iterator iterator = this.trackedPlayers.iterator(); // CraftBukkit - for (EntityPlayer trackedPlayer : this.trackedPlayers) { - EntityPlayer entityplayer = trackedPlayer; + while (iterator.hasNext()) { + EntityHuman entityhuman = (EntityHuman) iterator.next(); + EntityPlayer entityplayer = (EntityPlayer) entityhuman; worldmap.a(entityplayer, itemstack); Packet packet = Items.FILLED_MAP.c(itemstack, this.tracker.world, entityplayer); @@ -112,16 +112,17 @@ public class EntityTrackerEntry { if (this.tracker.vehicle == null) { ++this.v; - i = MathHelper.floor(this.tracker.locX * 32.0D); + i = MathHelper.floor((this.tracker.locX) * 32.0D); j = MathHelper.floor(this.tracker.locY * 32.0D); - int k = MathHelper.floor(this.tracker.locZ * 32.0D); + int k = MathHelper.floor((this.tracker.locZ) * 32.0D); int l = MathHelper.d(this.tracker.yaw * 256.0F / 360.0F); int i1 = MathHelper.d(this.tracker.pitch * 256.0F / 360.0F); + //System.out.println(String.format("%s, %s, %s", this.tracker.locX, this.tracker.locY, this.tracker.locZ)); int j1 = i - this.xLoc; int k1 = j - this.yLoc; int l1 = k - this.zLoc; Object object = null; - boolean flag = Math.abs(j1) >= 4 || Math.abs(k1) >= 4 || Math.abs(l1) >= 4 || this.m % 60 == 0; + boolean flag = Math.abs(j1) >= 2 || Math.abs(k1) >= 2 || Math.abs(l1) >= 2; boolean flag1 = Math.abs(l - this.yRot) >= 4 || Math.abs(i1 - this.xRot) >= 4; if (this.m > 0 || this.tracker instanceof EntityArrow) { // PaperSpigot - Moved up @@ -138,26 +139,28 @@ public class EntityTrackerEntry { } // CraftBukkit end - if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128 && this.v <= 100 && !this.x && this.y == this.tracker.onGround) { // Kohi - greatly reduce forced teleport interval - 400 -> 100 - if ((!flag || !flag1) && !(this.tracker instanceof EntityArrow)) { - if (flag) { - object = new PacketPlayOutEntity.PacketPlayOutRelEntityMove(this.tracker.getId(), (byte) j1, (byte) k1, (byte) l1, this.tracker.onGround); - } else if (flag1) { - object = new PacketPlayOutEntity.PacketPlayOutEntityLook(this.tracker.getId(), (byte) l, (byte) i1, this.tracker.onGround); + + if (!(j1 == 0 && k1 == 0 && l1 == 0 && !flag1)) { + if (j1 >= -128 && j1 < 128 && k1 >= -128 && k1 < 128 && l1 >= -128 && l1 < 128 && this.v <= 5 && !this.x && this.y == this.tracker.onGround) { + if ((!flag || !flag1) && !(this.tracker instanceof EntityArrow)) { + if (flag) { + object = new PacketPlayOutEntity.PacketPlayOutRelEntityMove(this.tracker.getId(), (byte) j1, (byte) k1, (byte) l1, this.tracker.onGround); + } else if (flag1) { + object = new PacketPlayOutEntity.PacketPlayOutEntityLook(this.tracker.getId(), (byte) l, (byte) i1, this.tracker.onGround); + } + } else { + object = new PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook(this.tracker.getId(), (byte) j1, (byte) k1, (byte) l1, (byte) l, (byte) i1, this.tracker.onGround); } } else { - object = new PacketPlayOutEntity.PacketPlayOutRelEntityMoveLook(this.tracker.getId(), (byte) j1, (byte) k1, (byte) l1, (byte) l, (byte) i1, this.tracker.onGround); + this.y = this.tracker.onGround; + this.v = 0; + // CraftBukkit start - Refresh list of who can see a player before sending teleport packet + if (this.tracker instanceof EntityPlayer) { + this.scanPlayers(new ArrayList<>(this.trackedPlayers)); + } + // CraftBukkit end + object = new PacketPlayOutEntityTeleport(this.tracker.getId(), i, j, k, (byte) l, (byte) i1, this.tracker.onGround); } - } else { - this.y = this.tracker.onGround; - this.v = 0; - // CraftBukkit start - Refresh list of who can see a player before sending teleport packet - if (this.tracker instanceof EntityPlayer) { - // SportPaper - Fix invisibility on teleport - this.scanPlayers(new ArrayList(this.tracker.world.players)); - } - // CraftBukkit end - object = new PacketPlayOutEntityTeleport(this.tracker.getId(), i, j, k, (byte) l, (byte) i1, this.tracker.onGround); } } @@ -261,11 +264,7 @@ public class EntityTrackerEntry { } if (!cancelled) { - if (this.tracker instanceof EntityPlayer) { - ((EntityPlayer) this.tracker).playerConnection.sendPacket(new PacketPlayOutEntityVelocity(this.tracker)); - } else if (this.tracker instanceof EntityArrow || this.tracker instanceof EntityProjectile) { - this.broadcast(new PacketPlayOutEntityVelocity(this.tracker)); - } + this.broadcastIncludingSelf(new PacketPlayOutEntityVelocity(this.tracker)); } // CraftBukkit end this.tracker.velocityChanged = false; @@ -277,51 +276,20 @@ public class EntityTrackerEntry { DataWatcher datawatcher = this.tracker.getDataWatcher(); if (datawatcher.a()) { - if (eSpigotConfig.obfuscatePlayerHealth && this.tracker instanceof EntityHuman) { - List changedMetadata = datawatcher.c(); - Iterator iter = changedMetadata.iterator(); - boolean found = false; - - while (iter.hasNext()) { - DataWatcher.WatchableObject watchable = iter.next(); - if (watchable.a() == 6) { - iter.remove(); - found = true; - } - } - - if (found) { - changedMetadata.add(new DataWatcher.WatchableObject(3, 6, 1.0F)); - } - - PacketPlayOutEntityMetadata modifiedPacket = new PacketPlayOutEntityMetadata(this.tracker.getId(), changedMetadata); - - // Beanes - Broadcast the modified metadata packet to everyone and send the correct packet to the player - this.broadcast(modifiedPacket); - if (this.tracker instanceof EntityPlayer) - ((EntityPlayer) this.tracker).playerConnection.sendPacket(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false)); - } else { - this.broadcastIncludingSelf(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false)); - } + this.broadcastIncludingSelf(new PacketPlayOutEntityMetadata(this.tracker.getId(), datawatcher, false)); } if (this.tracker instanceof EntityLiving) { AttributeMapServer attributemapserver = (AttributeMapServer) ((EntityLiving) this.tracker).getAttributeMap(); - Set set = attributemapserver.getAttributes(); + Set set = attributemapserver.getAttributes(); if (!set.isEmpty()) { // CraftBukkit start - Send scaled max health if (this.tracker instanceof EntityPlayer) { ((EntityPlayer) this.tracker).getBukkitEntity().injectScaledMaxHealth(set, false); - ((EntityPlayer) this.tracker).playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set)); // MineHQ } // CraftBukkit end - // MineHQ start - // this.broadcastIncludingSelf(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set)); // CraftBukkit - if (this.tracker.passenger instanceof EntityPlayer) { - ((EntityPlayer) this.tracker.passenger).playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set)); - } - // MineHQ end + this.broadcastIncludingSelf(new PacketPlayOutUpdateAttributes(this.tracker.getId(), set)); } set.clear(); @@ -330,25 +298,35 @@ public class EntityTrackerEntry { } public void broadcast(Packet packet) { - for (EntityPlayer entityplayer : this.trackedPlayers) + Iterator iterator = this.trackedPlayers.iterator(); + + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); + entityplayer.playerConnection.sendPacket(packet); + } + } public void broadcastIncludingSelf(Packet packet) { this.broadcast(packet); - if (this.tracker instanceof EntityPlayer) + if (this.tracker instanceof EntityPlayer) { ((EntityPlayer) this.tracker).playerConnection.sendPacket(packet); + } + } public void a() { + Iterator iterator = this.trackedPlayers.iterator(); + + while (iterator.hasNext()) { + EntityPlayer entityplayer = (EntityPlayer) iterator.next(); - for (EntityPlayer entityplayer : this.trackedPlayers) { entityplayer.d(this.tracker); } } - // Untrack entity public void a(EntityPlayer entityplayer) { if (this.trackedPlayers.contains(entityplayer)) { entityplayer.d(this.tracker); @@ -357,7 +335,8 @@ public class EntityTrackerEntry { } - public void updatePlayer(EntityPlayer entityplayer) { + public void updatePlayerFor(EntityPlayer entityplayer) { + org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot if (entityplayer != this.tracker) { if (this.c(entityplayer)) { if (!this.trackedPlayers.contains(entityplayer) && (this.e(entityplayer) || this.tracker.attachedToPlayer)) { @@ -385,8 +364,6 @@ public class EntityTrackerEntry { entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateEntityNBT(this.tracker.getId(), nbttagcompound)); } - // MineHQ start - /* if (this.tracker instanceof EntityLiving) { AttributeMapServer attributemapserver = (AttributeMapServer) ((EntityLiving) this.tracker).getAttributeMap(); Collection collection = attributemapserver.c(); @@ -401,8 +378,6 @@ public class EntityTrackerEntry { entityplayer.playerConnection.sendPacket(new PacketPlayOutUpdateAttributes(this.tracker.getId(), collection)); } } - */ - // MineHQ end this.j = this.tracker.motX; this.k = this.tracker.motY; @@ -438,22 +413,17 @@ public class EntityTrackerEntry { } // CraftBukkit start - Fix for nonsensical head yaw - if(this.tracker instanceof EntityLiving) { // SportPaper - avoid processing entities that can't change head rotation - this.i = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F); - // SportPaper start - // This was originally introduced by CraftBukkit, though the implementation is wrong since it's broadcasting - // the packet again in a method that is already called for each player. This would create a very serious performance issue - // with high player and entity counts (each sendPacket call involves waking up the event loop and flushing the network stream). - // this.broadcast(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) i)); - entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) i)); - // SportPaper end - } + this.i = MathHelper.d(this.tracker.getHeadRotation() * 256.0F / 360.0F); + this.broadcast(new PacketPlayOutEntityHeadRotation(this.tracker, (byte) i)); // CraftBukkit end if (this.tracker instanceof EntityLiving) { EntityLiving entityliving = (EntityLiving) this.tracker; + Iterator iterator = entityliving.getEffects().iterator(); + + while (iterator.hasNext()) { + MobEffect mobeffect = (MobEffect) iterator.next(); - for (MobEffect mobeffect : entityliving.getEffects()) { entityplayer.playerConnection.sendPacket(new PacketPlayOutEntityEffect(this.tracker.getId(), mobeffect)); } } @@ -475,17 +445,18 @@ public class EntityTrackerEntry { return d0 >= (double) (-this.b) && d0 <= (double) this.b && d1 >= (double) (-this.b) && d1 <= (double) this.b && this.tracker.a(entityplayer); } - protected boolean e(EntityPlayer entityplayer) { // IonSpigot - private -> protected + private boolean e(EntityPlayer entityplayer) { return entityplayer.u().getPlayerChunkMap().a(entityplayer, this.tracker.ae, this.tracker.ag); } public void scanPlayers(List list) { - for (EntityHuman entityHuman : list) { - this.updatePlayer((EntityPlayer) entityHuman); + for (int i = 0; i < list.size(); ++i) { + this.updatePlayerFor((EntityPlayer) list.get(i)); } + } - protected Packet c() { + private Packet c() { if (this.tracker.dead) { // CraftBukkit start - Remove useless error spam, just return // EntityTrackerEntry.p.warn("Fetching addPacket for removed entity"); @@ -596,7 +567,11 @@ public class EntityTrackerEntry { } public void clear(EntityPlayer entityplayer) { - if (this.trackedPlayers.remove(entityplayer)) // eSpigot - Directly remove + org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot + if (this.trackedPlayers.contains(entityplayer)) { + this.trackedPlayers.remove(entityplayer); entityplayer.d(this.tracker); + } + } } \ No newline at end of file diff --git a/eSpigot-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/eSpigot-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java index a8deb68..28b710f 100644 --- a/eSpigot-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java +++ b/eSpigot-Server/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java @@ -1027,9 +1027,9 @@ public class CraftPlayer extends CraftHumanEntity implements Player { if (!eSpigotConfig.showHiddenPlayersInTab) getHandle().playerConnection.sendPacket(new PacketPlayOutPlayerInfo(PacketPlayOutPlayerInfo.EnumPlayerInfoAction.ADD_PLAYER, other)); - EntityTrackerEntry entry = tracker.trackedEntities.get(other.getId()); + EntityTrackerEntry entry = (EntityTrackerEntry) tracker.trackedEntities.get(other.getId()); if (entry != null && !entry.trackedPlayers.contains(getHandle())) { - entry.updatePlayer(getHandle()); + entry.updatePlayerFor(getHandle()); } }