From c91c0ca068bed6bdaff9d46af9bd33c2c1c27c13 Mon Sep 17 00:00:00 2001 From: Mycelium <1312264863@qq.com> Date: Fri, 6 Sep 2024 18:16:16 +0800 Subject: [PATCH 1/2] [Bug fix] See issues [#238], [#239] for details. - magnet flag can turn on, on non-container block. - magnet feature behavior is incorrect with mult container. - magnet feature behavior is incorrect with furnace-like. - droptransfer feature can bind with non-container block. - droptransfer feature cleared item when bind a non-container block. - droptransfer feature can nested shulker box. --- src/main/java/com/griefcraft/lwc/LWC.java | 228 ++++++++++++++---- .../modules/flag/BaseFlagModule.java | 13 + .../griefcraft/modules/flag/MagnetModule.java | 50 ++-- .../modules/modes/DropTransferModule.java | 6 +- src/main/resources/lang/lwc_cn.properties | 1 + src/main/resources/lang/lwc_en.properties | 1 + 6 files changed, 233 insertions(+), 66 deletions(-) diff --git a/src/main/java/com/griefcraft/lwc/LWC.java b/src/main/java/com/griefcraft/lwc/LWC.java index f6f43c3d..1901e7be 100644 --- a/src/main/java/com/griefcraft/lwc/LWC.java +++ b/src/main/java/com/griefcraft/lwc/LWC.java @@ -92,11 +92,14 @@ import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; +import org.bukkit.block.Furnace; +import org.bukkit.block.ShulkerBox; import org.bukkit.block.data.type.Chest; import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; +import org.bukkit.inventory.FurnaceInventory; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; @@ -442,65 +445,204 @@ public boolean canAdminProtection(Player player, Protection protection) { return event.getAccess() == Permission.Access.ADMIN; } + /** + * Calculate The number of items that can be deposit in a furnace-like. + * + * Fuel slot allows only fuel items. + * Result slot does not allow deposits. + * + * @param furnaceLike (Not Null) Furnace-like block. + * @param itemStack (Not Null) Item stack for deposit. + * @return Number of items that can be deposit. + */ + public int getMaxDepositAmount(Furnace furnaceLike, ItemStack itemStack) { + FurnaceInventory inventory = furnaceLike.getInventory(); + ItemStack sourceSlot = inventory.getSmelting(); + ItemStack fuelSlot = inventory.getFuel(); + + // source slot is empty, can deposit + if (sourceSlot == null) { + return itemStack.getAmount(); + } + + boolean isItemStackFuel = itemStack.getType().isFuel(); + + // source slot not empty, but can stack deposit + if (sourceSlot.getAmount() < sourceSlot.getMaxStackSize()) { + if (itemStack.isSimilar(sourceSlot)) { + return Math.min( + sourceSlot.getMaxStackSize() - sourceSlot.getAmount(), + itemStack.getAmount() + ); + } + } + + // can't stack deposit to source slot or source slot is full + // mean the same thing + if (fuelSlot == null) { + if (isItemStackFuel) { + return itemStack.getAmount(); + } + return 0; + } + if (fuelSlot.getAmount() < fuelSlot.getMaxStackSize()) { + if (itemStack.isSimilar(fuelSlot)) { + return Math.min( + fuelSlot.getMaxStackSize() - fuelSlot.getAmount(), + itemStack.getAmount() + ); + } + } + + return 0; + } + + /** + * Calculate The number of items that can be deposit in a container. + * + * @param block (Not Null) Container block has inventory. + * @param itemStack (Not Null) Item stack for container deposit. + * @return Number of items that can be deposit. + */ + public int getMaxDepositAmount(Block block, ItemStack itemStack) { + BlockState blockState = block.getState(); + + // this block has neither block status nor inventory + if (blockState == null || !(blockState instanceof InventoryHolder)) { + return 0; + } + + // nesting is forbidden on shulker boxes + if (blockState instanceof ShulkerBox && itemStack.getType().toString().endsWith("SHULKER_BOX")) { + return 0; + } + + Inventory inventory = ((InventoryHolder) blockState).getInventory(); + + // for Furnace-like blocks + if (blockState instanceof Furnace) { + return this.getMaxDepositAmount((Furnace) blockState, itemStack); + } + + // has empty slot, can deposit? + if (inventory.firstEmpty() != -1) { + return itemStack.getAmount(); + } + + // has no empty slot, but can stack deposit? + if (itemStack.getMaxStackSize() == 1) { + // non-stackable items + return 0; + } + Map sameTypeItemStacks = inventory.all(itemStack.getType()); + for (ItemStack sameItemStack : sameTypeItemStacks.values()) { + if (sameItemStack.getAmount() >= sameItemStack.getMaxStackSize()) { + continue; + } + if (itemStack.isSimilar(sameItemStack)) { + return Math.min( + sameItemStack.getMaxStackSize() - sameItemStack.getAmount(), + itemStack.getAmount() + ); + } + } + + return 0; + } + /** * Deposit items into an inventory chest Works with double chests. - * + * + * NOTE: Returns empty map if the entire item is deposit, + * non-empty map if a partial amount of items is deposit, + * null if item can't be deposit. + * * @param block * @param itemStack - * @return remaining items (if any) + * @return (Nullable) remaining items. */ public Map depositItems(Block block, ItemStack itemStack) { - BlockState blockState; + BlockState blockState = block.getState(); + // not a container, leave the item intact + if (blockState == null || !(blockState instanceof InventoryHolder)) { + return null; + } - if ((blockState = block.getState()) != null && (blockState instanceof InventoryHolder)) { - Block doubleChestBlock = null; - InventoryHolder holder = (InventoryHolder) blockState; + Block doubleChestBlock = null; + if (DoubleChestMatcher.PROTECTABLES_CHESTS.contains(block.getType())) { + doubleChestBlock = findAdjacentDoubleChest(block); + } - if (DoubleChestMatcher.PROTECTABLES_CHESTS.contains(block.getType())) { - doubleChestBlock = findAdjacentDoubleChest(block); - } else if (block.getType() == Material.FURNACE) { - Inventory inventory = holder.getInventory(); + Map empty = new HashMap<>(); + int itemStackAmount = itemStack.getAmount(); - if (inventory.getItem(0) != null && inventory.getItem(1) != null) { - if (inventory.getItem(0).getType() == itemStack.getType() - && inventory.getItem(0) - .getMaxStackSize() >= (inventory.getItem(0).getAmount() + itemStack.getAmount())) { - // ItemStack fits on Slot 0 - } else if (inventory.getItem(1).getType() == itemStack.getType() - && inventory.getItem(1) - .getMaxStackSize() >= (inventory.getItem(1).getAmount() + itemStack.getAmount())) { - // ItemStack fits on Slot 1 - } else { - return null; - } - } - } + // remove unreasonable item + if (itemStackAmount <= 0) { + return empty; + } - if (itemStack.getAmount() <= 0) { - return new HashMap(); - } + // reached deposit limit, leave the item intact + int canDepositAmount = getMaxDepositAmount(block, itemStack); + if (canDepositAmount == 0) { + return null; + } - Map remaining = holder.getInventory().addItem(itemStack); + Inventory inventory = ((InventoryHolder) blockState).getInventory(); + Map remaining; + + // furnace-like is special, we don't want to handle it to addItem method directly + if (blockState instanceof Furnace) { + // for furnace-like blocks + Furnace furnaceLike = (Furnace) blockState; + FurnaceInventory snapshotInventory = furnaceLike.getSnapshotInventory(); + + ItemStack resultSlotBackup = snapshotInventory.getResult(); + // avoid addItem method stack deposit into result slot + snapshotInventory.setResult(null); + + // can't deposit them all + if (canDepositAmount < itemStackAmount) { + // split item stack into 2 parts + int restAmount = itemStackAmount - canDepositAmount; + ItemStack canDepositPart = itemStack.clone(); + ItemStack theRestPart = itemStack.clone(); + + canDepositPart.setAmount(canDepositAmount); + theRestPart.setAmount(restAmount); + // deposit can deposit part, drop the rest part into item + remaining = snapshotInventory.addItem(canDepositPart); + remaining.put(-1, theRestPart); + itemStack.setAmount(restAmount); + } else { + remaining = snapshotInventory.addItem(itemStack); + } - // we have remainders, deal with it + // restore backup and commit update + snapshotInventory.setResult(resultSlotBackup); + furnaceLike.update(true, false); + } else { + // other container block + remaining = inventory.addItem(itemStack); + } + + // we have remainders, deal with it + if (remaining.size() > 0) { + int key = remaining.keySet().iterator().next(); + ItemStack remainingItemStack = remaining.get(key); + + // is it a double chest ????? + if (doubleChestBlock != null) { + InventoryHolder holder2 = (InventoryHolder) doubleChestBlock.getState(); + remaining = holder2.getInventory().addItem(remainingItemStack); + } + + // recheck remaining in the event of double chest being used if (remaining.size() > 0) { - int key = remaining.keySet().iterator().next(); - ItemStack remainingItemStack = remaining.get(key); - - // is it a double chest ????? - if (doubleChestBlock != null) { - InventoryHolder holder2 = (InventoryHolder) doubleChestBlock.getState(); - remaining = holder2.getInventory().addItem(remainingItemStack); - } - - // recheck remaining in the event of double chest being used - if (remaining.size() > 0) { - return remaining; - } + return remaining; } } - return new HashMap(); + return empty; } /** diff --git a/src/main/java/com/griefcraft/modules/flag/BaseFlagModule.java b/src/main/java/com/griefcraft/modules/flag/BaseFlagModule.java index 3310d8de..fec12ae6 100644 --- a/src/main/java/com/griefcraft/modules/flag/BaseFlagModule.java +++ b/src/main/java/com/griefcraft/modules/flag/BaseFlagModule.java @@ -38,6 +38,9 @@ import com.griefcraft.scripting.event.LWCProtectionInteractEvent; import com.griefcraft.util.Colors; import com.griefcraft.util.StringUtil; + +import org.bukkit.block.BlockState; +import org.bukkit.block.Container; import org.bukkit.command.CommandSender; public class BaseFlagModule extends JavaModule { @@ -85,6 +88,16 @@ public void onProtectionInteract(LWCProtectionInteractEvent event) { flag = new Flag(type); } + // magnet flag can't use on non-container block. + if (flag.getType() == Flag.Type.MAGNET) { + BlockState targetBlockState = protection.getBlock().getState(); + if (!(targetBlockState instanceof Container)) { + lwc.sendLocale(player, "protection.interact.flag.magnet.notcontainer", "flag", StringUtil.capitalizeFirstLetter(flagName)); + lwc.removeModes(player); + return; + } + } + if (shouldAdd) { protection.addFlag(flag); lwc.sendLocale(player, "protection.interact.flag.add", "flag", StringUtil.capitalizeFirstLetter(flagName)); diff --git a/src/main/java/com/griefcraft/modules/flag/MagnetModule.java b/src/main/java/com/griefcraft/modules/flag/MagnetModule.java index 419f7993..060ca3dc 100644 --- a/src/main/java/com/griefcraft/modules/flag/MagnetModule.java +++ b/src/main/java/com/griefcraft/modules/flag/MagnetModule.java @@ -41,6 +41,7 @@ import org.bukkit.Server; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.Container; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.Item; @@ -154,27 +155,34 @@ public void run() { List protections = lwc.getPhysicalDatabase().loadProtections(world.getName(), x, y, z, radius); for (Protection protection : protections) { - if (protection.hasFlag(Flag.Type.MAGNET)) { - - if (protection.getBukkitWorld().getName() != item.getWorld().getName()) - continue; - - // we only want inventory blocks - if (!(protection.getBlock().getState() instanceof InventoryHolder)) { - continue; - } - - // never allow a shulker box to enter another shulker box - if (item.getItemStack().getType().toString().contains("SHULKER_BOX") && protection.getBlock().getType().toString().contains("SHULKER_BOX")) { - continue; - } - - MagnetNode node = new MagnetNode(); - node.item = item; - node.protection = protection; - items.offer(node); - break; + if (!protection.hasFlag(Flag.Type.MAGNET)) { + continue; } + + if (protection.getBukkitWorld().getName() != item.getWorld().getName()) + continue; + + // we only want container blocks + if (!(protection.getBlock().getState() instanceof Container)) { + continue; + } + + // never allow a shulker box to enter another shulker box + if (item.getItemStack().getType().toString().contains("SHULKER_BOX") && protection.getBlock().getType().toString().contains("SHULKER_BOX")) { + continue; + } + + // don't try to enter a full container + boolean isFull = lwc.getMaxDepositAmount(protection.getBlock(), stack) == 0; + if (isFull) { + continue; + } + + MagnetNode node = new MagnetNode(); + node.item = item; + node.protection = protection; + items.offer(node); + break; } } } @@ -206,7 +214,7 @@ public void run() { return; } - // we cancelled the item drop for some reason + // reached deposit limit, leave the item intact if (remaining == null) { continue; } diff --git a/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java b/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java index 2a8133d3..9112895d 100644 --- a/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java +++ b/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java @@ -40,6 +40,7 @@ import com.griefcraft.scripting.event.LWCProtectionInteractEvent; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.block.BlockState; import org.bukkit.block.Container; import org.bukkit.command.CommandSender; import org.bukkit.entity.Item; @@ -161,11 +162,12 @@ public void onProtectionInteract(LWCProtectionInteractEvent event) { if (!canAccess) { lwc.sendLocale(player, "protection.interact.dropxfer.noaccess"); } else { - if (event.getEvent().getClickedBlock() instanceof Container) { + Block clickedBlock = event.getEvent().getClickedBlock(); + BlockState blockState = clickedBlock.getState(); + if (!(blockState instanceof Container)) { lwc.sendLocale(player, "protection.interact.dropxfer.notchest"); player.removeAllActions(); event.setResult(Result.CANCEL); - return; } diff --git a/src/main/resources/lang/lwc_cn.properties b/src/main/resources/lang/lwc_cn.properties index c98dbc57..acfc49e8 100644 --- a/src/main/resources/lang/lwc_cn.properties +++ b/src/main/resources/lang/lwc_cn.properties @@ -223,6 +223,7 @@ protection.onplace.create.finalize=%dark_green%成功创建了%type% %block%的 # Flag protection.interact.flag.add=%dark_green%成功打开%dark_aqua% %flag%%dark_green%保护 protection.interact.flag.remove=%dark_red%成功移除%dark_aqua% %flag%%dark_red%保护 +protection.interact.flag.magnet.notcontainer=%dark_aqua%%flag% %dark_red%功能只能应用在容器上 # Creation protection.interact.create.password=%dark_aqua%为了方便起见,你在下次登陆前都不用输入密码了。 diff --git a/src/main/resources/lang/lwc_en.properties b/src/main/resources/lang/lwc_en.properties index 9110c623..e5803a65 100644 --- a/src/main/resources/lang/lwc_en.properties +++ b/src/main/resources/lang/lwc_en.properties @@ -271,6 +271,7 @@ protection.onplace.create.finalize=%dark_green%Created a %type% %block% successf # Flag protection.interact.flag.add=%dark_green%Turned on the flag%dark_aqua% %flag%%dark_green% for the protection successfully protection.interact.flag.remove=%dark_red%Removed the flag%dark_aqua% %flag%%dark_red% for the protection successfully +protection.interact.flag.magnet.notcontainer=%dark_red%The %dark_aqua%%flag%%dark_red% flag applies only to containers # Creation protection.interact.create.password=%dark_aqua%For convenience, you don't have to enter your password until you next log in. From 30bdd6f27136d75e11c2acc1a1633ae92c3c1e72 Mon Sep 17 00:00:00 2001 From: Mycelium <1312264863@qq.com> Date: Sun, 22 Sep 2024 17:59:22 +0800 Subject: [PATCH 2/2] Chinese translate and some bug fix with droptransfer. for deatils see issue [#241](https://github.com/pop4959/LWCX/issues/241) --- src/main/java/com/griefcraft/lwc/LWC.java | 33 ++-- .../modules/modes/DropTransferModule.java | 23 ++- src/main/resources/lang/lwc_cn.properties | 159 +++++++++++++----- 3 files changed, 151 insertions(+), 64 deletions(-) diff --git a/src/main/java/com/griefcraft/lwc/LWC.java b/src/main/java/com/griefcraft/lwc/LWC.java index 1901e7be..72e2a7f9 100644 --- a/src/main/java/com/griefcraft/lwc/LWC.java +++ b/src/main/java/com/griefcraft/lwc/LWC.java @@ -202,13 +202,6 @@ public static LWC getInstance() { return instance; } - /** - * Get a string representation of a block type - * - * @param id - * @return - */ - /** * Get a string representation of a block material * @@ -216,22 +209,22 @@ public static LWC getInstance() { * @return */ public static String materialToString(Material material) { - if (material != null) { - String materialName = normalizeMaterialName(material); + if (material == null) { + return ""; + } - // attempt to match the locale - String locale = LWC.getInstance().getPlugin().getMessageParser().parseMessage(materialName.toLowerCase()); + String materialName = normalizeMaterialName(material); - // if it starts with UNKNOWN_LOCALE, use the default material name - if (locale == null) { - locale = materialName; - } + // attempt to match the locale + String locale = LWC.getInstance().getPlugin().getMessageParser().parseMessage(materialName.toLowerCase()); - locale = locale.replace('_', ' '); - return StringUtil.capitalizeFirstLetter(locale); + // if it starts with UNKNOWN_LOCALE, use the default material name + if (locale == null) { + locale = materialName; } - return ""; + locale = locale.replace('_', ' '); + return StringUtil.capitalizeFirstLetter(locale); } /** @@ -251,10 +244,6 @@ public static String normalizeMaterialName(Material material) { name = "Sign"; } - if (name.contains("furnace")) { - name = "furnace"; - } - if (name.endsWith("_")) { name = name.substring(0, name.length() - 1); } diff --git a/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java b/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java index 9112895d..822d90f3 100644 --- a/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java +++ b/src/main/java/com/griefcraft/modules/modes/DropTransferModule.java @@ -37,6 +37,7 @@ import com.griefcraft.scripting.event.LWCBlockInteractEvent; import com.griefcraft.scripting.event.LWCCommandEvent; import com.griefcraft.scripting.event.LWCDropItemEvent; +import com.griefcraft.scripting.event.LWCProtectionDestroyEvent; import com.griefcraft.scripting.event.LWCProtectionInteractEvent; import org.bukkit.World; import org.bukkit.block.Block; @@ -110,10 +111,12 @@ public void onDropItem(LWCDropItemEvent event) { } Protection protection = lwc.getPhysicalDatabase().loadProtection(protectionId); + boolean isRealOwner = protection.isRealOwner(bPlayer); - if (protection == null) { + if (protection == null || !isRealOwner) { lwc.sendLocale(player, "lwc.nolongerexists"); - player.disableMode(player.getMode("dropTransfer")); + lwc.sendLocale(player, "protection.modes.dropxfer.off.finalize"); + player.disableMode(player.getMode("+dropTransfer")); return; } @@ -145,6 +148,21 @@ public void onDropItem(LWCDropItemEvent event) { item.remove(); } + @Override + public void onDestroyProtection(LWCProtectionDestroyEvent event) { + // turn off droptransfer if status is on when destroy bind target. + Player player = event.getPlayer(); + LWCPlayer lwcPlayer = LWCPlayer.getPlayer(player); + int target = getPlayerDropTransferTarget(lwcPlayer); + + if (target == -1 || !isPlayerDropTransferring(lwcPlayer)) { + return; + } + + lwcPlayer.disableMode(lwcPlayer.getMode("+dropTransfer")); + lwc.sendLocale(player, "protection.modes.dropxfer.off.finalize"); + } + @Override public void onProtectionInteract(LWCProtectionInteractEvent event) { LWC lwc = event.getLWC(); @@ -182,6 +200,7 @@ public void onProtectionInteract(LWCProtectionInteractEvent event) { player.enableMode(mode); lwc.sendLocale(player, "protection.interact.dropxfer.finalize"); + event.getEvent().setCancelled(true); } player.removeAllActions(); // ignore the persist mode diff --git a/src/main/resources/lang/lwc_cn.properties b/src/main/resources/lang/lwc_cn.properties index acfc49e8..5de4a149 100644 --- a/src/main/resources/lang/lwc_cn.properties +++ b/src/main/resources/lang/lwc_cn.properties @@ -20,33 +20,31 @@ no=%dark_red%否 # Some generic responses and block names you=你 chest=箱子 +trapped_chest=陷阱箱 + +# 熔炉类 furnace=熔炉 +blast_furnace=高炉 +smoker=烟熏炉 + dispenser=发射器 -sign=木牌 -wooden_door=橡木门 -spruce_door=云杉木门 -birch_door=桦木门 -jungle_door=丛林木门 -acacia_door=金合欢木门 -dark_oak_door=深色橡木门 -iron_door=铁门 -trap_door=陷阱门 -fence_gate=栅栏门 -spruce_fence_gate=云杉木栅栏门 -birch_fence_gate=桦木栅栏门 -jungle_fence_gate=丛林木栅栏门 -acacia_fence_gate=金合欢木栅栏门 -dark_oak_fence_gate=深色橡木栅栏门 -trapped_chest=陷阱木牌 -ender_chest=末地木牌 +dropper=投掷器 +barrel=木桶 +composter=堆肥桶 +lectern=讲台 +ender_chest=末影箱 + +# 潜影盒类 +shulker_box=潜影盒 white_shulker_box=白色潜影盒 orange_shulker_box=橙色潜影盒 magenta_shulker_box=品红色潜影盒 light_blue_shulker_box=浅蓝色潜影盒 yellow_shulker_box=黄色潜影盒 lime_shulker_box=绿黄色潜影盒 -pink_shulker_box=粉色潜影盒 +pink_shulker_box=粉红色潜影盒 gray_shulker_box=灰色潜影盒 +light_gray_shulker_box=淡灰色潜影盒 silver_shulker_box=银色潜影盒 cyan_shulker_box=青色潜影盒 purple_shulker_box=紫色潜影盒 @@ -56,6 +54,85 @@ green_shulker_box=绿色潜影盒 red_shulker_box=红色潜影盒 black_shulker_box=黑色潜影盒 +sign=告示牌 + +# 门类 +oak_door=橡木门 +spruce_door=云杉木门 +birch_door=白桦木门 +jungle_door=丛林木门 +acacia_door=金合欢木门 +dark_oak_door=深色橡木门 +mangrove_door=红树木门 +cherry_door=樱花木门 +bamboo_door=竹门 +crimson_door=绯红木门 +warped_door=诡异木门 +iron_door=铁门 + +# 栅栏门类 +oak_fence_gate=橡木栅栏门 +spruce_fence_gate=云杉木栅栏门 +birch_fence_gate=白桦木栅栏门 +jungle_fence_gate=从林木栅栏门 +acacia_fence_gate=金合欢木栅栏门 +dark_oak_fence_gate=深色橡木栅栏门 +mangrove_fence_gate=红树木栅栏门 +cherry_fence_gate=樱花木栅栏门 +bamboo_fence_gate=竹栅栏门 +crimson_fence_gate=绯红木栅栏门 +warped_fence_gate=诡异木栅栏门 + +# 活板门类 +oak_trapdoor=橡木活板门 +spruce_trapdoor=云杉木活板门 +birch_trapdoor=白桦木活板门 +jungle_trapdoor=从林木活板门 +acacia_trapdoor=金合欢木活板门 +dark_oak_trapdoor=深色橡木活板门 +mangrove_trapdoor=红树木活板门 +cherry_trapdoor=樱花木活板门 +bamboo_trapdoor=竹活板门 +crimson_trapdoor=绯红木活板门 +warped_trapdoor=诡异木活板门 +iron_trapdoor=铁活板门 + +# 旗帜类 +white_banner=白色旗帜 +light_gray_banner=淡灰色旗帜 +gray_banner=灰色旗帜 +black_banner=黑色旗帜 +brown_banner=棕色旗帜 +red_banner=红色旗帜 +orange_banner=橙色旗帜 +yellow_banner=黄色旗帜 +lime_banner=黄绿色旗帜 +green_banner=绿色旗帜 +cyan_banner=青色旗帜 +light_blue_banner=淡蓝色旗帜 +blue_banner=蓝色旗帜 +purple_banner=紫色旗帜 +magenta_banner=品红色旗帜 +pink_banner=粉红色旗帜 + +white_wall_banner=白色悬挂旗帜 +light_gray_wall_banner=淡灰色悬挂旗帜 +gray_wall_banner=灰色悬挂旗帜 +black_wall_banner=黑色悬挂旗帜 +brown_wall_banner=棕色悬挂旗帜 +red_wall_banner=红色悬挂旗帜 +orange_wall_banner=橙色悬挂旗帜 +yellow_wall_banner=黄色悬挂旗帜 +lime_wall_banner=黄绿色悬挂旗帜 +green_wall_banner=绿色悬挂旗帜 +cyan_wall_banner=青色悬挂旗帜 +light_blue_wall_banner=淡蓝色悬挂旗帜 +blue_wall_banner=蓝色悬挂旗帜 +purple_wall_banner=紫色悬挂旗帜 +magenta_wall_banner=品红色悬挂旗帜 +pink_wall_banner=粉红色悬挂旗帜 + + # Internal LWC error (if this shows up, something went terribly wrong most likely) protection.internalerror=%dark_red%[LWC]发生内部错误,请联系管理员。%white% :%id% @@ -126,22 +203,24 @@ protection.modes.persist.off=\ %dark_green%命令已停止 protection.modes.dropxfer.help=\ -%dark_green%LWC 漏斗权限 \n\ -\n\ -/lwc mode droptransfer%dark_aqua% select%white% - 选择你要更改漏洞权限的箱子 \n\ -/lwc mode droptransfer%dark_aqua% on%white% - 打开漏斗权限 \n\ -/lwc mode droptransfer%dark_aqua% off%white% - 关闭漏斗权限 \n\ -/lwc mode droptransfer%dark_aqua% status%white% - 检查漏斗权限 -protection.modes.dropxfer.selectchest=%dark_red%请在切换漏斗权限前选择一个箱子 -protection.modes.dropxfer.select.error=%dark_red%请在选择其他箱子前关闭漏洞权限编辑状态 -protection.modes.dropxfer.select.finalize=%dark_aqua%请左键点击你要修改漏洞权限的箱子 +%dark_green%LWC 丢出速递 \n\ +---\n\ +让丢出的物品,直接存储进你选定的容器中。\n\ +---\n\ +/lwc mode droptransfer%dark_aqua% select%white% - 选择你丢出速递的目标容器 \n\ +/lwc mode droptransfer%dark_aqua% on%white% - 开启丢出速递 \n\ +/lwc mode droptransfer%dark_aqua% off%white% - 关闭丢出速递 \n\ +/lwc mode droptransfer%dark_aqua% status%white% - 查看丢出速递运行状态 +protection.modes.dropxfer.selectchest=%dark_red%请在切换丢出速递功能前选择一个容器 +protection.modes.dropxfer.select.error=%dark_red%想要更改目标容器请先关闭丢出速递功能 +protection.modes.dropxfer.select.finalize=%dark_aqua%请选择一个容器作为丢出速递的目标 protection.modes.dropxfer.on.finalize=\ -%dark_aqua%漏斗权限打开了 \n\ -%dark_aqua%物品将可以掉落到这个箱子中 -protection.modes.dropxfer.off.finalize=%dark_aqua%漏斗权限关闭了 -protection.modes.dropxfer.status.off=%dark_aqua%修改漏斗失败 -protection.modes.dropxfer.status.active=%dark_aqua%当前漏斗权限状态为%dark_green%开启 -protection.modes.dropxfer.status.inactive=%dark_aqua%当前漏斗权限状态为%dark_red%关闭 +%dark_aqua%丢出速递打开了 \n\ +%dark_aqua%物品将可以存储到这个容器中 +protection.modes.dropxfer.off.finalize=%dark_aqua%丢出速递关闭了 +protection.modes.dropxfer.status.off=%dark_aqua%你还没有选定一个目标容器 +protection.modes.dropxfer.status.active=%dark_aqua%当前丢出速递状态为%dark_green%开启 +protection.modes.dropxfer.status.inactive=%dark_aqua%当前丢出速递状态为%dark_red%关闭 # Admin (large command set) @@ -247,14 +326,14 @@ protection.interact.info.raw=\ # Drop transfer protection.interact.dropxfer.notprotected=\ -%dark_red%你不能选择一个未锁定的箱子作为漏斗保护权限的目标。\n\ -%dark_red%使用"/lwc mode droptransfer select"命令重试。\n\ +%dark_red%你不能选择一个未锁定的容器作为丢出速递的目标。\n\ +%dark_red%使用"/lwc mode droptransfer select"命令重试。 protection.interact.dropxfer.noaccess=\ -%dark_red%你不能选择一个你没有权限操作的箱子作为漏斗保护权限的目标。\n\ +%dark_red%你不能选择一个你无权访问作为丢出速递的目标容器。\n\ %dark_red%如果是一个密码箱,请解锁后再试。\n\ %dark_red%使用"/lwc mode droptransfer select"命令重试。 -protection.interact.dropxfer.notchest=%dark_red%你必须选择一个箱子作为更改漏斗权限的目标! -protection.interact.dropxfer.finalize=%dark_green%已更改目标箱子的漏斗权限! +protection.interact.dropxfer.notchest=%dark_red%你必须选择一个容器作为更改丢出速递的目标! +protection.interact.dropxfer.finalize=%dark_green%已更改目标容器的丢出速递状态! ################## ## Help screens ## @@ -462,8 +541,8 @@ lwc.worldguard.blacklisted=%dark_red%此区域不允许使用LWC保护! lwc.towny.blocked=%dark_red%你只能在城镇中使用LWC保护方块! -lwc.dropxfer.chestfull=你的箱子已经塞不下啦, 多余的物品已返回原处. -lwc.dropxfer.acrossworlds=%dark_red%你不能在不同的世界里转移物品! +lwc.dropxfer.chestfull=你的容器已经塞不下啦, 多余的物品已退回. +lwc.dropxfer.acrossworlds=%dark_red%你不能在不同的世界里速递物品! lwc.unlock.noselection=%dark_red%请先打开一个受密码保护的容器.