spigot/CraftBukkit-Patches/0006-Async-Operation-Catching.patch
2021-07-13 19:18:55 +10:00

260 lines
13 KiB
Diff

From 7fb143e4edf53f66474157e5056894de1d68c399 Mon Sep 17 00:00:00 2001
From: md_5 <git@md-5.net>
Date: Tue, 25 Mar 2014 16:10:01 +1100
Subject: [PATCH] Async Operation Catching
Catch and throw an exception when a potentially unsafe operation occurs on a thread other than the main server thread.
diff --git a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
index 83dbdb987..87aa223a3 100644
--- a/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
+++ b/src/main/java/net/minecraft/server/level/PlayerChunkMap.java
@@ -1067,6 +1067,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.e {
}
protected void addEntity(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity track"); // Spigot
if (!(entity instanceof EntityComplexPart)) {
EntityTypes<?> entitytypes = entity.getEntityType();
int i = entitytypes.getChunkRange() * 16;
@@ -1102,6 +1103,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.e {
}
protected void removeEntity(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity untrack"); // Spigot
if (entity instanceof EntityPlayer) {
EntityPlayer entityplayer = (EntityPlayer) entity;
@@ -1323,6 +1325,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.e {
}
public void clear(EntityPlayer entityplayer) {
+ org.spigotmc.AsyncCatcher.catchOp("player tracker clear"); // Spigot
if (this.seenBy.remove(entityplayer.connection)) {
this.serverEntity.a(entityplayer);
}
@@ -1330,6 +1333,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.e {
}
public void updatePlayer(EntityPlayer entityplayer) {
+ org.spigotmc.AsyncCatcher.catchOp("player tracker update"); // Spigot
if (entityplayer != this.entity) {
Vec3D vec3d = entityplayer.getPositionVector().d(this.entity.getPositionVector()); // MC-155077, SPIGOT-5113
int i = Math.min(this.b(), (PlayerChunkMap.this.viewDistance - 1) * 16);
diff --git a/src/main/java/net/minecraft/server/level/WorldServer.java b/src/main/java/net/minecraft/server/level/WorldServer.java
index f299cbf90..3216150bf 100644
--- a/src/main/java/net/minecraft/server/level/WorldServer.java
+++ b/src/main/java/net/minecraft/server/level/WorldServer.java
@@ -942,6 +942,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
// CraftBukkit start
private boolean addEntity0(Entity entity, CreatureSpawnEvent.SpawnReason spawnReason) {
+ org.spigotmc.AsyncCatcher.catchOp("entity add"); // Spigot
if (entity.isRemoved()) {
// WorldServer.LOGGER.warn("Tried to add entity {} but it was marked as removed already", EntityTypes.getName(entity.getEntityType())); // CraftBukkit
return false;
@@ -1725,6 +1726,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
@Override
public LevelEntityGetter<Entity> getEntities() {
+ org.spigotmc.AsyncCatcher.catchOp("Chunk getEntities call"); // Spigot
return this.entityManager.d();
}
@@ -1786,6 +1788,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
public void b(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity register"); // Spigot
WorldServer.this.getChunkProvider().addEntity(entity);
if (entity instanceof EntityPlayer) {
WorldServer.this.players.add((EntityPlayer) entity);
@@ -1811,6 +1814,7 @@ public class WorldServer extends World implements GeneratorAccessSeed {
}
public void a(Entity entity) {
+ org.spigotmc.AsyncCatcher.catchOp("entity unregister"); // Spigot
WorldServer.this.getChunkProvider().removeEntity(entity);
if (entity instanceof EntityPlayer) {
EntityPlayer entityplayer = (EntityPlayer) entity;
diff --git a/src/main/java/net/minecraft/world/entity/EntityLiving.java b/src/main/java/net/minecraft/world/entity/EntityLiving.java
index d259e5b95..9ba350597 100644
--- a/src/main/java/net/minecraft/world/entity/EntityLiving.java
+++ b/src/main/java/net/minecraft/world/entity/EntityLiving.java
@@ -1072,6 +1072,7 @@ public abstract class EntityLiving extends Entity {
}
public boolean addEffect(MobEffect mobeffect, @Nullable Entity entity, EntityPotionEffectEvent.Cause cause) {
+ org.spigotmc.AsyncCatcher.catchOp("effect add"); // Spigot
if (isTickingEffects) {
effectsToProcess.add(new ProcessableEffect(mobeffect, cause));
return true;
diff --git a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java
index cd869556a..7ff8a20e7 100644
--- a/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java
+++ b/src/main/java/net/minecraft/world/item/crafting/CraftingManager.java
@@ -82,6 +82,7 @@ public class CraftingManager extends ResourceDataJson {
// CraftBukkit start
public void addRecipe(IRecipe<?> irecipe) {
+ org.spigotmc.AsyncCatcher.catchOp("Recipe Add"); // Spigot
Object2ObjectLinkedOpenHashMap<MinecraftKey, IRecipe<?>> map = this.recipes.get(irecipe.g()); // CraftBukkit
if (map.containsKey(irecipe.getKey())) {
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java
index a8c5013a3..61767a794 100644
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBase.java
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBase.java
@@ -129,10 +129,13 @@ public abstract class BlockBase {
}
@Deprecated
- public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) {}
+ public void onPlace(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) {
+ org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
+ }
@Deprecated
public void remove(IBlockData iblockdata, World world, BlockPosition blockposition, IBlockData iblockdata1, boolean flag) {
+ org.spigotmc.AsyncCatcher.catchOp("block remove"); // Spigot
if (iblockdata.isTileEntity() && !iblockdata.a(iblockdata1.getBlock())) {
world.removeTileEntity(blockposition);
}
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftServer.java b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
index db424a6e1..51a8f7967 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftServer.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftServer.java
@@ -735,6 +735,7 @@ public final class CraftServer implements Server {
public boolean dispatchCommand(CommandSender sender, String commandLine) {
Validate.notNull(sender, "Sender cannot be null");
Validate.notNull(commandLine, "CommandLine cannot be null");
+ org.spigotmc.AsyncCatcher.catchOp("command dispatch"); // Spigot
if (commandMap.dispatch(sender, commandLine)) {
return true;
diff --git a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
index 05d8a187e..fad5223a2 100644
--- a/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
+++ b/src/main/java/org/bukkit/craftbukkit/CraftWorld.java
@@ -398,6 +398,7 @@ public class CraftWorld implements World {
@Override
public boolean unloadChunkRequest(int x, int z) {
+ org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
if (isChunkLoaded(x, z)) {
world.getChunkProvider().removeTicket(TicketType.PLUGIN, new ChunkCoordIntPair(x, z), 1, Unit.INSTANCE);
}
@@ -406,6 +407,7 @@ public class CraftWorld implements World {
}
private boolean unloadChunk0(int x, int z, boolean save) {
+ org.spigotmc.AsyncCatcher.catchOp("chunk unload"); // Spigot
if (!isChunkLoaded(x, z)) {
return true;
}
@@ -420,6 +422,7 @@ public class CraftWorld implements World {
@Override
public boolean regenerateChunk(int x, int z) {
+ org.spigotmc.AsyncCatcher.catchOp("chunk regenerate"); // Spigot
throw new UnsupportedOperationException("Not supported in this Minecraft version! Unless you can fix it, this is not a bug :)");
/*
if (!unloadChunk0(x, z, false)) {
@@ -471,6 +474,7 @@ public class CraftWorld implements World {
@Override
public boolean loadChunk(int x, int z, boolean generate) {
+ org.spigotmc.AsyncCatcher.catchOp("chunk load"); // Spigot
IChunkAccess chunk = world.getChunkProvider().getChunkAt(x, z, generate ? ChunkStatus.FULL : ChunkStatus.EMPTY, true);
// If generate = false, but the chunk already exists, we will get this back.
@@ -1102,6 +1106,7 @@ public class CraftWorld implements World {
@Override
public Collection<Entity> getNearbyEntities(BoundingBox boundingBox, Predicate<Entity> filter) {
+ org.spigotmc.AsyncCatcher.catchOp("getNearbyEntities"); // Spigot
Validate.notNull(boundingBox, "Bounding box is null!");
AxisAlignedBB bb = new AxisAlignedBB(boundingBox.getMinX(), boundingBox.getMinY(), boundingBox.getMinZ(), boundingBox.getMaxX(), boundingBox.getMaxY(), boundingBox.getMaxZ());
@@ -1256,6 +1261,7 @@ public class CraftWorld implements World {
@Override
public void save() {
+ org.spigotmc.AsyncCatcher.catchOp("world save"); // Spigot
this.server.checkSaveState();
boolean oldSave = world.noSave;
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
index 3f3729517..dbd2dcad0 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftEntity.java
@@ -530,6 +530,7 @@ public abstract class CraftEntity implements org.bukkit.entity.Entity {
@Override
public List<org.bukkit.entity.Entity> getNearbyEntities(double x, double y, double z) {
+ org.spigotmc.AsyncCatcher.catchOp("getNearbyEntities"); // Spigot
List<Entity> notchEntityList = entity.level.getEntities(entity, entity.getBoundingBox().grow(x, y, z), Predicates.alwaysTrue());
List<org.bukkit.entity.Entity> bukkitEntityList = new java.util.ArrayList<org.bukkit.entity.Entity>(notchEntityList.size());
diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
index 89c49b6d8..e3b2cf7b3 100644
--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
+++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftPlayer.java
@@ -331,6 +331,7 @@ public class CraftPlayer extends CraftHumanEntity implements Player {
@Override
public void kickPlayer(String message) {
+ org.spigotmc.AsyncCatcher.catchOp("player kick"); // Spigot
if (getHandle().connection == null) return;
getHandle().connection.disconnect(message == null ? "" : message);
diff --git a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
index 51942cbde..6c63051e8 100644
--- a/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
+++ b/src/main/java/org/bukkit/craftbukkit/scoreboard/CraftScoreboardManager.java
@@ -41,6 +41,7 @@ public final class CraftScoreboardManager implements ScoreboardManager {
@Override
public CraftScoreboard getNewScoreboard() {
+ org.spigotmc.AsyncCatcher.catchOp("scoreboard creation"); // Spigot
CraftScoreboard scoreboard = new CraftScoreboard(new ScoreboardServer(server));
scoreboards.add(scoreboard);
return scoreboard;
diff --git a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
index 2e057fd4c..ddef523ea 100644
--- a/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
+++ b/src/main/java/org/bukkit/craftbukkit/util/ServerShutdownThread.java
@@ -12,6 +12,7 @@ public class ServerShutdownThread extends Thread {
@Override
public void run() {
try {
+ org.spigotmc.AsyncCatcher.enabled = false; // Spigot
server.close();
} finally {
try {
diff --git a/src/main/java/org/spigotmc/AsyncCatcher.java b/src/main/java/org/spigotmc/AsyncCatcher.java
new file mode 100644
index 000000000..aeed76972
--- /dev/null
+++ b/src/main/java/org/spigotmc/AsyncCatcher.java
@@ -0,0 +1,17 @@
+package org.spigotmc;
+
+import net.minecraft.server.MinecraftServer;
+
+public class AsyncCatcher
+{
+
+ public static boolean enabled = true;
+
+ public static void catchOp(String reason)
+ {
+ if ( enabled && Thread.currentThread() != MinecraftServer.getServer().serverThread )
+ {
+ throw new IllegalStateException( "Asynchronous " + reason + "!" );
+ }
+ }
+}
--
2.25.1