PaperMC/Spigot-Server-Patches/0490-Protect-Bedrock-and-End-Portal-Frames-from-being-des.patch
Prof-Bloodstone 42433c2626
Updated Upstream (Bukkit/CraftBukkit) (#3980)
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

Bukkit Changes:
09f10fd9 SPIGOT-5950: Add PrepareSmithingEvent event

CraftBukkit Changes:
7c03d257 SPIGOT-6011: End Gateways do not work on Non-Main End Worlds
d492e363 SPIGOT-6015: Small Armor Stand doesn't drop items
5db13eea SPIGOT-5950: Add PrepareSmithingEvent event
2020-07-22 19:35:44 -04:00

168 lines
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 ac01d492872fde6df2b7113005457c714b91fe44..754e2f84526ce9d9eab1a5a4180be643d030b70a 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 4f9c6b25f152b348a00dadf4b8f58ec3adc3476e..81725611d5b8c10c05d561984f92dc67349900ec 100644
--- a/src/main/java/net/minecraft/server/Block.java
+++ b/src/main/java/net/minecraft/server/Block.java
@@ -25,6 +25,14 @@ 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.MOVING_PISTON; // try to prevent creation of headless pistons
+ }
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 aa4bfc9fe8e917c1c19838b0a7b045a11fc9300b..ff770a3b0e5c4fcccc498ecca51dad9863b0fe0e 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 c068a4115e3b82f4886d822d2472e8b522946674..6b1253fe7e8d4bb71d4d19c063d3e84c167c4d7b 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 22a19e761fdec68cc9405988b977021a8b6398eb..e408ec8c645e9ceb278a13a5b0de8ecf57f3929e 100644
--- a/src/main/java/net/minecraft/server/Explosion.java
+++ b/src/main/java/net/minecraft/server/Explosion.java
@@ -124,6 +124,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.k.a(this, this.world, blockposition, iblockdata, fluid);
@@ -277,7 +278,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 302b0eda863dcaf7eeea7b0e1820929a46f44c54..5f81997db78c989e942351e80a0d2558f4b90fcd 100644
--- a/src/main/java/net/minecraft/server/World.java
+++ b/src/main/java/net/minecraft/server/World.java
@@ -406,6 +406,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);