Prevent Double PlayerChunkMap adds crashing server

Suspected case would be around the technique used in .stopRiding
Stack will identify any causer of this and warn instead of crashing.
This commit is contained in:
Aikar 2020-04-02 01:42:39 -04:00
parent c569dccd4e
commit ac79088eb6
2 changed files with 24 additions and 14 deletions

View File

@ -320,11 +320,18 @@
}
}
@@ -1215,9 +1291,11 @@
@@ -1215,9 +1291,18 @@
}
public void addEntity(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
+ // Paper start - ignore and warn about illegal addEntity calls instead of crashing server
+ if (!entity.valid || entity.level() != this.level || this.entityMap.containsKey(entity.getId())) {
+ LOGGER.error("Illegal ChunkMap::addEntity for world " + this.level.getWorld().getName()
+ + ": " + entity + (this.entityMap.containsKey(entity.getId()) ? " ALREADY CONTAINED (This would have crashed your server)" : ""), new Throwable());
+ return;
+ }
+ // Paper end - ignore and warn about illegal addEntity calls instead of crashing server
if (!(entity instanceof EnderDragonPart)) {
EntityType<?> entitytypes = entity.getType();
int i = entitytypes.clientTrackingRange() * 16;
@ -332,7 +339,7 @@
if (i != 0) {
int j = entitytypes.updateInterval();
@@ -1250,6 +1328,7 @@
@@ -1250,6 +1335,7 @@
}
protected void removeEntity(Entity entity) {
@ -340,7 +347,7 @@
if (entity instanceof ServerPlayer entityplayer) {
this.updatePlayerStatus(entityplayer, false);
ObjectIterator objectiterator = this.entityMap.values().iterator();
@@ -1391,7 +1470,7 @@
@@ -1391,7 +1477,7 @@
});
}
@ -349,7 +356,7 @@
protected ChunkDistanceManager(final Executor workerExecutor, final Executor mainThreadExecutor) {
super(workerExecutor, mainThreadExecutor);
@@ -1424,7 +1503,7 @@
@@ -1424,7 +1510,7 @@
public final Set<ServerPlayerConnection> seenBy = Sets.newIdentityHashSet();
public TrackedEntity(final Entity entity, final int i, final int j, final boolean flag) {
@ -358,7 +365,7 @@
this.entity = entity;
this.range = i;
this.lastSectionPos = SectionPos.of((EntityAccess) entity);
@@ -1469,6 +1548,7 @@
@@ -1469,6 +1555,7 @@
}
public void removePlayer(ServerPlayer player) {
@ -366,7 +373,7 @@
if (this.seenBy.remove(player.connection)) {
this.serverEntity.removePairing(player);
}
@@ -1476,6 +1556,7 @@
@@ -1476,6 +1563,7 @@
}
public void updatePlayer(ServerPlayer player) {
@ -374,7 +381,7 @@
if (player != this.entity) {
Vec3 vec3d = player.position().subtract(this.entity.position());
int i = ChunkMap.this.getPlayerViewDistance(player);
@@ -1484,6 +1565,11 @@
@@ -1484,6 +1572,11 @@
double d2 = d0 * d0;
boolean flag = d1 <= d2 && this.entity.broadcastToPlayer(player) && ChunkMap.this.isChunkTracked(player, this.entity.chunkPosition().x, this.entity.chunkPosition().z);
@ -386,7 +393,7 @@
if (flag) {
if (this.seenBy.add(player.connection)) {
this.serverEntity.addPairing(player);
@@ -1506,6 +1592,7 @@
@@ -1506,6 +1599,7 @@
while (iterator.hasNext()) {
Entity entity = (Entity) iterator.next();
int j = entity.getType().clientTrackingRange() * 16;

View File

@ -79,7 +79,7 @@
+ public final LevelStorageSource.LevelStorageAccess convertable;
+ public final UUID uuid;
+ public boolean hasPhysicsEvent = true; // Paper - BlockPhysicsEvent
+
+ public LevelChunk getChunkIfLoaded(int x, int z) {
+ return this.chunkSource.getChunk(x, z, false);
+ }
@ -129,7 +129,7 @@
+ }
+ int minBlockX = Mth.floor(axisalignedbb.minX - 1.0E-7D) - 3;
+ int minBlockZ = Mth.floor(axisalignedbb.minZ - 1.0E-7D) - 3;
+
+ int maxBlockX = Mth.floor(axisalignedbb.maxX + 1.0E-7D) + 3;
+ int maxBlockZ = Mth.floor(axisalignedbb.maxZ + 1.0E-7D) + 3;
+
@ -947,20 +947,23 @@
@Override
public CrashReportCategory fillReportDetails(CrashReport report) {
CrashReportCategory crashreportsystemdetails = super.fillReportDetails(report);
@@ -1836,6 +2216,7 @@
@@ -1836,7 +2216,8 @@
}
public void onTrackingStart(Entity entity) {
- ServerLevel.this.getChunkSource().addEntity(entity);
+ org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
ServerLevel.this.getChunkSource().addEntity(entity);
+ // ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server; moved down below valid=true
if (entity instanceof ServerPlayer entityplayer) {
ServerLevel.this.players.add(entityplayer);
@@ -1864,9 +2245,52 @@
ServerLevel.this.updateSleepingPlayerList();
@@ -1864,9 +2245,53 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::add);
+ entity.inWorld = true; // CraftBukkit - Mark entity as in world
+ entity.valid = true; // CraftBukkit
+ ServerLevel.this.getChunkSource().addEntity(entity); // Paper - ignore and warn about illegal addEntity calls instead of crashing server
+ // Paper start - Entity origin API
+ if (entity.getOriginVector() == null) {
+ entity.setOrigin(entity.getBukkitEntity().getLocation());
@ -1008,7 +1011,7 @@
ServerLevel.this.getChunkSource().removeEntity(entity);
if (entity instanceof ServerPlayer entityplayer) {
ServerLevel.this.players.remove(entityplayer);
@@ -1895,6 +2319,15 @@
@@ -1895,6 +2320,15 @@
}
entity.updateDynamicGameEventListener(DynamicGameEventListener::remove);