diff options
author | David <david@panic.tk> | 2018-11-07 23:50:06 +0100 |
---|---|---|
committer | David <david@panic.tk> | 2018-11-07 23:50:06 +0100 |
commit | 604cf01967ede98bf5024e4926bb0777fc4e8eee (patch) | |
tree | e2fa63d7e683769ee3bf3eddc75280648e92eb04 /src/main/java/com/redstoner/modules/signalstrength | |
parent | e86c52ef7c0e1e33c6af0e8674b038976bec11cc (diff) |
Converted Modules to gradle
Diffstat (limited to 'src/main/java/com/redstoner/modules/signalstrength')
-rw-r--r-- | src/main/java/com/redstoner/modules/signalstrength/SignalStrength.cmd | 14 | ||||
-rw-r--r-- | src/main/java/com/redstoner/modules/signalstrength/SignalStrength.java | 194 |
2 files changed, 208 insertions, 0 deletions
diff --git a/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.cmd b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.cmd new file mode 100644 index 0000000..1cfb0fd --- /dev/null +++ b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.cmd @@ -0,0 +1,14 @@ +command signalstrength { + alias ss; + perm utils.signalstrength; + [int:strength] { + run ss strength; + type player; + help "Sets the amount of items in a container to achieve the given signal strength. Uses redstone dust."; + } + [int:strength] [string:material] { + run ssm strength material; + type player; + help "Sets the amount of itmes in a container to achieve the given signal strength. Uses the material specified."; + } +}
\ No newline at end of file diff --git a/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.java b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.java new file mode 100644 index 0000000..b613b09 --- /dev/null +++ b/src/main/java/com/redstoner/modules/signalstrength/SignalStrength.java @@ -0,0 +1,194 @@ +package com.redstoner.modules.signalstrength; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Set; + +import org.bukkit.Bukkit; +import org.bukkit.ChatColor; +import org.bukkit.GameMode; +import org.bukkit.Material; +import org.bukkit.Nameable; +import org.bukkit.block.Block; +import org.bukkit.block.BlockFace; +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; + +@Commands(CommandHolderType.File) +@Version(major = 4, minor = 0, revision = 2, compatible = 4) +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) + { + return ssm(sender, strength, Material.REDSTONE.toString()); + } + + @Command(hook = "ssm") + public boolean ssm(CommandSender sender, int strength, String material) + { + if (strength < 0 || strength > 15) + { + getLogger().message(sender, true, "The strength must be between 0 and 15!"); + return true; + } + + Player player = (Player) sender; + if (player.getGameMode() != GameMode.CREATIVE) + { + getLogger().message(sender, true, "You must be in creative mode to do that"); + return true; + } + + Material itemType = Material.matchMaterial(material); + if (itemType == null) + { + getLogger().message(sender, true, "The material " + material + " could not be recognized"); + return true; + } + + // 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<Material>) 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(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 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<Block> containerBlocks = new ArrayList<>(); + containerBlocks.add(targetBlock); + + Material blockType = targetBlock.getType(); + if (inventory.getType() == InventoryType.CHEST) + { + 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 fullStackCount = itemCount / stackSize; + int remaining = itemCount % stackSize; + for (Block containerBlock : containerBlocks) + { + // Below checks should evaluate to false, but let's be safe. + 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(); + for (int i = 0; i < fullStackCount; i++) + 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); + return true; + } + + private static Inventory getInventory(Block b) + { + BlockState state = b.getState(); + if (state instanceof InventoryHolder) + return ((InventoryHolder) state).getInventory(); + return null; + } + + private static int computeRequiredItemCount(int strength, int stackSize, int slotCount) + { + 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) + { + return -1; + } + // 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('_', ' '); + } + +} |