088fa6f28b
Upstream has released updates that appear to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing Bukkit Changes: 5b289e69 SPIGOT-5778: Added World.getGameTime method CraftBukkit Changes: d97d91871 SPIGOT-6347: Nether Portals Default to Nether, even in Nether 8aa6a953f SPIGOT-5778: Added World.getGameTime method Spigot Changes: 73fb6094 #107: Add async catching to chunk entity add/remove
273 Zeilen
15 KiB
Diff
273 Zeilen
15 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Joseph Hirschfeld <joe@ibj.io>
|
|
Date: Thu, 3 Mar 2016 03:15:41 -0600
|
|
Subject: [PATCH] Add exception reporting event
|
|
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..f699ce18ca044f813e194ef2786b7ea853ea86e7
|
|
--- /dev/null
|
|
+++ b/src/main/java/com/destroystokyo/paper/ServerSchedulerReportingWrapper.java
|
|
@@ -0,0 +1,38 @@
|
|
+package com.destroystokyo.paper;
|
|
+
|
|
+import com.google.common.base.Preconditions;
|
|
+import org.bukkit.craftbukkit.scheduler.CraftTask;
|
|
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
|
+import com.destroystokyo.paper.exception.ServerSchedulerException;
|
|
+
|
|
+/**
|
|
+ * Reporting wrapper to catch exceptions not natively
|
|
+ */
|
|
+public class ServerSchedulerReportingWrapper implements Runnable {
|
|
+
|
|
+ private final CraftTask internalTask;
|
|
+
|
|
+ public ServerSchedulerReportingWrapper(CraftTask internalTask) {
|
|
+ this.internalTask = Preconditions.checkNotNull(internalTask, "internalTask");
|
|
+ }
|
|
+
|
|
+ @Override
|
|
+ public void run() {
|
|
+ try {
|
|
+ internalTask.run();
|
|
+ } catch (RuntimeException e) {
|
|
+ internalTask.getOwner().getServer().getPluginManager().callEvent(
|
|
+ new ServerExceptionEvent(new ServerSchedulerException(e, internalTask))
|
|
+ );
|
|
+ throw e;
|
|
+ } catch (Throwable t) {
|
|
+ internalTask.getOwner().getServer().getPluginManager().callEvent(
|
|
+ new ServerExceptionEvent(new ServerSchedulerException(t, internalTask))
|
|
+ ); //Do not rethrow, since it is not permitted with Runnable#run
|
|
+ }
|
|
+ }
|
|
+
|
|
+ public CraftTask getInternalTask() {
|
|
+ return internalTask;
|
|
+ }
|
|
+}
|
|
diff --git a/src/main/java/net/minecraft/server/Chunk.java b/src/main/java/net/minecraft/server/Chunk.java
|
|
index 0d0f36c62d260390827321aa6472f51a3a204c95..01655fd86f9a3218036f8b5404e233d32e0904a5 100644
|
|
--- a/src/main/java/net/minecraft/server/Chunk.java
|
|
+++ b/src/main/java/net/minecraft/server/Chunk.java
|
|
@@ -1,5 +1,6 @@
|
|
package net.minecraft.server;
|
|
|
|
+import com.destroystokyo.paper.exception.ServerInternalException;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.collect.Sets;
|
|
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
|
@@ -619,10 +620,15 @@ public class Chunk implements IChunkAccess {
|
|
this.tileEntities.remove(blockposition);
|
|
// Paper end
|
|
} else {
|
|
- System.out.println("Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ()
|
|
- + " (" + getType(blockposition) + ") where there was no entity tile!");
|
|
- System.out.println("Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16));
|
|
- new Exception().printStackTrace();
|
|
+ // Paper start
|
|
+ ServerInternalException e = new ServerInternalException(
|
|
+ "Attempted to place a tile entity (" + tileentity + ") at " + tileentity.position.getX() + ","
|
|
+ + tileentity.position.getY() + "," + tileentity.position.getZ()
|
|
+ + " (" + getType(blockposition) + ") where there was no entity tile!\n" +
|
|
+ "Chunk coordinates: " + (this.loc.x * 16) + "," + (this.loc.z * 16));
|
|
+ e.printStackTrace();
|
|
+ ServerInternalException.reportInternalException(e);
|
|
+ // Paper end
|
|
// CraftBukkit end
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java
|
|
index bf0ccfb9bf20422b90ef26370d113b49be7d730b..060887d765604e4be82913607bb6266a278f5db6 100644
|
|
--- a/src/main/java/net/minecraft/server/NameReferencingFileConverter.java
|
|
+++ b/src/main/java/net/minecraft/server/NameReferencingFileConverter.java
|
|
@@ -1,5 +1,6 @@
|
|
package net.minecraft.server;
|
|
|
|
+import com.destroystokyo.paper.exception.ServerInternalException;
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Maps;
|
|
import com.google.common.io.Files;
|
|
@@ -353,6 +354,7 @@ public class NameReferencingFileConverter {
|
|
root = NBTCompressedStreamTools.a(new java.io.FileInputStream(file5));
|
|
} catch (Exception exception) {
|
|
exception.printStackTrace();
|
|
+ ServerInternalException.reportInternalException(exception); // Paper
|
|
}
|
|
|
|
if (root != null) {
|
|
@@ -366,6 +368,7 @@ public class NameReferencingFileConverter {
|
|
NBTCompressedStreamTools.a(root, new java.io.FileOutputStream(file2));
|
|
} catch (Exception exception) {
|
|
exception.printStackTrace();
|
|
+ ServerInternalException.reportInternalException(exception); // Paper
|
|
}
|
|
}
|
|
// CraftBukkit end
|
|
diff --git a/src/main/java/net/minecraft/server/PlayerChunkMap.java b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
index b40f6b7d45028b5bc58a222e2d54cb8693273325..0542dde09d288488b88e17a044cc508d5d39782f 100644
|
|
--- a/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/PlayerChunkMap.java
|
|
@@ -761,6 +761,7 @@ public class PlayerChunkMap extends IChunkLoader implements PlayerChunk.d {
|
|
return true;
|
|
} catch (Exception exception) {
|
|
PlayerChunkMap.LOGGER.error("Failed to save chunk {},{}", chunkcoordintpair.x, chunkcoordintpair.z, exception);
|
|
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(exception); // Paper
|
|
return false;
|
|
}
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/RegionFile.java b/src/main/java/net/minecraft/server/RegionFile.java
|
|
index 135f38cc5d5d2fa3866aa1063df49a96b5e72ac2..f722b148464b7b8e515dba25aeffe8dfd3c0d6c3 100644
|
|
--- a/src/main/java/net/minecraft/server/RegionFile.java
|
|
+++ b/src/main/java/net/minecraft/server/RegionFile.java
|
|
@@ -261,6 +261,7 @@ public class RegionFile implements AutoCloseable {
|
|
return true;
|
|
}
|
|
} catch (IOException ioexception) {
|
|
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(ioexception); // Paper
|
|
return false;
|
|
}
|
|
}
|
|
@@ -333,6 +334,7 @@ public class RegionFile implements AutoCloseable {
|
|
filechannel.write(bytebuffer);
|
|
} catch (Throwable throwable1) {
|
|
throwable = throwable1;
|
|
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper
|
|
throw throwable1;
|
|
} finally {
|
|
if (filechannel != null) {
|
|
diff --git a/src/main/java/net/minecraft/server/SpawnerCreature.java b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
index d787fab2c25e31ca6caa56c5e47409512c5ac568..137ee1b453b80e96c1a8fa3271f6350f9294cafb 100644
|
|
--- a/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
+++ b/src/main/java/net/minecraft/server/SpawnerCreature.java
|
|
@@ -14,6 +14,7 @@ import org.apache.logging.log4j.LogManager;
|
|
import org.apache.logging.log4j.Logger;
|
|
|
|
// CraftBukkit start
|
|
+import com.destroystokyo.paper.exception.ServerInternalException;
|
|
import org.bukkit.event.entity.CreatureSpawnEvent.SpawnReason;
|
|
// CraftBukkit end
|
|
|
|
@@ -268,6 +269,7 @@ public final class SpawnerCreature {
|
|
}
|
|
} catch (Exception exception) {
|
|
SpawnerCreature.LOGGER.warn("Failed to create mob", exception);
|
|
+ ServerInternalException.reportInternalException(exception); // Paper
|
|
return null;
|
|
}
|
|
}
|
|
@@ -374,6 +376,7 @@ public final class SpawnerCreature {
|
|
entity = biomesettingsmobs_c.c.a((World) worldaccess.getMinecraftWorld());
|
|
} catch (Exception exception) {
|
|
SpawnerCreature.LOGGER.warn("Failed to create mob", exception);
|
|
+ ServerInternalException.reportInternalException(exception); // Paper
|
|
continue;
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/VillageSiege.java b/src/main/java/net/minecraft/server/VillageSiege.java
|
|
index 1844a6504acc420bdfaaf8f045c569e970d055db..d6aadbda5c5a17976659f57ee04cf9b917e09160 100644
|
|
--- a/src/main/java/net/minecraft/server/VillageSiege.java
|
|
+++ b/src/main/java/net/minecraft/server/VillageSiege.java
|
|
@@ -1,5 +1,7 @@
|
|
package net.minecraft.server;
|
|
|
|
+import com.destroystokyo.paper.exception.ServerInternalException;
|
|
+
|
|
import java.util.Iterator;
|
|
import javax.annotation.Nullable;
|
|
import org.apache.logging.log4j.LogManager;
|
|
@@ -104,6 +106,7 @@ public class VillageSiege implements MobSpawner {
|
|
entityzombie.prepare(worldserver, worldserver.getDamageScaler(entityzombie.getChunkCoordinates()), EnumMobSpawn.EVENT, (GroupDataEntity) null, (NBTTagCompound) null);
|
|
} catch (Exception exception) {
|
|
VillageSiege.LOGGER.warn("Failed to create zombie for village siege at {}", vec3d, exception);
|
|
+ ServerInternalException.reportInternalException(exception); // Paper
|
|
return;
|
|
}
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
|
index eb0af6775d60e2cd610dde6e7c4874d4b01d6054..3638ae7c0eba5b1ef811bc1629334e9c483bef6f 100644
|
|
--- a/src/main/java/net/minecraft/server/World.java
|
|
+++ b/src/main/java/net/minecraft/server/World.java
|
|
@@ -1,5 +1,10 @@
|
|
package net.minecraft.server;
|
|
|
|
+import co.aikar.timings.Timing;
|
|
+import co.aikar.timings.Timings;
|
|
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
|
+import com.destroystokyo.paper.exception.ServerInternalException;
|
|
+import com.google.common.base.MoreObjects;
|
|
import com.google.common.collect.Lists;
|
|
import com.mojang.serialization.Codec;
|
|
import java.io.IOException;
|
|
@@ -685,8 +690,11 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
|
gameprofilerfiller.exit();
|
|
} catch (Throwable throwable) {
|
|
// Paper start - Prevent tile entity and entity crashes
|
|
- System.err.println("TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ());
|
|
+ String msg = "TileEntity threw exception at " + tileentity.world.getWorld().getName() + ":" + tileentity.position.getX() + "," + tileentity.position.getY() + "," + tileentity.position.getZ();
|
|
+ System.err.println(msg);
|
|
throwable.printStackTrace();
|
|
+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
|
|
+ // Paper end
|
|
tilesThisCycle--;
|
|
this.tileEntityListTick.remove(tileTickPosition--);
|
|
continue;
|
|
@@ -756,8 +764,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
|
consumer.accept(entity);
|
|
} catch (Throwable throwable) {
|
|
// Paper start - Prevent tile entity and entity crashes
|
|
- System.err.println("Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ());
|
|
+ String msg = "Entity threw exception at " + entity.world.getWorld().getName() + ":" + entity.locX() + "," + entity.locY() + "," + entity.locZ();
|
|
+ System.err.println(msg);
|
|
throwable.printStackTrace();
|
|
+ getServer().getPluginManager().callEvent(new ServerExceptionEvent(new ServerInternalException(msg, throwable)));
|
|
entity.dead = true;
|
|
return;
|
|
// Paper end
|
|
diff --git a/src/main/java/net/minecraft/server/WorldPersistentData.java b/src/main/java/net/minecraft/server/WorldPersistentData.java
|
|
index 141a8e31151010e5a0bd8d4661033f109f6a2e67..138c6d707e33cd352aa4b26dfb279c5b77448de0 100644
|
|
--- a/src/main/java/net/minecraft/server/WorldPersistentData.java
|
|
+++ b/src/main/java/net/minecraft/server/WorldPersistentData.java
|
|
@@ -144,6 +144,7 @@ public class WorldPersistentData {
|
|
}
|
|
} catch (Throwable throwable6) {
|
|
throwable = throwable6;
|
|
+ com.destroystokyo.paper.exception.ServerInternalException.reportInternalException(throwable); // Paper
|
|
throw throwable6;
|
|
} finally {
|
|
if (fileinputstream != null) {
|
|
diff --git a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
|
index ffe9cc1011226d604dc5499e7692e9a9a5132b72..9b6d9373abb59a30c2835ca891282d07559281f5 100644
|
|
--- a/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
|
+++ b/src/main/java/org/bukkit/craftbukkit/scheduler/CraftScheduler.java
|
|
@@ -16,6 +16,9 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|
import java.util.concurrent.atomic.AtomicReference;
|
|
import java.util.function.Consumer;
|
|
import java.util.logging.Level;
|
|
+import com.destroystokyo.paper.ServerSchedulerReportingWrapper;
|
|
+import com.destroystokyo.paper.event.server.ServerExceptionEvent;
|
|
+import com.destroystokyo.paper.exception.ServerSchedulerException;
|
|
import org.apache.commons.lang.Validate;
|
|
import org.bukkit.plugin.IllegalPluginAccessException;
|
|
import org.bukkit.plugin.Plugin;
|
|
@@ -419,6 +422,8 @@ public class CraftScheduler implements BukkitScheduler {
|
|
msg,
|
|
throwable);
|
|
}
|
|
+ org.bukkit.Bukkit.getServer().getPluginManager().callEvent(
|
|
+ new ServerExceptionEvent(new ServerSchedulerException(msg, throwable, task)));
|
|
// Paper end
|
|
} finally {
|
|
currentTask = null;
|
|
@@ -426,7 +431,7 @@ public class CraftScheduler implements BukkitScheduler {
|
|
parsePending();
|
|
} else {
|
|
debugTail = debugTail.setNext(new CraftAsyncDebugger(currentTick + RECENT_TICKS, task.getOwner(), task.getTaskClass()));
|
|
- executor.execute(task);
|
|
+ executor.execute(new ServerSchedulerReportingWrapper(task)); // Paper
|
|
// We don't need to parse pending
|
|
// (async tasks must live with race-conditions if they attempt to cancel between these few lines of code)
|
|
}
|