diff --git a/src/main/java/com/minecolonies/api/util/constant/WindowConstants.java b/src/main/java/com/minecolonies/api/util/constant/WindowConstants.java index 462499b27c7..7e1b586f27c 100755 --- a/src/main/java/com/minecolonies/api/util/constant/WindowConstants.java +++ b/src/main/java/com/minecolonies/api/util/constant/WindowConstants.java @@ -397,6 +397,11 @@ public final class WindowConstants */ public static final String BUTTON_REMOVE_BLOCK = "removeBlock"; + /** + * Button to obtain a permissions scepter. + */ + public static final String BUTTON_BLOCK_TOOL = "blockTool"; + /** * Button to select a block for a replacement. */ diff --git a/src/main/java/com/minecolonies/api/util/constant/translation/ToolTranslationConstants.java b/src/main/java/com/minecolonies/api/util/constant/translation/ToolTranslationConstants.java index 6907184333c..74aee42ec53 100644 --- a/src/main/java/com/minecolonies/api/util/constant/translation/ToolTranslationConstants.java +++ b/src/main/java/com/minecolonies/api/util/constant/translation/ToolTranslationConstants.java @@ -93,6 +93,8 @@ public class ToolTranslationConstants @NonNls public static final String TOOL_PERMISSION_SCEPTER_SET_MODE = "com.minecolonies.coremod.item.permissionscepter.setmode"; @NonNls + public static final String TOOL_PERMISSION_SCEPTER_MODE = "com.minecolonies.coremod.item.permissionscepter.mode"; + @NonNls public static final String TOOL_PERMISSION_SCEPTER_MODE_BLOCK = "com.minecolonies.coremod.item.permissionscepter.mode.block"; @NonNls public static final String TOOL_PERMISSION_SCEPTER_MODE_LOCATION = "com.minecolonies.coremod.item.permissionscepter.mode.location"; diff --git a/src/main/java/com/minecolonies/core/client/gui/townhall/WindowPermissionsPage.java b/src/main/java/com/minecolonies/core/client/gui/townhall/WindowPermissionsPage.java index 444ceedcca0..2f089bfb1ab 100644 --- a/src/main/java/com/minecolonies/core/client/gui/townhall/WindowPermissionsPage.java +++ b/src/main/java/com/minecolonies/core/client/gui/townhall/WindowPermissionsPage.java @@ -9,11 +9,14 @@ import com.ldtteam.blockui.views.DropDownList; import com.ldtteam.blockui.views.ScrollingList; import com.minecolonies.api.colony.permissions.*; +import com.minecolonies.api.items.ModItems; import com.minecolonies.api.util.BlockPosUtil; import com.minecolonies.api.util.SoundUtils; import com.minecolonies.core.colony.buildings.workerbuildings.BuildingTownHall; import com.minecolonies.core.network.messages.PermissionsMessage; import com.minecolonies.core.network.messages.server.colony.ChangeFreeToInteractBlockMessage; +import com.minecolonies.core.network.messages.server.colony.building.GiveToolMessage; +import net.minecraft.ChatFormatting; import net.minecraft.ResourceLocationException; import net.minecraft.client.Minecraft; import net.minecraft.client.player.LocalPlayer; @@ -117,6 +120,7 @@ public WindowPermissionsPage(final BuildingTownHall.View building) registerButton(BUTTON_TRIGGER, this::trigger); registerButton(BUTTON_ADD_BLOCK, this::addBlock); registerButton(BUTTON_REMOVE_BLOCK, this::removeBlock); + registerButton(BUTTON_BLOCK_TOOL, this::giveBlockTool); registerButton(BUTTON_ADD_RANK, this::addRank); registerButton(TOWNHALL_RANK_BUTTON, this::onRankButtonClicked); registerButton(BUTTON_REMOVE_RANK, this::onRemoveRankButtonClicked); @@ -256,7 +260,8 @@ public void onOpened() final TextField playerNameField = findPaneOfTypeByID(INPUT_ADDPLAYER_NAME, TextField.class); final TextField rankNameField = findPaneOfTypeByID(INPUT_ADDRANK_NAME, TextField.class); final Button addRankButton = findPaneOfTypeByID(BUTTON_ADD_RANK, Button.class); - + final Button addBlockButton = findPaneOfTypeByID(BUTTON_ADD_BLOCK, Button.class); + final Button blockToolButton = findPaneOfTypeByID(BUTTON_BLOCK_TOOL, Button.class); if (building.getColony().getPermissions().hasPermission(player, Action.EDIT_PERMISSIONS)) { @@ -264,6 +269,8 @@ public void onOpened() playerNameField.setEnabled(true); rankNameField.setEnabled(true); addRankButton.setEnabled(true); + addBlockButton.setEnabled(true); + blockToolButton.setEnabled(true); } else { @@ -279,6 +286,8 @@ public void onOpened() addPlayerButton.setEnabled(false); playerNameField.setEnabled(false); addRankButton.setEnabled(false); + addBlockButton.setEnabled(false); + blockToolButton.setEnabled(false); } findPaneOfTypeByID(TOWNHALL_RANK_TYPE_PICKER, DropDownList.class).setSelectedIndex(actionsRank.isColonyManager() ? 0 : (actionsRank.isHostile() ? 1 : 2)); @@ -422,6 +431,14 @@ else if (row < freeBlocks.size() + freePositions.size()) } } + /** + * Gives the player a Permission Scepter. + */ + private void giveBlockTool(final Button button) + { + Network.getNetwork().sendToServer(new GiveToolMessage(buildingView, ModItems.permTool)); + } + /** * Fills the free blocks list in the GUI. */ @@ -444,13 +461,25 @@ public void updateElement(final int index, @NotNull final Pane rowPane) { if (index < freeBlocks.size()) { - rowPane.findPaneOfTypeByID(NAME_LABEL, Text.class).setText(Component.literal(BuiltInRegistries.BLOCK.getKey(freeBlocks.get(index)).toString())); + final Block block = freeBlocks.get(index); + final MutableComponent text = Component.literal(ForgeRegistries.BLOCKS.getKey(block).toString()); + text.append(Component.literal("\n")).append(block.getName().withStyle(ChatFormatting.DARK_GRAY)); + rowPane.findPaneOfTypeByID(NAME_LABEL, Text.class).setText(text); } else { final BlockPos pos = freePositions.get(index - freeBlocks.size()); - rowPane.findPaneOfTypeByID(NAME_LABEL, Text.class).setText(Component.literal(pos.getX() + " " + pos.getY() + " " + pos.getZ())); + final MutableComponent text = Component.literal(pos.getX() + " " + pos.getY() + " " + pos.getZ()); + if (building.getColony().getWorld().isLoaded(pos)) + { + final BlockState state = building.getColony().getWorld().getBlockState(pos); + text.append(Component.literal("\n")).append(state.getBlock().getName().withStyle(ChatFormatting.DARK_GRAY)); + } + rowPane.findPaneOfTypeByID(NAME_LABEL, Text.class).setText(text); } + + final boolean canEdit = building.getColony().getPermissions().hasPermission(Minecraft.getInstance().player, Action.EDIT_PERMISSIONS); + rowPane.findPaneOfTypeByID(BUTTON_REMOVE_BLOCK, Button.class).setEnabled(canEdit); } }); } @@ -467,7 +496,7 @@ private void addBlock() { final Block block = BuiltInRegistries.BLOCK.get(new ResourceLocation(inputText)); - if (block != null) + if (block != null && !block.defaultBlockState().isAir()) { building.getColony().addFreeBlock(block); new ChangeFreeToInteractBlockMessage(building.getColony(), block, ChangeFreeToInteractBlockMessage.MessageType.ADD_BLOCK).sendToServer(); diff --git a/src/main/java/com/minecolonies/core/items/ItemScepterPermission.java b/src/main/java/com/minecolonies/core/items/ItemScepterPermission.java index 72b3754573b..c1d7156902b 100755 --- a/src/main/java/com/minecolonies/core/items/ItemScepterPermission.java +++ b/src/main/java/com/minecolonies/core/items/ItemScepterPermission.java @@ -2,28 +2,43 @@ import com.minecolonies.api.colony.IColonyManager; import com.minecolonies.api.colony.IColonyView; +import com.minecolonies.api.colony.permissions.Action; +import com.minecolonies.api.items.IBlockOverlayItem; import com.minecolonies.api.util.MessageUtils; import com.minecolonies.core.network.messages.server.colony.ChangeFreeToInteractBlockMessage; -import net.minecraft.world.level.block.Block; -import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.screens.Screen; +import net.minecraft.core.BlockPos; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; +import net.minecraft.world.InteractionResultHolder; import net.minecraft.world.entity.player.Player; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; import net.minecraft.world.item.context.UseOnContext; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.InteractionResultHolder; -import net.minecraft.world.InteractionResult; -import net.minecraft.world.InteractionHand; -import net.minecraft.core.BlockPos; import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.Block; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.phys.AABB; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import static com.minecolonies.api.util.constant.translation.ToolTranslationConstants.*; /** * Permission scepter. used to add free to interact blocks or positions to the colonies permission list */ -public class ItemScepterPermission extends AbstractItemMinecolonies +public class ItemScepterPermission extends AbstractItemMinecolonies implements IBlockOverlayItem { /** * The NBT tag of the mode @@ -40,6 +55,10 @@ public class ItemScepterPermission extends AbstractItemMinecolonies */ private static final String TAG_VALUE_MODE_LOCATION = "modeLocation"; + private static final int GREEN_OVERLAY = 0xFF00FF00; + private static final int BLOCK_OVERLAY_RANGE_XZ = 32; + private static final int BLOCK_OVERLAY_RANGE_Y = 6; + /** * constructor. *

@@ -62,10 +81,13 @@ private static InteractionResult handleAddBlockType( final BlockState blockState = iColonyView.getWorld().getBlockState(pos); final Block block = blockState.getBlock(); + final ChangeFreeToInteractBlockMessage.MessageType type = Screen.hasControlDown() + ? ChangeFreeToInteractBlockMessage.MessageType.REMOVE_BLOCK + : ChangeFreeToInteractBlockMessage.MessageType.ADD_BLOCK; final ChangeFreeToInteractBlockMessage message = new ChangeFreeToInteractBlockMessage( iColonyView, block, - ChangeFreeToInteractBlockMessage.MessageType.ADD_BLOCK); + type); message.sendToServer(); return InteractionResult.SUCCESS; @@ -78,7 +100,10 @@ private static InteractionResult handleAddLocation( final BlockPos pos, final IColonyView iColonyView) { - final ChangeFreeToInteractBlockMessage message = new ChangeFreeToInteractBlockMessage(iColonyView, pos, ChangeFreeToInteractBlockMessage.MessageType.ADD_BLOCK); + final ChangeFreeToInteractBlockMessage.MessageType type = Screen.hasControlDown() + ? ChangeFreeToInteractBlockMessage.MessageType.REMOVE_BLOCK + : ChangeFreeToInteractBlockMessage.MessageType.ADD_BLOCK; + final ChangeFreeToInteractBlockMessage message = new ChangeFreeToInteractBlockMessage(iColonyView, pos, type); message.sendToServer(); return InteractionResult.SUCCESS; @@ -161,6 +186,63 @@ private static void toggleItemMode(final Player playerIn, final CompoundTag comp } } + @NotNull + @Override + public List getOverlayBoxes(@NotNull final Level world, @NotNull final Player player, @NotNull final ItemStack stack) + { + final List boxes = new ArrayList<>(); + final IColonyView colony = IColonyManager.getInstance().getClosestColonyView(world, player.blockPosition()); + if (colony == null || !colony.getPermissions().hasPermission(player, Action.EDIT_PERMISSIONS)) + { + return boxes; + } + + final String itemMode = stack.getOrCreateTag().getString(TAG_ITEM_MODE); + switch (itemMode) + { + case TAG_VALUE_MODE_BLOCK: + final Set freeBlocks = new HashSet<>(colony.getFreeBlocks()); + for (final BlockPos pos : BlockPos.withinManhattan(player.blockPosition(), BLOCK_OVERLAY_RANGE_XZ, BLOCK_OVERLAY_RANGE_Y, BLOCK_OVERLAY_RANGE_XZ)) + { + if (world.isLoaded(pos) && freeBlocks.contains(world.getBlockState(pos).getBlock())) + { + boxes.add(new OverlayBox(AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(pos)), GREEN_OVERLAY, 0.02f, true)); + } + } + break; + case TAG_VALUE_MODE_LOCATION: + default: + for (final BlockPos pos : colony.getFreePositions()) + { + boxes.add(new OverlayBox(AABB.unitCubeFromLowerCorner(Vec3.atLowerCornerOf(pos)), GREEN_OVERLAY, 0.02f, true)); + } + break; + } + + return boxes; + } + + @Override + public void appendHoverText(@NotNull final ItemStack stack, @Nullable final Level level, + @NotNull final List tooltip, @NotNull final TooltipFlag flags) + { + final String itemMode = stack.getOrCreateTag().getString(TAG_ITEM_MODE); + final MutableComponent mode; + switch (itemMode) + { + case TAG_VALUE_MODE_BLOCK: + mode = Component.translatable(TOOL_PERMISSION_SCEPTER_MODE_BLOCK); + break; + case TAG_VALUE_MODE_LOCATION: + default: + mode = Component.translatable(TOOL_PERMISSION_SCEPTER_MODE_LOCATION); + break; + } + tooltip.add(Component.translatable(TOOL_PERMISSION_SCEPTER_MODE, mode.withStyle(ChatFormatting.YELLOW))); + + super.appendHoverText(stack, level, tooltip, flags); + } + @NotNull private static InteractionResult handleItemAction( final CompoundTag compound, diff --git a/src/main/java/com/minecolonies/core/network/messages/server/colony/ChangeFreeToInteractBlockMessage.java b/src/main/java/com/minecolonies/core/network/messages/server/colony/ChangeFreeToInteractBlockMessage.java index 59ccd892c30..ec82cecc7e6 100755 --- a/src/main/java/com/minecolonies/core/network/messages/server/colony/ChangeFreeToInteractBlockMessage.java +++ b/src/main/java/com/minecolonies/core/network/messages/server/colony/ChangeFreeToInteractBlockMessage.java @@ -106,8 +106,13 @@ protected Action permissionNeeded() @Override protected void onExecute(final PlayPayloadContext ctxIn, final ServerPlayer player, final IColony colony) { - //Verify player has permission to change this huts settings - if (msgType == MessageType.ADD_BLOCK) + final Player player = ctxIn.getSender(); + if (player == null) + { + return; + } + + if (type == MessageType.ADD_BLOCK) { switch (msgMode) { diff --git a/src/main/resources/assets/minecolonies/gui/townhall/layoutpermissions.xml b/src/main/resources/assets/minecolonies/gui/townhall/layoutpermissions.xml index 9681ad1b230..a33c2817ec0 100755 --- a/src/main/resources/assets/minecolonies/gui/townhall/layoutpermissions.xml +++ b/src/main/resources/assets/minecolonies/gui/townhall/layoutpermissions.xml @@ -5,16 +5,16 @@ -