Prevent NoClassDefError crash and notify on crash

By: David <dmck2b@gmail.com>
This commit is contained in:
CraftBukkit/Spigot 2014-04-21 12:43:08 +01:00
parent f1087e18c1
commit 8b9d2faa11
3 changed files with 37 additions and 18 deletions

View file

@ -57,7 +57,7 @@
public abstract class Level implements LevelAccessor, AutoCloseable {
public static final Codec<ResourceKey<Level>> RESOURCE_KEY_CODEC = ResourceKey.codec(Registries.DIMENSION);
@@ -121,23 +144,62 @@
@@ -121,23 +144,63 @@
private final DamageSources damageSources;
private long subTickCount;
@ -83,6 +83,7 @@
+ public final org.spigotmc.SpigotWorldConfig spigotConfig; // Spigot
+
+ public final SpigotTimings.WorldTimingsHandler timings; // Spigot
+ public static BlockPos lastPhysicsProblem; // Spigot
+
+ public CraftWorld getWorld() {
+ return this.world;
@ -129,7 +130,7 @@
}
};
} else {
@@ -145,11 +207,48 @@
@@ -145,11 +208,48 @@
}
this.thread = Thread.currentThread();
@ -183,7 +184,7 @@
}
@Override
@@ -207,6 +306,18 @@
@@ -207,6 +307,18 @@
@Override
public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
@ -202,12 +203,12 @@
if (this.isOutsideBuildHeight(pos)) {
return false;
} else if (!this.isClientSide && this.isDebug()) {
@@ -214,44 +325,117 @@
@@ -214,44 +326,123 @@
} else {
LevelChunk chunk = this.getChunkAt(pos);
Block block = state.getBlock();
- BlockState iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0);
+
+ // CraftBukkit start - capture blockstates
+ boolean captured = false;
+ if (this.captureBlockStates && !this.capturedBlockStates.containsKey(pos)) {
@ -216,7 +217,7 @@
+ captured = true;
+ }
+ // CraftBukkit end
+
+ BlockState iblockdata1 = chunk.setBlockState(pos, state, (flags & 64) != 0, (flags & 1024) == 0); // CraftBukkit custom NO_PLACE flag
+
if (iblockdata1 == null) {
@ -275,7 +276,13 @@
+ // CraftBukkit start
+ if (!this.captureBlockStates) { // Don't notify clients or update physics while capturing blockstates
+ // Modularize client and physic updates
+ this.notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, maxUpdateDepth);
+ // Spigot start
+ try {
+ this.notifyAndUpdatePhysics(pos, chunk, iblockdata1, state, iblockdata2, flags, maxUpdateDepth);
+ } catch (StackOverflowError ex) {
+ Level.lastPhysicsProblem = new BlockPos(pos);
+ }
+ // Spigot end
+ }
+ // CraftBukkit end
+
@ -335,7 +342,7 @@
public void onBlockStateChange(BlockPos pos, BlockState oldBlock, BlockState newBlock) {}
@@ -340,6 +524,14 @@
@@ -340,6 +531,14 @@
@Override
public BlockState getBlockState(BlockPos pos) {
@ -350,7 +357,7 @@
if (this.isOutsideBuildHeight(pos)) {
return Blocks.VOID_AIR.defaultBlockState();
} else {
@@ -440,12 +632,15 @@
@@ -440,12 +639,15 @@
ProfilerFiller gameprofilerfiller = Profiler.get();
gameprofilerfiller.push("blockEntities");
@ -366,7 +373,7 @@
Iterator<TickingBlockEntity> iterator = this.blockEntityTickers.iterator();
boolean flag = this.tickRateManager().runsNormally();
@@ -459,13 +654,16 @@
@@ -459,13 +661,16 @@
}
}
@ -383,15 +390,15 @@
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity");
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked");
@@ -510,13 +708,29 @@
@@ -510,13 +715,29 @@
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
- return this.isOutsideBuildHeight(pos) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(pos).getBlockEntity(pos, LevelChunk.EntityCreationType.IMMEDIATE));
+ // CraftBukkit start
+ return this.getBlockEntity(pos, true);
+ }
+
}
+ @Nullable
+ public BlockEntity getBlockEntity(BlockPos blockposition, boolean validate) {
+ if (this.capturedTileEntities.containsKey(blockposition)) {
@ -399,8 +406,8 @@
+ }
+ // CraftBukkit end
+ return this.isOutsideBuildHeight(blockposition) ? null : (!this.isClientSide && Thread.currentThread() != this.thread ? null : this.getChunkAt(blockposition).getBlockEntity(blockposition, LevelChunk.EntityCreationType.IMMEDIATE));
}
+ }
+
public void setBlockEntity(BlockEntity blockEntity) {
BlockPos blockposition = blockEntity.getBlockPos();
@ -414,7 +421,7 @@
this.getChunkAt(blockposition).addAndRegisterBlockEntity(blockEntity);
}
}
@@ -643,7 +857,7 @@
@@ -643,7 +864,7 @@
for (int k = 0; k < j; ++k) {
EnderDragonPart entitycomplexpart = aentitycomplexpart[k];
@ -423,7 +430,7 @@
if (t0 != null && predicate.test(t0)) {
result.add(t0);
@@ -912,7 +1126,7 @@
@@ -912,7 +1133,7 @@
public static enum ExplosionInteraction implements StringRepresentable {

View file

@ -18,7 +18,7 @@
public interface NeighborUpdater {
@@ -50,6 +56,17 @@
@@ -50,7 +56,22 @@
static void executeUpdate(Level world, BlockState state, BlockPos pos, Block sourceBlock, @Nullable Orientation orientation, boolean notify) {
try {
@ -34,5 +34,10 @@
+ }
+ // CraftBukkit end
state.handleNeighborChanged(world, pos, sourceBlock, orientation, notify);
+ // Spigot Start
+ } catch (StackOverflowError ex) {
+ world.lastPhysicsProblem = new BlockPos(pos);
+ // Spigot End
} catch (Throwable throwable) {
CrashReport crashreport = CrashReport.forThrowable(throwable, "Exception while updating neighbours");
CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block being updated");

View file

@ -74,6 +74,13 @@ public class WatchdogThread extends Thread
log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" );
log.log( Level.SEVERE, "Spigot version: " + Bukkit.getServer().getVersion() );
//
if ( net.minecraft.world.level.Level.lastPhysicsProblem != null )
{
log.log( Level.SEVERE, "------------------------------" );
log.log( Level.SEVERE, "During the run of the server, a physics stackoverflow was supressed" );
log.log( Level.SEVERE, "near " + net.minecraft.world.level.Level.lastPhysicsProblem );
}
//
log.log( Level.SEVERE, "------------------------------" );
log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Spigot!):" );
WatchdogThread.dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().serverThread.getId(), Integer.MAX_VALUE ), log );