From b40a39727c5b7b2ee5ae5b92f4902688417691a4 Mon Sep 17 00:00:00 2001 From: Dico200 Date: Mon, 30 Oct 2017 23:04:21 +0000 Subject: [PATCH 1/4] Add ModToggledObserver - Moved shared logic of observer and piston into ModToggledLogPlaceAbstract --- .../blockplacemods/mods/ModAbstract.java | 1 + .../mods/ModToggledLogPlaceAbstract.java | 40 +++++++++++++++++ .../mods/ModToggledObserver.java | 43 +++++++++++++++++++ .../blockplacemods/mods/ModToggledPiston.java | 37 +++++----------- 4 files changed, 94 insertions(+), 27 deletions(-) create mode 100644 src/com/redstoner/modules/blockplacemods/mods/ModToggledLogPlaceAbstract.java create mode 100644 src/com/redstoner/modules/blockplacemods/mods/ModToggledObserver.java diff --git a/src/com/redstoner/modules/blockplacemods/mods/ModAbstract.java b/src/com/redstoner/modules/blockplacemods/mods/ModAbstract.java index 2ef97fc..5a383d8 100644 --- a/src/com/redstoner/modules/blockplacemods/mods/ModAbstract.java +++ b/src/com/redstoner/modules/blockplacemods/mods/ModAbstract.java @@ -48,6 +48,7 @@ public abstract class ModAbstract implements Mod, Listener ModAbstract.logger = logger; registerMod(new ModToggledCauldron()); registerMod(new ModToggledPiston()); + registerMod(new ModToggledObserver()); registerMod(new ModToggledStep()); registerMod(new ModToggledTorch()); registerMod(new ModInventory("dropper", InventoryType.DROPPER)); diff --git a/src/com/redstoner/modules/blockplacemods/mods/ModToggledLogPlaceAbstract.java b/src/com/redstoner/modules/blockplacemods/mods/ModToggledLogPlaceAbstract.java new file mode 100644 index 0000000..17c414b --- /dev/null +++ b/src/com/redstoner/modules/blockplacemods/mods/ModToggledLogPlaceAbstract.java @@ -0,0 +1,40 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.GameMode; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.block.BlockPlaceEvent; + +/** + * A mod that makes placement of directional blocks act the way placement of logs does normally. + * Quartz pillar placement works like this too. + * + * Placed blocks face the block you clicked to place them. + */ +public abstract class ModToggledLogPlaceAbstract extends ModToggledAbstract { + + protected ModToggledLogPlaceAbstract(String name, boolean enabledByDefault) { + super(name, enabledByDefault); + } + + @SuppressWarnings("deprecation") + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + public void onBlockPlace(BlockPlaceEvent event) + { + Player player = event.getPlayer(); + Block block; + if (hasEnabled(player) && !player.isSneaking() && player.getGameMode() == GameMode.CREATIVE + && isApplicableToPlacedBlock(block = event.getBlock())) + { + block.setData((byte) getBlockDataForFacing(block.getFace(event.getBlockAgainst()))); + } + } + + protected abstract int getBlockDataForFacing(BlockFace direction); + + protected abstract boolean isApplicableToPlacedBlock(Block block); + +} diff --git a/src/com/redstoner/modules/blockplacemods/mods/ModToggledObserver.java b/src/com/redstoner/modules/blockplacemods/mods/ModToggledObserver.java new file mode 100644 index 0000000..8084bf4 --- /dev/null +++ b/src/com/redstoner/modules/blockplacemods/mods/ModToggledObserver.java @@ -0,0 +1,43 @@ +package com.redstoner.modules.blockplacemods.mods; + +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; + +public class ModToggledObserver extends ModToggledLogPlaceAbstract { + + protected ModToggledObserver() { + super("observer", false); + } + + @Override + public String getDescription() { + return "If active, observers face the block you place them against"; + } + + @Override + protected boolean isApplicableToPlacedBlock(Block block) { + return block.getType() == Material.OBSERVER; + } + + @Override + protected int getBlockDataForFacing(BlockFace direction) { + switch (direction) { + case UP: + return 0; + default: + case DOWN: + return 1; + case SOUTH: + return 2; + case NORTH: + return 3; + case EAST: + return 4; + case WEST: + return 5; + } + } + + +} diff --git a/src/com/redstoner/modules/blockplacemods/mods/ModToggledPiston.java b/src/com/redstoner/modules/blockplacemods/mods/ModToggledPiston.java index 9561a34..29e810c 100644 --- a/src/com/redstoner/modules/blockplacemods/mods/ModToggledPiston.java +++ b/src/com/redstoner/modules/blockplacemods/mods/ModToggledPiston.java @@ -1,15 +1,10 @@ package com.redstoner.modules.blockplacemods.mods; -import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.block.BlockPlaceEvent; -public class ModToggledPiston extends ModToggledAbstract +public class ModToggledPiston extends ModToggledLogPlaceAbstract { public ModToggledPiston() { @@ -22,28 +17,17 @@ public class ModToggledPiston extends ModToggledAbstract return "If active, pistons face the block you place them against"; } - @SuppressWarnings("deprecation") - @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onBlockPlace(BlockPlaceEvent event) - { - Player player = event.getPlayer(); - if (hasEnabled(player) && !player.isSneaking() && player.getGameMode() == GameMode.CREATIVE - && isPiston(event.getBlock().getType())) - { - Block block = event.getBlock(); - block.setData((byte) pistonDataForFace(block.getFace(event.getBlockAgainst()))); - } + @Override + protected boolean isApplicableToPlacedBlock(Block block) { + Material type = block.getType(); + return type == Material.PISTON_BASE || type == Material.PISTON_STICKY_BASE; } - private boolean isPiston(Material block) - { - return block == Material.PISTON_BASE || block == Material.PISTON_STICKY_BASE; - } - - private int pistonDataForFace(BlockFace face) - { - switch (face) + @Override + protected int getBlockDataForFacing(BlockFace direction) { + switch (direction) { + default: case DOWN: return 0; case UP: @@ -56,8 +40,7 @@ public class ModToggledPiston extends ModToggledAbstract return 4; case EAST: return 5; - default: - return 0; } } + } From eb86275fceff7d0da4c175727b0d295b9dd9bdda Mon Sep 17 00:00:00 2001 From: Dico200 Date: Tue, 31 Oct 2017 00:12:25 +0000 Subject: [PATCH 2/4] Fix a fallback command duplicate and bump version to 4.1.1 --- src/com/redstoner/modules/blockplacemods/BlockPlaceMods.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/com/redstoner/modules/blockplacemods/BlockPlaceMods.java b/src/com/redstoner/modules/blockplacemods/BlockPlaceMods.java index eeff1b9..6befbae 100644 --- a/src/com/redstoner/modules/blockplacemods/BlockPlaceMods.java +++ b/src/com/redstoner/modules/blockplacemods/BlockPlaceMods.java @@ -27,7 +27,7 @@ import com.redstoner.utils.CommandMap; @Commands(CommandHolderType.None) @AutoRegisterListener -@Version(major = 4, minor = 0, revision = 0, compatible = 4) +@Version(major = 4, minor = 1, revision = 1, compatible = 4) public final class BlockPlaceMods implements Module, Listener { @Override @@ -89,7 +89,7 @@ public final class BlockPlaceMods implements Module, Listener String pluginName = Main.plugin.getName().toLowerCase(); // @noformat return new String[]{"mod", pluginName + ":mod", - "set", pluginName + ":mod", + "set", pluginName + ":set", "toggle", pluginName + ":toggle" }; // @format From 56a6495a77914458d71ce2873c0ce7fa9a9dd352 Mon Sep 17 00:00:00 2001 From: Dico200 Date: Thu, 9 Nov 2017 08:58:44 +0000 Subject: [PATCH 3/4] Fix signalstrength module (tested) --- .../signalstrength/SignalStrength.java | 151 ++++++++++-------- 1 file changed, 88 insertions(+), 63 deletions(-) diff --git a/src/com/redstoner/modules/signalstrength/SignalStrength.java b/src/com/redstoner/modules/signalstrength/SignalStrength.java index 39decac..024f0dc 100644 --- a/src/com/redstoner/modules/signalstrength/SignalStrength.java +++ b/src/com/redstoner/modules/signalstrength/SignalStrength.java @@ -1,8 +1,11 @@ package com.redstoner.modules.signalstrength; -import java.util.ArrayList; -import java.util.HashSet; - +import com.nemez.cmdmgr.Command; +import com.redstoner.annotations.Commands; +import com.redstoner.annotations.Version; +import com.redstoner.misc.CommandHolderType; +import com.redstoner.modules.Module; +import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; @@ -10,121 +13,143 @@ import org.bukkit.block.BlockState; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.event.block.BlockPlaceEvent; +import org.bukkit.event.inventory.InventoryType; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.InventoryHolder; import org.bukkit.inventory.ItemStack; -import com.nemez.cmdmgr.Command; -import com.redstoner.annotations.Commands; -import com.redstoner.annotations.Version; -import com.redstoner.misc.CommandHolderType; -import com.redstoner.modules.Module; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; @Commands(CommandHolderType.File) @Version(major = 4, minor = 0, revision = 0, compatible = 4) public class SignalStrength implements Module { - + @Command(hook = "ss") public boolean ss(CommandSender sender, int strength) { - return ssm(sender, strength, Material.REDSTONE_WIRE.toString()); + return ssm(sender, strength, Material.REDSTONE.toString()); } - + @Command(hook = "ssm") public boolean ssm(CommandSender sender, int strength, String material) { - Material item_type = Material.getMaterial(material); + Material itemType = Material.matchMaterial(material); + if (itemType == null) + { + getLogger().message(sender, true, "The material " + material + " could not be recognized"); + return true; + } Player player = (Player) sender; - Block target_block = player.getTargetBlock(new HashSet(), 5); - if (target_block == null) + + // Empty set in the first argument would make it always return the first block, because no block types are + // considered to be transparent. Only a value of null is treated as "air only". + Block targetBlock = player.getTargetBlock((Set) null, 5); + if (targetBlock == null) { getLogger().message(sender, true, "That command can only be used if a container is targeted!"); return true; } - Inventory inventory = getInventory(target_block); + Inventory inventory = getInventory(targetBlock); if (inventory == null) { getLogger().message(sender, true, "That command can only be used if a container is targeted!"); return true; } + // --------Get the stack size and required amount of items to achieve the desired signal strength--------- - int stack_size = item_type.getMaxStackSize(); - int slot_count = inventory.getSize(); - int item_count = required_item_count(strength, stack_size, slot_count); - if (item_count == -1) + int stackSize = itemType.getMaxStackSize(); + int slotCount = inventory.getSize(); + int itemCount = computeRequiredItemCount(strength, stackSize, slotCount); + if (itemCount == -1) { getLogger().message(sender, true, "The desired signal strength could not be achieved with the requested item type"); return true; } // #--------Add the other side of the chest if target is a double chest and check if player can build--------- - ArrayList container_blocks = getAllContainers(target_block); - for (Block b : container_blocks) + ArrayList containerBlocks = new ArrayList<>(); + containerBlocks.add(targetBlock); + + Material blockType = targetBlock.getType(); + if (inventory.getType() == InventoryType.CHEST) { - if (!canBuild(player, b)) + Arrays.stream(new BlockFace[]{BlockFace.EAST, BlockFace.SOUTH, BlockFace.WEST, BlockFace.NORTH}) + .map(targetBlock::getRelative) + .filter(b -> b.getType() == blockType) + .forEach(containerBlocks::add); + } + + for (Block containerBlock : containerBlocks) + { + if (!canBuild(player, containerBlock)) { getLogger().message(sender, true, "You can not build here!"); return true; } } // #----------------Insert items------------- - int full_stack_count = item_count / stack_size; - int remaining = item_count % stack_size; - for (Block b : container_blocks) + int fullStackCount = itemCount / stackSize; + int remaining = itemCount % stackSize; + for (Block containerBlock : containerBlocks) { - Inventory inv = getInventory(b); + // Below checks should evaluate to false, but let's be safe. + Inventory inv = getInventory(containerBlock); + if (inv == null) continue; + inv.clear(); - for (int i = 0; i < full_stack_count; i++) - inv.setItem(i, new ItemStack(item_type, stack_size)); + for (int i = 0; i < fullStackCount; i++) + inv.setItem(i, new ItemStack(itemType, stackSize)); if (remaining > 0) - inv.setItem(full_stack_count, new ItemStack(item_type, remaining)); + inv.setItem(fullStackCount, new ItemStack(itemType, remaining)); } - getLogger().message(sender, - "Comparators attached to this Inventory will now put out a signal strength of" + strength); + getLogger().message(sender, "Comparators attached to this " + enumNameToHumanName(blockType.name()) + + " will now put out a signal strength of " + strength); return true; } - - private int required_item_count(int strength, int stack_size, int slot_count) - { - int item_count = -1; - if (strength == 0) - item_count = 0; - else if (strength == 1) - item_count = 1; - else - item_count = (int) Math.ceil(slot_count * stack_size / 14.0 * (strength - 1)); - int resulting_strength = item_count == 0 ? 0 : (int) Math.ceil(1 + 14.0 * item_count / stack_size / slot_count); - // Clarification on these formulas at https://minecraft.gamepedia.com/Redstone_Comparator#Containers - return resulting_strength == strength ? item_count : -1; - } - - private Inventory getInventory(Block b) + + private static Inventory getInventory(Block b) { BlockState state = b.getState(); if (state instanceof InventoryHolder) return ((InventoryHolder) state).getInventory(); return null; } - - private boolean canBuild(Player p, Block b) + + private static int computeRequiredItemCount(int strength, int stackSize, int slotCount) { - BlockPlaceEvent e = new BlockPlaceEvent(b, b.getState(), b.getRelative(BlockFace.DOWN), - p.getInventory().getItemInMainHand(), p, true, EquipmentSlot.HAND); - return e.isCancelled(); - } - - private ArrayList getAllContainers(Block b) - { - ArrayList result = new ArrayList(); - result.add(b); - for (BlockFace face : BlockFace.values()) + int itemCount = -1; + if (strength == 0) + itemCount = 0; + else if (strength == 1) + itemCount = 1; + else + itemCount = (int) Math.ceil(slotCount * stackSize / 14.0 * (strength - 1)); + + // Reverse engineer the calculation to verify + int resultingStrength = itemCount == 0 ? 0 : (int) Math.floor(1 + 14.0 * itemCount / stackSize / slotCount); + if (resultingStrength != strength) { - Block b2 = b.getRelative(face); - if (getInventory(b2) != null) - result.add(b2); + return -1; } - return result; + // Clarification on these formulas at https://minecraft.gamepedia.com/Redstone_Comparator#Containers + return itemCount; } + + private static boolean canBuild(Player p, Block b) + { + BlockPlaceEvent event = new BlockPlaceEvent(b, b.getState(), b.getRelative(BlockFace.DOWN), + p.getInventory().getItemInMainHand(), p, true, EquipmentSlot.HAND); + Bukkit.getPluginManager().callEvent(event); + return !event.isCancelled(); + } + + private static String enumNameToHumanName(String enumName) + { + return enumName.toLowerCase().replace('_', ' '); + } + } From a1e7b0beefab9790531385c7f1e42eef148e713a Mon Sep 17 00:00:00 2001 From: Dico200 Date: Thu, 9 Nov 2017 12:49:11 +0000 Subject: [PATCH 4/4] Make containers affected by /ss display a custom title with the signal strength --- .../signalstrength/SignalStrength.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/com/redstoner/modules/signalstrength/SignalStrength.java b/src/com/redstoner/modules/signalstrength/SignalStrength.java index 024f0dc..e1048f9 100644 --- a/src/com/redstoner/modules/signalstrength/SignalStrength.java +++ b/src/com/redstoner/modules/signalstrength/SignalStrength.java @@ -6,7 +6,9 @@ import com.redstoner.annotations.Version; import com.redstoner.misc.CommandHolderType; import com.redstoner.modules.Module; import org.bukkit.Bukkit; +import org.bukkit.ChatColor; import org.bukkit.Material; +import org.bukkit.Nameable; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.BlockState; @@ -28,6 +30,18 @@ import java.util.Set; public class SignalStrength implements Module { + private static final String namePrefix = ChatColor.GREEN.toString() + ChatColor.RESET + ChatColor.DARK_PURPLE + "Signal Strength: " + ChatColor.RED + ChatColor.BOLD; + + private static String nameForSignalStrength(int strength) + { + return namePrefix + strength; + } + + private static boolean isSignalStrengthNameOrEmpty(String name) + { + return name == null || name.isEmpty() || name.startsWith(namePrefix); + } + @Command(hook = "ss") public boolean ss(CommandSender sender, int strength) { @@ -97,7 +111,16 @@ public class SignalStrength implements Module for (Block containerBlock : containerBlocks) { // Below checks should evaluate to false, but let's be safe. - Inventory inv = getInventory(containerBlock); + BlockState blockState = containerBlock.getState(); + if (!(blockState instanceof InventoryHolder)) continue; + + if (blockState instanceof Nameable && isSignalStrengthNameOrEmpty(((Nameable) blockState).getCustomName())) + { + ((Nameable) blockState).setCustomName(nameForSignalStrength(strength)); + blockState.update(); + } + + Inventory inv = ((InventoryHolder) blockState).getInventory(); if (inv == null) continue; inv.clear(); @@ -105,6 +128,7 @@ public class SignalStrength implements Module inv.setItem(i, new ItemStack(itemType, stackSize)); if (remaining > 0) inv.setItem(fullStackCount, new ItemStack(itemType, remaining)); + } getLogger().message(sender, "Comparators attached to this " + enumNameToHumanName(blockType.name()) + " will now put out a signal strength of " + strength); @@ -152,4 +176,5 @@ public class SignalStrength implements Module return enumName.toLowerCase().replace('_', ' '); } + }