654b792caf
Upstream has released updates that appears to apply and compile correctly. This update has not been tested by PaperMC and as with ANY update, please do your own testing CraftBukkit Changes:a339310c
#755: Fix NPE when calling getInventory() for virtual EnderChests2577f9bf
Increase outdated build delay1dabfdc8
#754: Fix pre-1.16 serialized SkullMeta being broken on 1.16+, losing textures
174 Zeilen
10 KiB
Diff
174 Zeilen
10 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: Aikar <aikar@aikar.co>
|
|
Date: Wed, 13 May 2020 23:01:26 -0400
|
|
Subject: [PATCH] Protect Bedrock and End Portal/Frames from being destroyed
|
|
|
|
This fixes exploits that let players destroy bedrock by Pistons, explosions
|
|
and Mushrooom/Tree generation.
|
|
|
|
These blocks are designed to not be broken except by creative players/commands.
|
|
So protect them from a multitude of methods of destroying them.
|
|
|
|
A config is provided if you rather let players use these exploits, and let
|
|
them destroy the worlds End Portals and get on top of the nether easy.
|
|
|
|
diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
index 093605fe8e079d9ec973702c55ea6caddf0369f1..3d63215a855c71d257b18a247eb7f0b2d7908bce 100644
|
|
--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
+++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java
|
|
@@ -411,4 +411,17 @@ public class PaperConfig {
|
|
private static void midTickChunkTasks() {
|
|
midTickChunkTasks = getInt("settings.chunk-tasks-per-tick", midTickChunkTasks);
|
|
}
|
|
+
|
|
+ public static boolean allowBlockPermanentBreakingExploits = false;
|
|
+ private static void allowBlockPermanentBreakingExploits() {
|
|
+ if (config.contains("allow-perm-block-break-exploits")) {
|
|
+ allowBlockPermanentBreakingExploits = config.getBoolean("allow-perm-block-break-exploits", false);
|
|
+ config.set("allow-perm-block-break-exploits", null);
|
|
+ }
|
|
+
|
|
+ config.set("settings.unsupported-settings.allow-permanent-block-break-exploits-readme", "This setting controls if players should be able to break bedrock, end portals and other intended to be permanent blocks.");
|
|
+ allowBlockPermanentBreakingExploits = getBoolean("settings.unsupported-settings.allow-permanent-block-break-exploits", allowBlockPermanentBreakingExploits);
|
|
+
|
|
+ }
|
|
+
|
|
}
|
|
diff --git a/src/main/java/net/minecraft/server/Block.java b/src/main/java/net/minecraft/server/Block.java
|
|
index b364ceafb4c3412b0d11b3b2e8b4321ed96769bb..a45ceff9ff970b996b2767379a2ecd4693f52d3a 100644
|
|
--- a/src/main/java/net/minecraft/server/Block.java
|
|
+++ b/src/main/java/net/minecraft/server/Block.java
|
|
@@ -23,6 +23,19 @@ public class Block extends BlockBase implements IMaterial {
|
|
protected final BlockStateList<Block, IBlockData> blockStateList;
|
|
private IBlockData blockData;
|
|
// Paper start
|
|
+ public final boolean isDestroyable() {
|
|
+ return com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits ||
|
|
+ this != Blocks.BEDROCK &&
|
|
+ this != Blocks.END_PORTAL_FRAME &&
|
|
+ this != Blocks.END_PORTAL &&
|
|
+ this != Blocks.END_GATEWAY &&
|
|
+ this != Blocks.COMMAND_BLOCK &&
|
|
+ this != Blocks.REPEATING_COMMAND_BLOCK &&
|
|
+ this != Blocks.CHAIN_COMMAND_BLOCK &&
|
|
+ this != Blocks.BARRIER &&
|
|
+ this != Blocks.STRUCTURE_BLOCK &&
|
|
+ this != Blocks.JIGSAW;
|
|
+ }
|
|
public co.aikar.timings.Timing timing;
|
|
public co.aikar.timings.Timing getTiming() {
|
|
if (timing == null) {
|
|
diff --git a/src/main/java/net/minecraft/server/BlockBase.java b/src/main/java/net/minecraft/server/BlockBase.java
|
|
index eeeffa989e7024dc345fafda822e0b29f928a759..b6081d259444f0d78736802b5d565faf776e825f 100644
|
|
--- a/src/main/java/net/minecraft/server/BlockBase.java
|
|
+++ b/src/main/java/net/minecraft/server/BlockBase.java
|
|
@@ -138,7 +138,7 @@ public abstract class BlockBase {
|
|
|
|
@Deprecated
|
|
public boolean a(IBlockData iblockdata, BlockActionContext blockactioncontext) {
|
|
- return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem());
|
|
+ return this.material.isReplaceable() && (blockactioncontext.getItemStack().isEmpty() || blockactioncontext.getItemStack().getItem() != this.getItem()) && (iblockdata.isDestroyable() || (blockactioncontext.getEntity() != null && blockactioncontext.getEntity().abilities.canInstantlyBuild)); // Paper
|
|
}
|
|
|
|
@Deprecated
|
|
@@ -342,7 +342,11 @@ public abstract class BlockBase {
|
|
public Block getBlock() {
|
|
return (Block) this.c;
|
|
}
|
|
-
|
|
+ // Paper start
|
|
+ public final boolean isDestroyable() {
|
|
+ return getBlock().isDestroyable();
|
|
+ }
|
|
+ // Paper end
|
|
public Material getMaterial() {
|
|
return this.g;
|
|
}
|
|
@@ -432,7 +436,7 @@ public abstract class BlockBase {
|
|
}
|
|
|
|
public EnumPistonReaction getPushReaction() {
|
|
- return this.getBlock().getPushReaction(this.p());
|
|
+ return !isDestroyable() ? EnumPistonReaction.BLOCK : this.getBlock().getPushReaction(this.p()); // Paper
|
|
}
|
|
|
|
public boolean i(IBlockAccess iblockaccess, BlockPosition blockposition) {
|
|
diff --git a/src/main/java/net/minecraft/server/BlockPiston.java b/src/main/java/net/minecraft/server/BlockPiston.java
|
|
index 417d1a6c3dbd23905672a847939d92a953bbc91c..0bab7dfb053c1aa92f5417c25fed5484e09bbec3 100644
|
|
--- a/src/main/java/net/minecraft/server/BlockPiston.java
|
|
+++ b/src/main/java/net/minecraft/server/BlockPiston.java
|
|
@@ -165,6 +165,12 @@ public class BlockPiston extends BlockDirectional {
|
|
@Override
|
|
public boolean a(IBlockData iblockdata, World world, BlockPosition blockposition, int i, int j) {
|
|
EnumDirection enumdirection = (EnumDirection) iblockdata.get(BlockPiston.FACING);
|
|
+ // Paper start - prevent retracting when we're facing the wrong way (we were replaced before retraction could occur)
|
|
+ EnumDirection directionQueuedAs = EnumDirection.fromType1(j & 7); // Paper - copied from below
|
|
+ if (!com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits && enumdirection != directionQueuedAs) {
|
|
+ return false;
|
|
+ }
|
|
+ // Paper end - prevent retracting when we're facing the wrong way
|
|
|
|
if (!world.isClientSide) {
|
|
boolean flag = this.a(world, blockposition, enumdirection);
|
|
@@ -196,7 +202,7 @@ public class BlockPiston extends BlockDirectional {
|
|
IBlockData iblockdata1 = (IBlockData) ((IBlockData) Blocks.MOVING_PISTON.getBlockData().set(BlockPistonMoving.a, enumdirection)).set(BlockPistonMoving.b, this.sticky ? BlockPropertyPistonType.STICKY : BlockPropertyPistonType.DEFAULT);
|
|
|
|
world.setTypeAndData(blockposition, iblockdata1, 20);
|
|
- world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true));
|
|
+ world.setTileEntity(blockposition, BlockPistonMoving.a((IBlockData) this.getBlockData().set(BlockPiston.FACING, EnumDirection.fromType1(j & 7)), enumdirection, false, true)); // Paper - diff on change, j is facing direction - copy this above
|
|
world.update(blockposition, iblockdata1.getBlock());
|
|
iblockdata1.a(world, blockposition, 2);
|
|
if (this.sticky) {
|
|
@@ -225,7 +231,14 @@ public class BlockPiston extends BlockDirectional {
|
|
}
|
|
}
|
|
} else {
|
|
- world.a(blockposition.shift(enumdirection), false);
|
|
+ // Paper start - fix headless pistons breaking blocks
|
|
+ BlockPosition headPos = blockposition.shift(enumdirection);
|
|
+ if (com.destroystokyo.paper.PaperConfig.allowBlockPermanentBreakingExploits || world.getType(headPos) == Blocks.PISTON_HEAD.getBlockData().set(FACING, enumdirection)) { // double check to make sure we're not a headless piston.
|
|
+ world.setAir(headPos, false);
|
|
+ } else {
|
|
+ ((WorldServer)world).getChunkProvider().flagDirty(headPos); // ... fix client desync
|
|
+ }
|
|
+ // Paper end - fix headless pistons breaking blocks
|
|
}
|
|
|
|
world.playSound((EntityHuman) null, blockposition, SoundEffects.BLOCK_PISTON_CONTRACT, SoundCategory.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F);
|
|
diff --git a/src/main/java/net/minecraft/server/Explosion.java b/src/main/java/net/minecraft/server/Explosion.java
|
|
index 9823fb5eebbfee026d3173c81368cf6e3e901f92..f263177e3d41fd5720c430be3dcb1b5e2adb0134 100644
|
|
--- a/src/main/java/net/minecraft/server/Explosion.java
|
|
+++ b/src/main/java/net/minecraft/server/Explosion.java
|
|
@@ -125,6 +125,7 @@ public class Explosion {
|
|
for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
|
|
BlockPosition blockposition = new BlockPosition(d4, d5, d6);
|
|
IBlockData iblockdata = this.world.getType(blockposition);
|
|
+ if (!iblockdata.isDestroyable()) continue; // Paper
|
|
Fluid fluid = iblockdata.getFluid(); // Paper
|
|
Optional<Float> optional = this.l.a(this, this.world, blockposition, iblockdata, fluid);
|
|
|
|
@@ -278,7 +279,7 @@ public class Explosion {
|
|
IBlockData iblockdata = this.world.getType(blockposition);
|
|
Block block = iblockdata.getBlock();
|
|
|
|
- if (!iblockdata.isAir()) {
|
|
+ if (!iblockdata.isAir() && iblockdata.isDestroyable()) { // Paper
|
|
BlockPosition blockposition1 = blockposition.immutableCopy();
|
|
|
|
this.world.getMethodProfiler().enter("explosion_blocks");
|
|
diff --git a/src/main/java/net/minecraft/server/World.java b/src/main/java/net/minecraft/server/World.java
|
|
index 54403c34e256d5264111048806b42404a9705b44..fd761c57980f6030f270a44f6492a00f12749703 100644
|
|
--- a/src/main/java/net/minecraft/server/World.java
|
|
+++ b/src/main/java/net/minecraft/server/World.java
|
|
@@ -362,6 +362,10 @@ public abstract class World implements GeneratorAccess, AutoCloseable {
|
|
public boolean a(BlockPosition blockposition, IBlockData iblockdata, int i, int j) {
|
|
// CraftBukkit start - tree generation
|
|
if (this.captureTreeGeneration) {
|
|
+ // Paper start
|
|
+ IBlockData type = getType(blockposition);
|
|
+ if (!type.isDestroyable()) return false;
|
|
+ // Paper end
|
|
CraftBlockState blockstate = capturedBlockStates.get(blockposition);
|
|
if (blockstate == null) {
|
|
blockstate = CapturedBlockState.getTreeBlockState(this, blockposition, i);
|