mirror of
https://github.com/PaperMC/Paper.git
synced 2024-11-22 18:45:54 +01:00
89d51d5f29
Because this exploit has been widely known for years and has not been fixed by Mojang, we decided that it was worth allowing people to toggle it on/off due to how easy it is to make it configurable. It should be noted that this decision does not promise all future exploits will be configurable.
170 lines
11 KiB
Diff
170 lines
11 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/net/minecraft/world/level/Explosion.java b/src/main/java/net/minecraft/world/level/Explosion.java
|
|
index 217018dbdd78af4b89d9d4e7154956593dfa8dae..093c814d6835f20b1208236db96bb40b4611936c 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Explosion.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Explosion.java
|
|
@@ -191,6 +191,7 @@ public class Explosion {
|
|
for (float f1 = 0.3F; f > 0.0F; f -= 0.22500001F) {
|
|
BlockPos blockposition = BlockPos.containing(d4, d5, d6);
|
|
BlockState iblockdata = this.level.getBlockState(blockposition);
|
|
+ if (!iblockdata.isDestroyable()) continue; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
|
|
FluidState fluid = iblockdata.getFluidState(); // Paper - Perf: Optimize call to getFluid for explosions
|
|
|
|
if (!this.level.isInWorldBounds(blockposition)) {
|
|
diff --git a/src/main/java/net/minecraft/world/level/Level.java b/src/main/java/net/minecraft/world/level/Level.java
|
|
index 8485ee703f9c18557818ff735001f02e2d119604..5bf0cc83faf973b0072b06b7ec2f02b3ecda8a9b 100644
|
|
--- a/src/main/java/net/minecraft/world/level/Level.java
|
|
+++ b/src/main/java/net/minecraft/world/level/Level.java
|
|
@@ -540,6 +540,10 @@ public abstract class Level implements LevelAccessor, AutoCloseable {
|
|
public boolean setBlock(BlockPos pos, BlockState state, int flags, int maxUpdateDepth) {
|
|
// CraftBukkit start - tree generation
|
|
if (this.captureTreeGeneration) {
|
|
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
|
|
+ BlockState type = getBlockState(pos);
|
|
+ if (!type.isDestroyable()) return false;
|
|
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
|
|
CraftBlockState blockstate = this.capturedBlockStates.get(pos);
|
|
if (blockstate == null) {
|
|
blockstate = CapturedBlockState.getTreeBlockState(this, pos, flags);
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
|
index 6896d46fce2e466ebee23ac2dc00312ec1beefdb..b60a52788e73de3dcb086c1a4628466b25c9d3ef 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
|
@@ -90,6 +90,19 @@ public class Block extends BlockBehaviour implements ItemLike {
|
|
protected final StateDefinition<Block, BlockState> stateDefinition;
|
|
private BlockState defaultBlockState;
|
|
// Paper start
|
|
+ public final boolean isDestroyable() {
|
|
+ return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
|
|
+ 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/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
|
index 3dfe79684f662ac7cae4583bfe03a633438b4df7..be74adc86f0ca467f3b59e7b57fd47a8f381d86e 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
|
@@ -212,6 +212,12 @@ public class PistonBaseBlock extends DirectionalBlock {
|
|
@Override
|
|
public boolean triggerEvent(BlockState state, Level world, BlockPos pos, int type, int data) {
|
|
Direction enumdirection = (Direction) state.getValue(PistonBaseBlock.FACING);
|
|
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; prevent retracting when we're facing the wrong way (we were replaced before retraction could occur)
|
|
+ Direction directionQueuedAs = Direction.from3DDataValue(data & 7); // Paper - copied from below
|
|
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits && enumdirection != directionQueuedAs) {
|
|
+ return false;
|
|
+ }
|
|
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
|
|
BlockState iblockdata1 = (BlockState) state.setValue(PistonBaseBlock.EXTENDED, true);
|
|
|
|
if (!world.isClientSide) {
|
|
@@ -252,7 +258,7 @@ public class PistonBaseBlock extends DirectionalBlock {
|
|
}
|
|
// Paper end - Fix sticky pistons and BlockPistonRetractEvent
|
|
world.setBlock(pos, iblockdata2, 20);
|
|
- world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true));
|
|
+ world.setBlockEntity(MovingPistonBlock.newMovingBlockEntity(pos, iblockdata2, (BlockState) this.defaultBlockState().setValue(PistonBaseBlock.FACING, Direction.from3DDataValue(data & 7)), enumdirection, false, true)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed; diff on change
|
|
world.blockUpdated(pos, iblockdata2.getBlock());
|
|
iblockdata2.updateNeighbourShapes(world, pos, 2);
|
|
if (this.isSticky) {
|
|
@@ -288,7 +294,14 @@ public class PistonBaseBlock extends DirectionalBlock {
|
|
}
|
|
}
|
|
} else {
|
|
- world.removeBlock(pos.relative(enumdirection), false);
|
|
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed; fix headless pistons breaking blocks
|
|
+ BlockPos headPos = pos.relative(enumdirection);
|
|
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits || world.getBlockState(headPos) == Blocks.PISTON_HEAD.defaultBlockState().setValue(FACING, enumdirection)) { // double check to make sure we're not a headless piston.
|
|
+ world.removeBlock(headPos, false);
|
|
+ } else {
|
|
+ ((ServerLevel) world).getChunkSource().blockChanged(headPos); // ... fix client desync
|
|
+ }
|
|
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
|
|
}
|
|
|
|
world.playSound((Player) null, pos, SoundEvents.PISTON_CONTRACT, SoundSource.BLOCKS, 0.5F, world.random.nextFloat() * 0.15F + 0.6F);
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
index e28ac8f7960f648099e5f3607530a406c72e5056..e493b34aa8726ed48f8e5db2ae8ea561cc5b1f75 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/state/BlockBehaviour.java
|
|
@@ -189,7 +189,7 @@ public abstract class BlockBehaviour implements FeatureElement {
|
|
/** @deprecated */
|
|
@Deprecated
|
|
public void onExplosionHit(BlockState state, Level world, BlockPos pos, Explosion explosion, BiConsumer<ItemStack, BlockPos> stackMerger) {
|
|
- if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK) {
|
|
+ if (!state.isAir() && explosion.getBlockInteraction() != Explosion.BlockInteraction.TRIGGER_BLOCK && state.isDestroyable()) { // Paper - Protect Bedrock and End Portal/Frames from being destroyed
|
|
Block block = state.getBlock();
|
|
boolean flag = explosion.getIndirectSourceEntity() instanceof Player;
|
|
|
|
@@ -285,7 +285,7 @@ public abstract class BlockBehaviour implements FeatureElement {
|
|
/** @deprecated */
|
|
@Deprecated
|
|
public boolean canBeReplaced(BlockState state, BlockPlaceContext context) {
|
|
- return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem()));
|
|
+ return state.canBeReplaced() && (context.getItemInHand().isEmpty() || !context.getItemInHand().is(this.asItem())) && (state.isDestroyable() || (context.getPlayer() != null && context.getPlayer().getAbilities().instabuild)); // Paper - Protect Bedrock and End Portal/Frames from being destroyed
|
|
}
|
|
|
|
/** @deprecated */
|
|
@@ -965,6 +965,12 @@ public abstract class BlockBehaviour implements FeatureElement {
|
|
return this.legacySolid;
|
|
}
|
|
|
|
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
|
|
+ public final boolean isDestroyable() {
|
|
+ return getBlock().isDestroyable();
|
|
+ }
|
|
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
|
|
+
|
|
public boolean isValidSpawn(BlockGetter world, BlockPos pos, EntityType<?> type) {
|
|
return this.getBlock().properties.isValidSpawn.test(this.asState(), world, pos, type);
|
|
}
|
|
@@ -1068,7 +1074,7 @@ public abstract class BlockBehaviour implements FeatureElement {
|
|
}
|
|
|
|
public PushReaction getPistonPushReaction() {
|
|
- return this.pushReaction;
|
|
+ return !this.isDestroyable() ? PushReaction.BLOCK : this.pushReaction; // Paper - Protect Bedrock and End Portal/Frames from being destroyed
|
|
}
|
|
|
|
public boolean isSolidRender(BlockGetter world, BlockPos pos) {
|
|
diff --git a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
|
|
index afdd4ecbff21e2172b390bcbdf74f3c1bbddafcc..bb739f8584dd3847152314aa995800f51907da2f 100644
|
|
--- a/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
|
|
+++ b/src/main/java/net/minecraft/world/level/portal/PortalForcer.java
|
|
@@ -221,6 +221,13 @@ public class PortalForcer {
|
|
for (int j = -1; j < 3; ++j) {
|
|
for (int k = -1; k < 4; ++k) {
|
|
temp.setWithOffset(pos, portalDirection.getStepX() * j + enumdirection1.getStepX() * distanceOrthogonalToPortal, k, portalDirection.getStepZ() * j + enumdirection1.getStepZ() * distanceOrthogonalToPortal);
|
|
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
|
|
+ if (!io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits) {
|
|
+ if (!this.level.getBlockState(temp).isDestroyable()) {
|
|
+ return false;
|
|
+ }
|
|
+ }
|
|
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
|
|
if (k < 0 && !this.level.getBlockState(temp).isSolid()) {
|
|
return false;
|
|
}
|