diff --git a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java index c6f800e10..98ba9e8a9 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/ModRegistry.java @@ -24,12 +24,14 @@ import dan200.computercraft.shared.common.ClearColourRecipe; import dan200.computercraft.shared.common.ColourableRecipe; import dan200.computercraft.shared.common.DefaultBundledRedstoneProvider; import dan200.computercraft.shared.common.HeldItemMenu; +import dan200.computercraft.shared.computer.blocks.CommandComputerBlock; import dan200.computercraft.shared.computer.blocks.CommandComputerBlockEntity; import dan200.computercraft.shared.computer.blocks.ComputerBlock; import dan200.computercraft.shared.computer.blocks.ComputerBlockEntity; import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.inventory.ComputerMenuWithoutInventory; import dan200.computercraft.shared.computer.inventory.ViewComputerMenu; +import dan200.computercraft.shared.computer.items.CommandComputerItem; import dan200.computercraft.shared.computer.items.ComputerItem; import dan200.computercraft.shared.computer.recipe.ComputerUpgradeRecipe; import dan200.computercraft.shared.data.BlockNamedEntityLootCondition; @@ -139,7 +141,7 @@ public final class ModRegistry { public static final RegistryEntry> COMPUTER_ADVANCED = REGISTRY.register("computer_advanced", () -> new ComputerBlock<>(computerProperties().mapColor(MapColor.GOLD), ComputerFamily.ADVANCED, BlockEntities.COMPUTER_ADVANCED)); - public static final RegistryEntry> COMPUTER_COMMAND = REGISTRY.register("computer_command", () -> new ComputerBlock<>( + public static final RegistryEntry> COMPUTER_COMMAND = REGISTRY.register("computer_command", () -> new CommandComputerBlock<>( computerProperties().strength(-1, 6000000.0F), ComputerFamily.COMMAND, BlockEntities.COMPUTER_COMMAND )); @@ -222,7 +224,7 @@ public final class ModRegistry { public static final RegistryEntry COMPUTER_NORMAL = ofBlock(Blocks.COMPUTER_NORMAL, ComputerItem::new); public static final RegistryEntry COMPUTER_ADVANCED = ofBlock(Blocks.COMPUTER_ADVANCED, ComputerItem::new); - public static final RegistryEntry COMPUTER_COMMAND = ofBlock(Blocks.COMPUTER_COMMAND, ComputerItem::new); + public static final RegistryEntry COMPUTER_COMMAND = ofBlock(Blocks.COMPUTER_COMMAND, CommandComputerItem::new); public static final RegistryEntry POCKET_COMPUTER_NORMAL = REGISTRY.register("pocket_computer_normal", () -> new PocketComputerItem(properties().stacksTo(1), ComputerFamily.NORMAL)); diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlock.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlock.java new file mode 100644 index 000000000..43606df51 --- /dev/null +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlock.java @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.shared.computer.blocks; + +import dan200.computercraft.shared.computer.core.ComputerFamily; +import dan200.computercraft.shared.platform.RegistryEntry; +import net.minecraft.world.level.block.GameMasterBlock; +import net.minecraft.world.level.block.entity.BlockEntityType; + +/** + * A subclass of {@link ComputerBlock} which implements {@link GameMasterBlock}, to prevent players breaking it without + * permission. + * + * @param The type of the computer block entity. + * @see dan200.computercraft.shared.computer.items.CommandComputerItem + */ +public class CommandComputerBlock extends ComputerBlock implements GameMasterBlock { + public CommandComputerBlock(Properties settings, ComputerFamily family, RegistryEntry> type) { + super(settings, family, type); + } +} diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlockEntity.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlockEntity.java index 86a4e8454..93a9d0113 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlockEntity.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/blocks/CommandComputerBlockEntity.java @@ -104,11 +104,15 @@ public class CommandComputerBlockEntity extends ComputerBlockEntity { if (server == null || !server.isCommandBlockEnabled()) { player.displayClientMessage(Component.translatable("advMode.notEnabled"), true); return false; - } else if (Config.commandRequireCreative ? !player.canUseGameMasterBlocks() : !server.getPlayerList().isOp(player.getGameProfile())) { + } else if (!canUseCommandBlock(player)) { player.displayClientMessage(Component.translatable("advMode.notAllowed"), true); return false; } return true; } + + private static boolean canUseCommandBlock(Player player) { + return Config.commandRequireCreative ? player.canUseGameMasterBlocks() : player.hasPermissions(2); + } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/items/AbstractComputerItem.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/items/AbstractComputerItem.java index 447bb8b11..5c40474de 100644 --- a/projects/common/src/main/java/dan200/computercraft/shared/computer/items/AbstractComputerItem.java +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/items/AbstractComputerItem.java @@ -64,13 +64,7 @@ public abstract class AbstractComputerItem extends BlockItem implements ICompute @Override public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) { - var family = getFamily(); - if (family != ComputerFamily.COMMAND) { - var id = getComputerID(stack); - if (id >= 0) { - return ComputerCraftAPI.createSaveDirMount(level.getServer(), "computer/" + id, Config.computerSpaceLimit); - } - } - return null; + var id = getComputerID(stack); + return id >= 0 ? ComputerCraftAPI.createSaveDirMount(level.getServer(), "computer/" + id, Config.computerSpaceLimit) : null; } } diff --git a/projects/common/src/main/java/dan200/computercraft/shared/computer/items/CommandComputerItem.java b/projects/common/src/main/java/dan200/computercraft/shared/computer/items/CommandComputerItem.java new file mode 100644 index 000000000..062bef8ad --- /dev/null +++ b/projects/common/src/main/java/dan200/computercraft/shared/computer/items/CommandComputerItem.java @@ -0,0 +1,38 @@ +// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers +// +// SPDX-License-Identifier: MPL-2.0 + +package dan200.computercraft.shared.computer.items; + +import dan200.computercraft.api.filesystem.Mount; +import dan200.computercraft.shared.computer.blocks.ComputerBlock; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.context.BlockPlaceContext; +import net.minecraft.world.level.block.state.BlockState; +import org.jetbrains.annotations.Nullable; + +/** + * A {@link ComputerItem} which prevents players placing it without permission. + * + * @see net.minecraft.world.item.GameMasterBlockItem + * @see dan200.computercraft.shared.computer.blocks.CommandComputerBlock + */ +public class CommandComputerItem extends ComputerItem { + public CommandComputerItem(ComputerBlock block, Properties settings) { + super(block, settings); + } + + @Override + protected @Nullable BlockState getPlacementState(BlockPlaceContext context) { + // Prohibit players placing this block in survival or when not opped. + var player = context.getPlayer(); + return player != null && !player.canUseGameMasterBlocks() ? null : super.getPlacementState(context); + } + + @Override + public @Nullable Mount createDataMount(ItemStack stack, ServerLevel level) { + // Don't allow command computers to be mounted in disk drives. + return null; + } +}