0faaa7da92
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: 19b7b7bd #561: Add clear weather World API 5929c808 #552: Add the ability to retrieve hit, step, fall, and other sounds from blocks. CraftBukkit Changes: e1ebdd92 #771: Add clear weather World API 424598d2 #752: Add the ability to retrieve hit, step, fall, and other sounds from blocks.
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 6f0c5a2d33001f59e560ec239c0edbd32de84ed8..ac6b291c103c432fdced603674345096326a9efe 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 62e7c6cb1b363d1ee626c4405f8c30e74aba03e9..1c06647fb6f8e757ca7a737a371cb1dec2aeb80e 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 a552cc5bebb1a70db2e679a514769d0ad791ad68..72de544c0782e4daff222a0ca04e5bc870cf148c 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 b479a25044ecf8c1a791729d643cf8dc90193b2b..8d59391befcbc2542a79758d2021ef51df59d815 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);
|