Remove MOST Synchronization from Chunk Map
This will provide quite a major performance boost by avoiding
synchronizing on EVERY chunk lookup.
Synchronize, even without contention, incurs processor cache flushes.
Considering this is the 2nd hottest method in the code base, lets
avoid doing that...
Additionally, chunk conversion operations were occuring while
under synchronization which lead to deadlocks.
Now the conversion will occur outside of the lock, and fix
that issue, resolving #1586
Note, that the chunk map is still thread safe for get operations!
The chunk map was never intended to be modified async with our
changes, as we post to main to modify the map, however
we do still synchronize for write operations (put, remove)
We also synchronize for async get operations, ensuring that
async gets are safe.
We do not need to synchronize main thread gets as the processor
cache will be insync since the map is only updated on the main thread.
However, if someone does try to delete or put concurrently, we
will force their operation back to the main thread.
2018-10-19 02:41:23 +00:00
|
|
|
From 7ac07ac07ac07ac07ac07ac07ac07ac07ac07ac0 Mon Sep 17 00:00:00 2001
|
2018-10-18 20:53:10 +00:00
|
|
|
From: Caleb Bassham <caleb.bassham@gmail.com>
|
|
|
|
Date: Fri, 28 Sep 2018 02:32:19 -0500
|
|
|
|
Subject: [PATCH] Call player spectator target events
|
|
|
|
|
|
|
|
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/EntityPlayer.java b/src/main/java/net/minecraft/server/EntityPlayer.java
|
Remove MOST Synchronization from Chunk Map
This will provide quite a major performance boost by avoiding
synchronizing on EVERY chunk lookup.
Synchronize, even without contention, incurs processor cache flushes.
Considering this is the 2nd hottest method in the code base, lets
avoid doing that...
Additionally, chunk conversion operations were occuring while
under synchronization which lead to deadlocks.
Now the conversion will occur outside of the lock, and fix
that issue, resolving #1586
Note, that the chunk map is still thread safe for get operations!
The chunk map was never intended to be modified async with our
changes, as we post to main to modify the map, however
we do still synchronize for write operations (put, remove)
We also synchronize for async get operations, ensuring that
async gets are safe.
We do not need to synchronize main thread gets as the processor
cache will be insync since the map is only updated on the main thread.
However, if someone does try to delete or put concurrently, we
will force their operation back to the main thread.
2018-10-19 02:41:23 +00:00
|
|
|
index 7ac07ac07ac0..7ac07ac07ac0 100644
|
2018-10-18 20:53:10 +00:00
|
|
|
--- a/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
|
|
+++ b/src/main/java/net/minecraft/server/EntityPlayer.java
|
|
|
|
@@ -62,7 +62,7 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
|
|
|
private EntityHuman.EnumChatVisibility cs;
|
|
|
|
private boolean ct = true;
|
|
|
|
private long cu = SystemUtils.b();
|
|
|
|
- private Entity cv;
|
|
|
|
+ private Entity cv; private void setSpectatorTargetField(Entity e) { this.cv = e; } // Paper - OBFHELPER
|
|
|
|
public boolean worldChangeInvuln;
|
|
|
|
private boolean cx; private void setHasSeenCredits(boolean has) { this.cx = has; } // Paper - OBFHELPER
|
|
|
|
private final RecipeBookServer cy;
|
2018-10-21 19:27:53 +00:00
|
|
|
@@ -1373,15 +1373,36 @@ public class EntityPlayer extends EntityHuman implements ICrafting {
|
2018-10-18 20:53:10 +00:00
|
|
|
return (Entity) (this.cv == null ? this : this.cv);
|
|
|
|
}
|
|
|
|
|
|
|
|
- public void setSpectatorTarget(Entity entity) {
|
|
|
|
+ public void setSpectatorTarget(Entity newSpectatorTarget) {
|
2018-10-21 19:27:53 +00:00
|
|
|
+ // Paper start - Add PlayerStartSpectatingEntityEvent and PlayerStopSpectatingEntity Event
|
2018-10-18 20:53:10 +00:00
|
|
|
Entity entity1 = this.getSpecatorTarget();
|
|
|
|
|
|
|
|
- this.cv = (Entity) (entity == null ? this : entity);
|
|
|
|
- if (entity1 != this.cv) {
|
2018-10-21 19:27:53 +00:00
|
|
|
- this.playerConnection.sendPacket(new PacketPlayOutCamera(this.cv));
|
|
|
|
- this.playerConnection.a(this.cv.locX, this.cv.locY, this.cv.locZ, this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit
|
2018-10-18 20:53:10 +00:00
|
|
|
+ if (newSpectatorTarget == null) {
|
|
|
|
+ newSpectatorTarget = this;
|
2018-10-21 19:27:53 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
+ if (entity1 == newSpectatorTarget) return; // new spec target is the current spec target
|
2018-10-18 20:53:10 +00:00
|
|
|
+
|
2018-10-21 19:27:53 +00:00
|
|
|
+ if (newSpectatorTarget == this) {
|
|
|
|
+ com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent playerStopSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStopSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity());
|
2018-10-18 20:53:10 +00:00
|
|
|
+
|
2018-10-21 19:27:53 +00:00
|
|
|
+ if (!playerStopSpectatingEntityEvent.callEvent()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent playerStartSpectatingEntityEvent = new com.destroystokyo.paper.event.player.PlayerStartSpectatingEntityEvent(this.getBukkitEntity(), entity1.getBukkitEntity(), newSpectatorTarget.getBukkitEntity());
|
2018-10-18 20:53:10 +00:00
|
|
|
+
|
2018-10-21 19:27:53 +00:00
|
|
|
+ if (!playerStartSpectatingEntityEvent.callEvent()) {
|
|
|
|
+ return;
|
2018-10-18 20:53:10 +00:00
|
|
|
+ }
|
2018-10-21 19:27:53 +00:00
|
|
|
+ }
|
2018-10-18 20:53:10 +00:00
|
|
|
+
|
|
|
|
+ setSpectatorTargetField(newSpectatorTarget);
|
2018-10-21 19:27:53 +00:00
|
|
|
+
|
|
|
|
+ this.playerConnection.sendPacket(new PacketPlayOutCamera(newSpectatorTarget));
|
|
|
|
+ // Paper end
|
|
|
|
+
|
|
|
|
+ this.playerConnection.a(this.cv.locX, this.cv.locY, this.cv.locZ, this.yaw, this.pitch, TeleportCause.SPECTATE); // CraftBukkit
|
2018-10-18 20:53:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
protected void E() {
|
|
|
|
--
|
|
|
|
2.19.1
|
|
|
|
|