From 02553174090c2279f1114900712aed4bbae9007e Mon Sep 17 00:00:00 2001 From: Aikar Date: Tue, 1 Mar 2016 23:52:34 -0600 Subject: [PATCH] Prevent block entity and entity crashes --- .../minecraft/world/level/Level.java.patch | 34 ++++++++++++++----- .../level/block/entity/BlockEntity.java.patch | 20 +++++++++-- .../world/level/chunk/LevelChunk.java.patch | 16 +++++++-- 3 files changed, 55 insertions(+), 15 deletions(-) diff --git a/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch b/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch index 0252c7c635..209e29afaf 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/Level.java.patch @@ -226,7 +226,7 @@ + // Paper start - if loaded @Nullable -+ @Override + @Override + public final ChunkAccess getChunkIfLoadedImmediately(int x, int z) { + return ((ServerLevel)this).chunkSource.getChunkAtIfLoadedImmediately(x, z); + } @@ -258,7 +258,7 @@ + return chunk == null ? null : chunk.getFluidState(blockposition); + } + - @Override ++ @Override public ChunkAccess getChunk(int chunkX, int chunkZ, ChunkStatus leastStatus, boolean create) { + // Paper end ChunkAccess ichunkaccess = this.getChunkSource().getChunk(chunkX, chunkZ, leastStatus, create); @@ -383,14 +383,14 @@ + + if ((i & 2) != 0 && (!this.isClientSide || (i & 4) == 0) && (this.isClientSide || chunk == null || (chunk.getFullStatus() != null && chunk.getFullStatus().isOrAfter(FullChunkStatus.BLOCK_TICKING)))) { // allow chunk to be null here as chunk.isReady() is false when we send our notification during block placement + this.sendBlockUpdated(blockposition, iblockdata1, iblockdata, i); - } ++ } + + if ((i & 1) != 0) { + this.blockUpdated(blockposition, iblockdata1.getBlock()); + if (!this.isClientSide && iblockdata.hasAnalogOutputSignal()) { + this.updateNeighbourForOutputSignal(blockposition, newBlock.getBlock()); + } -+ } + } + + if ((i & 16) == 0 && j > 0) { + int k = i & -34; @@ -470,7 +470,7 @@ } else if (flag && this.shouldTickBlocksAt(tickingblockentity.getPos())) { tickingblockentity.tick(); } -@@ -461,6 +720,7 @@ +@@ -461,17 +720,18 @@ this.tickingBlockEntities = false; gameprofilerfiller.pop(); @@ -478,6 +478,22 @@ } public void guardEntityTick(Consumer tickConsumer, T entity) { + try { + tickConsumer.accept(entity); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Entity being ticked"); +- +- entity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent block entity and entity crashes ++ final String msg = String.format("Entity threw exception at %s:%s,%s,%s", entity.level().getWorld().getName(), entity.getX(), entity.getY(), entity.getZ()); ++ MinecraftServer.LOGGER.error(msg, throwable); ++ entity.discard(org.bukkit.event.entity.EntityRemoveEvent.Cause.DISCARD); ++ // Paper end - Prevent block entity and entity crashes + } + } + @@ -510,13 +770,29 @@ @Nullable @Override @@ -485,8 +501,8 @@ - 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)) { @@ -494,8 +510,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(); diff --git a/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch b/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch index 38f32457ea..615c1970ee 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/block/entity/BlockEntity.java.patch @@ -50,7 +50,21 @@ return nbttagcompound; } -@@ -263,13 +287,19 @@ +@@ -234,7 +258,12 @@ + public void fillCrashReportCategory(CrashReportCategory crashReportSection) { + crashReportSection.setDetail("Name", this::getNameForReporting); + if (this.level != null) { +- CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.getBlockState()); ++ // Paper start - Prevent block entity and entity crashes ++ BlockState block = this.getBlockState(); ++ if (block != null) { ++ CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, block); ++ } ++ // Paper end - Prevent block entity and entity crashes + CrashReportCategory.populateBlockDetails(crashReportSection, this.level, this.worldPosition, this.level.getBlockState(this.worldPosition)); + } + } +@@ -263,13 +292,19 @@ } public final void applyComponents(DataComponentMap defaultComponents, DataComponentPatch components) { @@ -72,7 +86,7 @@ @Nullable @Override public T get(DataComponentType type) { -@@ -284,9 +314,13 @@ +@@ -284,9 +319,13 @@ } }); Objects.requireNonNull(set); @@ -87,7 +101,7 @@ } protected void collectImplicitComponents(DataComponentMap.Builder builder) {} -@@ -321,6 +355,15 @@ +@@ -321,6 +360,15 @@ } } diff --git a/paper-server/patches/sources/net/minecraft/world/level/chunk/LevelChunk.java.patch b/paper-server/patches/sources/net/minecraft/world/level/chunk/LevelChunk.java.patch index ee4f0e5883..52e05f8c93 100644 --- a/paper-server/patches/sources/net/minecraft/world/level/chunk/LevelChunk.java.patch +++ b/paper-server/patches/sources/net/minecraft/world/level/chunk/LevelChunk.java.patch @@ -322,10 +322,20 @@ this.ticker = blockentityticker; } -@@ -872,6 +993,7 @@ +@@ -867,11 +988,12 @@ - this.blockEntity.fillCrashReportCategory(crashreportsystemdetails); - throw new ReportedException(crashreport); + gameprofilerfiller.pop(); + } catch (Throwable throwable) { +- CrashReport crashreport = CrashReport.forThrowable(throwable, "Ticking block entity"); +- CrashReportCategory crashreportsystemdetails = crashreport.addCategory("Block entity being ticked"); +- +- this.blockEntity.fillCrashReportCategory(crashreportsystemdetails); +- throw new ReportedException(crashreport); ++ // Paper start - Prevent block entity and entity crashes ++ final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ()); ++ net.minecraft.server.MinecraftServer.LOGGER.error(msg, throwable); ++ LevelChunk.this.removeBlockEntity(this.getPos()); ++ // Paper end - Prevent block entity and entity crashes + // Spigot start } }