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.
This commit is contained in:
@@ -1,11 +1,30 @@
|
||||
--- a/net/minecraft/world/level/block/Block.java
|
||||
+++ b/net/minecraft/world/level/block/Block.java
|
||||
@@ -292,15 +292,41 @@
|
||||
});
|
||||
state.spawnAfterBreak((ServerLevel) world, pos, ItemStack.EMPTY, true);
|
||||
}
|
||||
+
|
||||
@@ -88,6 +88,21 @@
|
||||
public static final int UPDATE_LIMIT = 512;
|
||||
protected final StateDefinition<Block, BlockState> stateDefinition;
|
||||
private BlockState defaultBlockState;
|
||||
+ // Paper start - Protect Bedrock and End Portal/Frames from being destroyed
|
||||
+ public final boolean isDestroyable() {
|
||||
+ return io.papermc.paper.configuration.GlobalConfiguration.get().unsupportedSettings.allowPermanentBlockBreakExploits ||
|
||||
+ this != Blocks.BARRIER &&
|
||||
+ 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.STRUCTURE_BLOCK &&
|
||||
+ this != Blocks.JIGSAW;
|
||||
+ }
|
||||
+ // Paper end - Protect Bedrock and End Portal/Frames from being destroyed
|
||||
@Nullable
|
||||
private Item item;
|
||||
private static final int CACHE_SIZE = 256;
|
||||
@@ -295,12 +310,38 @@
|
||||
|
||||
}
|
||||
|
||||
+ // Paper start - Add BlockBreakBlockEvent
|
||||
+ public static boolean dropResources(BlockState state, LevelAccessor levelAccessor, BlockPos pos, @Nullable BlockEntity blockEntity, BlockPos source) {
|
||||
@@ -25,9 +44,9 @@
|
||||
+ block.popExperience(serverLevel, pos, event.getExpToDrop()); // Paper - Properly handle xp dropping
|
||||
+ }
|
||||
+ return true;
|
||||
}
|
||||
+ }
|
||||
+ // Paper end - Add BlockBreakBlockEvent
|
||||
|
||||
+
|
||||
public static void dropResources(BlockState state, Level world, BlockPos pos, @Nullable BlockEntity blockEntity, @Nullable Entity entity, ItemStack tool) {
|
||||
+ // Paper start - Properly handle xp dropping
|
||||
+ dropResources(state, world, pos, blockEntity, entity, tool, true);
|
||||
@@ -43,7 +62,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
@@ -340,7 +366,13 @@
|
||||
@@ -340,7 +381,13 @@
|
||||
ItemEntity entityitem = (ItemEntity) itemEntitySupplier.get();
|
||||
|
||||
entityitem.setDefaultPickUpDelay();
|
||||
@@ -58,7 +77,7 @@
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -348,8 +380,13 @@
|
||||
@@ -348,8 +395,13 @@
|
||||
}
|
||||
|
||||
public void popExperience(ServerLevel world, BlockPos pos, int size) {
|
||||
@@ -73,7 +92,7 @@
|
||||
}
|
||||
|
||||
}
|
||||
@@ -367,10 +404,18 @@
|
||||
@@ -367,10 +419,18 @@
|
||||
return this.defaultBlockState();
|
||||
}
|
||||
|
||||
@@ -94,7 +113,7 @@
|
||||
}
|
||||
|
||||
public void setPlacedBy(Level world, BlockPos pos, BlockState state, @Nullable LivingEntity placer, ItemStack itemStack) {}
|
||||
@@ -490,15 +535,35 @@
|
||||
@@ -490,15 +550,35 @@
|
||||
return this.builtInRegistryHolder;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,20 @@
|
||||
world.blockEvent(pos, this, b0, enumdirection.get3DDataValue());
|
||||
}
|
||||
|
||||
@@ -229,6 +248,13 @@
|
||||
@@ -197,6 +216,12 @@
|
||||
@Override
|
||||
protected 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) {
|
||||
@@ -229,8 +254,15 @@
|
||||
|
||||
BlockState iblockdata2 = (BlockState) ((BlockState) Blocks.MOVING_PISTON.defaultBlockState().setValue(MovingPistonBlock.FACING, enumdirection)).setValue(MovingPistonBlock.TYPE, this.isSticky ? PistonType.STICKY : PistonType.DEFAULT);
|
||||
|
||||
@@ -45,9 +58,12 @@
|
||||
+ }
|
||||
+ // 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));
|
||||
+ 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());
|
||||
@@ -255,6 +281,13 @@
|
||||
iblockdata2.updateNeighbourShapes(world, pos, 2);
|
||||
if (this.isSticky) {
|
||||
@@ -255,11 +287,25 @@
|
||||
if (type == 1 && !iblockdata3.isAir() && PistonBaseBlock.isPushable(iblockdata3, world, blockposition1, enumdirection.getOpposite(), false, enumdirection) && (iblockdata3.getPistonPushReaction() == PushReaction.NORMAL || iblockdata3.is(Blocks.PISTON) || iblockdata3.is(Blocks.STICKY_PISTON))) {
|
||||
this.moveBlocks(world, pos, enumdirection, false);
|
||||
} else {
|
||||
@@ -61,18 +77,31 @@
|
||||
world.removeBlock(pos.relative(enumdirection), false);
|
||||
}
|
||||
}
|
||||
@@ -335,7 +368,49 @@
|
||||
} 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);
|
||||
@@ -335,7 +381,49 @@
|
||||
BlockState[] aiblockdata = new BlockState[list.size() + list2.size()];
|
||||
Direction enumdirection1 = extend ? dir : dir.getOpposite();
|
||||
int i = 0;
|
||||
+ // CraftBukkit start
|
||||
+ final org.bukkit.block.Block bblock = world.getWorld().getBlockAt(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
||||
+
|
||||
+ final List<BlockPos> moved = pistonextendschecker.getToPush();
|
||||
+ final List<BlockPos> broken = pistonextendschecker.getToDestroy();
|
||||
+
|
||||
+ List<org.bukkit.block.Block> blocks = new AbstractList<org.bukkit.block.Block>() {
|
||||
+
|
||||
|
||||
+ @Override
|
||||
+ public int size() {
|
||||
+ return moved.size() + broken.size();
|
||||
@@ -111,7 +140,7 @@
|
||||
BlockPos blockposition3;
|
||||
int j;
|
||||
BlockState iblockdata1;
|
||||
@@ -345,7 +420,7 @@
|
||||
@@ -345,7 +433,7 @@
|
||||
iblockdata1 = world.getBlockState(blockposition3);
|
||||
BlockEntity tileentity = iblockdata1.hasBlockEntity() ? world.getBlockEntity(blockposition3) : null;
|
||||
|
||||
@@ -120,7 +149,7 @@
|
||||
world.setBlock(blockposition3, Blocks.AIR.defaultBlockState(), 18);
|
||||
world.gameEvent((Holder) GameEvent.BLOCK_DESTROY, blockposition3, GameEvent.Context.of(iblockdata1));
|
||||
if (!iblockdata1.is(BlockTags.FIRE)) {
|
||||
@@ -358,13 +433,25 @@
|
||||
@@ -358,13 +446,25 @@
|
||||
BlockState iblockdata2;
|
||||
|
||||
for (j = list.size() - 1; j >= 0; --j) {
|
||||
|
||||
@@ -37,6 +37,15 @@
|
||||
if (state.hasBlockEntity() && !state.is(newState.getBlock())) {
|
||||
world.removeBlockEntity(pos);
|
||||
}
|
||||
@@ -166,7 +178,7 @@
|
||||
}
|
||||
|
||||
protected void onExplosionHit(BlockState state, ServerLevel 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;
|
||||
|
||||
@@ -174,8 +186,10 @@
|
||||
BlockEntity tileentity = state.hasBlockEntity() ? world.getBlockEntity(pos) : null;
|
||||
LootParams.Builder lootparams_a = (new LootParams.Builder(world)).withParameter(LootContextParams.ORIGIN, Vec3.atCenterOf(pos)).withParameter(LootContextParams.TOOL, ItemStack.EMPTY).withOptionalParameter(LootContextParams.BLOCK_ENTITY, tileentity).withOptionalParameter(LootContextParams.THIS_ENTITY, explosion.getDirectSourceEntity());
|
||||
@@ -50,6 +59,15 @@
|
||||
}
|
||||
|
||||
state.spawnAfterBreak(world, pos, ItemStack.EMPTY, flag);
|
||||
@@ -243,7 +257,7 @@
|
||||
}
|
||||
|
||||
protected 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
|
||||
}
|
||||
|
||||
protected boolean canBeReplaced(BlockState state, Fluid fluid) {
|
||||
@@ -851,7 +865,15 @@
|
||||
this.spawnTerrainParticles = blockbase_info.spawnTerrainParticles;
|
||||
this.instrument = blockbase_info.instrument;
|
||||
@@ -81,7 +99,20 @@
|
||||
|
||||
this.legacySolid = this.calculateSolid();
|
||||
this.occlusionShape = this.canOcclude ? ((Block) this.owner).getOcclusionShape(this.asState()) : Shapes.empty();
|
||||
@@ -945,19 +969,19 @@
|
||||
@@ -925,6 +949,12 @@
|
||||
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);
|
||||
}
|
||||
@@ -945,19 +975,19 @@
|
||||
return this.occlusionShape;
|
||||
}
|
||||
|
||||
@@ -106,7 +137,15 @@
|
||||
return this.isAir;
|
||||
}
|
||||
|
||||
@@ -1035,7 +1059,7 @@
|
||||
@@ -1028,14 +1058,14 @@
|
||||
}
|
||||
|
||||
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() {
|
||||
return this.solidRender;
|
||||
}
|
||||
|
||||
@@ -115,24 +154,22 @@
|
||||
return this.canOcclude;
|
||||
}
|
||||
|
||||
@@ -1125,9 +1149,15 @@
|
||||
@@ -1125,7 +1155,13 @@
|
||||
}
|
||||
|
||||
public void onPlace(Level world, BlockPos pos, BlockState state, boolean notify) {
|
||||
- this.getBlock().onPlace(this.asState(), world, pos, state, notify);
|
||||
+ // CraftBukkit start
|
||||
+ this.onPlace(world, pos, state, notify, null);
|
||||
}
|
||||
|
||||
+ }
|
||||
+
|
||||
+ public void onPlace(Level world, BlockPos blockposition, BlockState iblockdata, boolean flag, @Nullable UseOnContext context) {
|
||||
+ this.getBlock().onPlace(this.asState(), world, blockposition, iblockdata, flag, context);
|
||||
+ // CraftBukkit end
|
||||
+ }
|
||||
+
|
||||
public void onRemove(Level world, BlockPos pos, BlockState state, boolean moved) {
|
||||
this.getBlock().onRemove(this.asState(), world, pos, state, moved);
|
||||
}
|
||||
@@ -1154,6 +1184,7 @@
|
||||
|
||||
public void onRemove(Level world, BlockPos pos, BlockState state, boolean moved) {
|
||||
@@ -1154,6 +1190,7 @@
|
||||
|
||||
public void spawnAfterBreak(ServerLevel world, BlockPos pos, ItemStack tool, boolean dropExperience) {
|
||||
this.getBlock().spawnAfterBreak(this.asState(), world, pos, tool, dropExperience);
|
||||
@@ -140,7 +177,7 @@
|
||||
}
|
||||
|
||||
public List<ItemStack> getDrops(LootParams.Builder builder) {
|
||||
@@ -1250,11 +1281,11 @@
|
||||
@@ -1250,11 +1287,11 @@
|
||||
return this.getBlock().builtInRegistryHolder().is(key);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user