Inconsistent with survival behavior
Code Analysis:
Code analysis by @unknown can be found in this comment.
Linked issues
relates to 2
Attachments
Comments 18
Code Analysis:
The following is based on a decompiled version of Minecraft 1.20.1 using MCP-Reborn.
net.minecraft.server.level.ServerPlayerGameMode.java // Original
public class ServerPlayerGameMode {
...
public boolean destroyBlock(BlockPos p_9281_) {
BlockState blockstate = this.level.getBlockState(p_9281_);
if (!this.player.getMainHandItem().getItem().canAttackBlock(blockstate, this.level, p_9281_, this.player)) {
return false;
} else {
BlockEntity blockentity = this.level.getBlockEntity(p_9281_);
Block block = blockstate.getBlock();
if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) {
this.level.sendBlockUpdated(p_9281_, blockstate, blockstate, 3);
return false;
} else if (this.player.blockActionRestricted(this.level, p_9281_, this.gameModeForPlayer)) {
return false;
} else {
block.playerWillDestroy(this.level, p_9281_, blockstate, this.player);
boolean flag = this.level.removeBlock(p_9281_, false);
if (flag) {
block.destroy(this.level, p_9281_, blockstate);
}
if (this.isCreative()) {
return true;
} else {
ItemStack itemstack = this.player.getMainHandItem();
ItemStack itemstack1 = itemstack.copy();
boolean flag1 = this.player.hasCorrectToolForDrops(blockstate);
itemstack.mineBlock(this.level, blockstate, p_9281_, this.player);
if (flag && flag1) {
block.playerDestroy(this.level, this.player, p_9281_, blockstate, blockentity, itemstack1);
}
return true;
}
}
}
}
...
}
As you can see, there is a piece of code that checks if the player is in creative (this.isCreative()
), if they are, then we return and do nothing about the block's state. Therefore this looks pretty intentional as a "feature" for Minecraft.
But, it looks like this bug report seems to be an official Mojang bug, so I will write a code analysis and fix to solve this problem.
Temporary Fix:
net.minecraft.server.level.ServerPlayerGameMode.java // Updated
public class ServerPlayerGameMode {
...
public boolean destroyBlock(BlockPos p_9281_) {
BlockState blockstate = this.level.getBlockState(p_9281_);
if (!this.player.getMainHandItem().getItem().canAttackBlock(blockstate, this.level, p_9281_, this.player)) {
return false;
} else {
BlockEntity blockentity = this.level.getBlockEntity(p_9281_);
Block block = blockstate.getBlock();
if (block instanceof GameMasterBlock && !this.player.canUseGameMasterBlocks()) {
this.level.sendBlockUpdated(p_9281_, blockstate, blockstate, 3);
return false;
} else if (this.player.blockActionRestricted(this.level, p_9281_, this.gameModeForPlayer)) {
return false;
} else {
block.playerWillDestroy(this.level, p_9281_, blockstate, this.player);
boolean flag = this.level.removeBlock(p_9281_, false);
if (flag) {
block.destroy(this.level, p_9281_, blockstate);
}
ItemStack itemstack = this.player.getMainHandItem();
ItemStack itemstack1 = itemstack.copy();
boolean flag1 = this.player.hasCorrectToolForDrops(blockstate);
itemstack.mineBlock(this.level, blockstate, p_9281_, this.player);
if (flag && flag1) {
block.playerDestroy(this.level, this.player, p_9281_, blockstate, blockentity, itemstack1);
}
return true;
}
}
}
...
}
In the code structure above, we simply remove the this.isCreative()
check so logic of the block's state will update even in creative.
WARNING: This code analysis and fix will allow creative players to drop item(s) upon breaking the block.
Hi there!
This is more than likely intended, as otherwise, there would be no way (except for commands) to remove ice in creative mode without it flooding an area.
Say you were building on a creative world with cheats disabled. You start placing down ice blocks in an item transporting system, but then realize that it is packed ice you should be using. You start breaking the ice blocks (the only thing you can do), but then your complex redstone contraption beneath it is now flooded.
Creative players should not have to use silk touch tools to be able to remove ice without creating water.