diff --git a/pom.xml b/pom.xml index 1b5114f..d354aa0 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ de.eldoria bigdoorsopener - 2.2.3 + 2.3.0 BigDoorsOpener https://github.com/eldoriarpg/BigDoorOpener Open and close doors automatically on certain conditions @@ -135,7 +135,7 @@ de.eldoria EldoUtilities - v1.0.12 + v1.0.16 compile diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/BDOCommand.java b/src/main/java/de/eldoria/bigdoorsopener/commands/BDOCommand.java new file mode 100644 index 0000000..592fa33 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/BDOCommand.java @@ -0,0 +1,70 @@ +package de.eldoria.bigdoorsopener.commands; + +import com.google.common.cache.Cache; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.About; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.CloneDoor; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.CopyCondition; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.DoorList; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.GiveKey; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.Help; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.Info; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.InvertOpen; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.Reload; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.RemoveCondition; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.SetCondition; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.SetEvaluator; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.SetState; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.StayOpen; +import de.eldoria.bigdoorsopener.commands.bdosubcommands.Unregister; +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.scheduler.DoorChecker; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.messages.MessageSender; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import nl.pim16aap2.bigDoors.BigDoors; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; + +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class BDOCommand extends de.eldoria.eldoutilities.simplecommands.EldoCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + private final Cache> pluginCache = C.getExpiringCache(30, TimeUnit.SECONDS); + + public BDOCommand(BigDoorsOpener plugin, BigDoors doors, Config config, DoorChecker doorChecker) { + this.localizer = BigDoorsOpener.localizer(); + messageSender = MessageSender.get(plugin); + BukkitAudiences bukkitAudiences = BukkitAudiences.create(plugin); + Help help = new Help(plugin); + setDefaultCommand(help); + registerCommand("help", help); + registerCommand("about", new About(plugin)); + registerCommand("cloneDoor", new CloneDoor(doors, config)); + registerCommand("copyCondition", new CopyCondition(doors, config)); + registerCommand("giveKey", new GiveKey(doors, config)); + registerCommand("info", new Info(doors, plugin, config)); + registerCommand("invertOpen", new InvertOpen(doors, config)); + registerCommand("list", new DoorList(doors, config)); + registerCommand("reload", new Reload(config, doorChecker, plugin)); + registerCommand("removeCondition", new RemoveCondition(doors, config)); + registerCommand("setCondition", new SetCondition(doors, config)); + registerCommand("setEvaluator", new SetEvaluator(doors, config)); + registerCommand("stayOpen", new StayOpen(doors, config)); + registerCommand("unregister", new Unregister(doors, config)); + registerCommand("setState", new SetState(doors, config)); + } + + @Override + public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { + if (!super.onCommand(sender, command, label, args)) { + messageSender.sendError(sender, localizer.getMessage("error.invalidCommand")); + return true; + } + return true; + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/BigDoorsOpenerCommand.java b/src/main/java/de/eldoria/bigdoorsopener/commands/BigDoorsOpenerCommand.java deleted file mode 100644 index df48661..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/commands/BigDoorsOpenerCommand.java +++ /dev/null @@ -1,1777 +0,0 @@ -package de.eldoria.bigdoorsopener.commands; - -import com.google.common.cache.Cache; -import com.sk89q.worldedit.bukkit.BukkitAdapter; -import com.sk89q.worldguard.protection.managers.RegionManager; -import com.sk89q.worldguard.protection.regions.ProtectedRegion; -import com.sk89q.worldguard.protection.regions.RegionContainer; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.config.Config; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionChain; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; -import de.eldoria.bigdoorsopener.doors.conditions.item.ItemHolding; -import de.eldoria.bigdoorsopener.doors.conditions.item.ItemOwning; -import de.eldoria.bigdoorsopener.doors.conditions.item.interacting.ItemBlock; -import de.eldoria.bigdoorsopener.doors.conditions.item.interacting.ItemClick; -import de.eldoria.bigdoorsopener.doors.conditions.location.Proximity; -import de.eldoria.bigdoorsopener.doors.conditions.location.Region; -import de.eldoria.bigdoorsopener.doors.conditions.location.SimpleRegion; -import de.eldoria.bigdoorsopener.doors.conditions.permission.DoorPermission; -import de.eldoria.bigdoorsopener.doors.conditions.permission.PermissionNode; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.MythicMob; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Placeholder; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Time; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Weather; -import de.eldoria.bigdoorsopener.listener.registration.InteractionRegistrationObject; -import de.eldoria.bigdoorsopener.listener.registration.RegisterInteraction; -import de.eldoria.bigdoorsopener.scheduler.BigDoorsAdapter; -import de.eldoria.bigdoorsopener.scheduler.DoorChecker; -import de.eldoria.bigdoorsopener.util.C; -import de.eldoria.bigdoorsopener.util.CachingJSEngine; -import de.eldoria.bigdoorsopener.util.JsSyntaxHelper; -import de.eldoria.bigdoorsopener.util.Permissions; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.container.Pair; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.messages.MessageSender; -import de.eldoria.eldoutilities.utils.ArgumentUtils; -import de.eldoria.eldoutilities.utils.ArrayUtil; -import de.eldoria.eldoutilities.utils.EnumUtil; -import de.eldoria.eldoutilities.utils.Parser; -import io.lumine.xikage.mythicmobs.MythicMobs; -import net.kyori.adventure.platform.bukkit.BukkitAudiences; -import net.kyori.adventure.text.TextComponent; -import net.kyori.adventure.text.event.ClickEvent; -import net.kyori.adventure.text.format.Style; -import net.kyori.adventure.text.format.TextDecoration; -import nl.pim16aap2.bigDoors.BigDoors; -import nl.pim16aap2.bigDoors.Door; -import org.bukkit.Bukkit; -import org.bukkit.Location; -import org.bukkit.WeatherType; -import org.bukkit.World; -import org.bukkit.command.Command; -import org.bukkit.command.CommandSender; -import org.bukkit.command.TabExecutor; -import org.bukkit.entity.HumanEntity; -import org.bukkit.entity.Player; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.plugin.PluginDescriptionFile; -import org.bukkit.util.BlockVector; -import org.bukkit.util.Vector; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.OptionalDouble; -import java.util.OptionalInt; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.regex.Pattern; -import java.util.stream.Collectors; - -public class BigDoorsOpenerCommand extends BigDoorsAdapter implements TabExecutor { - private static final CachingJSEngine ENGINE; - // Tabcomplete utils - private static final String[] CONDITION_TYPES; - private static final String[] CONDITION_GROUPS; - private static final String[] PROXIMITY_FORM; - private static final String[] WEATHER_TYPE; - private static final String[] EVALUATOR_TYPES; - private final BigDoorsOpener plugin; - private final Config config; - private final Localizer localizer; - private final DoorChecker doorChecker; - private final MessageSender messageSender; - private final RegisterInteraction registerInteraction; - private final RegionContainer regionContainer; - private final BukkitAudiences bukkitAudiences; - - private final Cache> pluginCache = C.getExpiringCache(30, TimeUnit.SECONDS); - - static { - ENGINE = BigDoorsOpener.JS(); - CONDITION_TYPES = Arrays.stream(ConditionType.values()) - .map(v -> v.conditionName) - .toArray(String[]::new); - CONDITION_GROUPS = Arrays.stream(ConditionType.ConditionGroup.values()) - .map(v -> v.name().toLowerCase().replace("_", "")) - .toArray(String[]::new); - PROXIMITY_FORM = Arrays.stream(Proximity.ProximityForm.values()) - .map(v -> v.name().toLowerCase()) - .toArray(String[]::new); - WEATHER_TYPE = Arrays.stream(WeatherType.values()) - .map(v -> v.name().toLowerCase()) - .toArray(String[]::new); - EVALUATOR_TYPES = Arrays.stream(ConditionalDoor.EvaluationType.values()) - .map(v -> v.name().toLowerCase()) - .toArray(String[]::new); - } - - - public BigDoorsOpenerCommand(BigDoorsOpener plugin, BigDoors doors, Config config, Localizer localizer, - DoorChecker doorChecker, RegisterInteraction registerInteraction) { - super(doors, localizer); - this.plugin = plugin; - this.config = config; - this.localizer = localizer; - messageSender = MessageSender.get(plugin); - this.doorChecker = doorChecker; - this.registerInteraction = registerInteraction; - regionContainer = BigDoorsOpener.getRegionContainer(); - this.bukkitAudiences = BukkitAudiences.create(plugin); - } - - @Override - public boolean onCommand(CommandSender sender, Command command, String label, String[] args) { - Player player = null; - if (sender instanceof Player) { - player = (Player) sender; - } - - if (args.length == 0 || (args.length == 1 && "help".equalsIgnoreCase(args[0]))) { - return help(sender); - } - - String cmd = args[0]; - - if ("about".equalsIgnoreCase(cmd)) { - return about(player); - } - - // TODO: Password door. Enter a password to open a door when a player approaches it. https://hub.spigotmc.org/javadocs/spigot/org/bukkit/conversations/Conversation.html - - String[] arguments = new String[0]; - if (args.length > 1) { - arguments = Arrays.copyOfRange(args, 1, args.length); - } - - // - if ("setCondition".equalsIgnoreCase(cmd)) { - return setCondition(player, arguments); - } - - // remove a key from a door: - // - if ("removeCondition".equalsIgnoreCase(cmd)) { - return removeCondition(player, arguments); - } - - // [condition] - if ("copyCondition".equalsIgnoreCase(cmd)) { - return copyCondition(player, arguments); - } - - // [condition] - if ("cloneDoor".equalsIgnoreCase(cmd)) { - return copyCondition(player, arguments); - } - - //bdo givekey [amount] [target] - if ("giveKey".equalsIgnoreCase(cmd)) { - return giveKey(player, arguments); - } - - // bdo info - if ("info".equalsIgnoreCase(cmd)) { - return info(sender, arguments, player); - } - - // bdo unregister - if ("unregister".equalsIgnoreCase(cmd)) { - return unregister(arguments, player); - } - - // bdo invertOpen - if ("invertOpen".equalsIgnoreCase(cmd)) { - return invertOpen(arguments, player); - } - - // bdo setEvaluator - if ("setEvaluator".equalsIgnoreCase(cmd)) { - return setEvaluator(player, arguments); - } - - //bdo stayOpen - if ("stayOpen".equalsIgnoreCase(cmd)) { - return stayOpen(player, arguments); - } - - //bdo list - if ("list".equalsIgnoreCase(cmd)) { - return list(player); - } - - //bdo reload - if ("reload".equalsIgnoreCase(cmd)) { - return reload(player); - } - messageSender.sendError(player, localizer.getMessage("error.invalidCommand")); - return true; - } - - // bdo help - private boolean help(CommandSender sender) { - TextComponent component = TextComponent.builder() - .append(TextComponent.builder(localizer.getMessage("help.title", - Replacement.create("PLUGIN_NAME", plugin.getDescription().getName()))) - .style(Style.builder().decoration(TextDecoration.BOLD, true).color(TextColors.GOLD).build()).build()) - .append(TextComponent.newline()) - .append(TextComponent.builder("setCondition ") - .style(Style.builder() - .color(TextColors.GOLD) - .decoration(TextDecoration.BOLD, false) - .build())) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("syntax.conditionValues") + ">") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.setCondition")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("removeCondition") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + ">") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.removeCondition")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("copyCondition") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.sourceDoor") + "> <" - + localizer.getMessage("syntax.targetDoor") + "> [" - + localizer.getMessage("syntax.condition") + "]") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.copyCondition")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("cloneDoor") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.sourceDoor") + "> <" - + localizer.getMessage("syntax.targetDoor") + ">") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.cloneDoor")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("giveKey") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> [" - + localizer.getMessage("syntax.amount") + "] [" - + localizer.getMessage("syntax.player") + "]") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.giveKey")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("info") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + ">") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.info")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("unregister") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + ">") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.unregister")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("invertOpen").color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + ">") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.invertOpen")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("setEvaluator") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.evaluationType") + "> [" - + localizer.getMessage("syntax.customEvaluator") + "]") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.setEvaluator")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("stayOpen") - .color(TextColors.GOLD)) - .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.seconds") + ">") - .color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.stayOpen")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("list") - .color(TextColors.GOLD)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.list")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("reload") - .color(TextColors.GOLD)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.reload")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("about") - .color(TextColors.GOLD)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.about")) - .color(TextColors.DARK_GREEN)) - .append(TextComponent.newline()) - .append(TextComponent.builder("help") - .color(TextColors.GOLD)) - .append(TextComponent.newline()) - .append(TextComponent.builder(" " + localizer.getMessage("help.help")) - .color(TextColors.DARK_GREEN)) - .build(); - - bukkitAudiences.audience(sender).sendMessage(component); - return true; - } - - // bdo about - private boolean about(Player player) { - PluginDescriptionFile descr = plugin.getDescription(); - String info = localizer.getMessage("about", - Replacement.create("PLUGIN_NAME", "Big Doors Opener").addFormatting('b'), - Replacement.create("AUTHORS", String.join(", ", descr.getAuthors())).addFormatting('b'), - Replacement.create("VERSION", descr.getVersion()).addFormatting('b'), - Replacement.create("WEBSITE", descr.getWebsite()).addFormatting('b'), - Replacement.create("DISCORD", "https://discord.gg/JJdx3xe").addFormatting('b')); - messageSender.sendMessage(player, info); - return true; - } - - // bdo setCondition - private boolean setCondition(Player player, String[] args) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, args, 2, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> [" - + localizer.getMessage("syntax.conditionValues") + "]")) { - return true; - } - - Door playerDoor = getPlayerDoor(args[0], player); - - if (playerDoor == null) { - return true; - } - - ConditionalDoor conditionalDoor = getOrRegister(playerDoor, player); - - if (conditionalDoor == null) { - return true; - } - - ConditionType type = EnumUtil.parse(args[1], ConditionType.class, true); - - if (type == null) { - messageSender.sendError(player, localizer.getMessage("error.invalidConditionType")); - return true; - } - - if (denyAccess(player, type.conditionGroup.permission, Permissions.ALL_CONDITION)) { - return true; - } - - ItemStack itemInMainHand = null; - if (player != null) { - itemInMainHand = player.getInventory().getItemInMainHand().clone(); - } - - ConditionChain conditionChain = conditionalDoor.getConditionChain(); - - String[] conditionArgs = new String[0]; - if (args.length > 2) { - conditionArgs = Arrays.copyOfRange(args, 2, args.length); - } - - switch (type) { - // - case ITEM_CLICK: - // - case ITEM_BLOCK: - // - case ITEM_HOLDING: - // - case ITEM_OWNING: - if (player == null) { - messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); - return true; - } - - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("syntax.amount") + "> [" - + localizer.getMessage("tabcomplete.consumed") + "]")) { - return true; - } - - // parse amount - OptionalInt amount = Parser.parseInt(conditionArgs[0]); - if (!amount.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidAmount")); - return true; - } - - if (amount.getAsInt() > 64 || amount.getAsInt() < 1) { - messageSender.sendError(player, localizer.getMessage("error.invalidRange", - Replacement.create("MIN", 1).addFormatting('6'), - Replacement.create("MAX", 64).addFormatting('6'))); - return true; - } - - Optional consume = ArgumentUtils.getOptionalParameter(conditionArgs, 1, Optional.of(false), Parser::parseBoolean); - if (!consume.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); - return true; - } - - itemInMainHand.setAmount(amount.getAsInt()); - if (type == ConditionType.ITEM_BLOCK) { - ItemBlock itemBlock = new ItemBlock(itemInMainHand, consume.get()); - // Register Keyhole object at registration listener. - registerInteraction.register(player, event -> { - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { - return false; - } - if (event.getClickedBlock() == null) return false; - BlockVector blockVector = event.getClickedBlock().getLocation().toVector().toBlockVector(); - itemBlock.setPosition(blockVector); - conditionalDoor.getConditionChain().setItem(itemBlock); - config.safeConfig(); - event.setCancelled(true); - messageSender.sendMessage(player, localizer.getMessage("setCondition.itemBlockRegistered")); - return true; - }); - messageSender.sendMessage(player, localizer.getMessage("setCondition.itemblock")); - } else if (type == ConditionType.ITEM_CLICK) { - conditionChain.setItem(new ItemClick(itemInMainHand, consume.get())); - messageSender.sendMessage(player, localizer.getMessage("setCondition.itemClick")); - } else if (type == ConditionType.ITEM_OWNING) { - conditionChain.setItem(new ItemOwning(itemInMainHand, consume.get())); - messageSender.sendMessage(player, localizer.getMessage("setCondition.itemOwning")); - } else { - conditionChain.setItem(new ItemHolding(itemInMainHand, consume.get())); - messageSender.sendMessage(player, localizer.getMessage("setCondition.itemHolding")); - } - break; - //
- case PROXIMITY: - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("tabcomplete.dimensions") + "> [" - + localizer.getMessage("syntax.proximityForm") + "]")) { - return true; - } - - Vector vector; - String[] coords = conditionArgs[0].split(","); - - // parse the size. - if (coords.length == 1) { - OptionalDouble size = Parser.parseDouble(conditionArgs[0]); - if (!size.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidNumber")); - return true; - } - vector = new Vector(size.getAsDouble(), size.getAsDouble(), size.getAsDouble()); - } else if (coords.length == 3) { - OptionalDouble x = Parser.parseDouble(coords[0]); - OptionalDouble y = Parser.parseDouble(coords[1]); - OptionalDouble z = Parser.parseDouble(coords[2]); - if (x.isPresent() && y.isPresent() && z.isPresent()) { - vector = new Vector(x.getAsDouble(), y.getAsDouble(), z.getAsDouble()); - } else { - messageSender.sendError(player, localizer.getMessage("error.invalidNumber")); - return true; - } - } else { - messageSender.sendError(player, localizer.getMessage("error.invalidVector")); - return true; - } - - // check if vector is inside bounds. - if (vector.getX() < 1 || vector.getX() > 100 - || vector.getY() < 1 || vector.getY() > 100 - || vector.getZ() < 1 || vector.getZ() > 100) { - messageSender.sendError(player, localizer.getMessage("error.invalidRange", - Replacement.create("MIN", 1).addFormatting('6'), - Replacement.create("MAX", 100).addFormatting('6'))); - return true; - } - - Proximity.ProximityForm form = ArgumentUtils.getOptionalParameter(conditionArgs, 1, Proximity.ProximityForm.CUBOID, (s) -> EnumUtil.parse(s, Proximity.ProximityForm.class)); - - if (form == null) { - messageSender.sendError(player, localizer.getMessage("error.invalidForm")); - return true; - } - - conditionChain.setLocation(new Proximity(vector, form)); - - // TODO: display region - - messageSender.sendMessage(player, localizer.getMessage("setCondition.proximity")); - break; - // - case REGION: - if (regionContainer == null) { - messageSender.sendError(player, localizer.getMessage("error.wgNotEnabled")); - return true; - } - - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("tabcomplete.regionName") + ">")) { - return true; - } - - if (player == null) { - messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); - return true; - } - RegionManager rm = regionContainer.get(BukkitAdapter.adapt(player.getWorld())); - if (rm == null) { - messageSender.sendError(player, localizer.getMessage("error.regionNotFound")); - return true; - } - ProtectedRegion region = rm.getRegion(conditionArgs[0]); - if (region == null) { - messageSender.sendError(player, localizer.getMessage("error.regionNotFound")); - return true; - } - conditionChain.setLocation(new Region(region, player.getWorld())); - messageSender.sendMessage(player, localizer.getMessage("setCondition.region")); - break; - case SIMPLE_REGION: - messageSender.sendMessage(player, localizer.getMessage("setCondition.firstPoint")); - registerInteraction.register(player, new InteractionRegistrationObject() { - private String world; - private BlockVector first; - - @Override - public boolean register(PlayerInteractEvent event) { - if (event.getAction() != Action.LEFT_CLICK_BLOCK) { - return false; - } - BlockVector vec = event.getClickedBlock().getLocation().toVector().toBlockVector(); - if (first == null) { - world = event.getPlayer().getWorld().getName(); - first = vec; - event.setCancelled(true); - messageSender.sendMessage(player, localizer.getMessage("setCondition.secondPoint")); - return false; - } - conditionalDoor.getConditionChain().setLocation(new SimpleRegion(first, vec, world)); - config.safeConfig(); - event.setCancelled(true); - messageSender.sendMessage(player, localizer.getMessage("setCondition.simpleRegionRegisterd")); - return true; - } - }); - break; - // permission - case PERMISSION_NODE: - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("tabcomplete.permissionNode") + ">")) { - return true; - } - - conditionChain.setPermission(new PermissionNode(conditionArgs[0])); - messageSender.sendMessage(player, localizer.getMessage("setCondition.permissionNode")); - break; - case DOOR_PERMISSION: - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("tabcomplete.doorPermission") + ">")) { - return true; - } - - int i = DoorPermission.parsePermissionLevel(conditionArgs[0]); - if (i < 0) { - messageSender.sendError(player, localizer.getMessage("error.invalidAccessLevel")); - return true; - } - conditionChain.setPermission(new DoorPermission(i)); - messageSender.sendMessage(player, localizer.getMessage("setCondition.doorPermission")); - break; - case TIME: - if (argumentsInvalid(player, conditionArgs, 2, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("syntax.openTime") + "> <" - + localizer.getMessage("syntax.closeTime") + "> [" - + localizer.getMessage("tabcomplete.forceState") + "]")) { - return true; - } - - // parse time - OptionalInt open = Parser.parseInt(conditionArgs[0]); - if (!open.isPresent()) { - open = Parser.parseTimeToTicks(conditionArgs[0]); - if (!open.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidOpenTime")); - return true; - } - } - - OptionalInt close = Parser.parseInt(conditionArgs[1]); - if (!close.isPresent()) { - close = Parser.parseTimeToTicks(conditionArgs[1]); - if (!close.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidCloseTime")); - return true; - } - } - - if (close.getAsInt() < 0 || close.getAsInt() > 24000 - || open.getAsInt() < 0 || open.getAsInt() > 24000) { - messageSender.sendError(player, localizer.getMessage("error.invalidRange", - Replacement.create("MIN", 0).addFormatting('6'), - Replacement.create("MAX", 24000).addFormatting('6'))); - return true; - } - - // parse optional force argument. - Optional force = ArgumentUtils.getOptionalParameter(conditionArgs, 2, Optional.of(false), Parser::parseBoolean); - - if (!force.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); - return true; - } - conditionChain.setTime(new Time(open.getAsInt(), close.getAsInt(), force.get())); - messageSender.sendMessage(player, localizer.getMessage("setCondition.time", - Replacement.create("OPEN", Parser.parseTicksToTime(open.getAsInt())), - Replacement.create("CLOSE", Parser.parseTicksToTime(close.getAsInt())))); - break; - case WEATHER: - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("syntax.weatherType") + ">")) { - return true; - } - - WeatherType weatherType = null; - for (WeatherType value : WeatherType.values()) { - if (value.name().equalsIgnoreCase(conditionArgs[0])) { - weatherType = value; - } - } - if (weatherType == null) { - messageSender.sendError(player, localizer.getMessage("error.invalidWeatherType")); - return true; - } - - Optional forceWeather = ArgumentUtils.getOptionalParameter(conditionArgs, 1, Optional.of(false), Parser::parseBoolean); - - if (!forceWeather.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); - return true; - } - - conditionChain.setWeather(new Weather(weatherType, forceWeather.get())); - messageSender.sendMessage(player, localizer.getMessage("setCondition.weather", - Replacement.create("OPEN", weatherType == WeatherType.CLEAR - ? localizer.getMessage("conditionDesc.clear") - : localizer.getMessage("conditionDesc.downfall")))); - break; - case PLACEHOLDER: - if (!BigDoorsOpener.isPlaceholderEnabled()) { - messageSender.sendError(player, localizer.getMessage("error.placeholderNotFound")); - return true; - } - - if (player == null) { - messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); - return true; - } - - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("syntax.customEvaluator") + ">")) { - return true; - } - - String evaluator = String.join(" ", conditionArgs); - - Pair result = JsSyntaxHelper.checkExecution(evaluator, BigDoorsOpener.JS(), player, false); - - switch (result.first) { - case UNBALANCED_PARENTHESIS: - messageSender.sendError(player, localizer.getMessage("error.unbalancedParenthesis")); - return true; - case INVALID_VARIABLE: - messageSender.sendError(player, localizer.getMessage("error.invalidVariable", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case INVALID_OPERATOR: - messageSender.sendError(player, localizer.getMessage("error.invalidOperator", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case INVALID_SYNTAX: - messageSender.sendError(player, localizer.getMessage("error.invalidSyntax", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case EXECUTION_FAILED: - messageSender.sendError(player, localizer.getMessage("error.executionFailed", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case NON_BOOLEAN_RESULT: - messageSender.sendError(player, localizer.getMessage("error.nonBooleanResult", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case FINE: - conditionChain.setPlaceholder(new Placeholder(JsSyntaxHelper.translateEvaluator(evaluator))); - break; - } - - messageSender.sendMessage(player, localizer.getMessage("setCondition.placeholder")); - break; - case MYTHIC_MOBS: - if (!BigDoorsOpener.isMythicMobsEnabled()) { - messageSender.sendError(player, localizer.getMessage("error.mythicMob")); - return true; - } - - if (argumentsInvalid(player, conditionArgs, 1, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + "> <" - + localizer.getMessage("syntax.mobType") + ">")) { - return true; - } - - String mob = conditionArgs[0]; - - boolean exists = MythicMobs.inst().getAPIHelper().getMythicMob(mob) != null; - - if (!exists) { - messageSender.sendError(player, localizer.getMessage("error.invalidMob")); - return true; - } - - conditionChain.setCondition(ConditionType.ConditionGroup.MYTHIC_MOB, new MythicMob(mob)); - messageSender.sendMessage(player, localizer.getMessage("setCondition.mythicMob")); - break; - default: - messageSender.sendError(player, localizer.getMessage("error.invalidConditionType")); - return true; - } - - // check if condition is in evaluator if a custom evaluator is present. - if (conditionalDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { - Pattern compile = Pattern.compile(type.conditionGroup.conditionParameter, Pattern.CASE_INSENSITIVE); - if (!compile.matcher(conditionalDoor.getEvaluator()).find()) { - messageSender.sendError(player, localizer.getMessage("warning.valueNotInEvaluator", - Replacement.create("VALUE", type.conditionGroup.conditionParameter).addFormatting('6'))); - } - } - - config.safeConfig(); - return true; - } - - // bdo removeCondition - private boolean removeCondition(Player player, String[] arguments) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, arguments, 2, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.condition") + ">")) { - return false; - } - - Door playerDoor = getPlayerDoor(arguments[0], player); - - if (playerDoor == null) { - return true; - } - - ConditionalDoor cDoor = getOrRegister(playerDoor, player); - - if (cDoor == null) { - return true; - } - - ConditionType.ConditionGroup type = EnumUtil.parse(arguments[1], ConditionType.ConditionGroup.class, true); - if (type == null) { - messageSender.sendError(player, localizer.getMessage("error.invalidConditionType")); - return true; - } - - if (denyAccess(player, type.permission, Permissions.ALL_CONDITION)) { - return true; - } - - ConditionChain conditionChain = cDoor.getConditionChain(); - - if (conditionChain.getCondition(type) == null) { - messageSender.sendError(player, localizer.getMessage("error.conditionNotSet")); - return true; - } else { - conditionChain.removeCondition(type); - } - - switch (type) { - case ITEM: - messageSender.sendMessage(player, localizer.getMessage("removeCondition.item")); - break; - case LOCATION: - messageSender.sendMessage(player, localizer.getMessage("removeCondition.location")); - break; - case PERMISSION: - messageSender.sendMessage(player, localizer.getMessage("removeCondition.permission")); - break; - case TIME: - messageSender.sendMessage(player, localizer.getMessage("removeCondition.time")); - break; - case WEATHER: - messageSender.sendMessage(player, localizer.getMessage("removeCondition.weather")); - break; - case PLACEHOLDER: - messageSender.sendMessage(player, localizer.getMessage("removeCondition.placeholder")); - break; - case MYTHIC_MOB: - messageSender.sendMessage(player, localizer.getMessage("removeCondition.mythicMob")); - break; - } - - // check if condition is in evaluator if a custom evaluator is present. - if (cDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { - Pattern compile = Pattern.compile(type.conditionParameter, Pattern.CASE_INSENSITIVE); - if (compile.matcher(cDoor.getEvaluator()).find()) { - messageSender.sendError(player, localizer.getMessage("warning.valueStillUsed", - Replacement.create("VALUE", type.conditionParameter).addFormatting('6'))); - } - } - - if (conditionChain.isEmpty()) { - messageSender.sendMessage(player, localizer.getMessage("warning.chainIsEmpty")); - } - - config.safeConfig(); - return true; - } - - // bdo copyCondition [condition] - private boolean copyCondition(Player player, String[] arguments) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, arguments, 2, - "<" + localizer.getMessage("syntax.sourceDoor") + "> <" - + localizer.getMessage("syntax.targetDoor") + "> [" - + localizer.getMessage("syntax.condition") + "]")) { - return true; - } - - Door playerSourceDoor = getPlayerDoor(arguments[0], player); - - if (playerSourceDoor == null) { - return true; - } - - ConditionalDoor sourceDoor = getOrRegister(playerSourceDoor, player); - - if (sourceDoor == null) { - return true; - } - - Door playerTargetDoor = getPlayerDoor(arguments[1], player); - - if (playerTargetDoor == null) { - return true; - } - - ConditionalDoor targetDoor = getOrRegister(playerTargetDoor, player); - - if (targetDoor == null) { - return true; - } - - ConditionChain sourceChain = sourceDoor.getConditionChain(); - - if (arguments.length == 2) { - if (denyAccess(player, Permissions.ALL_CONDITION)) { - return true; - } - - targetDoor.setConditionChain(sourceChain.copy()); - messageSender.sendMessage(player, localizer.getMessage("copyCondition.copiedAll", - Replacement.create("SOURCE", playerSourceDoor.getName()).addFormatting('6'), - Replacement.create("TARGET", playerTargetDoor.getName()).addFormatting('6'))); - config.safeConfig(); - return true; - } - - ConditionType.ConditionGroup type = EnumUtil.parse(arguments[2], ConditionType.ConditionGroup.class); - - if (type == null) { - messageSender.sendError(player, localizer.getMessage("error.invalidConditionType")); - return true; - } - - if (denyAccess(player, type.permission, Permissions.ALL_CONDITION)) { - return true; - } - - ConditionChain targetChain = targetDoor.getConditionChain(); - - DoorCondition condition = sourceChain.getCondition(type); - - if (condition == null) { - messageSender.sendError(player, localizer.getMessage("error.conditionNotSet")); - return true; - } - - targetChain.setCondition(type, sourceChain.getCondition(type)); - - config.safeConfig(); - messageSender.sendMessage(player, localizer.getMessage("copyCondition.copiedSingle", - Replacement.create("CONDITION", type.conditionParameter).addFormatting('6'), - Replacement.create("SOURCE", playerSourceDoor.getName()).addFormatting('6'), - Replacement.create("TARGET", playerTargetDoor.getName()).addFormatting('6'))); - return true; - } - - private boolean cloneDoor(Player player, String[] arguments) { - if (denyAccess(player, Permissions.USE)) return true; - if (denyAccess(player, Permissions.ALL_CONDITION)) return true; - - if (argumentsInvalid(player, arguments, 2, - "<" + localizer.getMessage("syntax.sourceDoor") + "> <" - + localizer.getMessage("syntax.targetDoor") + ">")) { - return true; - } - - Door playerSourceDoor = getPlayerDoor(arguments[0], player); - - if (playerSourceDoor == null) return true; - - ConditionalDoor sourceDoor = getOrRegister(playerSourceDoor, player); - - if (sourceDoor == null) return true; - - Door playerTargetDoor = getPlayerDoor(arguments[1], player); - - if (playerTargetDoor == null) return true; - - ConditionalDoor targetDoor = getOrRegister(playerTargetDoor, player); - - if (targetDoor == null) return true; - - targetDoor.setConditionChain(sourceDoor.getConditionChain().copy()); - - targetDoor.setStayOpen(sourceDoor.getStayOpen()); - - if (sourceDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { - targetDoor.setEvaluator(sourceDoor.getEvaluator()); - } else { - targetDoor.setEvaluator(sourceDoor.getEvaluationType()); - } - - targetDoor.setInvertOpen(sourceDoor.isInvertOpen()); - - config.safeConfig(); - messageSender.sendMessage(player, localizer.getMessage("cloneDoor.message", - Replacement.create("SOURCE", playerSourceDoor.getName()).addFormatting('6'), - Replacement.create("TARGET", playerTargetDoor.getName()).addFormatting('6'))); - return true; - } - - // bdo giveKey - private boolean giveKey(Player player, String[] arguments) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (player == null) { - if (argumentsInvalid(null, arguments, 3, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.amount") + "> <" - + localizer.getMessage("syntax.player") + ">")) { - return true; - } - } else { - if (argumentsInvalid(player, arguments, 1, - "<" + localizer.getMessage("syntax.doorId") + "> [" - + localizer.getMessage("syntax.amount") + "] [" - + localizer.getMessage("syntax.player") + "]")) { - return true; - } - } - - Pair door = getConditionalPlayerDoor(arguments[0], player); - - if (door == null) { - return true; - } - - if (door.first.getConditionChain().getItem() == null) { - messageSender.sendError(player, localizer.getMessage("error.noItemConditionSet")); - return true; - } - - ItemStack item = door.first.getConditionChain().getItem().getItem(); - - OptionalInt amount = ArgumentUtils.getOptionalParameter(arguments, 1, OptionalInt.of(64), Parser::parseInt); - - if (!amount.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidAmount")); - return true; - } - - Player target = ArgumentUtils.getOptionalParameter(arguments, 2, player, Bukkit::getPlayer); - - if (target == null) { - messageSender.sendError(player, localizer.getMessage("error.playerNotFound")); - return true; - } - - ItemStack clone = item.clone(); - clone.setAmount(amount.getAsInt()); - target.getInventory().addItem(clone); - if (target != player) { - messageSender.sendMessage(player, localizer.getMessage("giveKey.send", - Replacement.create("AMOUNT", amount.getAsInt()), - Replacement.create("ITEMNAME", item.hasItemMeta() ? (item.getItemMeta().hasDisplayName() - ? item.getItemMeta().getDisplayName() - : item.getType().name().toLowerCase()) - : item.getType().name().toLowerCase()), - Replacement.create("TARGET", target.getDisplayName()))); - } - messageSender.sendMessage(target, localizer.getMessage("giveKey.received", - Replacement.create("AMOUNT", amount.getAsInt()), - Replacement.create("ITEMNAME", item.hasItemMeta() ? (item.getItemMeta().hasDisplayName() - ? item.getItemMeta().getDisplayName() - : item.getType().name().toLowerCase()) - : item.getType().name().toLowerCase()))); - return true; - } - - //bdo info - private boolean info(CommandSender sender, String[] args, Player player) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, args, 1, "<" + localizer.getMessage("syntax.doorId") + ">")) { - return true; - } - - Pair door = getConditionalPlayerDoor(args[0], player); - if (door == null) { - return true; - } - - ConditionalDoor cDoor = door.first; - TextComponent.Builder builder = TextComponent.builder() - .append(TextComponent.builder(door.second.getName() + " ").color(C.highlightColor).decoration(TextDecoration.BOLD, true)) - .append(TextComponent.builder("(Id:" + door.second.getDoorUID() + ") ").decoration(TextDecoration.BOLD, true)).color(C.highlightColor) - .append(TextComponent.builder(localizer.getMessage("info.info")).color(C.baseColor).decoration(TextDecoration.BOLD, true)) - .append(TextComponent.newline()).decoration(TextDecoration.BOLD, false) - .append(TextComponent.builder(localizer.getMessage("info.world") + " ").color(C.baseColor)) - .append(TextComponent.builder(cDoor.getWorld()).color(C.highlightColor)) - .append(TextComponent.newline() - .append(TextComponent.builder(""))); - - // append evaluator - builder.append(TextComponent.builder(localizer.getMessage("info.evaluator") + " ").color(C.baseColor)); - if (cDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { - builder.append(TextComponent.builder(cDoor.getEvaluator() + " ").color(C.highlightColor)) - .append(TextComponent.builder("[" + localizer.getMessage("info.edit") + "]") - .style(Style.builder().decoration(TextDecoration.UNDERLINED, true) - .color(TextColors.GREEN).build()) - .clickEvent(ClickEvent.suggestCommand("/bdo setEvaluator " + cDoor.getDoorUID() + " custom " + cDoor.getEvaluator()))); - } else { - builder.append(TextComponent.builder(cDoor.getEvaluationType().name()).color(C.highlightColor)); - } - builder.append(TextComponent.newline()); - - // append open time - builder.append(TextComponent.builder(localizer.getMessage("info.stayOpen") + " ").color(C.baseColor)) - .append(TextComponent.builder(cDoor.getStayOpen() + " ").color(C.highlightColor)) - .append(TextComponent.builder("[" + localizer.getMessage("info.edit") + "]") - .style(Style.builder().decoration(TextDecoration.UNDERLINED, true) - .color(TextColors.GREEN).build()) - .clickEvent(ClickEvent.suggestCommand("/bdo stayOpen " + cDoor.getDoorUID() + " " + cDoor.getStayOpen()))) - .append(TextComponent.newline()); - - // start of key list - builder.append(TextComponent.builder(localizer.getMessage("info.conditions")) - .style(Style.builder().color(C.highlightColor).decoration(TextDecoration.BOLD, true).build())); - - ConditionChain conditionChain = cDoor.getConditionChain(); - - for (Pair condition : conditionChain.getConditionsWrapped()) { - builder.append(TextComponent.newline()); - if (condition.first != null) { - builder.append(condition.first.getDescription(localizer)) - .append(TextComponent.newline()) - .append(TextComponent.builder("[" + localizer.getMessage("info.remove") + "]") - .style(Style.builder().color(TextColors.DARK_RED) - .decoration(TextDecoration.UNDERLINED, true).build()) - .clickEvent(ClickEvent.runCommand(condition.first.getRemoveCommand(cDoor)))) - .append(TextComponent.builder(" ")) - .append(TextComponent.builder("[" + localizer.getMessage("info.edit") + "]") - .style(Style.builder().color(TextColors.GREEN) - .decoration(TextDecoration.UNDERLINED, true).build()) - .clickEvent(ClickEvent.suggestCommand(condition.first.getCreationCommand(cDoor)))); - } else { - builder.append(TextComponent.builder(localizer.getMessage(condition.second.infoKey) + " ").color(TextColors.AQUA)) - .append(TextComponent.newline()) - .append(TextComponent.builder("[" + localizer.getMessage("info.add") + "]") - .color(TextColors.GREEN) - .clickEvent(ClickEvent.suggestCommand(condition.second.getBaseSetCommand(cDoor)))); - } - } - - bukkitAudiences.audience(sender).sendMessage(builder.build()); - return true; - } - - //bdo unregister - private boolean unregister(String[] args, Player player) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, args, 1, "<" + localizer.getMessage("syntax.doorId") + ">")) { - return true; - } - - Pair door = getConditionalPlayerDoor(args[0], player); - - if (door == null) { - return true; - } - - config.getDoors().remove(door.second.getDoorUID()); - doorChecker.unregister(door.first); - config.safeConfig(); - - messageSender.sendMessage(player, localizer.getMessage("unregister.message", - Replacement.create("DOOR_NAME", door.second.getName()).addFormatting('6'))); - return true; - } - - //bdo invertOpen - private boolean invertOpen(String[] args, Player player) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, args, 1, "<" + localizer.getMessage("syntax.doorId") + ">")) { - return true; - } - - Pair door = getConditionalPlayerDoor(args[0], player); - if (door == null) { - return true; - } - - door.first.invertOpen(); - messageSender.sendMessage(player, localizer.getMessage("invertOpen.inverted")); - config.safeConfig(); - return true; - } - - //bod setEvaluator [args] - private boolean setEvaluator(Player player, String[] arguments) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, arguments, 2, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.evaluationType") + "> [" - + localizer.getMessage("syntax.customEvaluator") + "]")) { - return true; - } - - Pair door = getConditionalPlayerDoor(arguments[0], player); - - if (door == null) { - return true; - } - - ConditionalDoor.EvaluationType type = EnumUtil.parse(arguments[1], ConditionalDoor.EvaluationType.class, false); - if (type == null) { - messageSender.sendMessage(player, localizer.getMessage("error.invalidEvaluationType")); - return true; - } - - if (type != ConditionalDoor.EvaluationType.CUSTOM) { - door.first.setEvaluator(type); - if (type == ConditionalDoor.EvaluationType.AND) { - messageSender.sendMessage(player, localizer.getMessage("setEvaluator.and")); - } else { - messageSender.sendMessage(player, localizer.getMessage("setEvaluator.or")); - } - config.safeConfig(); - return true; - } - - if (denyAccess(player, Permissions.CUSTOM_EVALUATOR)) { - return true; - } - - if (arguments.length < 3) { - messageSender.sendError(player, localizer.getMessage("error.noEvaluatorFound")); - return true; - } - String evaluator = String.join(" ", Arrays.copyOfRange(arguments, 2, arguments.length)); - Pair result = JsSyntaxHelper.validateEvaluator(evaluator, ENGINE); - - switch (result.first) { - case UNBALANCED_PARENTHESIS: - messageSender.sendError(player, localizer.getMessage("error.unbalancedParenthesis")); - return true; - case INVALID_VARIABLE: - messageSender.sendError(player, localizer.getMessage("error.invalidVariable", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case INVALID_OPERATOR: - messageSender.sendError(player, localizer.getMessage("error.invalidOperator", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case INVALID_SYNTAX: - messageSender.sendError(player, localizer.getMessage("error.invalidSyntax", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case EXECUTION_FAILED: - messageSender.sendError(player, localizer.getMessage("error.executionFailed", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case NON_BOOLEAN_RESULT: - messageSender.sendError(player, localizer.getMessage("error.nonBooleanResult", - Replacement.create("ERROR", result.second).addFormatting('6'))); - return true; - case FINE: - door.first.setEvaluator(JsSyntaxHelper.translateEvaluator(evaluator)); - break; - } - config.safeConfig(); - messageSender.sendMessage(player, localizer.getMessage("setEvaluator.custom", - Replacement.create("EVALUATOR", door.first.getEvaluator()).addFormatting('6'))); - return true; - } - - // bdo stayOpen - private boolean stayOpen(Player player, String[] arguments) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - if (argumentsInvalid(player, arguments, 2, - "<" + localizer.getMessage("syntax.doorId") + "> <" - + localizer.getMessage("syntax.seconds") + ">")) { - return true; - } - - Pair door = getConditionalPlayerDoor(arguments[0], player); - - if (door == null) { - return true; - } - - OptionalInt optionalInt = Parser.parseInt(arguments[1]); - if (!optionalInt.isPresent()) { - messageSender.sendError(player, localizer.getMessage("error.invalidAmount")); - return true; - } - door.first.setStayOpen(optionalInt.getAsInt()); - messageSender.sendMessage(player, localizer.getMessage("stayOpen.message", - Replacement.create("SECONDS", optionalInt.getAsInt()))); - config.safeConfig(); - return true; - } - - // bdo list - private boolean list(Player player) { - if (denyAccess(player, Permissions.USE)) { - return true; - } - - Map doors = config.getDoors(); - StringBuilder builder = new StringBuilder(localizer.getMessage("list.title")).append("\n"); - - if (player.hasPermission(Permissions.ACCESS_ALL)) { - for (ConditionalDoor value : doors.values()) { - Door door = getDoor(null, String.valueOf(value.getDoorUID())); - builder.append(value.getDoorUID()).append(" | ") - .append("§6").append(door.getName()).append("§r") - .append(" (").append(door.getWorld().getName()).append(")\n"); - } - } else { - List registeredDoors = getDoors(player, null) - .stream() - .filter(d -> doors.containsKey(d.getDoorUID())) - .collect(Collectors.toList()); - for (Door value : registeredDoors) { - builder.append(value.getDoorUID()).append(" | ") - .append("§6").append(value.getName()).append("§r") - .append(" (").append(value.getWorld().getName()).append(")\n"); - } - } - - messageSender.sendMessage(player, builder.toString()); - return true; - } - - // bdo reload - private boolean reload(Player player) { - if (denyAccess(player, Permissions.RELOAD)) { - return true; - } - - config.reloadConfig(); - doorChecker.reload(); - plugin.onEnable(); - messageSender.sendMessage(player, localizer.getMessage("reload.completed")); - return true; - } - - /** - * Returns the door from config or creates it if not in config. - * - * @param door door to get. - * @param player player which wants to get the door. - * @return door or null if the door does not exist in BD. - */ - private ConditionalDoor getOrRegister(Door door, Player player) { - World world = door.getWorld(); - - if (world == null) { - messageSender.sendError(player, localizer.getMessage("error.worldNotLoaded")); - return null; - } - - if (config.getDoors().containsKey(door.getDoorUID())) { - return config.getDoors().get(door.getDoorUID()); - } - - Location max = door.getMaximum(); - Location min = door.getMinimum(); - Vector vector = new Vector( - (max.getX() + min.getX()) / 2, - (max.getY() + min.getY()) / 2, - (max.getZ() + min.getZ()) / 2); - - ConditionalDoor conditionalDoor = config.getDoors().computeIfAbsent(door.getDoorUID(), - doorId -> new ConditionalDoor(doorId, world.getName(), vector)); - - doorChecker.register(conditionalDoor); - return conditionalDoor; - } - - /** - * Tries to find the door for a player. - * Will call {@link #getPlayerDoor(String, Player)} to retrieve a door. - * Will check if the door is already registered. - * - * @param doorUID uid or name of the door - * @param player player which requests this door. - * @return door with conditional door or null if the door is not registered or the user has no access. - */ - private Pair getConditionalPlayerDoor(String doorUID, Player player) { - Door door = getPlayerDoor(doorUID, player); - if (door == null) { - return null; - } - - ConditionalDoor timedDoor = config.getDoors().get(door.getDoorUID()); - if (timedDoor == null) { - messageSender.sendMessage(player, localizer.getMessage("error.doorNotRegistered")); - return null; - } - return new Pair<>(timedDoor, door); - } - - /** - * Tries to find a door. - * Will search for a door of the player. - * If no door is found a search in all doors by id is performed. - * If the player has the {@link Permissions#ACCESS_ALL} permission, - * a door will be returned even when its not owned by the player. - * - * @param doorUID uid or name of the door. - * @param player player which performed the request. - * @return door if the door exists and the player is allowed to access it. Otherwise null. - */ - private Door getPlayerDoor(String doorUID, Player player) { - if (player == null) { - // requester is console. should always have access to all doors. - Door door = getDoor(null, doorUID); - if (door == null) { - messageSender.sendError(null, localizer.getMessage("error.doorNotFound")); - return null; - } - return door; - } - - // sender id not console. retrieve door of player. - List doors = getDoors(player, doorUID); - - if (doors.isEmpty()) { - // door is null. check if door exists anyway - Door door = getDoor(null, doorUID); - if (door == null) { - messageSender.sendError(player, localizer.getMessage("error.doorNotFound")); - return null; - } - // when the door exists and the player has access to all doors return it. - if (player.hasPermission(Permissions.ACCESS_ALL)) { - return door; - } else { - messageSender.sendError(player, localizer.getMessage("error.notYourDoor")); - } - return null; - } - - if (doors.size() != 1) { - messageSender.sendMessage(player, localizer.getMessage("error.ambiguousDoorName")); - return null; - } - - return doors.get(0); - } - - /** - * Checks if the provided arguments are invalid. - * - * @param player player which executed the command. - * @param args arguments to check - * @param length min amount of arguments. - * @param syntax correct syntax - * @return true if the arguments are invalid - */ - private boolean argumentsInvalid(Player player, String[] args, int length, String syntax) { - if (args.length < length) { - messageSender.sendError(player, localizer.getMessage("error.invalidArguments", - Replacement.create("SYNTAX", syntax).addFormatting('6'))); - return true; - } - return false; - } - - private boolean denyAccess(CommandSender sender, String... permissions) { - return denyAccess(sender, false, permissions); - } - - private boolean denyAccess(CommandSender sender, boolean silent, String... permissions) { - if (sender == null) { - return false; - } - - Player player = null; - - if (sender instanceof Player) { - player = (Player) sender; - } - - if (player == null) { - return false; - } - for (String permission : permissions) { - if (player.hasPermission(permission)) { - return false; - } - } - if (!silent) { - messageSender.sendMessage(player, localizer.getMessage("error.permission", - Replacement.create("PERMISSION", String.join(", ", permissions)).addFormatting('6'))); - } - return true; - } - - @Override - public List onTabComplete(CommandSender sender, Command command, String alias, String[] args) { - String cmd = args[0]; - - if (!(sender instanceof Player)) return null; - Player player = (Player) sender; - - if (args.length > 10) { - return Collections.singletonList("(╯°□°)╯︵ ┻━┻"); - } - - if (args.length == 1) { - return ArrayUtil.startingWithInArray(cmd, - new String[] {"help", "about", - "setCondition", "removeCondition", "copyCondition", "cloneDoor", - "info", "giveKey", "unregister", "invertOpen", "setEvaluator", - "stayOpen", "list", "reload"}) - .collect(Collectors.toList()); - } - - if ("setCondition".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - if (args.length == 3) { - return ArrayUtil.startingWithInArray(args[2], CONDITION_TYPES).collect(Collectors.toList()); - } - - ConditionType type = EnumUtil.parse(args[2], ConditionType.class, true); - if (type == null) { - return Collections.singletonList(localizer.getMessage("error.invalidConditionType")); - } - - if (denyAccess(sender, true, type.conditionGroup.permission, Permissions.ALL_CONDITION)) { - return Collections.singletonList(localizer.getMessage("error.permission", - Replacement.create("PERMISSION", type.conditionGroup.permission + ", " + Permissions.ALL_CONDITION))); - } - - switch (type) { - case ITEM_CLICK: - case ITEM_BLOCK: - case ITEM_HOLDING: - case ITEM_OWNING: - if (args.length == 4) { - return Collections.singletonList("<" + localizer.getMessage("syntax.amount") + ">"); - } - if (args.length == 5) { - if (args[4].isEmpty()) { - return Arrays.asList("true", "false"); - } - return Arrays.asList("[" + localizer.getMessage("tabcomplete.consumed") + "]", "true", "false"); - } - break; - case PROXIMITY: - if (args.length == 4) { - return Arrays.asList("<" + localizer.getMessage("tabcomplete.dimensions") + ">", ""); - } - if (args.length == 5) { - return ArrayUtil.startingWithInArray(args[4], PROXIMITY_FORM).collect(Collectors.toList()); - } - break; - case REGION: - if (args.length == 4) { - return Collections.singletonList("<" + localizer.getMessage("tabcomplete.regionName") + ">"); - } - break; - case PERMISSION_NODE: - if (args.length == 4) { - return Collections.singletonList("<" + localizer.getMessage("tabcomplete.permissionNode") + ">"); - } - break; - case DOOR_PERMISSION: - if (args.length == 4) { - return ArrayUtil.startingWithInArray(args[3], new String[] {"owner", "editor", "user"}).collect(Collectors.toList()); - } - break; - case TIME: - if (args.length == 4) { - return Collections.singletonList("<" + localizer.getMessage("tabcomplete.setTimed.open") + ">"); - } - if (args.length == 5) { - return Collections.singletonList("<" + localizer.getMessage("tabcomplete.setTimed.close") + ">"); - } - if (args.length == 6) { - if (args[5].isEmpty()) { - return Arrays.asList("true", "false"); - } - return Arrays.asList("[" + localizer.getMessage("tabcomplete.forceState") + "]", "true", "false"); - } - break; - case WEATHER: - if (args.length == 4) { - return ArrayUtil.startingWithInArray(args[3], WEATHER_TYPE).collect(Collectors.toList()); - } - break; - case PLACEHOLDER: - return Collections.singletonList("<" + localizer.getMessage("syntax.customEvaluator") + ">"); - case MYTHIC_MOBS: - List mythicMobs; - try { - mythicMobs = (List) pluginCache.get("mythicMobs", () -> MythicMobs.inst() - .getMobManager().getMobTypes() - .parallelStream() - .map(m -> m.getInternalName()) - .collect(Collectors.toList())); - } catch (ExecutionException e) { - plugin.getLogger().log(Level.WARNING, "Could not build mob names.", e); - return Collections.emptyList(); - } - return ArrayUtil.startingWithInArray(args[3], mythicMobs.toArray(new String[0])).collect(Collectors.toList()); - } - } - - if ("removeCondition".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - if (args.length == 3) { - return ArrayUtil.startingWithInArray(args[2], CONDITION_GROUPS).collect(Collectors.toList()); - } - } - - if ("copyCondition".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - if (args.length == 3) { - return getDoorCompletion(player, args[2]); - } - if (args.length == 4) { - return ArrayUtil.startingWithInArray(args[3], CONDITION_GROUPS).collect(Collectors.toList()); - } - } - - if ("cloneDoor".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - if (args.length == 3) { - return getDoorCompletion(player, args[2]); - } - } - - if ("info".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - } - - if ("unregister".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - } - - if ("invertOpen".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - } - - if ("setEvaluator".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - if (args.length == 3) { - return ArrayUtil.startingWithInArray(args[2], EVALUATOR_TYPES).collect(Collectors.toList()); - } - - ConditionalDoor.EvaluationType parse = EnumUtil.parse(args[2], ConditionalDoor.EvaluationType.class); - - if (parse == null) { - return Collections.singletonList(localizer.getMessage("error.invalidEvaluationType")); - } - - if (parse == ConditionalDoor.EvaluationType.CUSTOM) { - if (denyAccess(sender, true, Permissions.CUSTOM_EVALUATOR)) { - return Collections.singletonList(localizer.getMessage("error.permission", - Replacement.create("PERMISSION", Permissions.CUSTOM_EVALUATOR))); - } - ArrayList list = new ArrayList<>(Arrays.asList(CONDITION_GROUPS)); - list.add("<" + localizer.getMessage("tabcomplete.validValues") + ">"); - list.add("currentState"); - return list; - } - } - - if ("giveKey".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - - if (args.length == 3) { - return Collections.singletonList("<" + localizer.getMessage("syntax.amount") + ">"); - } - - if (args.length == 4) { - return Bukkit.getOnlinePlayers().stream() - .filter(p -> p.getName().toLowerCase().startsWith(args[3])) - .map(HumanEntity::getName) - .collect(Collectors.toList()); - } - } - - if ("stayOpen".equalsIgnoreCase(cmd)) { - if (args.length == 2) { - return getDoorCompletion(player, args[1]); - } - if (args.length == 3) { - return Collections.singletonList("<" + localizer.getMessage("syntax.amount") + ">"); - } - } - - return Collections.emptyList(); - } - - @SuppressWarnings("unchecked") - public List getDoorCompletion(Player player, String name) { - if (player == null) { - return Collections.singletonList("<" + localizer.getMessage("syntax.doorId") + ">"); - } - List doors; - try { - doors = (List) pluginCache.get("doors", - () -> new ArrayList<>(getDoors())); - } catch (ExecutionException e) { - plugin.getLogger().log(Level.WARNING, "Could not build tab completion cache for door names.", e); - return Collections.singletonList("<" + localizer.getMessage("syntax.doorId") + ">"); - } - List doorNames; - try { - doorNames = (List) pluginCache.get(player.getName() + "doors", - () -> { - if (player.hasPermission(Permissions.ACCESS_ALL)) { - return doors.stream() - .map(d -> d.getPlayerUUID().equals(player.getUniqueId()) - ? d.getName() : String.valueOf(d.getDoorUID())) - .collect(Collectors.toList()); - } - - // Map door names for doors where the player is the creator and can use the door name - return getDoors(player).stream() - .map(d -> d.getPermission() == 0 ? d.getName() : String.valueOf(d.getDoorUID())) - .collect(Collectors.toList()); - }); - } catch ( - ExecutionException e) { - plugin.getLogger().log(Level.WARNING, "Could not build tab completion cache for door names.", e); - return Collections.singletonList("<" + localizer.getMessage("syntax.doorId") + ">"); - } - - return ArrayUtil.startingWithInArray(name, - doorNames.toArray(new String[0])) - .collect(Collectors.toList()); - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/CommandHelper.java b/src/main/java/de/eldoria/bigdoorsopener/commands/CommandHelper.java new file mode 100644 index 0000000..74e0d99 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/CommandHelper.java @@ -0,0 +1,88 @@ +package de.eldoria.bigdoorsopener.commands; + +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +public final class CommandHelper { + private static final Localizer LOCALIZER; + + static { + LOCALIZER = BigDoorsOpener.localizer(); + } + + private CommandHelper() { + } + + /** + * Checks if the provided arguments are invalid. + * + * @param sender user which executed the command. + * @param args arguments to check + * @param length min amount of arguments. + * @param syntax correct syntax + * @return true if the arguments are invalid + */ + public static boolean argumentsInvalid(CommandSender sender, String[] args, int length, String syntax) { + return argumentsInvalid(sender, BigDoorsOpener.getPluginMessageSender(), BigDoorsOpener.localizer(), args, length, syntax); + } + + /** + * Checks if the provided arguments are invalid. + * + * @param sender user which executed the command. + * @param messageSender message sender for calling home. + * @param localizer localizer for localization stuff. + * @param args arguments to check + * @param length min amount of arguments. + * @param syntax correct syntax + * @return true if the arguments are invalid + */ + public static boolean argumentsInvalid(CommandSender sender, MessageSender messageSender, Localizer localizer, String[] args, int length, String syntax) { + if (args.length < length) { + messageSender.sendError(sender, localizer.getMessage("error.invalidArguments", + Replacement.create("SYNTAX", syntax).addFormatting('6'))); + return true; + } + return false; + } + + + public static boolean denyAccess(CommandSender sender, String... permissions) { + return denyAccess(sender, false, permissions); + } + + public static boolean denyAccess(CommandSender sender, boolean silent, String... permissions) { + if (sender == null) { + return false; + } + + Player player = null; + + if (sender instanceof Player) { + player = (Player) sender; + } + + if (player == null) { + return false; + } + for (String permission : permissions) { + if (player.hasPermission(permission)) { + return false; + } + } + if (!silent) { + BigDoorsOpener.getPluginMessageSender().sendMessage(player, + LOCALIZER.getMessage("error.permission", + Replacement.create("PERMISSION", String.join(", ", permissions)).addFormatting('6'))); + } + return true; + } + + public static Player getPlayerFromSender(CommandSender sender) { + return sender instanceof Player ? (Player) sender : null; + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/About.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/About.java new file mode 100644 index 0000000..3306c5f --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/About.java @@ -0,0 +1,45 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; +import org.bukkit.plugin.PluginDescriptionFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +public class About extends de.eldoria.eldoutilities.simplecommands.EldoCommand { + private final Localizer localizer; + private final Plugin plugin; + private final MessageSender messageSender; + + public About(Plugin plugin) { + this.localizer = BigDoorsOpener.localizer(); + this.plugin = plugin; + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + PluginDescriptionFile descr = plugin.getDescription(); + String info = localizer.getMessage("about", + Replacement.create("PLUGIN_NAME", "Big Doors Opener").addFormatting('b'), + Replacement.create("AUTHORS", String.join(", ", descr.getAuthors())).addFormatting('b'), + Replacement.create("VERSION", descr.getVersion()).addFormatting('b'), + Replacement.create("WEBSITE", descr.getWebsite()).addFormatting('b'), + Replacement.create("DISCORD", "https://discord.gg/JJdx3xe").addFormatting('b')); + messageSender.sendMessage(sender, info); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/CloneDoor.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/CloneDoor.java new file mode 100644 index 0000000..48b2b4b --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/CloneDoor.java @@ -0,0 +1,98 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.core.events.DoorModifiedEvent; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class CloneDoor extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public CloneDoor(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) return true; + if (denyAccess(sender, Permissions.ALL_CONDITION)) return true; + + if (argumentsInvalid(sender, args, 2, + "<" + localizer.getMessage("syntax.sourceDoor") + "> <" + + localizer.getMessage("syntax.targetDoor") + ">")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Door playerSourceDoor = getPlayerDoor(args[0], playerFromSender); + + if (playerSourceDoor == null) return true; + + ConditionalDoor sourceDoor = getOrRegister(playerSourceDoor, playerFromSender); + + if (sourceDoor == null) return true; + + Door playerTargetDoor = getPlayerDoor(args[1], playerFromSender); + + if (playerTargetDoor == null) return true; + + ConditionalDoor targetDoor = getOrRegister(playerTargetDoor, playerFromSender); + + if (targetDoor == null) return true; + + targetDoor.setConditionBag(sourceDoor.getConditionBag().copy()); + + targetDoor.setStayOpen(sourceDoor.getStayOpen()); + + if (sourceDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { + targetDoor.setEvaluator(sourceDoor.getEvaluator()); + } else { + targetDoor.setEvaluator(sourceDoor.getEvaluationType()); + } + + targetDoor.setInvertOpen(sourceDoor.isInvertOpen()); + + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(targetDoor)); + + messageSender.sendMessage(sender, localizer.getMessage("cloneDoor.message", + Replacement.create("SOURCE", playerSourceDoor.getName()).addFormatting('6'), + Replacement.create("TARGET", playerTargetDoor.getName()).addFormatting('6'))); + return true; + + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + if (args.length == 2) { + return getDoorCompletion(sender, args[1]); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/CopyCondition.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/CopyCondition.java new file mode 100644 index 0000000..6122659 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/CopyCondition.java @@ -0,0 +1,140 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.core.conditions.ConditionGroup; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class CopyCondition extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public CopyCondition(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 2, + "<" + localizer.getMessage("syntax.sourceDoor") + "> <" + + localizer.getMessage("syntax.targetDoor") + "> [" + + localizer.getMessage("syntax.condition") + "]")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Door playerSourceDoor = getPlayerDoor(args[0], playerFromSender); + + if (playerSourceDoor == null) { + return true; + } + + ConditionalDoor sourceDoor = getOrRegister(playerSourceDoor, playerFromSender); + + if (sourceDoor == null) { + return true; + } + + Door playerTargetDoor = getPlayerDoor(args[1], playerFromSender); + + if (playerTargetDoor == null) { + return true; + } + + ConditionalDoor targetDoor = getOrRegister(playerTargetDoor, playerFromSender); + + if (targetDoor == null) { + return true; + } + + ConditionBag sourceBag = sourceDoor.getConditionBag(); + + if (args.length == 2) { + if (denyAccess(sender, Permissions.ALL_CONDITION)) { + return true; + } + + targetDoor.setConditionBag(sourceBag.copy()); + messageSender.sendMessage(sender, localizer.getMessage("copyCondition.copiedAll", + Replacement.create("SOURCE", playerSourceDoor.getName()).addFormatting('6'), + Replacement.create("TARGET", playerTargetDoor.getName()).addFormatting('6'))); + return true; + } + + Optional optionalGroup = ConditionRegistrar.getConditionGroup(args[2]); + + if (!optionalGroup.isPresent()) { + messageSender.sendError(sender, localizer.getMessage("error.invalidConditionType")); + return true; + } + + ConditionGroup conditionGroup = optionalGroup.get(); + + if (denyAccess(sender, Permissions.getConditionPermission(conditionGroup.getName()), Permissions.ALL_CONDITION)) { + return true; + } + + ConditionBag targetBag = targetDoor.getConditionBag(); + + Optional condition = sourceBag.getCondition(conditionGroup); + + if (!condition.isPresent()) { + messageSender.sendError(sender, localizer.getMessage("error.conditionNotSet")); + return true; + } + + targetBag.putCondition(condition.get().clone()); + + messageSender.sendMessage(sender, localizer.getMessage("copyCondition.copiedSingle", + Replacement.create("CONDITION", conditionGroup.getName()).addFormatting('6'), + Replacement.create("SOURCE", playerSourceDoor.getName()).addFormatting('6'), + Replacement.create("TARGET", playerTargetDoor.getName()).addFormatting('6'))); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + if (args.length == 2) { + return getDoorCompletion(sender, args[1]); + } + if (args.length == 3) { + return ArrayUtil.startingWithInArray(args[2], ConditionRegistrar.getGroups().toArray(new String[0])).collect(Collectors.toList()); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/DoorList.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/DoorList.java new file mode 100644 index 0000000..48473a5 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/DoorList.java @@ -0,0 +1,76 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.messages.MessageSender; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.Map; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class DoorList extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + private final Config config; + + public DoorList(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.config = config; + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + Map doors = config.getDoorMap(); + StringBuilder builder = new StringBuilder(localizer.getMessage("list.title")).append("\n"); + + Player playerFromSender = getPlayerFromSender(sender); + + if (sender.hasPermission(Permissions.ACCESS_ALL)) { + for (ConditionalDoor value : doors.values()) { + Door door = getDoor(String.valueOf(value.getDoorUID())); + builder.append(value.getDoorUID()).append(" | ") + .append("§6").append(door.getName()).append("§r") + .append(" (").append(door.getWorld().getName()).append(")\n"); + } + } else { + java.util.List registeredDoors = getDoors(playerFromSender, null) + .stream() + .filter(d -> doors.containsKey(d.getDoorUID())) + .collect(Collectors.toList()); + for (Door value : registeredDoors) { + builder.append(value.getDoorUID()).append(" | ") + .append("§6").append(value.getName()).append("§r") + .append(" (").append(value.getWorld().getName()).append(")\n"); + } + } + + messageSender.sendMessage(sender, builder.toString()); + return true; + + } + + @Override + public java.util.@Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/GiveKey.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/GiveKey.java new file mode 100644 index 0000000..fbcaed6 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/GiveKey.java @@ -0,0 +1,140 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.item.Item; +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.utils.ArgumentUtils; +import de.eldoria.eldoutilities.utils.Parser; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.Bukkit; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.HumanEntity; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.OptionalInt; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class GiveKey extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public GiveKey(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + if (playerFromSender == null) { + if (argumentsInvalid(null, args, 3, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.amount") + "> <" + + localizer.getMessage("syntax.player") + ">")) { + return true; + } + } else { + if (argumentsInvalid(sender, args, 1, + "<" + localizer.getMessage("syntax.doorId") + "> [" + + localizer.getMessage("syntax.amount") + "] [" + + localizer.getMessage("syntax.player") + "]")) { + return true; + } + } + + Pair door = getConditionalPlayerDoor(args[0], playerFromSender); + + if (door == null) { + return true; + } + + Optional condition = door.first.getConditionBag().getCondition("item"); + + if (!condition.isPresent()) { + messageSender.sendError(sender, localizer.getMessage("error.noItemConditionSet")); + return true; + } + + ItemStack item = ((Item) condition.get()).getItem(); + + OptionalInt amount = ArgumentUtils.getOptionalParameter(args, 1, OptionalInt.of(64), Parser::parseInt); + + if (!amount.isPresent()) { + messageSender.sendError(sender, localizer.getMessage("error.invalidAmount")); + return true; + } + + Player target = ArgumentUtils.getOptionalParameter(args, 2, playerFromSender, Bukkit::getPlayer); + + if (target == null) { + messageSender.sendError(sender, localizer.getMessage("error.playerNotFound")); + return true; + } + + ItemStack clone = item.clone(); + clone.setAmount(amount.getAsInt()); + target.getInventory().addItem(clone); + if (target != playerFromSender) { + messageSender.sendMessage(playerFromSender, localizer.getMessage("giveKey.send", + Replacement.create("AMOUNT", amount.getAsInt()), + Replacement.create("ITEMNAME", item.hasItemMeta() ? (item.getItemMeta().hasDisplayName() + ? item.getItemMeta().getDisplayName() + : item.getType().name().toLowerCase()) + : item.getType().name().toLowerCase()), + Replacement.create("TARGET", target.getDisplayName()))); + } + messageSender.sendMessage(target, localizer.getMessage("giveKey.received", + Replacement.create("AMOUNT", amount.getAsInt()), + Replacement.create("ITEMNAME", item.hasItemMeta() ? (item.getItemMeta().hasDisplayName() + ? item.getItemMeta().getDisplayName() + : item.getType().name().toLowerCase()) + : item.getType().name().toLowerCase()))); + return true; + + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + + if (args.length == 2) { + return Collections.singletonList("<" + localizer.getMessage("syntax.amount") + ">"); + } + + if (args.length == 3) { + return Bukkit.getOnlinePlayers().stream() + .filter(p -> p.getName().toLowerCase().startsWith(args[2])) + .map(HumanEntity::getName) + .collect(Collectors.toList()); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Help.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Help.java new file mode 100644 index 0000000..4c45c47 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Help.java @@ -0,0 +1,165 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.simplecommands.EldoCommand; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextDecoration; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +public class Help extends EldoCommand { + private final Localizer localizer; + private final Plugin plugin; + private final BukkitAudiences bukkitAudiences; + + public Help(Plugin plugin) { + this.plugin = plugin; + this.localizer = BigDoorsOpener.localizer(); + bukkitAudiences = BukkitAudiences.create(plugin); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + TextComponent component = TextComponent.builder() + .append(TextComponent.builder(localizer.getMessage("help.title", + Replacement.create("PLUGIN_NAME", plugin.getDescription().getName()))) + .style(Style.builder().decoration(TextDecoration.BOLD, true).color(TextColors.GOLD).build()).build()) + .append(TextComponent.newline()) + .append(TextComponent.builder("setCondition ") + .style(Style.builder() + .color(TextColors.GOLD) + .decoration(TextDecoration.BOLD, false) + .build())) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.conditionValues") + ">") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.setCondition")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("removeCondition") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + ">") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.removeCondition")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("copyCondition") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.sourceDoor") + "> <" + + localizer.getMessage("syntax.targetDoor") + "> [" + + localizer.getMessage("syntax.condition") + "]") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.copyCondition")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("cloneDoor") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.sourceDoor") + "> <" + + localizer.getMessage("syntax.targetDoor") + ">") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.cloneDoor")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("giveKey") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> [" + + localizer.getMessage("syntax.amount") + "] [" + + localizer.getMessage("syntax.player") + "]") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.giveKey")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("info") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + ">") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.info")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("unregister") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + ">") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.unregister")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("invertOpen").color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + ">") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.invertOpen")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("setEvaluator") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.evaluationType") + "> [" + + localizer.getMessage("syntax.customEvaluator") + "]") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.setEvaluator")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("stayOpen") + .color(TextColors.GOLD)) + .append(TextComponent.builder(" <" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.seconds") + ">") + .color(TextColors.AQUA)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.stayOpen")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("list") + .color(TextColors.GOLD)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.list")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("reload") + .color(TextColors.GOLD)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.reload")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("about") + .color(TextColors.GOLD)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.about")) + .color(TextColors.DARK_GREEN)) + .append(TextComponent.newline()) + .append(TextComponent.builder("help") + .color(TextColors.GOLD)) + .append(TextComponent.newline()) + .append(TextComponent.builder(" " + localizer.getMessage("help.help")) + .color(TextColors.DARK_GREEN)) + .build(); + + bukkitAudiences.audience(sender).sendMessage(component); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Info.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Info.java new file mode 100644 index 0000000..c9ad9d1 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Info.java @@ -0,0 +1,131 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import net.kyori.adventure.platform.bukkit.BukkitAudiences; +import net.kyori.adventure.text.TextComponent; +import net.kyori.adventure.text.event.ClickEvent; +import net.kyori.adventure.text.format.Style; +import net.kyori.adventure.text.format.TextDecoration; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class Info extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final BukkitAudiences bukkitAudiences; + + public Info(BigDoors bigDoors, Plugin plugin, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + bukkitAudiences = BukkitAudiences.create(plugin); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 1, "<" + localizer.getMessage("syntax.doorId") + ">")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Pair door = getConditionalPlayerDoor(args[0], playerFromSender); + if (door == null) { + return true; + } + + ConditionalDoor cDoor = door.first; + TextComponent.Builder builder = TextComponent.builder() + .append(TextComponent.builder(door.second.getName() + " ").color(C.highlightColor).decoration(TextDecoration.BOLD, true)) + .append(TextComponent.builder("(Id:" + door.second.getDoorUID() + ") ").decoration(TextDecoration.BOLD, true)).color(C.highlightColor) + .append(TextComponent.builder(localizer.getMessage("info.info")).color(C.baseColor).decoration(TextDecoration.BOLD, true)) + .append(TextComponent.newline()).decoration(TextDecoration.BOLD, false) + .append(TextComponent.builder(localizer.getMessage("info.state") + " ").color(C.baseColor)) + .append(TextComponent.builder(localizer.getMessage(cDoor.isEnabled() ? "info.state.enabled" : "info.state.disabled")).color(C.highlightColor)) + .append(TextComponent.newline()) + .append(TextComponent.builder(localizer.getMessage("info.world") + " ").color(C.baseColor)) + .append(TextComponent.builder(cDoor.getWorld()).color(C.highlightColor)) + .append(TextComponent.newline() + .append(TextComponent.builder(""))); + + // append evaluator + builder.append(TextComponent.builder(localizer.getMessage("info.evaluator") + " ").color(C.baseColor)); + if (cDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { + builder.append(TextComponent.builder(cDoor.getEvaluator() + " ").color(C.highlightColor)) + .append(TextComponent.builder("[" + localizer.getMessage("info.edit") + "]") + .style(Style.builder().decoration(TextDecoration.UNDERLINED, true) + .color(TextColors.GREEN).build()) + .clickEvent(ClickEvent.suggestCommand("/bdo setEvaluator " + cDoor.getDoorUID() + " custom " + cDoor.getEvaluator()))); + } else { + builder.append(TextComponent.builder(cDoor.getEvaluationType().name()).color(C.highlightColor)); + } + builder.append(TextComponent.newline()); + + // append open time + builder.append(TextComponent.builder(localizer.getMessage("info.stayOpen") + " ").color(C.baseColor)) + .append(TextComponent.builder(cDoor.getStayOpen() + " ").color(C.highlightColor)) + .append(TextComponent.builder("[" + localizer.getMessage("info.edit") + "]") + .style(Style.builder().decoration(TextDecoration.UNDERLINED, true) + .color(TextColors.GREEN).build()) + .clickEvent(ClickEvent.suggestCommand("/bdo stayOpen " + cDoor.getDoorUID() + " " + cDoor.getStayOpen()))) + .append(TextComponent.newline()); + + // start of key list + builder.append(TextComponent.builder(localizer.getMessage("info.conditions")) + .style(Style.builder().color(C.highlightColor).decoration(TextDecoration.BOLD, true).build())); + + ConditionBag conditionBag = cDoor.getConditionBag(); + + for (DoorCondition condition : conditionBag.getConditions()) { + builder.append(TextComponent.newline()) + .append(condition.getDescription(localizer)) + .append(TextComponent.newline()) + .append(TextComponent.builder("[" + localizer.getMessage("info.remove") + "]") + .style(Style.builder().color(TextColors.DARK_RED) + .decoration(TextDecoration.UNDERLINED, true).build()) + .clickEvent(ClickEvent.runCommand(condition.getRemoveCommand(cDoor)))) + .append(TextComponent.builder(" ")) + .append(TextComponent.builder("[" + localizer.getMessage("info.edit") + "]") + .style(Style.builder().color(TextColors.GREEN) + .decoration(TextDecoration.UNDERLINED, true).build()) + .clickEvent(ClickEvent.suggestCommand(condition.getCreationCommand(cDoor)))); + } + + bukkitAudiences.audience(sender).sendMessage(builder.build()); + return true; + + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/InvertOpen.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/InvertOpen.java new file mode 100644 index 0000000..6c0b4a3 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/InvertOpen.java @@ -0,0 +1,66 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.messages.MessageSender; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class InvertOpen extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public InvertOpen(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 1, "<" + localizer.getMessage("syntax.doorId") + ">")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Pair door = getConditionalPlayerDoor(args[0], playerFromSender); + if (door == null) { + return true; + } + + door.first.invertOpen(); + messageSender.sendMessage(sender, localizer.getMessage("invertOpen.inverted")); + return true; + + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Reload.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Reload.java new file mode 100644 index 0000000..07d0948 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Reload.java @@ -0,0 +1,54 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.scheduler.DoorChecker; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.simplecommands.EldoCommand; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; + +public class Reload extends EldoCommand { + private final Config config; + private final DoorChecker doorChecker; + private final Plugin plugin; + private final MessageSender messageSender; + private final Localizer localizer; + + public Reload(Config config, DoorChecker doorChecker, Plugin plugin) { + this.config = config; + this.doorChecker = doorChecker; + this.plugin = plugin; + messageSender = BigDoorsOpener.getPluginMessageSender(); + localizer = BigDoorsOpener.localizer(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.RELOAD)) { + return true; + } + + config.reloadConfig(); + doorChecker.reload(); + plugin.onEnable(); + messageSender.sendMessage(sender, localizer.getMessage("reload.completed")); + return true; + + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/RemoveCondition.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/RemoveCondition.java new file mode 100644 index 0000000..e78f3b2 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/RemoveCondition.java @@ -0,0 +1,119 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.core.conditions.ConditionGroup; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class RemoveCondition extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public RemoveCondition(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 2, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + ">")) { + return false; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Door playerDoor = getPlayerDoor(args[0], playerFromSender); + + if (playerDoor == null) { + return true; + } + + ConditionalDoor cDoor = getOrRegister(playerDoor, playerFromSender); + + if (cDoor == null) { + return true; + } + + Optional optionalGroup = ConditionRegistrar.getConditionGroup(args[1]); + + if (!optionalGroup.isPresent()) { + messageSender.sendError(sender, localizer.getMessage("error.invalidConditionType")); + return true; + } + ConditionGroup container = optionalGroup.get(); + + String group = container.getName(); + + if (denyAccess(sender, Permissions.getConditionPermission(group), Permissions.ALL_CONDITION)) { + return true; + } + + ConditionBag conditionBag = cDoor.getConditionBag(); + + if (!conditionBag.isConditionSet(container)) { + messageSender.sendError(sender, localizer.getMessage("error.conditionNotSet")); + return true; + } else { + conditionBag.removeCondition(container); + } + + messageSender.sendMessage(sender, localizer.getMessage("removeCondition." + group)); + + // check if condition is in evaluator if a custom evaluator is present. + if (cDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { + Pattern compile = Pattern.compile(group, Pattern.CASE_INSENSITIVE); + if (compile.matcher(cDoor.getEvaluator()).find()) { + messageSender.sendError(sender, localizer.getMessage("warning.valueStillUsed", + Replacement.create("VALUE", group).addFormatting('6'))); + } + } + + if (conditionBag.isEmpty()) { + messageSender.sendMessage(sender, localizer.getMessage("warning.chainIsEmpty")); + } + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + if (args.length == 2) { + return ArrayUtil.startingWithInArray(args[1], ConditionRegistrar.getGroups().toArray(new String[0])).collect(Collectors.toList()); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetCondition.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetCondition.java new file mode 100644 index 0000000..dfef1bf --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetCondition.java @@ -0,0 +1,127 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class SetCondition extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public SetCondition(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 2, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> [" + + localizer.getMessage("syntax.conditionValues") + "]")) { + return true; + } + + Player player = getPlayerFromSender(sender); + + Door playerDoor = getPlayerDoor(args[0], player); + + if (playerDoor == null) { + return true; + } + + ConditionalDoor conditionalDoor = getOrRegister(playerDoor, player); + + if (conditionalDoor == null) { + return true; + } + + Optional conditionByName = ConditionRegistrar.getConditionByName(args[1]); + + if (!conditionByName.isPresent()) { + messageSender.sendError(sender, localizer.getMessage("error.invalidConditionType")); + return true; + } + + ConditionContainer condition = conditionByName.get(); + + String group = condition.getGroup(); + + if (denyAccess(player, Permissions.getConditionPermission(condition), + Permissions.ALL_CONDITION)) { + return true; + } + + String[] conditionArgs = new String[0]; + if (args.length > 2) { + conditionArgs = Arrays.copyOfRange(args, 2, args.length); + } + + condition.create(player, messageSender, conditionalDoor.getConditionBag(), conditionArgs); + + if (conditionalDoor.getEvaluationType() == ConditionalDoor.EvaluationType.CUSTOM) { + Pattern compile = Pattern.compile(group, Pattern.CASE_INSENSITIVE); + if (!compile.matcher(conditionalDoor.getEvaluator()).find()) { + messageSender.sendError(player, localizer.getMessage("warning.valueNotInEvaluator", + Replacement.create("VALUE", group).addFormatting('6'))); + } + } + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + if (args.length == 2) { + return ArrayUtil.startingWithInArray(args[1], ConditionRegistrar.getConditions().toArray(new String[0])).collect(Collectors.toList()); + } + + Optional conditionByName = ConditionRegistrar.getConditionByName(args[1]); + + if (!conditionByName.isPresent()) { + return Collections.singletonList(localizer.getMessage("error.invalidConditionType")); + } + + ConditionContainer container = conditionByName.get(); + + if (denyAccess(sender, true, Permissions.getConditionPermission(container.getGroup()), Permissions.ALL_CONDITION)) { + return Collections.singletonList(localizer.getMessage("error.permission", + Replacement.create("PERMISSION", Permissions.getConditionPermission(container.getGroup()) + ", " + Permissions.ALL_CONDITION))); + } + return container.onTabComplete(sender, localizer, Arrays.copyOfRange(args, 2, args.length)); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetEvaluator.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetEvaluator.java new file mode 100644 index 0000000..c9a4fe8 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetEvaluator.java @@ -0,0 +1,160 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.JsSyntaxHelper; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import de.eldoria.eldoutilities.utils.EnumUtil; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class SetEvaluator extends BigDoorsAdapterCommand { + + private static final String[] EVALUATOR_TYPES; + private final Localizer localizer; + private final MessageSender messageSender; + + static { + EVALUATOR_TYPES = Arrays.stream(ConditionalDoor.EvaluationType.values()) + .map(v -> v.name().toLowerCase()) + .toArray(String[]::new); + } + + public SetEvaluator(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 2, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.evaluationType") + "> [" + + localizer.getMessage("syntax.customEvaluator") + "]")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Pair door = getConditionalPlayerDoor(args[0], playerFromSender); + + if (door == null) { + return true; + } + + ConditionalDoor.EvaluationType type = EnumUtil.parse(args[1], ConditionalDoor.EvaluationType.class, false); + if (type == null) { + messageSender.sendMessage(sender, localizer.getMessage("error.invalidEvaluationType")); + return true; + } + + if (type != ConditionalDoor.EvaluationType.CUSTOM) { + door.first.setEvaluator(type); + if (type == ConditionalDoor.EvaluationType.AND) { + messageSender.sendMessage(sender, localizer.getMessage("setEvaluator.and")); + } else { + messageSender.sendMessage(sender, localizer.getMessage("setEvaluator.or")); + } + return true; + } + + if (denyAccess(sender, Permissions.CUSTOM_EVALUATOR)) { + return true; + } + + if (args.length < 3) { + messageSender.sendError(sender, localizer.getMessage("error.noEvaluatorFound")); + return true; + } + String evaluator = String.join(" ", Arrays.copyOfRange(args, 2, args.length)); + Pair result = JsSyntaxHelper.validateEvaluator(evaluator, BigDoorsOpener.JS()); + + switch (result.first) { + case UNBALANCED_PARENTHESIS: + messageSender.sendError(sender, localizer.getMessage("error.unbalancedParenthesis")); + return true; + case INVALID_VARIABLE: + messageSender.sendError(sender, localizer.getMessage("error.invalidVariable", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return true; + case INVALID_OPERATOR: + messageSender.sendError(sender, localizer.getMessage("error.invalidOperator", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return true; + case INVALID_SYNTAX: + messageSender.sendError(sender, localizer.getMessage("error.invalidSyntax", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return true; + case EXECUTION_FAILED: + messageSender.sendError(sender, localizer.getMessage("error.executionFailed", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return true; + case NON_BOOLEAN_RESULT: + messageSender.sendError(sender, localizer.getMessage("error.nonBooleanResult", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return true; + case FINE: + door.first.setEvaluator(JsSyntaxHelper.translateEvaluator(evaluator)); + break; + } + messageSender.sendMessage(sender, localizer.getMessage("setEvaluator.custom", + Replacement.create("EVALUATOR", door.first.getEvaluator()).addFormatting('6'))); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + if (args.length == 2) { + return ArrayUtil.startingWithInArray(args[1], EVALUATOR_TYPES).collect(Collectors.toList()); + } + + ConditionalDoor.EvaluationType parse = EnumUtil.parse(args[1], ConditionalDoor.EvaluationType.class); + + if (parse == null) { + return Collections.singletonList(localizer.getMessage("error.invalidEvaluationType")); + } + + if (parse == ConditionalDoor.EvaluationType.CUSTOM) { + if (denyAccess(sender, true, Permissions.CUSTOM_EVALUATOR)) { + return Collections.singletonList(localizer.getMessage("error.permission", + Replacement.create("PERMISSION", Permissions.CUSTOM_EVALUATOR))); + } + ArrayList list = new ArrayList<>(ConditionRegistrar.getGroups()); + list.add("currentState"); + list.add("<" + localizer.getMessage("tabcomplete.validValues") + ">"); + return list; + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetState.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetState.java new file mode 100644 index 0000000..33b630d --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/SetState.java @@ -0,0 +1,86 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import de.eldoria.eldoutilities.utils.Parser; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class SetState extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public SetState(BigDoors bigDoors, Config config) { + super(bigDoors, config); + localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 2, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.state") + ">")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Pair door = getConditionalPlayerDoor(args[0], playerFromSender); + + if (door == null) { + return true; + } + + Optional state = Parser.parseBoolean(args[1], "enabled", "disabled"); + if (!state.isPresent()) { + messageSender.sendMessage(sender, localizer.getMessage("error.invalidState")); + return true; + } + + if (state.get()) { + messageSender.sendMessage(sender, localizer.getMessage("setState.enabled")); + } else { + messageSender.sendMessage(sender, localizer.getMessage("setState.disabled")); + } + door.first.setEnabled(state.get()); + return true; + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + if (args.length == 2) { + return ArrayUtil.startingWithInArray(args[1], new String[] {"enabled", "disabled"}).collect(Collectors.toList()); + } + + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/StayOpen.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/StayOpen.java new file mode 100644 index 0000000..add3e70 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/StayOpen.java @@ -0,0 +1,81 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.utils.Parser; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; +import java.util.OptionalInt; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class StayOpen extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + + public StayOpen(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 2, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.seconds") + ">")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Pair door = getConditionalPlayerDoor(args[0], playerFromSender); + + if (door == null) { + return true; + } + + OptionalInt optionalInt = Parser.parseInt(args[1]); + if (!optionalInt.isPresent()) { + messageSender.sendError(sender, localizer.getMessage("error.invalidAmount")); + return true; + } + door.first.setStayOpen(optionalInt.getAsInt()); + messageSender.sendMessage(sender, localizer.getMessage("stayOpen.message", + Replacement.create("SECONDS", optionalInt.getAsInt()))); + return true; + + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + if (args.length == 2) { + return Collections.singletonList("<" + localizer.getMessage("syntax.amount") + ">"); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Unregister.java b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Unregister.java new file mode 100644 index 0000000..45adf1e --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/commands/bdosubcommands/Unregister.java @@ -0,0 +1,72 @@ +package de.eldoria.bigdoorsopener.commands.bdosubcommands; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapterCommand; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collections; +import java.util.List; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.denyAccess; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public class Unregister extends BigDoorsAdapterCommand { + private final Localizer localizer; + private final MessageSender messageSender; + private final Config config; + + public Unregister(BigDoors bigDoors, Config config) { + super(bigDoors, config); + this.config = config; + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + @Override + public boolean onCommand(@NotNull CommandSender sender, @NotNull Command command, @NotNull String label, @NotNull String[] args) { + if (denyAccess(sender, Permissions.USE)) { + return true; + } + + if (argumentsInvalid(sender, args, 1, "<" + localizer.getMessage("syntax.doorId") + ">")) { + return true; + } + + Player playerFromSender = getPlayerFromSender(sender); + + Pair door = getConditionalPlayerDoor(args[0], playerFromSender); + + if (door == null) { + return true; + } + + config.removeDoor(door.second.getDoorUID()); + + messageSender.sendMessage(sender, localizer.getMessage("unregister.message", + Replacement.create("DOOR_NAME", door.second.getName()).addFormatting('6'))); + return true; + + } + + @Override + public @Nullable List onTabComplete(@NotNull CommandSender sender, @NotNull Command command, @NotNull String alias, @NotNull String[] args) { + if (args.length == 1) { + return getDoorCompletion(sender, args[0]); + } + return Collections.emptyList(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/ConditionHelper.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/ConditionHelper.java new file mode 100644 index 0000000..82bd714 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/ConditionHelper.java @@ -0,0 +1,22 @@ +package de.eldoria.bigdoorsopener.conditions; + +import org.bukkit.configuration.serialization.SerializableAs; + +public final class ConditionHelper { + private ConditionHelper() { + } + + /** + * Get the serialized of the class based on {@link SerializableAs} + * + * @param condition condition to check + * @return serialized name of class + * @throws IllegalStateException when the annotation is not present. + */ + public static String serializedName(Class condition) throws IllegalStateException { + if (!condition.isAnnotationPresent(SerializableAs.class)) { + throw new IllegalStateException("Missing serialization annotation in class " + condition.getName()); + } + return condition.getAnnotation(SerializableAs.class).value(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/DoorCondition.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/DoorCondition.java similarity index 64% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/DoorCondition.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/DoorCondition.java index 09133a1..bbfcacc 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/DoorCondition.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/DoorCondition.java @@ -1,12 +1,15 @@ -package de.eldoria.bigdoorsopener.doors.conditions; +package de.eldoria.bigdoorsopener.conditions; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.eldoutilities.localization.Localizer; import net.kyori.adventure.text.TextComponent; import org.bukkit.World; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * A interface which represents a condition which opens a door under specific circumstances. @@ -18,13 +21,13 @@ public interface DoorCondition extends ConfigurationSerializable, Cloneable { /** * Indicates if the key would open the door under the current circumstances. * - * @param player player which should be checked. + * @param player player which should be checked. Is null if the condition is {@link Scope#WORLD} * @param world world of the door * @param door door data * @param currentState the current state of the door. * @return true if the key settings are matched. */ - Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState); + Boolean isOpen(@Nullable Player player, @NotNull World world, @NotNull ConditionalDoor door, @NotNull boolean currentState); /** * Get the description of the door condition. @@ -52,17 +55,19 @@ public interface DoorCondition extends ConfigurationSerializable, Cloneable { /** * This method is called after the check for the door of this condition is done and a new evaluation cycle starts. - * Deletes any internal data in this key. + * Deletes any internal data in this condition */ - void evaluated(); + default void evaluated() { + } DoorCondition clone(); /** - * Returns the scope of the condition. - * @return condition scope + * This method will be called when a door with this key was opened. Only once. + * This method will only be called, when the {@link ConditionContainer#getScope()} is set to {@link Scope#PLAYER}. + * + * @param player player which opened the door. */ - default ConditionScope.Scope getScope() { - return getClass().getAnnotation(ConditionScope.class).value(); + default void opened(Player player) { } } diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/DoorState.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/DoorState.java new file mode 100644 index 0000000..c77339b --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/DoorState.java @@ -0,0 +1,3 @@ +package de.eldoria.bigdoorsopener.conditions; + +public enum DoorState {OPEN, CLOSED} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/Item.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/Item.java similarity index 90% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/Item.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/item/Item.java index 7e5dd26..832a092 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/Item.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/Item.java @@ -1,7 +1,7 @@ -package de.eldoria.bigdoorsopener.doors.conditions.item; +package de.eldoria.bigdoorsopener.conditions.item; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.bigdoorsopener.util.TextColors; import de.eldoria.eldoutilities.crossversion.ServerVersion; @@ -12,6 +12,7 @@ import lombok.Getter; import net.kyori.adventure.text.TextComponent; import net.kyori.adventure.text.event.HoverEvent; +import org.bukkit.command.CommandSender; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; @@ -19,6 +20,9 @@ import org.bukkit.inventory.meta.ItemMeta; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; import java.util.Map; @Getter @@ -73,12 +77,26 @@ public Item(ItemStack item, boolean consumed) { this.consumed = consumed; } + public static List onTabComplete(CommandSender sender, Localizer localizer, String[] args) { + if (args.length == 1) { + return Collections.singletonList("<" + localizer.getMessage("syntax.amount") + ">"); + } + if (args.length == 2) { + if (args[1].isEmpty()) { + return Arrays.asList("true", "false"); + } + return Arrays.asList("[" + localizer.getMessage("tabcomplete.consumed") + "]", "true", "false"); + } + return Collections.emptyList(); + } + /** * This method will be called when a door with this key was opened. Only once. * * @param player player which opened the door. */ - public abstract void used(Player player); + @Override + public abstract void opened(Player player); /** * Checks if a player has a item in the off or main hand. diff --git a/src/main/java/de/eldoria/bigdoorsopener/listener/ItemConditionListener.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemConditionListener.java similarity index 51% rename from src/main/java/de/eldoria/bigdoorsopener/listener/ItemConditionListener.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemConditionListener.java index 3491790..e139f20 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/listener/ItemConditionListener.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemConditionListener.java @@ -1,14 +1,17 @@ -package de.eldoria.bigdoorsopener.listener; +package de.eldoria.bigdoorsopener.conditions.item; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.item.interacting.ItemInteraction; import de.eldoria.bigdoorsopener.config.Config; -import de.eldoria.bigdoorsopener.doors.conditions.item.interacting.ItemInteraction; -import de.eldoria.bigdoorsopener.scheduler.BigDoorsAdapter; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapter; import de.eldoria.eldoutilities.localization.Localizer; import nl.pim16aap2.bigDoors.BigDoors; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.player.PlayerInteractEvent; +import java.util.Optional; + /** * This listener controls when a player tries to open a door with a item. */ @@ -16,16 +19,18 @@ public class ItemConditionListener extends BigDoorsAdapter implements Listener { private final Config config; public ItemConditionListener(BigDoors bigDoors, Localizer localizer, Config config) { - super(bigDoors, localizer); + super(bigDoors); this.config = config; } @EventHandler public void onItemInteract(PlayerInteractEvent event) { - config.getDoors().values().forEach(d -> { - if (d.getConditionChain().getItem() == null) return; - if (d.getConditionChain().getItem() instanceof ItemInteraction) { - ((ItemInteraction) d.getConditionChain().getItem()).clicked(event, isAvailableToOpen(d)); + config.getDoors().forEach(d -> { + if (!d.isEnabled()) return; + Optional item = d.getConditionBag().getCondition("item"); + if ((!item.isPresent())) return; + if (item.get() instanceof ItemInteraction) { + ((ItemInteraction) item.get()).clicked(event, isAvailableToOpen(d)); } }); } diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemHolding.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemHolding.java new file mode 100644 index 0000000..e35364e --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemHolding.java @@ -0,0 +1,125 @@ +package de.eldoria.bigdoorsopener.conditions.item; + +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArgumentUtils; +import de.eldoria.eldoutilities.utils.Parser; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Map; +import java.util.Optional; +import java.util.OptionalInt; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + +/** + * A key which will be open when the player is holding a key in his hand. + */ +@SerializableAs("itemHoldingCondition") +public class ItemHolding extends Item { + public ItemHolding(ItemStack item, boolean consumed) { + super(item, consumed); + } + + public static ItemHolding deserialize(Map map) { + TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); + ItemStack stack = resolvingMap.getValue("item"); + boolean consumed = resolvingMap.getValue("consumed"); + return new ItemHolding(stack, consumed); + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(ItemHolding.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (player == null) { + messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); + return; + } + + if (argumentsInvalid(player, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.amount") + "> [" + + localizer.getMessage("tabcomplete.consumed") + "]")) { + return; + } + + // parse amount + OptionalInt amount = Parser.parseInt(arguments[0]); + if (!amount.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidAmount")); + return; + } + + if (amount.getAsInt() > 64 || amount.getAsInt() < 1) { + messageSender.sendError(player, localizer.getMessage("error.invalidRange", + Replacement.create("MIN", 1).addFormatting('6'), + Replacement.create("MAX", 64).addFormatting('6'))); + return; + } + + Optional consume = ArgumentUtils.getOptionalParameter(arguments, 1, Optional.of(false), Parser::parseBoolean); + if (!consume.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); + return; + } + + ItemStack itemInMainHand = player.getInventory().getItemInMainHand().clone(); + + itemInMainHand.setAmount(amount.getAsInt()); + conditionBag.putCondition(new ItemHolding(itemInMainHand, consume.get())); + messageSender.sendMessage(player, localizer.getMessage("setCondition.itemHolding")); + + }) + .onTabComplete(Item::onTabComplete) + .withMeta("itemHolding", "item", ConditionContainer.Builder.Cost.PLAYER_MEDIUM.cost) + .build(); + } + + @Override + public void opened(Player player) { + if (!isConsumed()) return; + tryTakeFromHands(player); + } + + @Override + public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { + return hasPlayerItemInHand(player); + } + + @Override + public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + return TextComponent.builder( + localizer.getMessage("conditionDesc.type.itemHolding", + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) + .append(TextComponent.newline()) + .append(super.getDescription(localizer)) + .build(); + } + + @Override + public String getCreationCommand(ConditionalDoor door) { + return SET_COMMAND + door.getDoorUID() + " itemHolding " + getItem().getAmount() + " " + isConsumed(); + } + + @Override + public void evaluated() { + + } + +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemOwning.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemOwning.java new file mode 100644 index 0000000..7ce7265 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/ItemOwning.java @@ -0,0 +1,120 @@ +package de.eldoria.bigdoorsopener.conditions.item; + +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArgumentUtils; +import de.eldoria.eldoutilities.utils.Parser; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Map; +import java.util.Optional; +import java.util.OptionalInt; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + +/** + * A key which opens a doow, when the player has it in his inventory. + */ +@SerializableAs("itemOwningCondition") +public class ItemOwning extends Item { + public ItemOwning(ItemStack item, boolean consumed) { + super(item, consumed); + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(ItemOwning.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (player == null) { + messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); + return; + } + + if (argumentsInvalid(player, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.amount") + "> [" + + localizer.getMessage("tabcomplete.consumed") + "]")) { + return; + } + + // parse amount + OptionalInt amount = Parser.parseInt(arguments[0]); + if (!amount.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidAmount")); + return; + } + + if (amount.getAsInt() > 64 || amount.getAsInt() < 1) { + messageSender.sendError(player, localizer.getMessage("error.invalidRange", + Replacement.create("MIN", 1).addFormatting('6'), + Replacement.create("MAX", 64).addFormatting('6'))); + return; + } + + Optional consume = ArgumentUtils.getOptionalParameter(arguments, 1, Optional.of(false), Parser::parseBoolean); + if (!consume.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); + return; + } + + ItemStack itemInMainHand = player.getInventory().getItemInMainHand().clone(); + + itemInMainHand.setAmount(amount.getAsInt()); + conditionBag.putCondition(new ItemOwning(itemInMainHand, consume.get())); + messageSender.sendMessage(player, localizer.getMessage("setCondition.itemOwning")); + }) + .onTabComplete(Item::onTabComplete) + .withMeta("itemOwning", "item", ConditionContainer.Builder.Cost.PLAYER_MEDIUM.cost) + .build(); + } + + @Override + public void opened(Player player) { + if (!isConsumed()) return; + takeFromInventory(player); + } + + @Override + public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { + return hasPlayerItemInInventory(player); + } + + public ItemOwning deserialize(Map map) { + TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); + ItemStack stack = resolvingMap.getValue("item"); + boolean consumed = resolvingMap.getValue("consumed"); + return new ItemOwning(stack, consumed); + } + + @Override + public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + + + return TextComponent.builder( + localizer.getMessage("conditionDesc.type.itemOwning", + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) + .append(TextComponent.newline()) + .append(super.getDescription(localizer)) + .build(); + } + + @Override + public String getCreationCommand(ConditionalDoor door) { + return SET_COMMAND + door.getDoorUID() + " itemOwning " + getItem().getAmount() + " " + isConsumed(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemBlock.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemBlock.java new file mode 100644 index 0000000..225f0ec --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemBlock.java @@ -0,0 +1,191 @@ +package de.eldoria.bigdoorsopener.conditions.item.interacting; + +import de.eldoria.bigdoorsopener.conditions.item.Item; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.core.listener.registration.RegisterInteraction; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArgumentUtils; +import de.eldoria.eldoutilities.utils.Parser; +import lombok.Setter; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.BlockVector; +import org.jetbrains.annotations.NotNull; + +import java.util.Map; +import java.util.Optional; +import java.util.OptionalInt; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + +/** + * A key which opens a door, when the player is clicking at a specific block + */ +@SerializableAs("itemBlockCondition") +public class ItemBlock extends ItemInteraction { + + @Setter + private BlockVector position; + + /** + * Creates a new item block condition without a set position. + * This object is incomplete and has to be initialized with the {@link #setPosition(BlockVector)} method before using. + * + * @param item + * @param consumed + */ + public ItemBlock(ItemStack item, boolean consumed) { + super(item, consumed); + } + + /** + * Constructor used for serialization. + * + * @param position position of block + * @param stack item stack of block + * @param consumed true if item should be consumed. + */ + private ItemBlock(BlockVector position, ItemStack stack, boolean consumed) { + super(stack, consumed); + this.position = position; + } + + public static ItemBlock deserialize(Map map) { + TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); + BlockVector position = resolvingMap.getValue("position"); + ItemStack stack = resolvingMap.getValue("item"); + boolean consumed = resolvingMap.getValue("consumed"); + return new ItemBlock(position, stack, consumed); + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(ItemBlock.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (player == null) { + messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); + return; + } + + if (argumentsInvalid(player, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.amount") + "> [" + + localizer.getMessage("tabcomplete.consumed") + "]")) { + return; + } + + // parse amount + OptionalInt amount = Parser.parseInt(arguments[0]); + if (!amount.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidAmount")); + return; + } + + if (amount.getAsInt() > 64 || amount.getAsInt() < 1) { + messageSender.sendError(player, localizer.getMessage("error.invalidRange", + Replacement.create("MIN", 1).addFormatting('6'), + Replacement.create("MAX", 64).addFormatting('6'))); + return; + } + + Optional consume = ArgumentUtils.getOptionalParameter(arguments, 1, Optional.of(false), Parser::parseBoolean); + if (!consume.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); + return; + } + + ItemStack itemInMainHand = player.getInventory().getItemInMainHand().clone(); + + itemInMainHand.setAmount(amount.getAsInt()); + ItemBlock itemBlock = new ItemBlock(itemInMainHand, consume.get()); + // Register Keyhole object at registration listener. + RegisterInteraction.getInstance().register(player, (event, mSender) -> { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { + return false; + } + if (event.getClickedBlock() == null) return false; + BlockVector blockVector = event.getClickedBlock().getLocation().toVector().toBlockVector(); + itemBlock.setPosition(blockVector); + conditionBag.putCondition(itemBlock); + event.setCancelled(true); + mSender.sendMessage(player, localizer.getMessage("setCondition.itemBlockRegistered")); + return true; + }); + }) + .onTabComplete(Item::onTabComplete) + .withMeta("itemBlock", "item", ConditionContainer.Builder.Cost.PLAYER_MEDIUM.cost) + .build(); + } + + @Override + public void opened(Player player) { + if (!isConsumed()) return; + takeFromInventory(player); + } + + @Override + public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { + if (hasPlayerItemInHand(player)) { + return super.isOpen(player, world, door, currentState); + } + return false; + } + + @Override + public void clicked(PlayerInteractEvent event, boolean available) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (event.getClickedBlock().getLocation().toVector().toBlockVector().equals(position)) { + event.setCancelled(true); + + super.clicked(event, available); + } + } + + @Override + public @NotNull Map serialize() { + return SerializationUtil.newBuilder(super.serialize()) + .add("position", position) + .build(); + } + + @Override + public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + + return TextComponent.builder( + localizer.getMessage("conditionDesc.type.itemBlock", + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) + .append(TextComponent.newline()) + .append(TextComponent.builder(localizer.getMessage("conditionDesc.keyhole") + " ").color(C.baseColor)) + .append(TextComponent.builder(position.toString()).color(C.highlightColor)) + .append(TextComponent.newline()) + .append(super.getDescription(localizer)) + .build(); + } + + @Override + public String getCreationCommand(ConditionalDoor door) { + return SET_COMMAND + door.getDoorUID() + " itemBlock " + getItem().getAmount() + " " + isConsumed(); + } + + @Override + public ItemBlock clone() { + return new ItemBlock(position, getItem(), isConsumed()); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemClick.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemClick.java new file mode 100644 index 0000000..1dcc6ce --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemClick.java @@ -0,0 +1,125 @@ +package de.eldoria.bigdoorsopener.conditions.item.interacting; + +import de.eldoria.bigdoorsopener.conditions.item.Item; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArgumentUtils; +import de.eldoria.eldoutilities.utils.Parser; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.Map; +import java.util.Optional; +import java.util.OptionalInt; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + +/** + * A key which open the door, when right clicked. + */ +@SerializableAs("itemClickCondition") +public class ItemClick extends ItemInteraction { + public ItemClick(ItemStack item, boolean consumed) { + super(item, consumed); + } + + public static ItemClick deserialize(Map map) { + TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); + ItemStack stack = resolvingMap.getValue("item"); + boolean consumed = resolvingMap.getValue("consumed"); + return new ItemClick(stack, consumed); + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(ItemClick.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (player == null) { + messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); + return; + } + + if (argumentsInvalid(player, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.amount") + "> [" + + localizer.getMessage("tabcomplete.consumed") + "]")) { + return; + } + + // parse amount + OptionalInt amount = Parser.parseInt(arguments[0]); + if (!amount.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidAmount")); + return; + } + + if (amount.getAsInt() > 64 || amount.getAsInt() < 1) { + messageSender.sendError(player, localizer.getMessage("error.invalidRange", + Replacement.create("MIN", 1).addFormatting('6'), + Replacement.create("MAX", 64).addFormatting('6'))); + return; + } + + Optional consume = ArgumentUtils.getOptionalParameter(arguments, 1, Optional.of(false), Parser::parseBoolean); + if (!consume.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); + return; + } + + ItemStack itemInMainHand = player.getInventory().getItemInMainHand().clone(); + + itemInMainHand.setAmount(amount.getAsInt()); + conditionBag.putCondition(new ItemClick(itemInMainHand, consume.get())); + messageSender.sendMessage(player, localizer.getMessage("setCondition.itemClick")); + }) + .onTabComplete(Item::onTabComplete) + .withMeta("itemClick", "item", ConditionContainer.Builder.Cost.PLAYER_MEDIUM.cost) + .build(); + } + + @Override + public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { + if (hasPlayerItemInHand(player)) { + return super.isOpen(player, world, door, currentState); + } + return false; + } + + @Override + public void opened(Player player) { + if (!isConsumed()) return; + tryTakeFromHands(player); + } + + @Override + public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + + + return TextComponent.builder( + localizer.getMessage("conditionDesc.type.itemClick", + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) + .append(TextComponent.newline()) + .append(super.getDescription(localizer)) + .build(); + } + + @Override + public String getCreationCommand(ConditionalDoor door) { + return SET_COMMAND + door.getDoorUID() + " itemClick " + getItem().getAmount() + " " + isConsumed(); + } + +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemInteraction.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemInteraction.java similarity index 87% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemInteraction.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemInteraction.java index 7ce1f36..f08497c 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemInteraction.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/item/interacting/ItemInteraction.java @@ -1,7 +1,7 @@ -package de.eldoria.bigdoorsopener.doors.conditions.item.interacting; +package de.eldoria.bigdoorsopener.conditions.item.interacting; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.item.Item; +import de.eldoria.bigdoorsopener.conditions.item.Item; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.event.player.PlayerInteractEvent; @@ -39,7 +39,7 @@ public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean * @param player player which opened the door. */ @Override - public abstract void used(Player player); + public abstract void opened(Player player); /** * This method is called when player interact event is fired. diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Location.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/Location.java similarity index 56% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Location.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/location/Location.java index c726de3..947d1a4 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Location.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/Location.java @@ -1,7 +1,7 @@ -package de.eldoria.bigdoorsopener.doors.conditions.location; +package de.eldoria.bigdoorsopener.conditions.location; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; public interface Location extends DoorCondition { @Override diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/location/Proximity.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/Proximity.java new file mode 100644 index 0000000..6922cce --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/Proximity.java @@ -0,0 +1,209 @@ +package de.eldoria.bigdoorsopener.conditions.location; + +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.functions.TriFunction; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArgumentUtils; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import de.eldoria.eldoutilities.utils.EnumUtil; +import de.eldoria.eldoutilities.utils.Parser; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + +/** + * A condition which opens the door when the player is within a specific range of defined by geometric form + */ +@SerializableAs("proximityCondition") +public class Proximity implements Location { + private final Vector dimensions; + private final ProximityForm proximityForm; + + public Proximity(Vector dimensions, ProximityForm proximityForm) { + this.dimensions = dimensions; + this.proximityForm = proximityForm; + } + + public Proximity(Map map) { + TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); + dimensions = resolvingMap.getValue("dimensions"); + String formString = resolvingMap.getValue("proximityForm"); + formString = formString.replaceAll("(?i)elipsoid", "ellipsoid"); + proximityForm = EnumUtil.parse(formString, ProximityForm.class); + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(Proximity.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (argumentsInvalid(player, messageSender, localizer, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("tabcomplete.dimensions") + "> [" + + localizer.getMessage("syntax.proximityForm") + "]")) { + return; + } + + Vector vector; + String[] coords = arguments[0].split(","); + + // parse the size. + if (coords.length == 1) { + OptionalDouble size = Parser.parseDouble(arguments[0]); + if (!size.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidNumber")); + return; + } + vector = new Vector(size.getAsDouble(), size.getAsDouble(), size.getAsDouble()); + } else if (coords.length == 3) { + OptionalDouble x = Parser.parseDouble(coords[0]); + OptionalDouble y = Parser.parseDouble(coords[1]); + OptionalDouble z = Parser.parseDouble(coords[2]); + if (x.isPresent() && y.isPresent() && z.isPresent()) { + vector = new Vector(x.getAsDouble(), y.getAsDouble(), z.getAsDouble()); + } else { + messageSender.sendError(player, localizer.getMessage("error.invalidNumber")); + return; + } + } else { + messageSender.sendError(player, localizer.getMessage("error.invalidVector")); + return; + } + + // check if vector is inside bounds. + if (vector.getX() < 1 || vector.getX() > 100 + || vector.getY() < 1 || vector.getY() > 100 + || vector.getZ() < 1 || vector.getZ() > 100) { + messageSender.sendError(player, localizer.getMessage("error.invalidRange", + Replacement.create("MIN", 1).addFormatting('6'), + Replacement.create("MAX", 100).addFormatting('6'))); + return; + } + + Proximity.ProximityForm form = ArgumentUtils.getOptionalParameter(arguments, 1, Proximity.ProximityForm.CUBOID, (s) -> EnumUtil.parse(s, Proximity.ProximityForm.class)); + + if (form == null) { + messageSender.sendError(player, localizer.getMessage("error.invalidForm")); + return; + } + + conditionBag.putCondition(new Proximity(vector, form)); + + // TODO: display region Maybe some day. In a far future... + + messageSender.sendMessage(player, localizer.getMessage("setCondition.proximity")); + }) + .onTabComplete((sender, localizer, args) -> { + final String[] proximityForm = Arrays.stream(Proximity.ProximityForm.values()) + .map(v -> v.name().toLowerCase()) + .toArray(String[]::new); + + if (args.length == 1) { + return Arrays.asList("<" + localizer.getMessage("tabcomplete.dimensions") + ">", ""); + } + if (args.length == 2) { + return ArrayUtil.startingWithInArray(args[1], proximityForm).collect(Collectors.toList()); + } + return Collections.emptyList(); + }) + .withMeta("proximity", "location", ConditionContainer.Builder.Cost.PLAYER_LOW.cost) + .build(); + } + + @Override + public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { + Vector vector = player.getLocation().toVector(); + return proximityForm.check.apply(door.getPosition(), + new Vector(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()), + dimensions); + } + + @Override + public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + + return TextComponent.builder( + localizer.getMessage("conditionDesc.type.proximity", + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) + .append(TextComponent.newline()) + .append(TextComponent.builder(localizer.getMessage("conditionDesc.size") + " ").color(C.baseColor)) + .append(TextComponent.builder(dimensions.toString()).color(C.highlightColor)) + .append(TextComponent.newline()) + .append(TextComponent.builder(localizer.getMessage("conditionDesc.proximityForm") + " ").color(C.baseColor)) + .append(TextComponent.builder(localizer.getMessage(proximityForm.localKey)).color(C.highlightColor)) + .build(); + } + + @Override + public String getCreationCommand(ConditionalDoor door) { + return SET_COMMAND + door.getDoorUID() + " proximity " + + dimensions.getX() + "," + dimensions.getY() + "," + dimensions.getZ() + + " " + proximityForm.name().toLowerCase(); + } + + @Override + public Proximity clone() { + return new Proximity(dimensions, proximityForm); + } + + @Override + public @NotNull Map serialize() { + return SerializationUtil.newBuilder() + .add("dimensions", dimensions) + .add("proximityForm", proximityForm) + .build(); + } + + public enum ProximityForm { + CUBOID("conditionDesc.proximityForm.cuboid", + (point, target, dimensions) -> { + if (Math.abs(point.getX() - target.getX()) > dimensions.getX()) return false; + if (Math.abs(point.getY() - target.getY()) > dimensions.getY()) return false; + return !(Math.abs(point.getZ() - target.getZ()) > dimensions.getZ()); + }), + ELLIPSOID("conditionDesc.proximityForm.ellipsoid", + (point, target, dimensions) -> + Math.pow((target.getX() - point.getX()) / dimensions.getX(), 2) + + Math.pow((target.getY() - point.getY()) / dimensions.getY(), 2) + + Math.pow((target.getZ() - point.getZ()) / dimensions.getZ(), 2) <= 1), + CYLINDER("conditionDesc.proximityForm.cylinder", + (point, target, dimensions) -> { + if (Math.abs(point.getY() - target.getY()) > dimensions.getY()) return false; + return Math.pow(target.getX() - point.getX(), 2) / Math.pow(dimensions.getX(), 2) + + Math.pow(target.getZ() - point.getZ(), 2) / Math.pow(dimensions.getZ(), 2) <= 1; + }); + + /** + * point, target, dimension + */ + public TriFunction check; + public final String localKey; + + ProximityForm(String localKey, TriFunction check) { + this.localKey = localKey; + this.check = check; + } + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Region.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/Region.java similarity index 55% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Region.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/location/Region.java index b7ec7ce..22f9f21 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Region.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/Region.java @@ -1,12 +1,15 @@ -package de.eldoria.bigdoorsopener.doors.conditions.location; +package de.eldoria.bigdoorsopener.conditions.location; import com.google.common.cache.Cache; import com.sk89q.worldedit.bukkit.BukkitAdapter; +import com.sk89q.worldguard.protection.managers.RegionManager; import com.sk89q.worldguard.protection.regions.ProtectedRegion; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; +import com.sk89q.worldguard.protection.regions.RegionContainer; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.bigdoorsopener.util.TextColors; import de.eldoria.eldoutilities.localization.Localizer; @@ -20,15 +23,18 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.logging.Level; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + /** * A condition which opens the door, when a player is inside a world guard region. */ @SerializableAs("regionCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) public class Region implements Location { private final ProtectedRegion region; private final World world; @@ -69,6 +75,51 @@ public Region(Map map) { BigDoorsOpener.logger().warning("A region key is used but world guard was not found."); } + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(Region.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + final RegionContainer regionContainer = BigDoorsOpener.getRegionContainer(); + Localizer localizer = BigDoorsOpener.localizer(); + if (regionContainer == null) { + messageSender.sendError(player, localizer.getMessage("error.wgNotEnabled")); + return; + } + + if (argumentsInvalid(player, messageSender, localizer, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("tabcomplete.regionName") + ">")) { + return; + } + + if (player == null) { + messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); + return; + } + RegionManager rm = regionContainer.get(BukkitAdapter.adapt(player.getWorld())); + if (rm == null) { + messageSender.sendError(player, localizer.getMessage("error.regionNotFound")); + return; + } + ProtectedRegion region = rm.getRegion(arguments[0]); + if (region == null) { + messageSender.sendError(player, localizer.getMessage("error.regionNotFound")); + return; + } + conditionBag.putCondition(new Region(region, player.getWorld())); + messageSender.sendMessage(player, localizer.getMessage("setCondition.region")); + + }) + .onTabComplete((sender, localizer, args) -> { + if (args.length == 1) { + return Collections.singletonList("<" + localizer.getMessage("tabcomplete.regionName") + ">"); + } + return Collections.emptyList(); + }) + .withMeta("region", "location", ConditionContainer.Builder.Cost.PLAYER_MEDIUM.cost) + .build(); + } + @Override public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { if (world != this.world) return false; @@ -85,9 +136,12 @@ public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean @Override public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + return TextComponent.builder( localizer.getMessage("conditionDesc.type.region", - Replacement.create("NAME", ConditionType.REGION.conditionName))).color(TextColors.AQUA) + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) .append(TextComponent.newline()) .append(TextComponent.builder(localizer.getMessage("conditionDesc.region") + " ").color(C.baseColor)) .append(TextComponent.builder(regionId)).color(C.highlightColor) @@ -102,11 +156,6 @@ public String getCreationCommand(ConditionalDoor door) { return SET_COMMAND + door.getDoorUID() + " region " + regionId; } - @Override - public void evaluated() { - - } - @Override public Region clone() { return new Region(world, region, worldName, regionId); @@ -119,4 +168,5 @@ public Region clone() { .add("region", regionId) .build(); } + } diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/SimpleRegion.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/SimpleRegion.java similarity index 55% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/SimpleRegion.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/location/SimpleRegion.java index 51cfe48..3247ead 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/SimpleRegion.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/location/SimpleRegion.java @@ -1,31 +1,38 @@ -package de.eldoria.bigdoorsopener.doors.conditions.location; +package de.eldoria.bigdoorsopener.conditions.location; import com.google.common.cache.Cache; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.core.listener.registration.InteractionRegistrationObject; +import de.eldoria.bigdoorsopener.core.listener.registration.RegisterInteraction; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.bigdoorsopener.util.TextColors; import de.eldoria.eldoutilities.localization.Localizer; import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.messages.MessageSender; import de.eldoria.eldoutilities.serialization.SerializationUtil; import de.eldoria.eldoutilities.serialization.TypeResolvingMap; import net.kyori.adventure.text.TextComponent; import org.bukkit.World; import org.bukkit.configuration.serialization.SerializableAs; import org.bukkit.entity.Player; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.util.BlockVector; import org.bukkit.util.Vector; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.Map; +import java.util.Optional; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; @SerializableAs("simpleRegionCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) public class SimpleRegion implements Location { private final BlockVector minimum; private final BlockVector maximum; @@ -46,6 +53,41 @@ public SimpleRegion(Map map) { world = resolvingMap.getValue("world"); } + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(SimpleRegion.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + messageSender.sendMessage(player, localizer.getMessage("setCondition.firstPoint")); + RegisterInteraction.getInstance().register(player, new InteractionRegistrationObject() { + private String world; + private BlockVector first; + + @Override + public boolean invoke(PlayerInteractEvent event, MessageSender messageSender) { + if (event.getAction() != Action.LEFT_CLICK_BLOCK) { + return false; + } + BlockVector vec = event.getClickedBlock().getLocation().toVector().toBlockVector(); + if (first == null) { + world = event.getPlayer().getWorld().getName(); + first = vec; + event.setCancelled(true); + messageSender.sendMessage(player, localizer.getMessage("setCondition.secondPoint")); + return false; + } + conditionBag.putCondition(new SimpleRegion(first, vec, world)); + event.setCancelled(true); + messageSender.sendMessage(player, localizer.getMessage("setCondition.simpleRegionRegisterd")); + return true; + } + }); + + }) + .onTabComplete((sender, localizer, args) -> Collections.emptyList()) + .withMeta("simpleRegion", "location", ConditionContainer.Builder.Cost.PLAYER_LOW.cost) + .build(); + } + @Override public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { try { @@ -64,9 +106,12 @@ public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean @Override public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + return TextComponent.builder( localizer.getMessage("conditionDesc.type.simpleRegion", - Replacement.create("NAME", ConditionType.SIMPLE_REGION.conditionName))).color(TextColors.AQUA) + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) .append(TextComponent.newline()) .append(TextComponent.builder(localizer.getMessage("conditionDesc.world") + " ").color(C.baseColor)) .append(TextComponent.builder(world)).color(C.highlightColor) @@ -84,11 +129,6 @@ public String getCreationCommand(ConditionalDoor door) { return SET_COMMAND + door.getDoorUID() + " simpleRegion"; } - @Override - public void evaluated() { - - } - @Override public SimpleRegion clone() { return new SimpleRegion(minimum, maximum, world); @@ -102,4 +142,5 @@ public SimpleRegion clone() { .add("world", world) .build(); } + } diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/DoorPermission.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/permission/DoorPermission.java similarity index 58% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/DoorPermission.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/permission/DoorPermission.java index b30aced..47d8a0b 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/DoorPermission.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/permission/DoorPermission.java @@ -1,17 +1,19 @@ -package de.eldoria.bigdoorsopener.doors.conditions.permission; +package de.eldoria.bigdoorsopener.conditions.permission; import com.google.common.cache.Cache; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.scheduler.BigDoorsAdapter; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapter; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.bigdoorsopener.util.TextColors; import de.eldoria.eldoutilities.localization.Localizer; import de.eldoria.eldoutilities.localization.Replacement; import de.eldoria.eldoutilities.serialization.SerializationUtil; import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArrayUtil; import net.kyori.adventure.text.TextComponent; import nl.pim16aap2.bigDoors.Door; import org.bukkit.World; @@ -19,32 +21,79 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.Map; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.logging.Level; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; /** * A condition which opens the door, when a player has a access level for the door. */ @SerializableAs("doorPermissionCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) public class DoorPermission extends BigDoorsAdapter implements Permission { private final int permissionLevel; private final Cache cache = C.getExpiringCache(30, TimeUnit.SECONDS); public DoorPermission(int permissionLevel) { - super(BigDoorsOpener.getBigDoors(), BigDoorsOpener.getLocalizer()); + super(BigDoorsOpener.getBigDoors()); this.permissionLevel = permissionLevel; } public DoorPermission(Map map) { - super(BigDoorsOpener.getBigDoors(), BigDoorsOpener.getLocalizer()); + super(BigDoorsOpener.getBigDoors()); TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); permissionLevel = resolvingMap.getValue("permissionLevel"); } + public static int parsePermissionLevel(String permission) { + if ("owner".equalsIgnoreCase(permission)) { + return 0; + } + if ("editor".equalsIgnoreCase(permission)) { + return 1; + } + if ("user".equalsIgnoreCase(permission)) { + return 2; + } + return -1; + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(DoorPermission.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (argumentsInvalid(player, messageSender, localizer, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("tabcomplete.doorPermission") + ">")) { + return; + } + + int i = DoorPermission.parsePermissionLevel(arguments[0]); + if (i < 0) { + messageSender.sendError(player, localizer.getMessage("error.invalidAccessLevel")); + return; + } + conditionBag.putCondition(new DoorPermission(i)); + messageSender.sendMessage(player, localizer.getMessage("setCondition.doorPermission")); + + }) + .onTabComplete((sender, localizer, args) -> { + if (args.length == 1) { + return ArrayUtil.startingWithInArray(args[0], new String[] {"owner", "editor", "user"}).collect(Collectors.toList()); + } + return Collections.emptyList(); + }) + .withMeta("doorPerm", "permission", ConditionContainer.Builder.Cost.PLAYER_MEDIUM.cost) + .build(); + } + @Override public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { try { @@ -62,9 +111,12 @@ public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean @Override public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + return TextComponent.builder( localizer.getMessage("conditionDesc.type.permission", - Replacement.create("NAME", ConditionType.PERMISSION_NODE.conditionName))).color(TextColors.AQUA) + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) .append(TextComponent.newline()) .append(TextComponent.builder(localizer.getMessage("conditionDesc.doorPermission") + " ").color(C.baseColor)) .append(TextComponent.builder(localizer.getMessage(getPermString())).color(C.highlightColor)) @@ -106,16 +158,4 @@ private String getPermString() { } } - public static int parsePermissionLevel(String permission) { - if ("owner".equalsIgnoreCase(permission)) { - return 0; - } - if ("editor".equalsIgnoreCase(permission)) { - return 1; - } - if ("user".equalsIgnoreCase(permission)) { - return 2; - } - return -1; - } } diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/Permission.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/permission/Permission.java similarity index 56% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/Permission.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/permission/Permission.java index 5a04948..abe5b75 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/Permission.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/permission/Permission.java @@ -1,7 +1,7 @@ -package de.eldoria.bigdoorsopener.doors.conditions.permission; +package de.eldoria.bigdoorsopener.conditions.permission; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; public interface Permission extends DoorCondition { @Override diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/PermissionNode.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/permission/PermissionNode.java similarity index 50% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/PermissionNode.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/permission/PermissionNode.java index 88cc85b..890bb49 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/permission/PermissionNode.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/permission/PermissionNode.java @@ -1,8 +1,10 @@ -package de.eldoria.bigdoorsopener.doors.conditions.permission; +package de.eldoria.bigdoorsopener.conditions.permission; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.bigdoorsopener.util.TextColors; import de.eldoria.eldoutilities.localization.Localizer; @@ -15,13 +17,16 @@ import org.bukkit.entity.Player; import org.jetbrains.annotations.NotNull; +import java.util.Collections; import java.util.Map; +import java.util.Optional; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; /** * A condition which opens the door, when a player has a specific permission. */ @SerializableAs("permissionCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) public class PermissionNode implements Permission { private final String permission; @@ -34,6 +39,32 @@ public PermissionNode(Map map) { permission = resolvingMap.getValue("permission"); } + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(PermissionNode.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + + if (argumentsInvalid(player, messageSender, localizer, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("tabcomplete.permissionNode") + ">")) { + return; + } + + conditionBag.putCondition(new PermissionNode(arguments[0])); + messageSender.sendMessage(player, localizer.getMessage("setCondition.permissionNode")); + + }) + .onTabComplete((sender, localizer, args) -> { + if (args.length == 1) { + return Collections.singletonList("<" + localizer.getMessage("tabcomplete.permissionNode") + ">"); + } + return Collections.emptyList(); + }) + .withMeta("permNode", "permission", ConditionContainer.Builder.Cost.PLAYER_LOW.cost) + .build(); + } + @Override public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { return player.hasPermission(permission); @@ -41,9 +72,12 @@ public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean @Override public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + return TextComponent.builder( localizer.getMessage("conditionDesc.type.permission", - Replacement.create("NAME", ConditionType.PERMISSION_NODE.conditionName))).color(TextColors.AQUA) + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) .append(TextComponent.newline()) .append(TextComponent.builder(localizer.getMessage("conditionDesc.permissionNode") + " ").color(C.baseColor)) .append(TextComponent.builder(permission).color(C.highlightColor)) @@ -71,4 +105,5 @@ public PermissionNode clone() { .add("permission", permission) .build(); } + } diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/Placeholder.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/Placeholder.java new file mode 100644 index 0000000..ae316ac --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/Placeholder.java @@ -0,0 +1,160 @@ +package de.eldoria.bigdoorsopener.conditions.standalone; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.bigdoorsopener.util.JsSyntaxHelper; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import me.clip.placeholderapi.PlaceholderAPI; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.Map; +import java.util.Optional; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + +/** + * A condition which uses the placeholder api. + */ +@SerializableAs("placeholderCondition") +public class Placeholder implements DoorCondition { + + private final String evaluator; + + public Placeholder(String evaluator) { + this.evaluator = evaluator; + } + + public Placeholder(Map map) { + TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); + evaluator = resolvingMap.getValue("evaluator"); + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(Placeholder.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (!BigDoorsOpener.isPlaceholderEnabled()) { + messageSender.sendError(player, localizer.getMessage("error.placeholderNotFound")); + return; + } + + if (player == null) { + messageSender.sendError(null, localizer.getMessage("error.notAllowedFromConsole")); + return; + } + + if (argumentsInvalid(player, messageSender, localizer, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.customEvaluator") + ">")) { + return; + } + + String evaluator = String.join(" ", arguments); + + Pair result = JsSyntaxHelper.checkExecution(evaluator, BigDoorsOpener.JS(), player, false); + + switch (result.first) { + case UNBALANCED_PARENTHESIS: + messageSender.sendError(player, localizer.getMessage("error.unbalancedParenthesis")); + return; + case INVALID_VARIABLE: + messageSender.sendError(player, localizer.getMessage("error.invalidVariable", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return; + case INVALID_OPERATOR: + messageSender.sendError(player, localizer.getMessage("error.invalidOperator", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return; + case INVALID_SYNTAX: + messageSender.sendError(player, localizer.getMessage("error.invalidSyntax", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return; + case EXECUTION_FAILED: + messageSender.sendError(player, localizer.getMessage("error.executionFailed", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return; + case NON_BOOLEAN_RESULT: + messageSender.sendError(player, localizer.getMessage("error.nonBooleanResult", + Replacement.create("ERROR", result.second).addFormatting('6'))); + return; + case FINE: + conditionBag.putCondition(new Placeholder(JsSyntaxHelper.translateEvaluator(evaluator))); + break; + } + + messageSender.sendMessage(player, localizer.getMessage("setCondition.placeholder")); + + }) + .onTabComplete((sender, localizer, args) -> Collections.singletonList("<" + localizer.getMessage("syntax.customEvaluator") + ">")) + .withMeta("placeholder", ConditionContainer.Builder.Cost.PLAYER_HIGH.cost) + .build(); + } + + @Override + public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { + if (BigDoorsOpener.isPlaceholderEnabled()) { + PlaceholderAPI.setPlaceholders(player, evaluator); + return BigDoorsOpener.JS().eval(PlaceholderAPI.setPlaceholders(player, evaluator), null); + } + BigDoorsOpener.logger().warning("A placeholder condition on door " + door.getDoorUID() + " was called but PlaceholderAPI is not active."); + return null; + } + + @Override + public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + + return TextComponent.builder( + localizer.getMessage("conditionDesc.type.placeholder", + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) + .append(TextComponent.newline()) + .append(TextComponent.builder(localizer.getMessage("conditionDesc.evaluator") + " ").color(C.baseColor)) + .append(TextComponent.builder(evaluator).color(C.highlightColor)) + .build(); + } + + @Override + public String getCreationCommand(ConditionalDoor door) { + return SET_COMMAND + door.getDoorUID() + " placeholder " + evaluator; + } + + @Override + public String getRemoveCommand(ConditionalDoor door) { + return REMOVE_COMMAND + door.getDoorUID() + " placeholder"; + } + + @Override + public void evaluated() { + + } + + @Override + public Placeholder clone() { + return new Placeholder(evaluator); + } + + @Override + public @NotNull Map serialize() { + return SerializationUtil.newBuilder() + .add("evaluator", evaluator) + .build(); + } + +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Time.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/Time.java similarity index 52% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Time.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/Time.java index d670e8d..1619012 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Time.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/Time.java @@ -1,17 +1,20 @@ -package de.eldoria.bigdoorsopener.doors.conditions.standalone; +package de.eldoria.bigdoorsopener.conditions.standalone; import com.google.common.cache.Cache; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; -import de.eldoria.bigdoorsopener.doors.conditions.DoorState; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.DoorState; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.bigdoorsopener.util.TextColors; import de.eldoria.eldoutilities.localization.Localizer; import de.eldoria.eldoutilities.localization.Replacement; import de.eldoria.eldoutilities.serialization.SerializationUtil; import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArgumentUtils; import de.eldoria.eldoutilities.utils.Parser; import net.kyori.adventure.text.TextComponent; import org.bukkit.World; @@ -20,15 +23,19 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import java.util.Arrays; +import java.util.Collections; import java.util.Map; import java.util.Optional; +import java.util.OptionalInt; import java.util.concurrent.ExecutionException; +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + /** * A key which defines the door state by current world time. */ @SerializableAs("timeCondition") -@ConditionScope(ConditionScope.Scope.WORLD) public class Time implements DoorCondition { // We use a static cache here for all time conditions. // The time condition is not very likely to change out of a sudden so the refresh cycle does not need to be precisely correct. @@ -66,8 +73,80 @@ public Time(Map map) { forceState = resolvingMap.getValue("forceState"); } + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(Time.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (argumentsInvalid(player, messageSender, localizer, arguments, 2, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.openTime") + "> <" + + localizer.getMessage("syntax.closeTime") + "> [" + + localizer.getMessage("tabcomplete.forceState") + "]")) { + return; + } + + // parse time + OptionalInt open = Parser.parseInt(arguments[0]); + if (!open.isPresent()) { + open = Parser.parseTimeToTicks(arguments[0]); + if (!open.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidOpenTime")); + return; + } + } + + OptionalInt close = Parser.parseInt(arguments[1]); + if (!close.isPresent()) { + close = Parser.parseTimeToTicks(arguments[1]); + if (!close.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidCloseTime")); + return; + } + } + + if (close.getAsInt() < 0 || close.getAsInt() > 24000 + || open.getAsInt() < 0 || open.getAsInt() > 24000) { + messageSender.sendError(player, localizer.getMessage("error.invalidRange", + Replacement.create("MIN", 0).addFormatting('6'), + Replacement.create("MAX", 24000).addFormatting('6'))); + return; + } + + // parse optional force argument. + Optional force = ArgumentUtils.getOptionalParameter(arguments, 2, Optional.of(false), Parser::parseBoolean); + + if (!force.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); + return; + } + conditionBag.putCondition(new Time(open.getAsInt(), close.getAsInt(), force.get())); + messageSender.sendMessage(player, localizer.getMessage("setCondition.time", + Replacement.create("OPEN", Parser.parseTicksToTime(open.getAsInt())), + Replacement.create("CLOSE", Parser.parseTicksToTime(close.getAsInt())))); + + }) + .onTabComplete((sender, localizer, args) -> { + if (args.length == 1) { + return Collections.singletonList("<" + localizer.getMessage("tabcomplete.setTimed.open") + ">"); + } + if (args.length == 2) { + return Collections.singletonList("<" + localizer.getMessage("tabcomplete.setTimed.close") + ">"); + } + if (args.length == 3) { + if (args[2].isEmpty()) { + return Arrays.asList("true", "false"); + } + return Arrays.asList("[" + localizer.getMessage("tabcomplete.forceState") + "]", "true", "false"); + } + return Collections.emptyList(); + }) + .withMeta("time", ConditionContainer.Builder.Cost.WORLD_LOW.cost) + .build(); + } + @Override - public Boolean isOpen(@Nullable Player player, World world, @Nullable ConditionalDoor door, boolean currentState) { + public Boolean isOpen(@Nullable Player player, World world, ConditionalDoor door, boolean currentState) { try { return STATE_CACHE.get(door.getDoorUID(), () -> Optional.ofNullable(shouldBeOpen(world.getFullTime()))).orElse(null); } catch (ExecutionException e) { @@ -77,9 +156,12 @@ public Boolean isOpen(@Nullable Player player, World world, @Nullable Conditiona @Override public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + return TextComponent.builder( localizer.getMessage("conditionDesc.type.time", - Replacement.create("NAME", ConditionType.TIME.conditionName))).color(TextColors.AQUA) + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) .append(TextComponent.newline()) .append(TextComponent.builder(localizer.getMessage("conditionDesc.open") + " ").color(C.baseColor)) .append(TextComponent.builder(Parser.parseTicksToTime(openTick)).color(C.highlightColor)) @@ -152,4 +234,5 @@ private long getDiff(long fullTime, long nextTime) { .build(); } + } diff --git a/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/mythicmobs/MythicMob.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/mythicmobs/MythicMob.java new file mode 100644 index 0000000..82cac8b --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/mythicmobs/MythicMob.java @@ -0,0 +1,150 @@ +package de.eldoria.bigdoorsopener.conditions.standalone.mythicmobs; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.bigdoorsopener.util.TextColors; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.localization.Replacement; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import io.lumine.xikage.mythicmobs.MythicMobs; +import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; +import net.kyori.adventure.text.TextComponent; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; + +@SerializableAs("mythicMobsCondition") +public class MythicMob implements DoorCondition { + private final String mobType; + private boolean state; + + public MythicMob(String mobType) { + this.mobType = mobType; + } + + public MythicMob(Map map) { + mobType = SerializationUtil.mapOf(map).getValue("mobType"); + } + + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(MythicMob.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (!BigDoorsOpener.isMythicMobsEnabled()) { + messageSender.sendError(player, localizer.getMessage("error.mythicMob")); + return; + } + + if (argumentsInvalid(player, messageSender, localizer, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.mobType") + ">")) { + return; + } + + String mob = arguments[0]; + + boolean exists = MythicMobs.inst().getAPIHelper().getMythicMob(mob) != null; + + if (!exists) { + messageSender.sendError(player, localizer.getMessage("error.invalidMob")); + return; + } + + conditionBag.putCondition(new MythicMob(mob)); + messageSender.sendMessage(player, localizer.getMessage("setCondition.mythicMob")); + + }) + .onTabComplete((sender, localizer, args) -> { + if (!BigDoorsOpener.isMythicMobsEnabled()) return Collections.emptyList(); + List mythicMobs; + try { + mythicMobs = (List) C.PLUGIN_CACHE.get("mythicMobs", () -> MythicMobs.inst() + .getMobManager().getMobTypes() + .parallelStream() + .map(m -> m.getInternalName()) + .collect(Collectors.toList())); + } catch (ExecutionException e) { + BigDoorsOpener.logger().log(Level.WARNING, "Could not build mob names.", e); + return Collections.emptyList(); + } + return ArrayUtil.startingWithInArray(args[3], mythicMobs.toArray(new String[0])).collect(Collectors.toList()); + }) + .withMeta("mythicMob", ConditionContainer.Builder.Cost.WORLD_LOW.cost) + .build(); + } + + @Override + public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { + if (BigDoorsOpener.isPlaceholderEnabled()) { + return state; + } + BigDoorsOpener.logger().warning("A mythic mobs condition on door " + door.getDoorUID() + " was called but MythicMobs is not active."); + return null; + } + + @Override + public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + + return TextComponent.builder( + localizer.getMessage("conditionDesc.type.mythicMob", + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) + .append(TextComponent.newline()) + .append(TextComponent.builder(localizer.getMessage("conditionDesc.mythicMob") + " ").color(C.baseColor)) + .append(TextComponent.builder(mobType).color(C.highlightColor)) + .build(); + } + + @Override + public String getCreationCommand(ConditionalDoor door) { + return SET_COMMAND + door.getDoorUID() + " mythicMobs " + mobType; + } + + @Override + public String getRemoveCommand(ConditionalDoor door) { + return REMOVE_COMMAND + door.getDoorUID() + " mythicMob"; + } + + @Override + public void evaluated() { + state = false; + } + + @Override + public MythicMob clone() { + return new MythicMob(mobType); + } + + @Override + public @NotNull Map serialize() { + return SerializationUtil.newBuilder() + .add("mobType", mobType) + .build(); + } + + public void killed(MythicMobDeathEvent event, boolean availableToOpen) { + if (event.getMob().getType().getInternalName().equalsIgnoreCase(mobType)) { + state = true; + } + } + +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/listener/MythicMobsListener.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/mythicmobs/MythicMobsListener.java similarity index 55% rename from src/main/java/de/eldoria/bigdoorsopener/listener/MythicMobsListener.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/mythicmobs/MythicMobsListener.java index 5d6f4ec..e2735c6 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/listener/MythicMobsListener.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/mythicmobs/MythicMobsListener.java @@ -1,27 +1,31 @@ -package de.eldoria.bigdoorsopener.listener; +package de.eldoria.bigdoorsopener.conditions.standalone.mythicmobs; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; import de.eldoria.bigdoorsopener.config.Config; -import de.eldoria.bigdoorsopener.scheduler.BigDoorsAdapter; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapter; import de.eldoria.eldoutilities.localization.Localizer; import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; import nl.pim16aap2.bigDoors.BigDoors; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import java.util.Optional; + public class MythicMobsListener extends BigDoorsAdapter implements Listener { private final Config config; public MythicMobsListener(BigDoors bigDoors, Localizer localizer, Config config) { - super(bigDoors, localizer); + super(bigDoors); this.config = config; } @EventHandler public void onMobDeath(MythicMobDeathEvent event) { - config.getDoors().values().forEach(d -> { - if (d.getConditionChain().getMythicMob() == null) return; - d.getConditionChain().getMythicMob().killed(event, isAvailableToOpen(d)); + config.getDoors().forEach(d -> { + Optional mythicMob = d.getConditionBag().getCondition("mythicMob"); + if (!mythicMob.isPresent()) return; + ((MythicMob) mythicMob.get()).killed(event, isAvailableToOpen(d)); }); } } diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Weather.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/weather/Weather.java similarity index 59% rename from src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Weather.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/weather/Weather.java index cf9d00a..e8283d7 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Weather.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/weather/Weather.java @@ -1,19 +1,23 @@ -package de.eldoria.bigdoorsopener.doors.conditions.standalone; +package de.eldoria.bigdoorsopener.conditions.standalone.weather; import com.google.common.cache.Cache; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; -import de.eldoria.bigdoorsopener.doors.conditions.DoorState; -import de.eldoria.bigdoorsopener.listener.WeatherListener; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.DoorState; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.bigdoorsopener.util.TextColors; import de.eldoria.eldoutilities.localization.Localizer; import de.eldoria.eldoutilities.localization.Replacement; import de.eldoria.eldoutilities.serialization.SerializationUtil; import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import de.eldoria.eldoutilities.utils.ArgumentUtils; +import de.eldoria.eldoutilities.utils.ArrayUtil; import de.eldoria.eldoutilities.utils.EnumUtil; +import de.eldoria.eldoutilities.utils.Parser; import net.kyori.adventure.text.TextComponent; import org.bukkit.Bukkit; import org.bukkit.WeatherType; @@ -24,15 +28,19 @@ import org.jetbrains.annotations.NotNull; import javax.annotation.Nullable; +import java.util.Arrays; +import java.util.Collections; import java.util.Map; import java.util.Optional; import java.util.concurrent.ExecutionException; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.argumentsInvalid; /** * A condition which opens the door based on the current weather in the world. */ @SerializableAs("weatherCondition") -@ConditionScope(ConditionScope.Scope.WORLD) public class Weather implements DoorCondition { // We use a static cache here for all weather conditions. // The weather condition is not very likely to change out of a sudden so the refresh cycle does not need to be precisely correct. @@ -51,6 +59,56 @@ public Weather(Map map) { forceState = resolvingMap.getValueOrDefault("forceState", false); } + public static ConditionContainer getConditionContainer() { + return ConditionContainer.ofClass(Weather.class, Scope.PLAYER) + .withFactory((player, messageSender, conditionBag, arguments) -> { + Localizer localizer = BigDoorsOpener.localizer(); + if (argumentsInvalid(player, messageSender, localizer, arguments, 1, + "<" + localizer.getMessage("syntax.doorId") + "> <" + + localizer.getMessage("syntax.condition") + "> <" + + localizer.getMessage("syntax.weatherType") + ">")) { + return; + } + + WeatherType weatherType = null; + for (WeatherType value : WeatherType.values()) { + if (value.name().equalsIgnoreCase(arguments[0])) { + weatherType = value; + } + } + if (weatherType == null) { + messageSender.sendError(player, localizer.getMessage("error.invalidWeatherType")); + return; + } + + Optional forceWeather = ArgumentUtils.getOptionalParameter(arguments, 1, Optional.of(false), Parser::parseBoolean); + + if (!forceWeather.isPresent()) { + messageSender.sendError(player, localizer.getMessage("error.invalidBoolean")); + return; + } + + conditionBag.putCondition(new Weather(weatherType, forceWeather.get())); + messageSender.sendMessage(player, localizer.getMessage("setCondition.weather", + Replacement.create("OPEN", weatherType == WeatherType.CLEAR + ? localizer.getMessage("conditionDesc.clear") + : localizer.getMessage("conditionDesc.downfall")))); + + }) + .onTabComplete((sender, localizer, args) -> { + final String[] weatherType = Arrays.stream(WeatherType.values()) + .map(v -> v.name().toLowerCase()) + .toArray(String[]::new); + + if (args.length == 1) { + return ArrayUtil.startingWithInArray(args[0], weatherType).collect(Collectors.toList()); + } + return Collections.emptyList(); + }) + .withMeta("weather", ConditionContainer.Builder.Cost.WORLD_LOW.cost) + .build(); + } + @Override public Boolean isOpen(@Nullable Player player, World world, ConditionalDoor door, boolean currentState) { try { @@ -111,9 +169,12 @@ private Boolean isRaining(ConditionalDoor door) { @Override public TextComponent getDescription(Localizer localizer) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(getClass()); + return TextComponent.builder( localizer.getMessage("conditionDesc.type.weather", - Replacement.create("NAME", ConditionType.WEATHER.conditionName))).color(TextColors.AQUA) + Replacement.create("NAME", containerByClass + .map(ConditionContainer::getName).orElse("undefined")))).color(TextColors.AQUA) .append(TextComponent.newline()) .append(TextComponent.builder(localizer.getMessage("conditionDesc.openWhen") + " ").color(C.baseColor)) .append(TextComponent.builder(weatherType == WeatherType.CLEAR @@ -157,4 +218,5 @@ private double getTemperature(World world, Vector pos) { .add("forceState", forceState) .build(); } + } diff --git a/src/main/java/de/eldoria/bigdoorsopener/listener/WeatherListener.java b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/weather/WeatherListener.java similarity index 94% rename from src/main/java/de/eldoria/bigdoorsopener/listener/WeatherListener.java rename to src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/weather/WeatherListener.java index 4595ed4..da46698 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/listener/WeatherListener.java +++ b/src/main/java/de/eldoria/bigdoorsopener/conditions/standalone/weather/WeatherListener.java @@ -1,4 +1,4 @@ -package de.eldoria.bigdoorsopener.listener; +package de.eldoria.bigdoorsopener.conditions.standalone.weather; import org.bukkit.World; import org.bukkit.event.EventHandler; diff --git a/src/main/java/de/eldoria/bigdoorsopener/config/Config.java b/src/main/java/de/eldoria/bigdoorsopener/config/Config.java index 395f3ee..3e5da06 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/config/Config.java +++ b/src/main/java/de/eldoria/bigdoorsopener/config/Config.java @@ -1,34 +1,48 @@ package de.eldoria.bigdoorsopener.config; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionChain; -import de.eldoria.bigdoorsopener.doors.conditions.location.Proximity; -import de.eldoria.bigdoorsopener.doors.conditions.permission.PermissionNode; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Time; +import de.eldoria.bigdoorsopener.conditions.location.Proximity; +import de.eldoria.bigdoorsopener.conditions.permission.PermissionNode; +import de.eldoria.bigdoorsopener.conditions.standalone.Time; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.events.DoorRegisteredEvent; +import de.eldoria.bigdoorsopener.core.events.DoorUnregisteredEvent; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; import lombok.Getter; +import org.bukkit.Bukkit; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.plugin.Plugin; import org.bukkit.util.Vector; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.function.Function; import java.util.logging.Logger; -@Getter public class Config { private final Plugin plugin; private final Map doors = new HashMap<>(); + @Getter private int approachRefreshRate; + @Getter private int timedRefreshRate; + @Getter private boolean enableMetrics; + @Getter private String language; + @Getter private int refreshRate; + @Getter private boolean checkUpdates; + @Getter private int jsCacheSize; + @Getter private Vector playerCheckRadius; public Config(Plugin plugin) { @@ -105,20 +119,20 @@ private void updateVersion0() { log.info("Converting door " + tD.getDoorUID()); ConditionalDoor cD = new ConditionalDoor(tD.getDoorUID(), tD.getWorld(), tD.getPosition()); - ConditionChain conditionChain = cD.getConditionChain(); + ConditionBag conditionBag = cD.getConditionBag(); if (tD.getPermission() != null && !tD.getPermission().isEmpty()) { - conditionChain.setPermission(new PermissionNode(tD.getPermission())); + conditionBag.putCondition(new PermissionNode(tD.getPermission())); log.info("Adding permission condition."); } if (!tD.isPermanentlyClosed()) { - conditionChain.setTime(new Time(tD.getTicksOpen(), tD.getTicksClose(), false)); + conditionBag.putCondition(new Time(tD.getTicksOpen(), tD.getTicksClose(), false)); log.info("Adding time condition."); } if (tD.getOpenRange() > 0) { - conditionChain.setLocation( + conditionBag.putCondition( new Proximity( new Vector(tD.getOpenRange(), tD.getOpenRange(), tD.getOpenRange()), Proximity.ProximityForm.ELLIPSOID)); @@ -214,4 +228,45 @@ public void safeConfig() { plugin.saveConfig(); } + public ConditionalDoor getDoor(Long key) { + return doors.get(key); + } + + public Set keySet() { + return doors.keySet(); + } + + public Collection getDoors() { + return doors.values(); + } + + public Map getDoorMap() { + return doors; + } + + public ConditionalDoor putDoorIfAbsent(Long key, ConditionalDoor value) { + ConditionalDoor conditionalDoor = doors.putIfAbsent(key, value); + Bukkit.getPluginManager().callEvent(new DoorUnregisteredEvent(conditionalDoor)); + return conditionalDoor; + } + + public boolean removeDoor(Long key) { + ConditionalDoor remove = doors.remove(key); + safeConfig(); + Bukkit.getPluginManager().callEvent(new DoorUnregisteredEvent(remove)); + return remove != null; + } + + public ConditionalDoor computeDoorIfAbsent(Long key, @NotNull Function mappingFunction) { + if (doors.containsKey(key)) { + return doors.get(key); + } + ConditionalDoor conditionalDoor = doors.computeIfAbsent(key, mappingFunction); + Bukkit.getPluginManager().callEvent(new DoorRegisteredEvent(conditionalDoor)); + return conditionalDoor; + } + + public boolean containsDoor(long key) { + return doors.containsKey(key); + } } diff --git a/src/main/java/de/eldoria/bigdoorsopener/BigDoorsOpener.java b/src/main/java/de/eldoria/bigdoorsopener/core/BigDoorsOpener.java similarity index 73% rename from src/main/java/de/eldoria/bigdoorsopener/BigDoorsOpener.java rename to src/main/java/de/eldoria/bigdoorsopener/core/BigDoorsOpener.java index b017c50..61e220b 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/BigDoorsOpener.java +++ b/src/main/java/de/eldoria/bigdoorsopener/core/BigDoorsOpener.java @@ -1,31 +1,34 @@ -package de.eldoria.bigdoorsopener; +package de.eldoria.bigdoorsopener.core; import com.sk89q.worldguard.WorldGuard; import com.sk89q.worldguard.protection.regions.RegionContainer; -import de.eldoria.bigdoorsopener.commands.BigDoorsOpenerCommand; +import de.eldoria.bigdoorsopener.commands.BDOCommand; +import de.eldoria.bigdoorsopener.conditions.item.ItemConditionListener; +import de.eldoria.bigdoorsopener.conditions.item.ItemHolding; +import de.eldoria.bigdoorsopener.conditions.item.ItemOwning; +import de.eldoria.bigdoorsopener.conditions.item.interacting.ItemBlock; +import de.eldoria.bigdoorsopener.conditions.item.interacting.ItemClick; +import de.eldoria.bigdoorsopener.conditions.location.Proximity; +import de.eldoria.bigdoorsopener.conditions.location.Region; +import de.eldoria.bigdoorsopener.conditions.location.SimpleRegion; +import de.eldoria.bigdoorsopener.conditions.permission.DoorPermission; +import de.eldoria.bigdoorsopener.conditions.permission.PermissionNode; +import de.eldoria.bigdoorsopener.conditions.standalone.Placeholder; +import de.eldoria.bigdoorsopener.conditions.standalone.Time; +import de.eldoria.bigdoorsopener.conditions.standalone.mythicmobs.MythicMob; +import de.eldoria.bigdoorsopener.conditions.standalone.mythicmobs.MythicMobsListener; +import de.eldoria.bigdoorsopener.conditions.standalone.weather.Weather; +import de.eldoria.bigdoorsopener.conditions.standalone.weather.WeatherListener; import de.eldoria.bigdoorsopener.config.Config; import de.eldoria.bigdoorsopener.config.TimedDoor; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionChain; -import de.eldoria.bigdoorsopener.doors.conditions.item.ItemHolding; -import de.eldoria.bigdoorsopener.doors.conditions.item.ItemOwning; -import de.eldoria.bigdoorsopener.doors.conditions.item.interacting.ItemBlock; -import de.eldoria.bigdoorsopener.doors.conditions.item.interacting.ItemClick; -import de.eldoria.bigdoorsopener.doors.conditions.location.Proximity; -import de.eldoria.bigdoorsopener.doors.conditions.location.Region; -import de.eldoria.bigdoorsopener.doors.conditions.location.SimpleRegion; -import de.eldoria.bigdoorsopener.doors.conditions.permission.DoorPermission; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.MythicMob; -import de.eldoria.bigdoorsopener.doors.conditions.permission.PermissionNode; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Placeholder; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Time; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Weather; -import de.eldoria.bigdoorsopener.listener.DoorOpenedListener; -import de.eldoria.bigdoorsopener.listener.ItemConditionListener; -import de.eldoria.bigdoorsopener.listener.MythicMobsListener; -import de.eldoria.bigdoorsopener.listener.WeatherListener; -import de.eldoria.bigdoorsopener.listener.registration.RegisterInteraction; -import de.eldoria.bigdoorsopener.scheduler.DoorChecker; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.listener.DoorOpenedListener; +import de.eldoria.bigdoorsopener.core.listener.ModificationListener; +import de.eldoria.bigdoorsopener.core.listener.registration.RegisterInteraction; +import de.eldoria.bigdoorsopener.core.scheduler.DoorChecker; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionChain; import de.eldoria.bigdoorsopener.util.CachingJSEngine; import de.eldoria.eldoutilities.container.Pair; import de.eldoria.eldoutilities.crossversion.ServerVersion; @@ -63,6 +66,7 @@ public class BigDoorsOpener extends JavaPlugin { private static boolean mythicMobsEnabled; @Getter private static RegionContainer regionContainer = null; + private static BigDoorsOpener instance; private final BukkitScheduler scheduler = Bukkit.getScheduler(); private Config config; private boolean initialized; @@ -70,14 +74,11 @@ public class BigDoorsOpener extends JavaPlugin { // External instances. private BigDoors doors; private Commander commander; - // scheduler private DoorChecker doorChecker; - // listener private WeatherListener weatherListener; private RegisterInteraction registerInteraction; - private static BigDoorsOpener instance; /** * Get the plugin logger instance. @@ -109,10 +110,14 @@ public static BigDoors getBigDoors() { return instance.doors; } - public static Localizer getLocalizer() { + public static Localizer localizer() { return instance.localizer; } + public static MessageSender getPluginMessageSender() { + return MessageSender.get(instance); + } + @Override public void onDisable() { super.onDisable(); @@ -130,6 +135,9 @@ public void onEnable() { instance = this; logger = this.getLogger(); + // Load external resources. Must be loaded first. + loadExternalSources(); + buildSerializer(); // create config @@ -148,11 +156,6 @@ public void onEnable() { //enable metrics enableMetrics(); - // Load external resources. - loadExternalSources(); - - registerListener(); - MessageSender.create(this, "§6[BDO] ", '2', 'c'); @@ -160,8 +163,10 @@ public void onEnable() { doorChecker = new DoorChecker(config, doors, localizer); scheduler.scheduleSyncRepeatingTask(this, doorChecker, 100, 1); + registerListener(); + registerCommand("bigdoorsopener", - new BigDoorsOpenerCommand(this, doors, config, localizer, doorChecker, registerInteraction)); + new BDOCommand(this, doors, config, doorChecker)); } if (initialized) { @@ -184,10 +189,15 @@ private void registerListener() { weatherListener = new WeatherListener(); PluginManager pm = Bukkit.getPluginManager(); pm.registerEvents(weatherListener, this); - registerInteraction = new RegisterInteraction(); + registerInteraction = new RegisterInteraction(MessageSender.get(this), config); pm.registerEvents(registerInteraction, this); pm.registerEvents(new ItemConditionListener(doors, localizer, config), this); pm.registerEvents(new DoorOpenedListener(config), this); + pm.registerEvents(doorChecker, this); + pm.registerEvents(new ModificationListener(config), this); + if (isMythicMobsEnabled()) { + pm.registerEvents(new MythicMobsListener(doors, localizer, config), this); + } } @SuppressWarnings( {"AssignmentToStaticFieldFromInstanceMethod", "VariableNotUsedInsideIf"}) @@ -241,7 +251,6 @@ private void loadExternalSources() throws InstantiationException { if (Bukkit.getPluginManager().isPluginEnabled("MythicMobs")) { mythicMobsEnabled = true; logger().info("MythicMobs found. Enabling mythic mobs listener."); - pm.registerEvents(new MythicMobsListener(doors, localizer, config), this); } else { logger().info("MythicMobs not found. MythicMobs conditions are disabled."); } @@ -256,20 +265,21 @@ private void loadExternalSources() throws InstantiationException { private void buildSerializer() { ConfigurationSerialization.registerClass(TimedDoor.class, "timedDoor"); ConfigurationSerialization.registerClass(ConditionChain.class, "conditionChain"); - ConfigurationSerialization.registerClass(ConditionalDoor.class, "conditionalDoor"); - ConfigurationSerialization.registerClass(ItemBlock.class, "itemBlockCondition"); - ConfigurationSerialization.registerClass(ItemClick.class, "itemClickCondition"); - ConfigurationSerialization.registerClass(ItemHolding.class, "itemHoldingCondition"); - ConfigurationSerialization.registerClass(ItemOwning.class, "itemOwningCondition"); - ConfigurationSerialization.registerClass(Proximity.class, "proximityCondition"); - ConfigurationSerialization.registerClass(Region.class, "regionCondition"); - ConfigurationSerialization.registerClass(SimpleRegion.class, "simpleRegionCondition"); - ConfigurationSerialization.registerClass(PermissionNode.class, "permissionCondition"); - ConfigurationSerialization.registerClass(DoorPermission.class, "doorPermissionCondition"); - ConfigurationSerialization.registerClass(Time.class, "timeCondition"); - ConfigurationSerialization.registerClass(Weather.class, "weatherCondition"); - ConfigurationSerialization.registerClass(Placeholder.class, "placeholderCondition"); - ConfigurationSerialization.registerClass(MythicMob.class, "mythicMobsCondition"); + ConfigurationSerialization.registerClass(ConditionBag.class); + ConfigurationSerialization.registerClass(ConditionalDoor.class); + ConditionRegistrar.registerCondition(ItemBlock.getConditionContainer()); + ConditionRegistrar.registerCondition(ItemClick.getConditionContainer()); + ConditionRegistrar.registerCondition(ItemHolding.getConditionContainer()); + ConditionRegistrar.registerCondition(ItemOwning.getConditionContainer()); + ConditionRegistrar.registerCondition(Proximity.getConditionContainer()); + ConditionRegistrar.registerCondition(Region.getConditionContainer()); + ConditionRegistrar.registerCondition(SimpleRegion.getConditionContainer()); + ConditionRegistrar.registerCondition(PermissionNode.getConditionContainer()); + ConditionRegistrar.registerCondition(DoorPermission.getConditionContainer()); + ConditionRegistrar.registerCondition(Time.getConditionContainer()); + ConditionRegistrar.registerCondition(Weather.getConditionContainer()); + ConditionRegistrar.registerCondition(Placeholder.getConditionContainer()); + ConditionRegistrar.registerCondition(MythicMob.getConditionContainer()); } /** @@ -304,13 +314,11 @@ private void enableMetrics() { // This will probably help to decide which should be developed further. metrics.addCustomChart(new Metrics.AdvancedPie("condition_types", () -> { Map counts = new HashMap<>(); - Collection values = config.getDoors().values(); - counts.put("item", (int) values.parallelStream().filter(d -> d.getConditionChain().getItem() != null).count()); - counts.put("location", (int) values.parallelStream().filter(d -> d.getConditionChain().getLocation() != null).count()); - counts.put("permission", (int) values.parallelStream().filter(d -> d.getConditionChain().getPermission() != null).count()); - counts.put("time", (int) values.parallelStream().filter(d -> d.getConditionChain().getTime() != null).count()); - counts.put("weather", (int) values.parallelStream().filter(d -> d.getConditionChain().getWeather() != null).count()); - counts.put("mythicMobs", (int) values.parallelStream().filter(d -> d.getConditionChain().getMythicMob() != null).count()); + Collection values = config.getDoors(); + for (String group : ConditionRegistrar.getGroups()) { + ConditionRegistrar.getConditionGroup(group).ifPresent(g -> + counts.put(group, (int) values.parallelStream().filter(d -> d.getConditionBag().isConditionSet(g)).count())); + } return counts; })); } diff --git a/src/main/java/de/eldoria/bigdoorsopener/scheduler/BigDoorsAdapter.java b/src/main/java/de/eldoria/bigdoorsopener/core/adapter/BigDoorsAdapter.java similarity index 95% rename from src/main/java/de/eldoria/bigdoorsopener/scheduler/BigDoorsAdapter.java rename to src/main/java/de/eldoria/bigdoorsopener/core/adapter/BigDoorsAdapter.java index 7e85e07..6d554d8 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/scheduler/BigDoorsAdapter.java +++ b/src/main/java/de/eldoria/bigdoorsopener/core/adapter/BigDoorsAdapter.java @@ -1,7 +1,7 @@ -package de.eldoria.bigdoorsopener.scheduler; +package de.eldoria.bigdoorsopener.core.adapter; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.eldoutilities.localization.Localizer; import de.eldoria.eldoutilities.localization.Replacement; import lombok.Getter; @@ -27,10 +27,10 @@ public abstract class BigDoorsAdapter { private final Server server = Bukkit.getServer(); private final Localizer localizer; - public BigDoorsAdapter(BigDoors bigDoors, Localizer localizer) { + public BigDoorsAdapter(BigDoors bigDoors) { this.bigDoors = bigDoors; commander = bigDoors.getCommander(); - this.localizer = localizer; + this.localizer = BigDoorsOpener.localizer(); } /** diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/adapter/BigDoorsAdapterCommand.java b/src/main/java/de/eldoria/bigdoorsopener/core/adapter/BigDoorsAdapterCommand.java new file mode 100644 index 0000000..8fd804a --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/adapter/BigDoorsAdapterCommand.java @@ -0,0 +1,267 @@ +package de.eldoria.bigdoorsopener.core.adapter; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.bigdoorsopener.util.Permissions; +import de.eldoria.eldoutilities.container.Pair; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.messages.MessageSender; +import de.eldoria.eldoutilities.simplecommands.EldoCommand; +import de.eldoria.eldoutilities.utils.ArrayUtil; +import nl.pim16aap2.bigDoors.BigDoors; +import nl.pim16aap2.bigDoors.Commander; +import nl.pim16aap2.bigDoors.Door; +import org.bukkit.Bukkit; +import org.bukkit.Location; +import org.bukkit.Server; +import org.bukkit.World; +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; +import org.bukkit.util.Vector; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ExecutionException; +import java.util.logging.Level; +import java.util.stream.Collectors; + +import static de.eldoria.bigdoorsopener.commands.CommandHelper.getPlayerFromSender; + +public abstract class BigDoorsAdapterCommand extends EldoCommand { + private final Commander commander; + private final BigDoors bigDoors; + private final Server server = Bukkit.getServer(); + private final Localizer localizer; + private final MessageSender messageSender; + private final Config config; + + public BigDoorsAdapterCommand(BigDoors bigDoors, Config config) { + this.bigDoors = bigDoors; + commander = bigDoors.getCommander(); + this.config = config; + this.localizer = BigDoorsOpener.localizer(); + messageSender = BigDoorsOpener.getPluginMessageSender(); + } + + + /** + * Get the door with a specific id. + * + * @param doorId id of the door as long or string + * @return Door with id if exists. + */ + @Nullable + protected Door getDoor(String doorId) { + return getDoor(null, doorId); + } + + /** + * Get the door with a specific id when the player the permission to access this door. + * + * @param player owner of the door. + * @param doorId id of the door as long or string + * @return Door with id if exists. + */ + @Nullable + protected Door getDoor(Player player, String doorId) { + return commander.getDoor(doorId, player); + } + + /** + * Get a list of doors owned by the player. + * + * @param player Player for which the doors should be retrieved. + * @return List of doors which are owned by the player + */ + public List getDoors(Player player) { + return getDoors(player, null); + } + + /** + * Get a list of doors owned by the player, which match the name. + * + * @param player Player for which the doors should be retrieved. + * @param name Get doors which match the name. + * @return List of doors which are owned by the player + */ + protected List getDoors(Player player, String name) { + return commander.getDoors(player.getUniqueId().toString(), name); + } + + /** + * Get a set of all existing doors. The door will always be owned by the creator. + * + * @return A set of doors. + */ + public Set getDoors() { + return commander.getDoors(); + } + + /** + * Tries to find a door. + * Will search for a door of the player. + * If no door is found a search in all doors by id is performed. + * If the player has the {@link Permissions#ACCESS_ALL} permission, + * a door will be returned even when its not owned by the player. + * + * @param doorUID uid or name of the door. + * @param player player which performed the request. + * @return door if the door exists and the player is allowed to access it. Otherwise null. + */ + protected Door getPlayerDoor(String doorUID, Player player) { + if (player == null) { + // requester is console. should always have access to all doors. + Door door = getDoor(doorUID); + if (door == null) { + messageSender.sendError(null, localizer.getMessage("error.doorNotFound")); + return null; + } + door.setPermission(0); + return door; + } + + // sender id not console. retrieve door of player. + List doors = getDoors(player, doorUID); + + if (doors.isEmpty()) { + // try to retrieve door by player + Door door = getDoor(player, doorUID); + + if (door != null) { + return door; + } + + // door is null. check if door exists anyway + door = getDoor(doorUID); + if (door == null) { + messageSender.sendError(player, localizer.getMessage("error.doorNotFound")); + return null; + } + + // when the door exists and the player has access to all doors return it. + if (player.hasPermission(Permissions.ACCESS_ALL)) { + door.setPermission(0); + return door; + } else { + messageSender.sendError(player, localizer.getMessage("error.notYourDoor")); + } + return null; + } + + if (doors.size() != 1) { + messageSender.sendMessage(player, localizer.getMessage("error.ambiguousDoorName")); + return null; + } + + return doors.get(0); + } + + /** + * Returns the door from config or creates it if not in config. + * + * @param door door to get. + * @param player player which wants to get the door. + * @return door or null if the door does not exist in BD. + */ + protected ConditionalDoor getOrRegister(Door door, Player player) { + World world = door.getWorld(); + + if (world == null) { + messageSender.sendError(player, localizer.getMessage("error.worldNotLoaded")); + return null; + } + + if (config.containsDoor(door.getDoorUID())) { + return config.getDoor(door.getDoorUID()); + } + + Location max = door.getMaximum(); + Location min = door.getMinimum(); + Vector vector = new Vector( + (max.getX() + min.getX()) / 2, + (max.getY() + min.getY()) / 2, + (max.getZ() + min.getZ()) / 2); + + return config.computeDoorIfAbsent(door.getDoorUID(), + doorId -> new ConditionalDoor(doorId, world.getName(), vector)); + } + + /** + * Tries to find the door for a player. + * Will call {@link #getPlayerDoor(String, Player)} to retrieve a door. + * Will check if the door is already registered. + * + * @param doorUID uid or name of the door + * @param player player which requests this door. + * @return door with conditional door or null if the door is not registered or the user has no access. + */ + public Pair getConditionalPlayerDoor(String doorUID, Player player) { + Door door = getPlayerDoor(doorUID, player); + if (door == null) { + return null; + } + + if (door.getPermission() > 1) { + messageSender.sendError(player, localizer.getMessage("error.notYourDoor")); + return null; + } + + ConditionalDoor conditionalDoor = config.getDoor(door.getDoorUID()); + if (conditionalDoor == null) { + messageSender.sendMessage(player, localizer.getMessage("error.doorNotRegistered")); + return null; + } + return new Pair<>(conditionalDoor, door); + } + + @SuppressWarnings("unchecked") + public List getDoorCompletion(CommandSender sender, String name) { + Player player = getPlayerFromSender(sender); + if (player == null) { + return Collections.singletonList("<" + localizer.getMessage("syntax.doorId") + ">"); + } + List doors; + try { + doors = (List) C.PLUGIN_CACHE.get("doors", + () -> { + List d = new ArrayList<>(); + d.addAll(getDoors()); + return d; + }); + } catch (ExecutionException e) { + BigDoorsOpener.logger().log(Level.WARNING, "Could not build tab completion cache for door names.", e); + return Collections.singletonList("<" + localizer.getMessage("syntax.doorId") + ">"); + } + List doorNames; + try { + doorNames = (List) C.PLUGIN_CACHE.get(player.getName() + "doors", + () -> { + if (player.hasPermission(Permissions.ACCESS_ALL)) { + return doors.stream() + .map(d -> d.getPlayerUUID().equals(player.getUniqueId()) + ? d.getName() : String.valueOf(d.getDoorUID())) + .collect(Collectors.toList()); + } + + // Map door names for doors where the player is the creator and can use the door name + return getDoors(player).stream() + .map(d -> d.getPermission() == 0 ? d.getName() : String.valueOf(d.getDoorUID())) + .collect(Collectors.toList()); + }); + } catch ( + ExecutionException e) { + BigDoorsOpener.logger().log(Level.WARNING, "Could not build tab completion cache for door names.", e); + return Collections.singletonList("<" + localizer.getMessage("syntax.doorId") + ">"); + } + + return ArrayUtil.startingWithInArray(name, + doorNames.toArray(new String[0])) + .collect(Collectors.toList()); + } +} + diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionContainer.java b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionContainer.java new file mode 100644 index 0000000..bf040d3 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionContainer.java @@ -0,0 +1,187 @@ +package de.eldoria.bigdoorsopener.core.conditions; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; +import de.eldoria.eldoutilities.consumer.QuadConsumer; +import de.eldoria.eldoutilities.functions.TriFunction; +import de.eldoria.eldoutilities.localization.Localizer; +import de.eldoria.eldoutilities.messages.MessageSender; +import org.bukkit.command.Command; +import org.bukkit.command.CommandSender; +import org.bukkit.command.TabCompleter; +import org.bukkit.entity.Player; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public final class ConditionContainer { + private final Class clazz; + private final Scope scope; + private final String name; + private final String group; + private final int cost; + private final QuadConsumer create; + private final TriFunction> onTabComplete; + + private ConditionContainer(Class clazz, Scope scope, String name, String group, int cost, QuadConsumer create, TriFunction> onTabComplete) { + this.clazz = clazz; + this.scope = scope; + this.name = name; + this.group = group; + this.cost = cost; + this.create = create; + this.onTabComplete = onTabComplete; + } + + public static Builder ofClass(Class clazz, Scope scope) { + return new Builder(clazz, scope); + } + + public Class getClazz() { + return clazz; + } + + public Scope getScope() { + return scope; + } + + public String getName() { + return name; + } + + public String getGroup() { + return group; + } + + public int getCost() { + return cost; + } + + /** + * Creates a new condition and adds it to the condition bag if the creation was successful. + * + * @param player player which wants to create this condition. + * @param messageSender message sender to send messages + * @param conditionBag condition bag where the condition should be set + * @param arguments arguments for condition creation + */ + public void create(Player player, MessageSender messageSender, ConditionBag conditionBag, String[] arguments) { + create.accept(player, messageSender, conditionBag, arguments); + } + + /** + * Handles the tab completion event for the wrapped condition. + * + * @param sender Source of the command. For players tab-completing a + * command inside of a command block, this will be the player, not + * the command block. + * @param localizer localizer for argument localization + * @param args The arguments passed to the command, including final + * partial argument to be completed and command label + * @return A List of possible completions for the final argument, or null + * to default to the command executor + */ + public List onTabComplete(CommandSender sender, Localizer localizer, String[] args) { + return onTabComplete.apply(sender, localizer, args); + } + + public static final class Builder { + private final Class clazz; + private final Scope scope; + private String name = null; + private String group = null; + private int cost = 50; + private QuadConsumer create = null; + private TriFunction> onTabComplete = (sender, localizer, strings) -> Collections.emptyList(); + + /** + * Creates a new builder instance for a condition of type {@code clazz}. + * + * @param clazz the class where the condition is for. + * @param scope scope of the condition + */ + private Builder(Class clazz, Scope scope) { + this.clazz = clazz; + this.scope = scope; + } + + /** + * This consumer must satisfy these rules: + *

- If a condition was added to the condition bag, a message must be send to the player via {@link MessageSender#sendMessage(Player, String)} + *

- If the condition can't be set, a message must be send to the player via {@link MessageSender#sendError(Player, String)} + *

- Do not remove any condition from the bag here. + *

- Do not try to save the config. + *

- The String[] input is only input for the condition itself. It does not contain anything else and may be empty. + *

- Use the message sender to send messages. + * + * @param create a consumer, which fullfills the rules above. + * @return this builder instance + */ + public Builder withFactory(QuadConsumer create) { + this.create = create; + return this; + } + + /** + * This quad function should handle the tab completion event like defined in + * {@link TabCompleter#onTabComplete(CommandSender, Command, String, String[])} + * + * @param onTabComplete a quad function which i + * @return this builder instance + */ + public Builder onTabComplete(TriFunction> onTabComplete) { + this.onTabComplete = onTabComplete; + return this; + } + + /** + * Set the meta for this condition + * + * @param name name and group of the condition. case sensitive. + * @param cost cost of the condition. describes the costs to calculate the condition in the given scope. + * @return this builder instance + */ + public Builder withMeta(String name, int cost) { + return withMeta(name, name, cost); + } + + /** + * Set the meta for the condition. + * + * @param name name of the condition. case sensitive. + * @param group group of the condition. case sensitive. + * @param cost cost of the condition. describes the costs to calculate the condition in the given scope. + * @return this builder instance + */ + public Builder withMeta(String name, String group, int cost) { + this.name = name; + this.group = group; + this.cost = cost; + return this; + } + + public ConditionContainer build() { + return new ConditionContainer(clazz, scope, Objects.requireNonNull(name), group, cost, create, onTabComplete); + } + + /** + * Provides estimated cost for conditions. + */ + public enum Cost { + PLAYER_HIGH(100), + PLAYER_MEDIUM(50), + PLAYER_LOW(10), + WORLD_HIGH(100), + WORLD_MEDIUM(50), + WORLD_LOW(10); + public final int cost; + + Cost(int cost) { + + this.cost = cost; + } + } + } + +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionGroup.java b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionGroup.java new file mode 100644 index 0000000..1af81f6 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionGroup.java @@ -0,0 +1,32 @@ +package de.eldoria.bigdoorsopener.core.conditions; + +import lombok.Getter; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public class ConditionGroup { + private final Map conditions = new HashMap<>(); + @Getter + private final String name; + + public ConditionGroup(String name) { + this.name = name; + } + + + void addCondition(ConditionContainer condition) { + conditions.put(condition.getName(), condition); + } + + public Set getConditions() { + return Collections.unmodifiableSet(conditions.keySet()); + } + + public Optional getConditionByName(String name) { + return Optional.ofNullable(conditions.get(name)); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionRegistrar.java b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionRegistrar.java new file mode 100644 index 0000000..932fed5 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/ConditionRegistrar.java @@ -0,0 +1,105 @@ +package de.eldoria.bigdoorsopener.core.conditions; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.core.conditions.exceptions.ConditionRegistrationException; +import org.bukkit.configuration.serialization.ConfigurationSerialization; +import org.bukkit.configuration.serialization.SerializableAs; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +public final class ConditionRegistrar { + private static final Map GROUPS = new HashMap<>(); + private static final Map, ConditionContainer> CONTAINER = new HashMap<>(); + + private ConditionRegistrar() { + } + + /** + * This will register a condition container at the condition registrat. + *

The provided class in the container requires the {@link SerializableAs} annotation. + * + * @param conditionContainer condition container to register + * @throws ConditionRegistrationException when the condition or its serialized name is already implemented + * @throws IllegalStateException when the annotation {@link SerializableAs} is not present + */ + public static void registerCondition(ConditionContainer conditionContainer) throws ConditionRegistrationException, IllegalStateException { + GROUPS.computeIfAbsent(conditionContainer.getGroup(), ConditionGroup::new).addCondition(conditionContainer); + + if (CONTAINER.containsKey(conditionContainer.getClazz())) { + throw new ConditionRegistrationException(conditionContainer.getClazz()); + } + + CONTAINER.put(conditionContainer.getClazz(), conditionContainer); + + ConfigurationSerialization.registerClass(conditionContainer.getClazz()); + } + + /** + * Get a condition container by class. + * Only registered classes will return a container. Subclasses and interfaces are ambigous and will not return a container. + * + * @param clazz class to request + * @return optional condition container + */ + public static Optional getContainerByClass(Class clazz) { + return Optional.ofNullable(CONTAINER.get(clazz)); + } + + /** + * Get the condition group with the provided name. + * + * @param string name of group + * @return optional group with group if present + */ + public static Optional getConditionGroup(String string) { + for (Map.Entry entry : GROUPS.entrySet()) { + if (entry.getKey().equalsIgnoreCase(string)) { + return Optional.ofNullable(entry.getValue()); + } + } + return Optional.empty(); + } + + /** + * Get all registered condition groups + * + * @return set of groups + */ + public static Set getGroups() { + return Collections.unmodifiableSet(GROUPS.keySet()); + } + + /** + * Get all registered conditions + * + * @return set of conditions. + */ + public static Set getConditions() { + Set conditions = new HashSet<>(); + GROUPS.values().forEach(c -> conditions.addAll(c.getConditions())); + return Collections.unmodifiableSet(conditions); + } + + /** + * Get a condition by name. + * + * @param name name of condition + * @return option condition container + */ + public static Optional getConditionByName(String name) { + for (ConditionGroup group : GROUPS.values()) { + for (String condition : group.getConditions()) { + if (condition.equalsIgnoreCase(name)) { + return group.getConditionByName(name); + } + } + } + return Optional.empty(); + } + +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/conditions/Scope.java b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/Scope.java new file mode 100644 index 0000000..6726fda --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/Scope.java @@ -0,0 +1,14 @@ +package de.eldoria.bigdoorsopener.core.conditions; + +public enum Scope { + /** + * This condition requires world evaluation. + *

It will only be called once in a evaluation cyclus. + */ + WORLD, + /** + * This condition requires per player evaluation. + *

It will be called for each player in a evaluation cyclus. + */ + PLAYER +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/conditions/exceptions/ConditionRegistrationException.java b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/exceptions/ConditionRegistrationException.java new file mode 100644 index 0000000..9ba93e7 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/conditions/exceptions/ConditionRegistrationException.java @@ -0,0 +1,7 @@ +package de.eldoria.bigdoorsopener.core.conditions.exceptions; + +public class ConditionRegistrationException extends RuntimeException { + public ConditionRegistrationException(Class clazz) { + super("Registration of condition " + clazz.getName() + " failed."); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/events/ConditionBagModifiedEvent.java b/src/main/java/de/eldoria/bigdoorsopener/core/events/ConditionBagModifiedEvent.java new file mode 100644 index 0000000..d4fad3e --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/events/ConditionBagModifiedEvent.java @@ -0,0 +1,31 @@ +package de.eldoria.bigdoorsopener.core.events; + +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; +import lombok.Getter; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class ConditionBagModifiedEvent extends Event { + private static final HandlerList HANDLERS = new HandlerList(); + @Getter + private final ConditionBag conditionBag; + + /** + * Create a new Door Unegistered Event. + * + * @param conditionBag bag which was modified. + */ + public ConditionBagModifiedEvent(ConditionBag conditionBag) { + this.conditionBag = conditionBag; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorModifiedEvent.java b/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorModifiedEvent.java new file mode 100644 index 0000000..8584ecb --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorModifiedEvent.java @@ -0,0 +1,31 @@ +package de.eldoria.bigdoorsopener.core.events; + +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import lombok.Getter; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class DoorModifiedEvent extends Event { + private static final HandlerList HANDLERS = new HandlerList(); + @Getter + private final ConditionalDoor door; + + /** + * Create a new Door Unegistered Event. + * + * @param door world where the blood night has ended. + */ + public DoorModifiedEvent(ConditionalDoor door) { + this.door = door; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorRegisteredEvent.java b/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorRegisteredEvent.java new file mode 100644 index 0000000..02f2f34 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorRegisteredEvent.java @@ -0,0 +1,31 @@ +package de.eldoria.bigdoorsopener.core.events; + +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import lombok.Getter; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class DoorRegisteredEvent extends Event { + private static final HandlerList HANDLERS = new HandlerList(); + @Getter + private final ConditionalDoor door; + + /** + * Create a new Door Registered Event. + * + * @param door world where the blood night has ended. + */ + public DoorRegisteredEvent(ConditionalDoor door) { + this.door = door; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorUnregisteredEvent.java b/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorUnregisteredEvent.java new file mode 100644 index 0000000..403aeca --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/events/DoorUnregisteredEvent.java @@ -0,0 +1,31 @@ +package de.eldoria.bigdoorsopener.core.events; + +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import lombok.Getter; +import org.bukkit.event.Event; +import org.bukkit.event.HandlerList; +import org.jetbrains.annotations.NotNull; + +public class DoorUnregisteredEvent extends Event { + private static final HandlerList HANDLERS = new HandlerList(); + @Getter + private final ConditionalDoor door; + + /** + * Create a new Door Unegistered Event. + * + * @param door world where the blood night has ended. + */ + public DoorUnregisteredEvent(ConditionalDoor door) { + this.door = door; + } + + public static HandlerList getHandlerList() { + return HANDLERS; + } + + @Override + public @NotNull HandlerList getHandlers() { + return HANDLERS; + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/exceptions/ConditionCreationException.java b/src/main/java/de/eldoria/bigdoorsopener/core/exceptions/ConditionCreationException.java new file mode 100644 index 0000000..faf890b --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/exceptions/ConditionCreationException.java @@ -0,0 +1,21 @@ +package de.eldoria.bigdoorsopener.core.exceptions; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; + +public class ConditionCreationException extends RuntimeException { + public ConditionCreationException(Class con) { + super("Could not create condition of type " + con.getName() + "."); + } + + public ConditionCreationException(Class con, Throwable cause) { + super("Could not create condition of type " + con.getName() + ".", cause); + } + + public ConditionCreationException(String message, Throwable cause) { + super(message, cause); + } + + public ConditionCreationException(String message) { + super(message); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/listener/DoorOpenedListener.java b/src/main/java/de/eldoria/bigdoorsopener/core/listener/DoorOpenedListener.java similarity index 84% rename from src/main/java/de/eldoria/bigdoorsopener/listener/DoorOpenedListener.java rename to src/main/java/de/eldoria/bigdoorsopener/core/listener/DoorOpenedListener.java index 28f529b..ddf876a 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/listener/DoorOpenedListener.java +++ b/src/main/java/de/eldoria/bigdoorsopener/core/listener/DoorOpenedListener.java @@ -1,7 +1,7 @@ -package de.eldoria.bigdoorsopener.listener; +package de.eldoria.bigdoorsopener.core.listener; import de.eldoria.bigdoorsopener.config.Config; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import nl.pim16aap2.bigDoors.Door; import nl.pim16aap2.bigDoors.events.DoorEventToggle; import nl.pim16aap2.bigDoors.events.DoorEventToggleEnd; @@ -18,7 +18,7 @@ public DoorOpenedListener(Config config) { @EventHandler public void doorOpened(DoorEventToggleEnd toggleEnd) { Door toggledDoor = toggleEnd.getDoor(); - ConditionalDoor conDoor = config.getDoors().get(toggledDoor.getDoorUID()); + ConditionalDoor conDoor = config.getDoor(toggledDoor.getDoorUID()); if (conDoor == null) return; if (toggleEnd.getToggleType() == DoorEventToggle.ToggleType.STATIC) return; diff --git a/src/main/java/de/eldoria/bigdoorsopener/core/listener/ModificationListener.java b/src/main/java/de/eldoria/bigdoorsopener/core/listener/ModificationListener.java new file mode 100644 index 0000000..ade9346 --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/core/listener/ModificationListener.java @@ -0,0 +1,37 @@ +package de.eldoria.bigdoorsopener.core.listener; + +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.bigdoorsopener.core.events.ConditionBagModifiedEvent; +import de.eldoria.bigdoorsopener.core.events.DoorModifiedEvent; +import de.eldoria.bigdoorsopener.core.events.DoorRegisteredEvent; +import de.eldoria.bigdoorsopener.core.events.DoorUnregisteredEvent; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class ModificationListener implements Listener { + private final Config config; + + public ModificationListener(Config config) { + this.config = config; + } + + @EventHandler + public void onConditionBagModification(ConditionBagModifiedEvent event) { + config.safeConfig(); + } + + @EventHandler + public void onDoorModifiedEvent(DoorModifiedEvent event) { + config.safeConfig(); + } + + @EventHandler + public void onDoorRegisteredEvent(DoorRegisteredEvent event) { + config.safeConfig(); + } + + @EventHandler + public void onDoorUnregisteredEvent(DoorUnregisteredEvent event) { + config.safeConfig(); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/listener/registration/InteractionRegistrationObject.java b/src/main/java/de/eldoria/bigdoorsopener/core/listener/registration/InteractionRegistrationObject.java similarity index 68% rename from src/main/java/de/eldoria/bigdoorsopener/listener/registration/InteractionRegistrationObject.java rename to src/main/java/de/eldoria/bigdoorsopener/core/listener/registration/InteractionRegistrationObject.java index 0954225..84827a2 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/listener/registration/InteractionRegistrationObject.java +++ b/src/main/java/de/eldoria/bigdoorsopener/core/listener/registration/InteractionRegistrationObject.java @@ -1,5 +1,6 @@ -package de.eldoria.bigdoorsopener.listener.registration; +package de.eldoria.bigdoorsopener.core.listener.registration; +import de.eldoria.eldoutilities.messages.MessageSender; import org.bukkit.event.player.PlayerInteractEvent; /** @@ -12,5 +13,5 @@ public interface InteractionRegistrationObject { * @param event interaction event of the player. * @return true if the registration is done and the object can be removed. */ - boolean register(PlayerInteractEvent event); + boolean invoke(PlayerInteractEvent event, MessageSender messageSender); } diff --git a/src/main/java/de/eldoria/bigdoorsopener/listener/registration/RegisterInteraction.java b/src/main/java/de/eldoria/bigdoorsopener/core/listener/registration/RegisterInteraction.java similarity index 62% rename from src/main/java/de/eldoria/bigdoorsopener/listener/registration/RegisterInteraction.java rename to src/main/java/de/eldoria/bigdoorsopener/core/listener/registration/RegisterInteraction.java index cfe5617..d71ee27 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/listener/registration/RegisterInteraction.java +++ b/src/main/java/de/eldoria/bigdoorsopener/core/listener/registration/RegisterInteraction.java @@ -1,5 +1,7 @@ -package de.eldoria.bigdoorsopener.listener.registration; +package de.eldoria.bigdoorsopener.core.listener.registration; +import de.eldoria.bigdoorsopener.config.Config; +import de.eldoria.eldoutilities.messages.MessageSender; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -13,15 +15,35 @@ * This listener allows to execute a call on a object which tries further actions though player interactions. */ public class RegisterInteraction implements Listener { + private static RegisterInteraction instance; private final Map registerObjects = new HashMap<>(); + private final MessageSender messageSender; + private final Config config; + + public RegisterInteraction(MessageSender messageSender, Config config) { + if (instance != null) { + throw new ExceptionInInitializerError("Register interaction is already initialized"); + } + + this.messageSender = messageSender; + this.config = config; + instance = this; + } + + public static RegisterInteraction getInstance() { + if (instance == null) { + throw new NullPointerException("Register interaction is not initialized"); + } + return instance; + } @EventHandler public void onPlayerInteraction(PlayerInteractEvent event) { if (registerObjects.containsKey(event.getPlayer().getUniqueId())) { InteractionRegistrationObject registrationObject = registerObjects.get(event.getPlayer().getUniqueId()); - boolean register = registrationObject.register(event); - if (register) { + if (registrationObject.invoke(event, messageSender)) { registerObjects.remove(event.getPlayer().getUniqueId()); + config.safeConfig(); } } } diff --git a/src/main/java/de/eldoria/bigdoorsopener/scheduler/DoorChecker.java b/src/main/java/de/eldoria/bigdoorsopener/core/scheduler/DoorChecker.java similarity index 84% rename from src/main/java/de/eldoria/bigdoorsopener/scheduler/DoorChecker.java rename to src/main/java/de/eldoria/bigdoorsopener/core/scheduler/DoorChecker.java index 29e980d..2b85fef 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/scheduler/DoorChecker.java +++ b/src/main/java/de/eldoria/bigdoorsopener/core/scheduler/DoorChecker.java @@ -1,10 +1,13 @@ -package de.eldoria.bigdoorsopener.scheduler; +package de.eldoria.bigdoorsopener.core.scheduler; import com.google.common.cache.Cache; -import de.eldoria.bigdoorsopener.BigDoorsOpener; +import de.eldoria.bigdoorsopener.conditions.location.Proximity; import de.eldoria.bigdoorsopener.config.Config; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.location.Proximity; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.adapter.BigDoorsAdapter; +import de.eldoria.bigdoorsopener.core.events.DoorRegisteredEvent; +import de.eldoria.bigdoorsopener.core.events.DoorUnregisteredEvent; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import de.eldoria.bigdoorsopener.util.C; import de.eldoria.eldoutilities.functions.TriFunction; import de.eldoria.eldoutilities.localization.Localizer; @@ -13,6 +16,8 @@ import org.bukkit.Server; import org.bukkit.World; import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; import org.bukkit.util.Vector; import java.util.HashMap; @@ -25,7 +30,7 @@ import java.util.concurrent.ExecutionException; import java.util.logging.Level; -public class DoorChecker extends BigDoorsAdapter implements Runnable { +public class DoorChecker extends BigDoorsAdapter implements Runnable, Listener { private final Queue doors = new LinkedList<>(); private final Server server = Bukkit.getServer(); @@ -37,35 +42,25 @@ public class DoorChecker extends BigDoorsAdapter implements Runnable { private final Set evaluated = new HashSet<>(); private final Cache> worldPlayers = C.getShortExpiringCache(); private final Cache chunkStateCache = C.getShortExpiringCache(); - private double doorUpdateInterval; private final TriFunction proximity = Proximity.ProximityForm.CUBOID.check; + private double doorUpdateInterval; public DoorChecker(Config config, BigDoors bigDoors, Localizer localizer) { - super(bigDoors, localizer); + super(bigDoors); this.config = config; - doors.addAll(config.getDoors().values()); + doors.addAll(config.getDoors()); } - /** - * Registers a new door at the door checker. - * Only registered doors will do anything. - * The door will only be registered if its not yet registered. - * - * @param door door to register. - */ - public void register(ConditionalDoor door) { - if (!doors.contains(door)) { - doors.add(door); + @EventHandler + public void onDoorRegister(DoorRegisteredEvent event) { + if (!doors.contains(event.getDoor())) { + doors.add(event.getDoor()); } } - /** - * Unregister a door. - * - * @param door door to unregister. - */ - public void unregister(ConditionalDoor door) { - doors.remove(door); + @EventHandler + public void onDoorUnregister(DoorUnregisteredEvent event) { + doors.remove(event.getDoor()); } /** @@ -75,7 +70,7 @@ public void unregister(ConditionalDoor door) { public void reload() { synchronized (doors) { doors.clear(); - doors.addAll(config.getDoors().values()); + doors.addAll(config.getDoors()); } } @@ -99,9 +94,8 @@ public void run() { assert door != null : "Door is null. How could this happen?"; if (!doorExists(door)) { - config.getDoors().remove(door.getDoorUID()); + config.removeDoor(door.getDoorUID()); BigDoorsOpener.logger().info("Door with id " + door.getDoorUID() + " has been deleted. Removing."); - config.safeConfig(); continue; } @@ -119,12 +113,12 @@ public void run() { } } catch (ExecutionException e) { BigDoorsOpener.logger().log(Level.WARNING, - "A error occured while calculating the chunk cache state. Please report this.", e); + "An error occured while calculating the chunk cache state. Please report this.", e); continue; } // skip busy doors. bcs why should we try to open/close a door we cant open/close - if (getCommander().isDoorBusy(door.getDoorUID())) { + if (getCommander().isDoorBusy(door.getDoorUID()) || !door.isEnabled()) { continue; } diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/ConditionalDoor.java b/src/main/java/de/eldoria/bigdoorsopener/door/ConditionalDoor.java similarity index 70% rename from src/main/java/de/eldoria/bigdoorsopener/doors/ConditionalDoor.java rename to src/main/java/de/eldoria/bigdoorsopener/door/ConditionalDoor.java index d07337f..d1de5d1 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/ConditionalDoor.java +++ b/src/main/java/de/eldoria/bigdoorsopener/door/ConditionalDoor.java @@ -1,13 +1,15 @@ -package de.eldoria.bigdoorsopener.doors; +package de.eldoria.bigdoorsopener.door; import com.google.common.base.Objects; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionChain; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.events.DoorModifiedEvent; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionBag; +import de.eldoria.bigdoorsopener.door.conditioncollections.ConditionChain; import de.eldoria.eldoutilities.serialization.SerializationUtil; import de.eldoria.eldoutilities.serialization.TypeResolvingMap; import de.eldoria.eldoutilities.utils.EnumUtil; import lombok.Getter; -import lombok.Setter; +import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.configuration.serialization.ConfigurationSerializable; import org.bukkit.configuration.serialization.SerializableAs; @@ -45,6 +47,8 @@ public class ConditionalDoor implements ConfigurationSerializable { */ private final Vector position; + private boolean enabled = true; + private Instant openTill; /** @@ -55,12 +59,10 @@ public class ConditionalDoor implements ConfigurationSerializable { /** * the type the condition chain uses to evaluate the conditions */ - private EvaluationType evaluationType = EvaluationType.OR; + private EvaluationType evaluationType = EvaluationType.AND; - @Getter - @Setter @Nonnull - private ConditionChain conditionChain; + private ConditionBag conditionBag; /** * Amount of time in seconds a door will stay open when opened. @@ -73,41 +75,36 @@ public class ConditionalDoor implements ConfigurationSerializable { /** * True if the door was registered in open state. */ - @Setter - @Getter private boolean invertOpen = false; - public ConditionalDoor(long doorUID, String world, Vector position, ConditionChain conditionChain) { + public ConditionalDoor(long doorUID, String world, Vector position, ConditionBag conditionChain) { this.doorUID = doorUID; this.world = world; this.position = position; - this.conditionChain = conditionChain; + this.conditionBag = conditionChain; } public ConditionalDoor(long doorUID, String world, Vector position) { - this(doorUID, world, position, new ConditionChain()); - } - - public ConditionalDoor(long doorUID, String world, Vector position, boolean invertOpen, String evaluator, - EvaluationType evaluationType, ConditionChain conditionChain, int stayOpen) { - this(doorUID, world, position, conditionChain); - this.invertOpen = invertOpen; - this.evaluator = evaluator; - this.evaluationType = evaluationType; - this.stayOpen = stayOpen; + this(doorUID, world, position, new ConditionBag()); } public ConditionalDoor(Map map) { TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - int doorUID = resolvingMap.getValue("doorUID"); - this.doorUID = doorUID; + doorUID = (int) resolvingMap.getValue("doorUID"); world = resolvingMap.getValue("world"); position = resolvingMap.getValue("position"); + enabled = resolvingMap.getValueOrDefault("enabled", true); invertOpen = resolvingMap.getValue("invertOpen"); evaluator = resolvingMap.getValue("evaluator"); evaluationType = EnumUtil.parse(resolvingMap.getValue("evaluationType"), EvaluationType.class); - conditionChain = resolvingMap.getValue("conditionChain"); + if (resolvingMap.containsKey("conditionChain")) { + ConditionChain conditionChain = resolvingMap.getValue("conditionChain"); + conditionBag = new ConditionBag(); + conditionChain.getConditions().stream().filter(java.util.Objects::nonNull).forEach(c -> conditionBag.putCondition(c)); + } else { + conditionBag = resolvingMap.getValue("conditionBag"); + } stayOpen = resolvingMap.getValue("stayOpen"); } @@ -128,12 +125,12 @@ public boolean getState(Player player, World world, boolean currentState) { switch (evaluationType) { case CUSTOM: - String custom = conditionChain.custom(evaluator, player, world, this, currentState); + String custom = conditionBag.custom(evaluator, player, world, this, currentState); return BigDoorsOpener.JS().eval(custom, currentState); case AND: - return conditionChain.and(player, world, this, currentState); + return conditionBag.and(player, world, this, currentState); case OR: - return conditionChain.or(player, world, this, currentState); + return conditionBag.or(player, world, this, currentState); default: throw new IllegalStateException("Unexpected value: " + evaluationType); } @@ -165,7 +162,7 @@ public int hashCode() { public void opened(@Nullable Player player) { waitForOpen = true; if (player == null) return; - conditionChain.opened(player); + conditionBag.opened(player); } /** @@ -177,11 +174,11 @@ public void opened() { } public void evaluated() { - conditionChain.evaluated(); + conditionBag.evaluated(); } public boolean requiresPlayerEvaluation() { - return conditionChain.requiresPlayerEvaluation(); + return conditionBag.requiresPlayerEvaluation(); } public void setEvaluator(EvaluationType evaluationType) { @@ -189,11 +186,13 @@ public void setEvaluator(EvaluationType evaluationType) { if (evaluationType == EvaluationType.OR || evaluationType == EvaluationType.AND) { evaluator = ""; } + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(this)); } public void setEvaluator(String evaluator) { this.evaluator = evaluator; evaluationType = EvaluationType.CUSTOM; + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(this)); } /** @@ -204,6 +203,7 @@ public void setEvaluator(String evaluator) { */ public void setStayOpen(int stayOpen) { this.stayOpen = stayOpen; + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(this)); } /** @@ -211,6 +211,7 @@ public void setStayOpen(int stayOpen) { */ public void invertOpen() { invertOpen = !invertOpen; + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(this)); } @Override @@ -219,15 +220,29 @@ public void invertOpen() { .add("doorUID", doorUID) .add("world", world) .add("position", position) + .add("enabled", enabled) .add("invertOpen", invertOpen) .add("evaluator", evaluator) .add("evaluationType", evaluationType) .add("stayOpen", stayOpen) - .add("conditionChain", conditionChain) + .add("conditionBag", conditionBag) .build(); } + public void setConditionBag(@Nonnull ConditionBag conditionBag) { + this.conditionBag = conditionBag; + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(this)); + } + public void setInvertOpen(boolean invertOpen) { + this.invertOpen = invertOpen; + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(this)); + } + + public void setEnabled(Boolean state) { + enabled = state; + Bukkit.getPluginManager().callEvent(new DoorModifiedEvent(this)); + } public enum EvaluationType { CUSTOM, AND, OR diff --git a/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionBag.java b/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionBag.java new file mode 100644 index 0000000..a6b2afd --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionBag.java @@ -0,0 +1,158 @@ +package de.eldoria.bigdoorsopener.door.conditioncollections; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionGroup; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.core.events.ConditionBagModifiedEvent; +import de.eldoria.bigdoorsopener.core.exceptions.ConditionCreationException; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import org.bukkit.Bukkit; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.TreeMap; +import java.util.stream.Collectors; + +@SerializableAs("bdoConditionBag") +public class ConditionBag implements ConditionCollection { + private final Map playerScope = new TreeMap<>(); + private final Map worldScope = new TreeMap<>(); + + private ConditionBag(Collection playerScope, Collection worldScope) { + playerScope.forEach(c -> { + ConditionRegistrar.getContainerByClass(c.getClass()).ifPresent(g -> this.playerScope.put(g.getGroup(), c)); + }); + worldScope.forEach(c -> { + ConditionRegistrar.getContainerByClass(c.getClass()).ifPresent(g -> this.worldScope.put(g.getGroup(), c)); + }); + } + + public ConditionBag() { + + } + + public ConditionBag(Map map) { + TypeResolvingMap typeResolvingMap = SerializationUtil.mapOf(map); + List conditions = (List) typeResolvingMap.get("conditions"); + conditions.forEach(this::putCondition); + } + + @Override + public @NotNull Map serialize() { + Collection values = playerScope.values(); + values.addAll(worldScope.values()); + return SerializationUtil.newBuilder().add("conditions", values).build(); + } + + public void putCondition(DoorCondition condition) { + Optional containerByClass = ConditionRegistrar.getContainerByClass(condition.getClass()); + if (!containerByClass.isPresent()) { + throw new ConditionCreationException("The requested condition " + condition.getClass().getName() + "is not registered"); + } + ConditionContainer container = containerByClass.get(); + if (container.getScope() == Scope.PLAYER) { + playerScope.put(container.getGroup(), condition); + } else { + worldScope.put(container.getGroup(), condition); + } + Bukkit.getPluginManager().callEvent(new ConditionBagModifiedEvent(this)); + } + + public boolean removeCondition(ConditionGroup container) { + boolean result = playerScope.remove(container.getName()) != null || worldScope.remove(container.getName()) != null; + Bukkit.getPluginManager().callEvent(new ConditionBagModifiedEvent(this)); + return result; + } + + public Optional getCondition(ConditionGroup container) { + return getCondition(container.getName()); + } + + public Optional getCondition(String group) { + Optional worldCon = Optional.ofNullable(worldScope.get(group)); + if (worldCon.isPresent()) return worldCon; + return Optional.ofNullable(playerScope.get(group)); + } + + public boolean isConditionSet(ConditionGroup container) { + return getCondition(container).isPresent(); + } + + @Override + public String custom(String string, Player player, World world, ConditionalDoor door, boolean currentState) { + String evaluationString = string; + + for (DoorCondition condition : getConditions()) { + Boolean state; + + Optional containerByClass = ConditionRegistrar.getContainerByClass(condition.getClass()); + if (!containerByClass.isPresent()) { + throw new ConditionCreationException("The requested condition is not registered"); + } + ConditionContainer container = containerByClass.get(); + + if (container.getScope() == Scope.PLAYER && player == null) { + state = false; + } else { + state = condition.isOpen(player, world, door, currentState); + } + evaluationString = evaluationString.replaceAll("(?i)" + container.getGroup(), + String.valueOf(state)); + } + + evaluationString = evaluationString.replaceAll("(?i)currentState", + String.valueOf(currentState)); + + // make sure that calculation does not fail even when the condition is not set. + for (String value : ConditionRegistrar.getGroups()) { + evaluationString = evaluationString.replaceAll("(?i)" + value, "null"); + } + + return evaluationString; + } + + @Override + public void evaluated() { + playerScope.values().forEach(DoorCondition::evaluated); + worldScope.values().forEach(DoorCondition::evaluated); + } + + @Override + public void opened(Player player) { + playerScope.values().forEach(c -> c.opened(player)); + } + + @Override + public boolean requiresPlayerEvaluation() { + return !playerScope.isEmpty(); + } + + @Override + public boolean isEmpty() { + return worldScope.isEmpty() && playerScope.isEmpty(); + } + + @Override + public ConditionBag copy() { + return new ConditionBag( + playerScope.values().stream().map(DoorCondition::clone).collect(Collectors.toList()), + worldScope.values().stream().map(DoorCondition::clone).collect(Collectors.toList())); + } + + @Override + public Collection getConditions() { + Collection values = playerScope.values(); + values.addAll(worldScope.values()); + return values; + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionChain.java b/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionChain.java new file mode 100644 index 0000000..408cbbb --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionChain.java @@ -0,0 +1,207 @@ +package de.eldoria.bigdoorsopener.door.conditioncollections; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.item.Item; +import de.eldoria.bigdoorsopener.conditions.location.Location; +import de.eldoria.bigdoorsopener.conditions.permission.Permission; +import de.eldoria.bigdoorsopener.conditions.standalone.Placeholder; +import de.eldoria.bigdoorsopener.conditions.standalone.Time; +import de.eldoria.bigdoorsopener.conditions.standalone.mythicmobs.MythicMob; +import de.eldoria.bigdoorsopener.conditions.standalone.weather.Weather; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.C; +import de.eldoria.bigdoorsopener.util.ConditionChainEvaluator; +import de.eldoria.eldoutilities.serialization.SerializationUtil; +import de.eldoria.eldoutilities.serialization.TypeResolvingMap; +import lombok.Getter; +import lombok.Setter; +import org.bukkit.World; +import org.bukkit.configuration.serialization.SerializableAs; +import org.bukkit.entity.Player; +import org.jetbrains.annotations.NotNull; + +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; + +/** + * A condition chain represents a set of multiple conditions. + * + * @deprecated This class is only present for serialization reasons and will be removed in the next major release. + * Use {@link ConditionBag} instead + */ +@Setter +@Getter +@SerializableAs("conditionChain") +@Deprecated +public class ConditionChain implements ConditionCollection { + private Item item = null; + private Location location = null; + private Permission permission = null; + private Time time = null; + private Weather weather = null; + private Placeholder placeholder = null; + private MythicMob mythicMob = null; + + public ConditionChain() { + } + + private ConditionChain(Item item, Location location, Permission permission, Time time, Weather weather, Placeholder placeholder, MythicMob mythicMob) { + this.item = item; + this.location = location; + this.permission = permission; + this.time = time; + this.weather = weather; + this.mythicMob = mythicMob; + } + + public static ConditionChain deserialize(Map map) { + TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); + Item item = resolvingMap.getValue("item"); + Location location = resolvingMap.getValue("location"); + Permission permission = resolvingMap.getValue("permission"); + Time time = resolvingMap.getValue("time"); + Weather weather = resolvingMap.getValue("weather"); + Placeholder placeholder = resolvingMap.getValueOrDefault("placeholder", null); + MythicMob mythicMob = resolvingMap.getValueOrDefault("mythicMob", null); + return new ConditionChain(item, location, permission, time, weather, placeholder, mythicMob); + } + + /** + * Evaluates the conditions with an or operator. + * + * @param player player which should be checked + * @param world world of the door + * @param door door which is checked + * @param currentState the current state of the door + * @return result of the conditions. + */ + @Override + public boolean or(Player player, World world, ConditionalDoor door, boolean currentState) { + // the conditions should be evaluated from the simpelest to the most expensive computation. + return ConditionChainEvaluator.or(player, world, door, currentState, + getConditions()); + } + + /** + * Evaluates the conditions with an and operator. + * + * @param player player which should be checked + * @param world world of the door + * @param door door which is checked + * @param currentState the current state of the door + * @return result of the conditions. + */ + @Override + + public boolean and(Player player, World world, ConditionalDoor door, boolean currentState) { + // the conditions should be evaluated from the simpelest to the most expensive computation. + return ConditionChainEvaluator.and(player, world, door, currentState, + getConditions()); + } + + /** + * Evaluates the chain with a custom evaluation string. + * + * @param string evaluator. + * @param player player which should be checked + * @param world world of the door + * @param door door which is checked + * @param currentState the current state of the door + * @return string with the values replaced. + */ + @Override + + public String custom(String string, Player player, World world, ConditionalDoor door, boolean currentState) { + return "null"; + } + + /** + * Checks if a key is present which needs a player lookup. + * + * @return true if a player key is present. + */ + @Override + + public boolean requiresPlayerEvaluation() { + return item != null || permission != null || location != null || placeholder != null; + } + + /** + * Called when the door was evaluated and a new evaluation cycle begins. + */ + @Override + + public void evaluated() { + if (item != null) { + item.evaluated(); + } + } + + /** + * Called when the chain was true and the door was opened. + * + * @param player player which opened the door. + */ + @Override + + public void opened(Player player) { + if (item != null) { + item.opened(player); + } + } + + @Override + public @NotNull Map serialize() { + return SerializationUtil.newBuilder() + .add("item", item) + .add("permission", permission) + .add("location", location) + .add("time", time) + .add("weather", weather) + .add("placeholder", placeholder) + .add("mythicMob", mythicMob) + .build(); + + } + + /** + * Checks if all conditions are null. + * + * @return true if all conditions are nulkl + */ + @Override + + public boolean isEmpty() { + for (DoorCondition condition : getConditions()) { + if (condition != null) return false; + } + return true; + } + + /** + * Get a mutable new condition chain with the same conditions like this condition chain. + * + * @return new condition chain. + */ + @Override + + public ConditionChain copy() { + return new ConditionChain(C.nonNullOrElse(item, Item::clone, null), C.nonNullOrElse(location, Location::clone, null), + C.nonNullOrElse(permission, Permission::clone, null), C.nonNullOrElse(time, Time::clone, null), + C.nonNullOrElse(weather, Weather::clone, null), C.nonNullOrElse(placeholder, Placeholder::clone, null), + C.nonNullOrElse(mythicMob, MythicMob::clone, null) + ); + } + + /** + * Get the conditions in a order from the less expensive to the most expensive computation time + * + * @return array of conditions. May contain null values. + */ + @Override + + public Collection getConditions() { + return Arrays.asList(location, time, weather, mythicMob, permission, item, placeholder); + } +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionCollection.java b/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionCollection.java new file mode 100644 index 0000000..cd8a46e --- /dev/null +++ b/src/main/java/de/eldoria/bigdoorsopener/door/conditioncollections/ConditionCollection.java @@ -0,0 +1,90 @@ +package de.eldoria.bigdoorsopener.door.conditioncollections; + +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; +import de.eldoria.bigdoorsopener.util.ConditionChainEvaluator; +import org.bukkit.World; +import org.bukkit.configuration.serialization.ConfigurationSerializable; +import org.bukkit.entity.Player; + +import java.util.Collection; + +public interface ConditionCollection extends ConfigurationSerializable, Cloneable { + /** + * Evaluates the conditions with an or operator. + * + * @param player player which should be checked + * @param world world of the door + * @param door door which is checked + * @param currentState the current state of the door + * @return result of the conditions. + */ + default boolean or(Player player, World world, ConditionalDoor door, boolean currentState) { + return ConditionChainEvaluator.or(player, world, door, currentState, getConditions()); + } + + /** + * Evaluates the conditions with an and operator. + * + * @param player player which should be checked + * @param world world of the door + * @param door door which is checked + * @param currentState the current state of the door + * @return result of the conditions. + */ + default boolean and(Player player, World world, ConditionalDoor door, boolean currentState) { + return ConditionChainEvaluator.and(player, world, door, currentState, getConditions()); + } + + /** + * Evaluates the chain with a custom evaluation string. + * + * @param string evaluator. + * @param player player which should be checked + * @param world world of the door + * @param door door which is checked + * @param currentState the current state of the door + * @return string with the values replaced. + */ + public String custom(String string, Player player, World world, ConditionalDoor door, boolean currentState); + + /** + * Called when the door was evaluated and a new evaluation cycle begins. + */ + public void evaluated(); + + /** + * Called when the chain was true and the door was opened. + * + * @param player player which opened the door. + */ + public void opened(Player player); + + /** + * Checks if a key is present which needs a player lookup. + * + * @return true if a player key is present. + */ + public boolean requiresPlayerEvaluation(); + + /** + * Checks if all conditions are null. + * + * @return true if all conditions are nulkl + */ + public boolean isEmpty(); + + /** + * Get a mutable new condition chain with the same conditions like this condition chain. + * + * @return new condition chain. + */ + public ConditionCollection copy(); + + /** + * Get the conditions in a order from the less expensive to the most expensive computation time + * + * @return array of conditions. May contain null values. + */ + public Collection getConditions(); +} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/ConditionScope.java b/src/main/java/de/eldoria/bigdoorsopener/doors/ConditionScope.java deleted file mode 100644 index 8ed88c3..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/ConditionScope.java +++ /dev/null @@ -1,17 +0,0 @@ -package de.eldoria.bigdoorsopener.doors; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface ConditionScope { - - Scope value(); - - public enum Scope { - WORLD, PLAYER - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/ConditionChain.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/ConditionChain.java deleted file mode 100644 index cf41ebd..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/ConditionChain.java +++ /dev/null @@ -1,340 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions; - -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.item.Item; -import de.eldoria.bigdoorsopener.doors.conditions.location.Location; -import de.eldoria.bigdoorsopener.doors.conditions.permission.Permission; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.MythicMob; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Placeholder; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Time; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Weather; -import de.eldoria.bigdoorsopener.util.C; -import de.eldoria.bigdoorsopener.util.ConditionChainEvaluator; -import de.eldoria.eldoutilities.container.Pair; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import de.eldoria.eldoutilities.serialization.TypeResolvingMap; -import lombok.Getter; -import lombok.Setter; -import org.bukkit.World; -import org.bukkit.configuration.serialization.ConfigurationSerializable; -import org.bukkit.configuration.serialization.SerializableAs; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -/** - * A condition chain represents a set of multiple conditions. - */ -@Setter -@Getter -@SerializableAs("conditionChain") -public class ConditionChain implements ConfigurationSerializable, Cloneable { - private Item item = null; - private Location location = null; - private Permission permission = null; - private Time time = null; - private Weather weather = null; - private Placeholder placeholder = null; - private MythicMob mythicMob = null; - - public ConditionChain() { - } - - private ConditionChain(Item item, Location location, Permission permission, Time time, Weather weather, Placeholder placeholder, MythicMob mythicMob) { - this.item = item; - this.location = location; - this.permission = permission; - this.time = time; - this.weather = weather; - this.mythicMob = mythicMob; - } - - public static ConditionChain deserialize(Map map) { - TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - Item item = resolvingMap.getValue("item"); - Location location = resolvingMap.getValue("location"); - Permission permission = resolvingMap.getValue("permission"); - Time time = resolvingMap.getValue("time"); - Weather weather = resolvingMap.getValue("weather"); - Placeholder placeholder = resolvingMap.getValueOrDefault("placeholder", null); - MythicMob mythicMob = resolvingMap.getValueOrDefault("mythicMob", null); - return new ConditionChain(item, location, permission, time, weather, placeholder, mythicMob); - } - - /** - * Evaluates the conditions with an or operator. - * - * @param player player which should be checked - * @param world world of the door - * @param door door which is checked - * @param currentState the current state of the door - * @return result of the conditions. - */ - public boolean or(Player player, World world, ConditionalDoor door, boolean currentState) { - // the conditions should be evaluated from the simpelest to the most expensive computation. - return ConditionChainEvaluator.or(player, world, door, currentState, - this); - } - - /** - * Evaluates the conditions with an and operator. - * - * @param player player which should be checked - * @param world world of the door - * @param door door which is checked - * @param currentState the current state of the door - * @return result of the conditions. - */ - public boolean and(Player player, World world, ConditionalDoor door, boolean currentState) { - // the conditions should be evaluated from the simpelest to the most expensive computation. - return ConditionChainEvaluator.and(player, world, door, currentState, - this); - } - - /** - * Evaluates the chain with a custom evaluation string. - * - * @param string evaluator. - * @param player player which should be checked - * @param world world of the door - * @param door door which is checked - * @param currentState the current state of the door - * @return string with the values replaced. - */ - public String custom(String string, Player player, World world, ConditionalDoor door, boolean currentState) { - String evaluationString = string; - - for (DoorCondition doorCondition : getConditions()) { - if (doorCondition == null) { - continue; - } - ConditionType.ConditionGroup condition = ConditionType.getType(doorCondition.getClass()); - if (condition == null) { - BigDoorsOpener.logger().warning("Class " + doorCondition.getClass().getSimpleName() + " is not registered as condition type." - + doorCondition.getClass().getSimpleName()); - continue; - } - Boolean state; - - if (doorCondition.getScope() == ConditionScope.Scope.PLAYER - && player == null) { - state = false; - } else { - state = doorCondition.isOpen(player, world, door, currentState); - } - evaluationString = evaluationString.replaceAll("(?i)" + condition.conditionParameter, - String.valueOf(state)); - } - - evaluationString = evaluationString.replaceAll("(?i)currentState", - String.valueOf(currentState)); - - // make sure that calculation does not fail even when the condition is not set. - for (ConditionType.ConditionGroup value : ConditionType.ConditionGroup.values()) { - evaluationString = evaluationString.replaceAll("(?i)" + value.conditionParameter, - "null"); - } - - return evaluationString; - } - - /** - * Checks if a key is present which needs a player lookup. - * - * @return true if a player key is present. - */ - public boolean requiresPlayerEvaluation() { - return item != null || permission != null || location != null || placeholder != null; - } - - /** - * Called when the door was evaluated and a new evaluation cycle begins. - */ - public void evaluated() { - if (item != null) { - item.evaluated(); - } - } - - /** - * Called when the chain was true and the door was opened. - * - * @param player player which opened the door. - */ - public void opened(Player player) { - if (item != null) { - item.used(player); - } - } - - @Override - public @NotNull Map serialize() { - return SerializationUtil.newBuilder() - .add("item", item) - .add("permission", permission) - .add("location", location) - .add("time", time) - .add("weather", weather) - .add("placeholder", placeholder) - .add("mythicMob", mythicMob) - .build(); - - } - - /** - * Checks if all conditions are null. - * - * @return true if all conditions are nulkl - */ - public boolean isEmpty() { - for (DoorCondition condition : getConditions()) { - if (condition != null) return false; - } - return true; - } - - /** - * Get a mutable new condition chain with the same conditions like this condition chain. - * - * @return new condition chain. - */ - public ConditionChain copy() { - return new ConditionChain(C.nonNullOrElse(item, Item::clone, null), C.nonNullOrElse(location, Location::clone, null), - C.nonNullOrElse(permission, Permission::clone, null), C.nonNullOrElse(time, Time::clone, null), - C.nonNullOrElse(weather, Weather::clone, null), C.nonNullOrElse(placeholder, Placeholder::clone, null), - C.nonNullOrElse(mythicMob, MythicMob::clone, null) - ); - } - - /** - * Get the conditions in a order from the less expensive to the most expensive computation time - * - * @return array of conditions. May contain null values. - */ - public DoorCondition[] getConditions() { - return new DoorCondition[] {location, time, weather, mythicMob, permission, item, placeholder}; - } - - /** - * Get the conditions wrapped to identify them. - * - * @return List of wrappet conditions. conditions may be null. - */ - public List> getConditionsWrapped() { - return Arrays.asList( - new Pair<>(location, ConditionType.ConditionGroup.LOCATION), - new Pair<>(permission, ConditionType.ConditionGroup.PERMISSION), - new Pair<>(time, ConditionType.ConditionGroup.TIME), - new Pair<>(weather, ConditionType.ConditionGroup.WEATHER), - new Pair<>(item, ConditionType.ConditionGroup.ITEM), - new Pair<>(placeholder, ConditionType.ConditionGroup.PLACEHOLDER), - new Pair<>(mythicMob, ConditionType.ConditionGroup.MYTHIC_MOB)); - } - - /** - * Get a condition via enum value - * - * @param group group to get - * @return condition - */ - public DoorCondition getCondition(ConditionType.ConditionGroup group) { - switch (group) { - case ITEM: - return item; - case LOCATION: - return location; - case PERMISSION: - return permission; - case TIME: - return time; - case WEATHER: - return weather; - case PLACEHOLDER: - return placeholder; - case MYTHIC_MOB: - return mythicMob; - default: - throw new IllegalStateException("Unexpected value: " + group); - } - } - - /** - * Set a condition via enum value. - * - * @param group group to set - * @param condition condition to set - */ - public void setCondition(ConditionType.ConditionGroup group, @Nullable DoorCondition condition) { - if (condition == null) { - removeCondition(group); - return; - } - - switch (group) { - case ITEM: - item = (Item) condition; - break; - case LOCATION: - location = (Location) condition; - break; - case PERMISSION: - permission = (Permission) condition; - break; - case TIME: - time = (Time) condition; - break; - case WEATHER: - weather = (Weather) condition; - break; - case PLACEHOLDER: - placeholder = (Placeholder) condition; - break; - case MYTHIC_MOB: - mythicMob = (MythicMob) condition; - break; - default: - throw new IllegalStateException("Unexpected value: " + group); - } - } - - /** - * Remove a condition by enum value. - * - * @param group condition group to remove - */ - public void removeCondition(ConditionType.ConditionGroup group) { - switch (group) { - case ITEM: - item = null; - break; - case LOCATION: - location = null; - break; - case PERMISSION: - permission = null; - break; - case TIME: - time = null; - break; - case WEATHER: - weather = null; - break; - case PLACEHOLDER: - placeholder = null; - break; - case MYTHIC_MOB: - mythicMob = null; - break; - default: - throw new IllegalStateException("Unexpected value: " + group); - } - } - - -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/ConditionType.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/ConditionType.java deleted file mode 100644 index 1513938..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/ConditionType.java +++ /dev/null @@ -1,88 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions; - -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.item.Item; -import de.eldoria.bigdoorsopener.doors.conditions.location.Location; -import de.eldoria.bigdoorsopener.doors.conditions.permission.Permission; -import de.eldoria.bigdoorsopener.doors.conditions.permission.PermissionNode; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.MythicMob; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Placeholder; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Time; -import de.eldoria.bigdoorsopener.doors.conditions.standalone.Weather; -import de.eldoria.bigdoorsopener.util.Permissions; - -public enum ConditionType { - ITEM_CLICK(ConditionGroup.ITEM), - ITEM_BLOCK(ConditionGroup.ITEM), - ITEM_HOLDING(ConditionGroup.ITEM), - ITEM_OWNING(ConditionGroup.ITEM), - PROXIMITY(ConditionGroup.LOCATION), - REGION(ConditionGroup.LOCATION), - SIMPLE_REGION(ConditionGroup.LOCATION), - PERMISSION_NODE(ConditionGroup.PERMISSION), - DOOR_PERMISSION(ConditionGroup.PERMISSION), - TIME(ConditionGroup.TIME), - WEATHER(ConditionGroup.WEATHER), - PLACEHOLDER(ConditionGroup.PLACEHOLDER), - MYTHIC_MOBS(ConditionGroup.MYTHIC_MOB); - - public final ConditionGroup conditionGroup; - public final String conditionName; - - ConditionType(ConditionGroup keyParameter) { - this.conditionGroup = keyParameter; - this.conditionName = name().replace("_", "").toLowerCase(); - } - - /** - * Get the type from a string - * - * @param keyType string as type - * @return - */ - public static ConditionType getType(String keyType) { - for (ConditionType value : values()) { - if (value.conditionName.equalsIgnoreCase(keyType)) { - return value; - } - } - return null; - } - - public static ConditionGroup getType(Class keyClass) { - for (ConditionGroup value : ConditionGroup.values()) { - if (value.keyClass.isAssignableFrom(keyClass)) { - return value; - } - } - return null; - } - - public enum ConditionGroup { - ITEM("item", "item", "info.item", Item.class, Permissions.ITEM_CONDITION), - LOCATION("location", "", "info.location", Location.class, Permissions.LOCATION_CONDITION), - PERMISSION("permission", "permission", "info.permission", Permission.class, Permissions.PERMISSION_CONDITION), - TIME("time", "time", "info.time", Time.class, Permissions.TIME_CONDITION), - WEATHER("weather", "weather", "info.weather", Weather.class, Permissions.WEATHER_CONDITION), - PLACEHOLDER("placeholder", "placeholder", "info.placeholder", Placeholder.class, Permissions.PLACEHOLDER_CONDITION), - MYTHIC_MOB("mythicMobs", "mythicMobs", "info.mythicmob", MythicMob.class, Permissions.MYTHIC_MOBS); - - public final String conditionParameter; - public final String infoKey; - public final Class keyClass; - public final String permission; - private final String baseSetCommand; - - ConditionGroup(String conditionParameter, String baseSetCommand, String infoKey, Class keyClass, String permission) { - this.conditionParameter = conditionParameter; - this.baseSetCommand = baseSetCommand; - this.infoKey = infoKey; - this.keyClass = keyClass; - this.permission = permission; - } - - public String getBaseSetCommand(ConditionalDoor door) { - return "/bdo setCondition " + door.getDoorUID() + " " + baseSetCommand + " "; - } - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/DoorState.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/DoorState.java deleted file mode 100644 index 26362b0..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/DoorState.java +++ /dev/null @@ -1,3 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions; - -public enum DoorState {OPEN, CLOSED} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/ItemHolding.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/ItemHolding.java deleted file mode 100644 index 44e5430..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/ItemHolding.java +++ /dev/null @@ -1,66 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions.item; - -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import de.eldoria.eldoutilities.serialization.TypeResolvingMap; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.World; -import org.bukkit.configuration.serialization.SerializableAs; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.util.Map; - -/** - * A key which will be open when the player is holding a key in his hand. - */ -@SerializableAs("itemHoldingCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) -public class ItemHolding extends Item { - public ItemHolding(ItemStack item, boolean consumed) { - super(item, consumed); - } - - public static ItemHolding deserialize(Map map) { - TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - ItemStack stack = resolvingMap.getValue("item"); - boolean consumed = resolvingMap.getValue("consumed"); - return new ItemHolding(stack, consumed); - } - - @Override - public void used(Player player) { - if (!isConsumed()) return; - tryTakeFromHands(player); - } - - @Override - public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { - return hasPlayerItemInHand(player); - } - - @Override - public TextComponent getDescription(Localizer localizer) { - return TextComponent.builder( - localizer.getMessage("conditionDesc.type.itemHolding", - Replacement.create("NAME", ConditionType.ITEM_HOLDING.conditionName))).color(TextColors.AQUA) - .append(TextComponent.newline()) - .append(super.getDescription(localizer)) - .build(); - } - - @Override - public String getCreationCommand(ConditionalDoor door) { - return SET_COMMAND + door.getDoorUID() + " itemHolding " + getItem().getAmount() + " " + isConsumed(); - } - - @Override - public void evaluated() { - - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/ItemOwning.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/ItemOwning.java deleted file mode 100644 index 73e624f..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/ItemOwning.java +++ /dev/null @@ -1,66 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions.item; - -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import de.eldoria.eldoutilities.serialization.TypeResolvingMap; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.World; -import org.bukkit.configuration.serialization.SerializableAs; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.util.Map; - -/** - * A key which opens a doow, when the player has it in his inventory. - */ -@SerializableAs("itemOwningCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) -public class ItemOwning extends Item { - public ItemOwning(ItemStack item, boolean consumed) { - super(item, consumed); - } - - @Override - public void used(Player player) { - if (!isConsumed()) return; - takeFromInventory(player); - } - - @Override - public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { - return hasPlayerItemInInventory(player); - } - - public ItemOwning deserialize(Map map) { - TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - ItemStack stack = resolvingMap.getValue("item"); - boolean consumed = resolvingMap.getValue("consumed"); - return new ItemOwning(stack, consumed); - } - - @Override - public TextComponent getDescription(Localizer localizer) { - return TextComponent.builder( - localizer.getMessage("conditionDesc.type.itemOwning", - Replacement.create("NAME", ConditionType.ITEM_OWNING.conditionName))).color(TextColors.AQUA) - .append(TextComponent.newline()) - .append(super.getDescription(localizer)) - .build(); - } - - @Override - public String getCreationCommand(ConditionalDoor door) { - return SET_COMMAND + door.getDoorUID() + " itemOwning " + getItem().getAmount() + " " + isConsumed(); - } - - @Override - public void evaluated() { - - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemBlock.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemBlock.java deleted file mode 100644 index aed664b..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemBlock.java +++ /dev/null @@ -1,119 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions.item.interacting; - -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.util.C; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import de.eldoria.eldoutilities.serialization.TypeResolvingMap; -import lombok.Setter; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.World; -import org.bukkit.configuration.serialization.SerializableAs; -import org.bukkit.entity.Player; -import org.bukkit.event.block.Action; -import org.bukkit.event.player.PlayerInteractEvent; -import org.bukkit.inventory.ItemStack; -import org.bukkit.util.BlockVector; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; - -/** - * A key which opens a door, when the player is clicking at a specific block - */ -@SerializableAs("itemBlockCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) -public class ItemBlock extends ItemInteraction { - - @Setter - private BlockVector position; - - /** - * Creates a new item block condition without a set position. - * This object is incomplete and has to be initialized with the {@link #setPosition(BlockVector)} method before using. - * - * @param item - * @param consumed - */ - public ItemBlock(ItemStack item, boolean consumed) { - super(item, consumed); - } - - /** - * Constructor used for serialization. - * - * @param position position of block - * @param stack item stack of block - * @param consumed true if item should be consumed. - */ - private ItemBlock(BlockVector position, ItemStack stack, boolean consumed) { - super(stack, consumed); - this.position = position; - } - - public static ItemBlock deserialize(Map map) { - TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - BlockVector position = resolvingMap.getValue("position"); - ItemStack stack = resolvingMap.getValue("item"); - boolean consumed = resolvingMap.getValue("consumed"); - return new ItemBlock(position, stack, consumed); - } - - @Override - public void used(Player player) { - if (!isConsumed()) return; - takeFromInventory(player); - } - - @Override - public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { - if (hasPlayerItemInHand(player)) { - return super.isOpen(player, world, door, currentState); - } - return false; - } - - @Override - public void clicked(PlayerInteractEvent event, boolean available) { - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - if (event.getClickedBlock().getLocation().toVector().toBlockVector().equals(position)) { - event.setCancelled(true); - - super.clicked(event, available); - } - } - - @Override - public @NotNull Map serialize() { - return SerializationUtil.newBuilder(super.serialize()) - .add("position", position) - .build(); - } - - @Override - public TextComponent getDescription(Localizer localizer) { - return TextComponent.builder( - localizer.getMessage("conditionDesc.type.itemBlock", - Replacement.create("NAME", ConditionType.ITEM_BLOCK.conditionName))).color(TextColors.AQUA) - .append(TextComponent.newline()) - .append(TextComponent.builder(localizer.getMessage("conditionDesc.keyhole") + " ").color(C.baseColor)) - .append(TextComponent.builder(position.toString()).color(C.highlightColor)) - .append(TextComponent.newline()) - .append(super.getDescription(localizer)) - .build(); - } - - @Override - public String getCreationCommand(ConditionalDoor door) { - return SET_COMMAND + door.getDoorUID() + " itemBlock " + getItem().getAmount() + " " + isConsumed(); - } - - @Override - public ItemBlock clone() { - return new ItemBlock(position, getItem(), isConsumed()); - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemClick.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemClick.java deleted file mode 100644 index f4a4b84..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/item/interacting/ItemClick.java +++ /dev/null @@ -1,66 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions.item.interacting; - -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import de.eldoria.eldoutilities.serialization.TypeResolvingMap; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.World; -import org.bukkit.configuration.serialization.SerializableAs; -import org.bukkit.entity.Player; -import org.bukkit.inventory.ItemStack; - -import java.util.Map; - -/** - * A key which open the door, when right clicked. - */ -@SerializableAs("itemClickCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) -public class ItemClick extends ItemInteraction { - public ItemClick(ItemStack item, boolean consumed) { - super(item, consumed); - } - - public static ItemClick deserialize(Map map) { - TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - ItemStack stack = resolvingMap.getValue("item"); - boolean consumed = resolvingMap.getValue("consumed"); - return new ItemClick(stack, consumed); - } - - @Override - public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { - if (hasPlayerItemInHand(player)) { - return super.isOpen(player, world, door, currentState); - } - return false; - } - - @Override - public void used(Player player) { - if (!isConsumed()) return; - tryTakeFromHands(player); - } - - @Override - public TextComponent getDescription(Localizer localizer) { - return TextComponent.builder( - localizer.getMessage("conditionDesc.type.itemClick", - Replacement.create("NAME", ConditionType.ITEM_CLICK.conditionName))).color(TextColors.AQUA) - .append(TextComponent.newline()) - .append(super.getDescription(localizer)) - .build(); - } - - @Override - public String getCreationCommand(ConditionalDoor door) { - return SET_COMMAND + door.getDoorUID() + " itemClick " + getItem().getAmount() + " " + isConsumed(); - } - - -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Proximity.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Proximity.java deleted file mode 100644 index 14e02ab..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/location/Proximity.java +++ /dev/null @@ -1,125 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions.location; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.util.C; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.functions.TriFunction; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import de.eldoria.eldoutilities.serialization.TypeResolvingMap; -import de.eldoria.eldoutilities.utils.EnumUtil; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.World; -import org.bukkit.configuration.serialization.SerializableAs; -import org.bukkit.entity.Player; -import org.bukkit.util.Vector; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; -import java.util.concurrent.TimeUnit; - -/** - * A condition which opens the door when the player is within a specific range of defined by geometric form - */ -@SerializableAs("proximityCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) -public class Proximity implements Location { - private final Vector dimensions; - private final ProximityForm proximityForm; - - public Proximity(Vector dimensions, ProximityForm proximityForm) { - this.dimensions = dimensions; - this.proximityForm = proximityForm; - } - - public Proximity(Map map) { - TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - dimensions = resolvingMap.getValue("dimensions"); - String formString = resolvingMap.getValue("proximityForm"); - formString = formString.replaceAll("(?i)elipsoid", "ellipsoid"); - proximityForm = EnumUtil.parse(formString, ProximityForm.class); - } - - @Override - public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { - Vector vector = player.getLocation().toVector(); - return proximityForm.check.apply(door.getPosition(), - new Vector(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()), - dimensions); - } - - @Override - public TextComponent getDescription(Localizer localizer) { - return TextComponent.builder( - localizer.getMessage("conditionDesc.type.proximity", - Replacement.create("NAME", ConditionType.PROXIMITY.conditionName))).color(TextColors.AQUA) - .append(TextComponent.newline()) - .append(TextComponent.builder(localizer.getMessage("conditionDesc.size") + " ").color(C.baseColor)) - .append(TextComponent.builder(dimensions.toString()).color(C.highlightColor)) - .append(TextComponent.newline()) - .append(TextComponent.builder(localizer.getMessage("conditionDesc.proximityForm") + " ").color(C.baseColor)) - .append(TextComponent.builder(localizer.getMessage(proximityForm.localKey)).color(C.highlightColor)) - .build(); - } - - @Override - public String getCreationCommand(ConditionalDoor door) { - return SET_COMMAND + door.getDoorUID() + " proximity " - + dimensions.getX() + "," + dimensions.getY() + "," + dimensions.getZ() - + " " + proximityForm.name().toLowerCase(); - } - - @Override - public void evaluated() { - } - - @Override - public Proximity clone() { - return new Proximity(dimensions, proximityForm); - } - - @Override - public @NotNull Map serialize() { - return SerializationUtil.newBuilder() - .add("dimensions", dimensions) - .add("proximityForm", proximityForm) - .build(); - } - - public enum ProximityForm { - CUBOID("conditionDesc.proximityForm.cuboid", - (point, target, dimensions) -> { - if (Math.abs(point.getX() - target.getX()) > dimensions.getX()) return false; - if (Math.abs(point.getY() - target.getY()) > dimensions.getY()) return false; - return !(Math.abs(point.getZ() - target.getZ()) > dimensions.getZ()); - }), - ELLIPSOID("conditionDesc.proximityForm.ellipsoid", - (point, target, dimensions) -> - Math.pow((target.getX() - point.getX()) / dimensions.getX(), 2) - + Math.pow((target.getY() - point.getY()) / dimensions.getY(), 2) - + Math.pow((target.getZ() - point.getZ()) / dimensions.getZ(), 2) <= 1), - CYLINDER("conditionDesc.proximityForm.cylinder", - (point, target, dimensions) -> { - if (Math.abs(point.getY() - target.getY()) > dimensions.getY()) return false; - return Math.pow(target.getX() - point.getX(), 2) / Math.pow(dimensions.getX(), 2) - + Math.pow(target.getZ() - point.getZ(), 2) / Math.pow(dimensions.getZ(), 2) <= 1; - }); - - /** - * point, target, dimension - */ - public TriFunction check; - public final String localKey; - - ProximityForm(String localKey, TriFunction check) { - this.localKey = localKey; - this.check = check; - } - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/MythicMob.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/MythicMob.java deleted file mode 100644 index 155f3fb..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/MythicMob.java +++ /dev/null @@ -1,86 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions.standalone; - -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; -import de.eldoria.bigdoorsopener.util.C; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import io.lumine.xikage.mythicmobs.api.bukkit.events.MythicMobDeathEvent; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.World; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; - -@ConditionScope(ConditionScope.Scope.WORLD) -public class MythicMob implements DoorCondition { - private final String mobType; - private boolean state; - - public MythicMob(String mobType) { - this.mobType = mobType; - } - - public MythicMob(Map map) { - mobType = SerializationUtil.mapOf(map).getValue("mobType"); - } - - @Override - public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { - if (BigDoorsOpener.isPlaceholderEnabled()) { - return state; - } - BigDoorsOpener.logger().warning("A mythic mobs condition on door " + door.getDoorUID() + " was called but MythicMobs is not active."); - return null; - } - - @Override - public TextComponent getDescription(Localizer localizer) { - return TextComponent.builder( - localizer.getMessage("conditionDesc.type.mythicMob", - Replacement.create("NAME", ConditionType.MYTHIC_MOBS.conditionName))).color(TextColors.AQUA) - .append(TextComponent.newline()) - .append(TextComponent.builder(localizer.getMessage("conditionDesc.mythicMob") + " ").color(C.baseColor)) - .append(TextComponent.builder(mobType).color(C.highlightColor)) - .build(); - } - - @Override - public String getCreationCommand(ConditionalDoor door) { - return SET_COMMAND + door.getDoorUID() + " mythicMobs " + mobType; - } - - @Override - public String getRemoveCommand(ConditionalDoor door) { - return REMOVE_COMMAND + door.getDoorUID() + " mythicMob"; - } - - @Override - public void evaluated() { - state = false; - } - - @Override - public MythicMob clone() { - return new MythicMob(mobType); - } - - @Override - public @NotNull Map serialize() { - return SerializationUtil.newBuilder() - .add("mobType", mobType) - .build(); - } - - public void killed(MythicMobDeathEvent event, boolean availableToOpen) { - if (event.getMob().getType().getInternalName().equalsIgnoreCase(mobType)) { - state = true; - } - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Placeholder.java b/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Placeholder.java deleted file mode 100644 index 9d7a67c..0000000 --- a/src/main/java/de/eldoria/bigdoorsopener/doors/conditions/standalone/Placeholder.java +++ /dev/null @@ -1,88 +0,0 @@ -package de.eldoria.bigdoorsopener.doors.conditions.standalone; - -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; -import de.eldoria.bigdoorsopener.util.C; -import de.eldoria.bigdoorsopener.util.TextColors; -import de.eldoria.eldoutilities.localization.Localizer; -import de.eldoria.eldoutilities.localization.Replacement; -import de.eldoria.eldoutilities.serialization.SerializationUtil; -import de.eldoria.eldoutilities.serialization.TypeResolvingMap; -import me.clip.placeholderapi.PlaceholderAPI; -import net.kyori.adventure.text.TextComponent; -import org.bukkit.World; -import org.bukkit.configuration.serialization.SerializableAs; -import org.bukkit.entity.Player; -import org.jetbrains.annotations.NotNull; - -import java.util.Map; - -/** - * A condition which uses the placeholder api. - */ -@SerializableAs("placeholderCondition") -@ConditionScope(ConditionScope.Scope.PLAYER) -public class Placeholder implements DoorCondition { - - private final String evaluator; - - public Placeholder(String evaluator) { - this.evaluator = evaluator; - } - - public Placeholder(Map map) { - TypeResolvingMap resolvingMap = SerializationUtil.mapOf(map); - evaluator = resolvingMap.getValue("evaluator"); - } - - @Override - public Boolean isOpen(Player player, World world, ConditionalDoor door, boolean currentState) { - if (BigDoorsOpener.isPlaceholderEnabled()) { - PlaceholderAPI.setPlaceholders(player, evaluator); - return BigDoorsOpener.JS().eval(PlaceholderAPI.setPlaceholders(player, evaluator), null); - } - BigDoorsOpener.logger().warning("A placeholder condition on door " + door.getDoorUID() + " was called but PlaceholderAPI is not active."); - return null; - } - - @Override - public TextComponent getDescription(Localizer localizer) { - return TextComponent.builder( - localizer.getMessage("conditionDesc.type.placeholder", - Replacement.create("NAME", ConditionType.PLACEHOLDER.conditionName))).color(TextColors.AQUA) - .append(TextComponent.newline()) - .append(TextComponent.builder(localizer.getMessage("conditionDesc.evaluator") + " ").color(C.baseColor)) - .append(TextComponent.builder(evaluator).color(C.highlightColor)) - .build(); - } - - @Override - public String getCreationCommand(ConditionalDoor door) { - return SET_COMMAND + door.getDoorUID() + " placeholder " + evaluator; - } - - @Override - public String getRemoveCommand(ConditionalDoor door) { - return REMOVE_COMMAND + door.getDoorUID() + " placeholder"; - } - - @Override - public void evaluated() { - - } - - @Override - public Placeholder clone() { - return new Placeholder(evaluator); - } - - @Override - public @NotNull Map serialize() { - return SerializationUtil.newBuilder() - .add("evaluator", evaluator) - .build(); - } -} diff --git a/src/main/java/de/eldoria/bigdoorsopener/util/C.java b/src/main/java/de/eldoria/bigdoorsopener/util/C.java index ec61f00..8ecf86a 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/util/C.java +++ b/src/main/java/de/eldoria/bigdoorsopener/util/C.java @@ -6,6 +6,7 @@ import com.google.common.cache.LoadingCache; import net.kyori.adventure.text.format.TextColor; +import java.util.List; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -13,6 +14,10 @@ * Pure utility class to save some global constants. */ public final class C { + /** + * A chaotic cache. Handle with care. ANARCHY! + */ + public static final Cache> PLUGIN_CACHE = C.getExpiringCache(30, TimeUnit.SECONDS); public static TextColor baseColor = TextColor.of(0, 170, 0); public static TextColor highlightColor = TextColor.of(255, 170, 0); diff --git a/src/main/java/de/eldoria/bigdoorsopener/util/CachingJSEngine.java b/src/main/java/de/eldoria/bigdoorsopener/util/CachingJSEngine.java index 26a112f..3a2eda9 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/util/CachingJSEngine.java +++ b/src/main/java/de/eldoria/bigdoorsopener/util/CachingJSEngine.java @@ -2,7 +2,7 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import de.eldoria.bigdoorsopener.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; import jdk.nashorn.api.scripting.NashornScriptEngineFactory; import javax.script.ScriptEngine; diff --git a/src/main/java/de/eldoria/bigdoorsopener/util/ConditionChainEvaluator.java b/src/main/java/de/eldoria/bigdoorsopener/util/ConditionChainEvaluator.java index adb6c5f..2c01c23 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/util/ConditionChainEvaluator.java +++ b/src/main/java/de/eldoria/bigdoorsopener/util/ConditionChainEvaluator.java @@ -1,12 +1,18 @@ package de.eldoria.bigdoorsopener.util; -import de.eldoria.bigdoorsopener.doors.ConditionScope; -import de.eldoria.bigdoorsopener.doors.ConditionalDoor; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionChain; -import de.eldoria.bigdoorsopener.doors.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.conditions.DoorCondition; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; +import de.eldoria.bigdoorsopener.core.conditions.Scope; +import de.eldoria.bigdoorsopener.door.ConditionalDoor; import org.bukkit.World; import org.bukkit.entity.Player; +import java.util.Collection; +import java.util.Optional; +import java.util.logging.Level; + public class ConditionChainEvaluator { private Boolean current; @@ -20,9 +26,9 @@ public class ConditionChainEvaluator { * @param conditions conditions to evaluate * @return the result of the chain evaluator */ - public static boolean or(Player player, World world, ConditionalDoor door, boolean currentState, ConditionChain conditions) { + public static boolean or(Player player, World world, ConditionalDoor door, boolean currentState, Collection conditions) { ConditionChainEvaluator evaluator = new ConditionChainEvaluator(); - for (DoorCondition doorCondition : conditions.getConditions()) { + for (DoorCondition doorCondition : conditions) { evaluator.or(doorCondition, player, world, door, currentState); } @@ -39,9 +45,9 @@ public static boolean or(Player player, World world, ConditionalDoor door, boole * @param conditions conditions to evaluate * @return the result of the chain evaluator */ - public static boolean and(Player player, World world, ConditionalDoor door, boolean currentState, ConditionChain conditions) { + public static boolean and(Player player, World world, ConditionalDoor door, boolean currentState, Collection conditions) { ConditionChainEvaluator evaluator = new ConditionChainEvaluator(); - for (DoorCondition doorCondition : conditions.getConditions()) { + for (DoorCondition doorCondition : conditions) { evaluator.and(doorCondition, player, world, door, currentState); } @@ -63,9 +69,16 @@ public ConditionChainEvaluator or(DoorCondition doorCondition, Player player, Wo if (current != null && current) return this; + Optional containerByClass = ConditionRegistrar.getContainerByClass(doorCondition.getClass()); + if (!containerByClass.isPresent()) { + BigDoorsOpener.logger().log(Level.WARNING, "Condition " + doorCondition.getClass() + " is requested but not registered."); + return this; + } + ConditionContainer container = containerByClass.get(); + Boolean open; - if (doorCondition.getScope() == ConditionScope.Scope.PLAYER && player == null) { + if (container.getScope() == Scope.PLAYER && player == null) { open = false; } else { open = doorCondition.isOpen(player, world, door, currentState); @@ -101,9 +114,16 @@ public ConditionChainEvaluator and(DoorCondition doorCondition, Player player, W if (current != null && !current) return this; + Optional containerByClass = ConditionRegistrar.getContainerByClass(doorCondition.getClass()); + if (!containerByClass.isPresent()) { + BigDoorsOpener.logger().log(Level.WARNING, "Condition " + doorCondition.getClass() + " is requested but not registered."); + return this; + } + ConditionContainer container = containerByClass.get(); + Boolean open; - if (doorCondition.getScope() == ConditionScope.Scope.PLAYER && player == null) { + if (container.getScope() == Scope.PLAYER && player == null) { open = false; } else { open = doorCondition.isOpen(player, world, door, currentState); diff --git a/src/main/java/de/eldoria/bigdoorsopener/util/JsSyntaxHelper.java b/src/main/java/de/eldoria/bigdoorsopener/util/JsSyntaxHelper.java index 70423f0..439a6d1 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/util/JsSyntaxHelper.java +++ b/src/main/java/de/eldoria/bigdoorsopener/util/JsSyntaxHelper.java @@ -1,18 +1,16 @@ package de.eldoria.bigdoorsopener.util; -import de.eldoria.bigdoorsopener.BigDoorsOpener; -import de.eldoria.bigdoorsopener.doors.conditions.ConditionType; +import de.eldoria.bigdoorsopener.core.BigDoorsOpener; +import de.eldoria.bigdoorsopener.core.conditions.ConditionRegistrar; import de.eldoria.eldoutilities.container.Pair; import de.eldoria.eldoutilities.utils.TextUtil; import me.clip.placeholderapi.PlaceholderAPI; import org.bukkit.entity.Player; import javax.script.ScriptException; -import java.util.Arrays; import java.util.concurrent.ExecutionException; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; public final class JsSyntaxHelper { @@ -20,9 +18,6 @@ public final class JsSyntaxHelper { private static final Pattern ALLOWED_OPERATORS = Pattern.compile("&&|\\|\\||!=|==|!"); private static final Pattern UNALLOWED_OPERATORS = Pattern.compile("&|\\||="); private static final Pattern SYNTAX = Pattern.compile("(\\||&|!|=|\\(|\\)|\\s|\\{|}|;)*"); - private static final String PLACEHOLDER = Arrays.stream(ConditionType.ConditionGroup.values()) - .map(ConditionType.ConditionGroup::name) - .collect(Collectors.joining("|")); private JsSyntaxHelper() { @@ -65,7 +60,7 @@ public static Pair validateEvaluator(String evaluator, } - String cleaned = evaluator.replaceAll("(?i)if|true|false|" + PLACEHOLDER + "|currentState|null|else", ""); + String cleaned = evaluator.replaceAll("(?i)if|true|false|" + getPlaceholder() + "|currentState|null|else", ""); Matcher matcher = VARIABLE.matcher(cleaned); if (matcher.find()) { return new Pair<>(ValidatorResult.INVALID_VARIABLE, matcher.group()); @@ -98,7 +93,7 @@ public static Pair validateEvaluator(String evaluator, public static Pair checkExecution(String evaluator, CachingJSEngine engine, Player player, boolean vanilla) { evaluator = translateEvaluator(evaluator); - evaluator = evaluator.replaceAll("(?i)currentState|" + PLACEHOLDER, "true"); + evaluator = evaluator.replaceAll("(?i)currentState|" + getPlaceholder(), "true"); if (BigDoorsOpener.isPlaceholderEnabled() && player != null && !vanilla) { evaluator = PlaceholderAPI.setPlaceholders(player, evaluator); @@ -115,6 +110,11 @@ public static Pair checkExecution(String evaluator, Cac return new Pair<>(ValidatorResult.FINE, evaluator); } + private static String getPlaceholder() { + return String.join("|", ConditionRegistrar.getGroups()); + + } + public enum ValidatorResult { /** * Indicates that the parenthesis on the string are not balanced diff --git a/src/main/java/de/eldoria/bigdoorsopener/util/Permissions.java b/src/main/java/de/eldoria/bigdoorsopener/util/Permissions.java index 3e13a22..af58006 100644 --- a/src/main/java/de/eldoria/bigdoorsopener/util/Permissions.java +++ b/src/main/java/de/eldoria/bigdoorsopener/util/Permissions.java @@ -1,5 +1,7 @@ package de.eldoria.bigdoorsopener.util; +import de.eldoria.bigdoorsopener.core.conditions.ConditionContainer; + /** * Class to store permission values. * We dont like to store permissions where we need it. Otheriwse changing them would be a real pain. @@ -31,7 +33,14 @@ public final class Permissions { // permission to access all conditions public static final String ALL_CONDITION = "bdo.condition.all"; - private Permissions() { } + + public static String getConditionPermission(ConditionContainer container) { + return getConditionPermission(container.getGroup()); + } + + public static String getConditionPermission(String group) { + return "bdo.condition." + group; + } } diff --git a/src/main/resources/messages.properties b/src/main/resources/messages.properties index bb98881..4ddddf5 100644 --- a/src/main/resources/messages.properties +++ b/src/main/resources/messages.properties @@ -3,7 +3,9 @@ cloneDoor.message=Cloned door %SOURCE% to %TARGET%. conditionDesc.clear=Clear conditionDesc.close=Close at: conditionDesc.consumed=Items consumed: +conditionDesc.doorPermission=Access Level: conditionDesc.downfall=Downfall +conditionDesc.editor=Editor conditionDesc.evaluator=Evaluator conditionDesc.forceState=Force State: conditionDesc.item=Item: @@ -13,6 +15,7 @@ conditionDesc.minPoint=Min Point: conditionDesc.mythicMob=Mythic Mob: conditionDesc.open=Open at: conditionDesc.openWhen=Open when: +conditionDesc.owner=Owner conditionDesc.permissionNode=Permission: conditionDesc.proximityForm=Form: conditionDesc.proximityForm.cuboid=Cuboid @@ -32,6 +35,7 @@ conditionDesc.type.region=Region (%NAME%) conditionDesc.type.simpleRegion=Simple Region (%NAME%) conditionDesc.type.time=Time (%NAME%) conditionDesc.type.weather=Weather (%NAME%) +conditionDesc.user=User conditionDesc.world=World: copyCondition.copiedAll=Copied all conditions from %SOURCE% to %TARGET%. copyCondition.copiedSingle=Copied condition %CONDITION% from %SOURCE% to %TARGET%. @@ -40,6 +44,7 @@ error.conditionNotSet=This condition is not set. error.doorNotFound=Door not found. error.doorNotRegistered=This door is not registered. error.executionFailed=Could not execute evaluator "%ERROR%". +error.invalidAccessLevel=The entered access level is invalid. error.invalidAmount=Invalid amount. error.invalidArguments=Invalid arguments.\nSyntax: %SYNTAX% error.invalidBoolean=Invalid boolean value. @@ -48,19 +53,23 @@ error.invalidCommand=This command does not exist. error.invalidConditionType=Invalid condition type. error.invalidEvaluationType=This is not a valid evaluation type. error.invalidForm=Invalid form. +error.invalidMob=Invalid mob type error.invalidNumber=Invalid number. error.invalidOpenTime=Invalid open time. error.invalidOperator="%ERROR%" is not a valid operator. error.invalidRange=The entered value is invalid. Value must be between %MIN% and %MAX%. +error.invalidState=Invalid State error.invalidSyntax="%ERROR%" is not valid syntax. error.invalidVariable="%ERROR%" is not a valid variable. error.invalidVector=Invalid Vector. error.invalidWeatherType=Invalid weather type. +error.mythicMob=MythicMobs is currently not active. error.noEvaluatorFound=No evaluator was found. Please enter one. error.noItemConditionSet=No item condition is set for this door. error.nonBooleanResult=Result is not a boolean "%ERROR%". error.notAllowedFromConsole=This command can not be executed via console. -error.permissionNode=You do not have the permissionNode to do this. (%PERMISSION%) +error.notYourDoor=This is not your door. +error.permission=You do not have the permission to do this. (%PERMISSION%) error.placeholderNotFound=Placeholder API is currently not active. error.playerNotFound=Player not found. error.regionNotFound=Region not found. @@ -94,9 +103,12 @@ info.info=Info: info.item=Item: info.location=Location: info.mythicmob=Mythic Mobs: -info.permissionNode=Permission: +info.permission=Permission: info.placeholder=Placeholder: info.remove=remove +info.state=State: +info.state.disabled=disabled +info.state.enabled=enabled info.stayOpen=Stay open: info.time=Time: info.weather=Weather: @@ -107,19 +119,20 @@ reload.completed=Reload complete. removeCondition.item=Item condition removed. removeCondition.location=Location condition removed. removeCondition.mythicMob=Mythic Mobs condition removed. -removeCondition.permissionNode=Permission condition removed. +removeCondition.permission=Permission condition removed. removeCondition.placeholder=Placeholder condition removed. removeCondition.time=Time condition removed. removeCondition.weather=Weather condition removed. +setCondition.doorPermission=Permission set to Door Permission. setCondition.firstPoint=Please click on the first point. setCondition.itemBlockRegistered=Item condition set to Item Block. setCondition.itemClick=Item condition set to Item Click. setCondition.itemHolding=Item condition set to Item Holding. setCondition.itemOwning=Item condition set to Item Owning. setCondition.itemblock=Please click on a block which should be the keyhole. +setCondition.mythicMob=MythicMob condition set. setCondition.permissionNode=Permission condition set. setCondition.placeholder=Placeholder condition set. -setCondition.mythicMob=MythicMob condition set. setCondition.proximity=Location condition set to Proximity. setCondition.region=Location condition set to Region. setCondition.secondPoint=Please click on the second point. @@ -129,6 +142,8 @@ setCondition.weather=Weather condition set.\nOpen at: %OPEN% setEvaluator.and=Using AND operator. Door will open if all conditions are true. setEvaluator.custom=Using custom evaluator "%EVALUATOR%". setEvaluator.or=Using OR operator. Door will open if one condition is true. +setState.disabled=Door is currently not managed by Big Doors Opener. +setState.enabled=Door is now managed by Big Doors Opener. stayOpen.message=The door will stay open for at least %SECONDS% seconds when opened. syntax.amount=amount syntax.closeTime=closeTime @@ -137,16 +152,19 @@ syntax.conditionValues=conditionValues syntax.customEvaluator=customEvaluator syntax.doorId=doorId syntax.evaluationType=evaluationType +syntax.mobType=mob type syntax.openTime=openTime syntax.player=player syntax.proximityForm=proximityForm syntax.seconds=seconds syntax.sourceDoor=sourceDoorId +syntax.state=state syntax.targetDoor=targetDoorId syntax.weatherType=weatherType tabcomplete.consumed=consumed tabcomplete.dimensions=dimensions tabcomplete.doorId=doorId +tabcomplete.doorPermission=doorPermission tabcomplete.forceState=forceState tabcomplete.permissionNode=own.permissionNode.node tabcomplete.regionName=region name @@ -157,13 +175,3 @@ unregister.message=Door %DOOR_NAME% unregistered. warning.chainIsEmpty=The door has no conditions set. The door will not change its state. Maybe you want to unregister it instead. warning.valueNotInEvaluator=The condition %VALUE% is missing in the evaluator. It will not have any influence on the door state yet. warning.valueStillUsed=The condition %VALUE% is still present in the evaluator. The evaluation will probably not work till it is removed. -error.mythicMob=MythicMobs is currently not active. -syntax.mobType=mob type -error.invalidMob=Invalid mob type -conditionDesc.owner=Owner -conditionDesc.user=User -conditionDesc.editor=Editor -conditionDesc.doorPermission=Access Level: -tabcomplete.doorPermission=doorPermission -error.invalidAccessLevel=The entered access level is invalid. -setCondition.doorPermission=Permission set to Door Permission. diff --git a/src/main/resources/messages_de_DE.properties b/src/main/resources/messages_de_DE.properties index 49b364d..9108a49 100644 --- a/src/main/resources/messages_de_DE.properties +++ b/src/main/resources/messages_de_DE.properties @@ -3,7 +3,9 @@ cloneDoor.message=Einstellungen von %SOURCE% auf %TARGET% kopiert. conditionDesc.clear=Sonnig conditionDesc.close=Schließt um: conditionDesc.consumed=Items verbauchen: +conditionDesc.doorPermission=Zugriffslevel: conditionDesc.downfall=Regen +conditionDesc.editor=Editor conditionDesc.evaluator=Evaluator conditionDesc.forceState=Erzwinge Zustand: conditionDesc.item=Item: @@ -13,6 +15,7 @@ conditionDesc.minPoint=Kleinster Punkt: conditionDesc.mythicMob=Mythic Mob: conditionDesc.open=Öffnet um: conditionDesc.openWhen=Öffnet wenn: +conditionDesc.owner=Owner conditionDesc.permissionNode=Berechtigung: conditionDesc.proximityForm=Annährungsregion: conditionDesc.proximityForm.cuboid=Würfel @@ -32,6 +35,7 @@ conditionDesc.type.region=Region (%NAME%) conditionDesc.type.simpleRegion=Einfache Region (%NAME%) conditionDesc.type.time=Zeit (%NAME%) conditionDesc.type.weather=Wetter (%NAME%) +conditionDesc.user=User conditionDesc.world=Welt: copyCondition.copiedAll=Alle Bedingungen von %SOURCE% wurden auf %TARGET% kopiert. copyCondition.copiedSingle=%CONDITION% wurde von %SOURCE% auf %TARGET% kopiert. @@ -40,6 +44,7 @@ error.conditionNotSet=Diese Bedingung ist nicht gesetzt. error.doorNotFound=Tor nicht gefunden. error.doorNotRegistered=Dieses Tor ist nicht registriert. error.executionFailed=Formel konnte nicht ausgeführt werden "%ERROR%". +error.invalidAccessLevel=Das eingegebene Zugriffslevel ist ungültig. error.invalidAmount=Ungültige Anzahl. error.invalidArguments=Ungültige Argumente.\nSyntax: %SYNTAX% error.invalidBoolean=Ungültiger boolsche Wert. @@ -48,19 +53,23 @@ error.invalidCommand=Dieser Befehl existiert nicht. error.invalidConditionType=Ungültige Bedingung error.invalidEvaluationType=Das ist kein gültiger Formel Typ. error.invalidForm=Ungültige Form. +error.invalidMob=Ungütliger Mob Typ error.invalidNumber=Ungültige Nummer. error.invalidOpenTime=Ungültige Öffnungszeit. error.invalidOperator="%ERROR%" ist kein gültiger Operator. error.invalidRange=Der eingegebene Wert ist ungültig. Er muss zwischen %MIN% und %MAX% liegen. +error.invalidState=Ungültiger Status error.invalidSyntax="%ERROR%" ist kein gültiger Syntax. error.invalidVariable="%ERROR%" ist keine gültige Variable. error.invalidVector=Ungültiger Vektor. error.invalidWeatherType=Ungültiger Wettertyp. +error.mythicMob=MythicMobs ist aktuell nicht aktiv. error.noEvaluatorFound=Keine formal gefunden. Bitte gib eine Formel ein. error.noItemConditionSet=Für dieses Tor ist keine Item Bedingung gesetzt. error.nonBooleanResult=Ergebnis ist kein boolscher Wert "%ERROR%". error.notAllowedFromConsole=Dieser Befehl kann nicht über die Konsole ausgeführt werden. -error.permissionNode=Du hast nicht die Erlaubnis, dies zu tun. (%PERMISSION%) +error.notYourDoor=Dies ist nicht dein Tor. +error.permission=Du hast nicht die Erlaubnis, dies zu tun. (%PERMISSION%) error.placeholderNotFound=Placeholder API ist aktuell nicht aktiv. error.playerNotFound=Spieler nicht gefunden. error.regionNotFound=Region nicht gefunden. @@ -94,9 +103,12 @@ info.info=Info: info.item=Item: info.location=Ort: info.mythicmob=Mythic Mobs: -info.permissionNode=Berechtigung: +info.permission=Berechtigung: info.placeholder=Placeholder: info.remove=entfernen +info.state=Status: +info.state.disabled=deaktiviert +info.state.enabled=aktiviert info.stayOpen=Offen bleiben: info.time=Zeit: info.weather=Wetter: @@ -111,12 +123,14 @@ removeCondition.permission=Berechtigungs Bedingung entfernt. removeCondition.placeholder=Placeholder Bedingung entfernt. removeCondition.time=Zeit Bedingung entfernt. removeCondition.weather=Wetter Bedingung entfernt. +setCondition.doorPermission=Permission wurde auf DoorPermission gesetzt. setCondition.firstPoint=Bitte klicke auf den ersten Punkt. setCondition.itemBlockRegistered=Item Bedingung gesetzt auf Item Block. setCondition.itemClick=Item Bedingung gesetzt auf Item Klick. setCondition.itemHolding=Item Bedingung gesetzt auf Item Halten. setCondition.itemOwning=Item Bedingung gesetzt auf Item Besitzen. setCondition.itemblock=Bitte klicke auf einen Block um ihn als Schlüsselloch zu definieren. +setCondition.mythicMob=MythicMob Bedingung gesetzt. setCondition.permissionNode=Berechtigungs Bedingungen gesetzt. setCondition.placeholder=Placeholder Bedingung aktiviert. setCondition.proximity=Ortsbedinung gesetzt zu Umgebung. @@ -128,6 +142,8 @@ setCondition.weather=Wetter Bedingung gesetzt.\nÖffnet bei: %OPEN% setEvaluator.and=Nutze UND Operator. Tor wird sich öffnen, wenn alle Bedingungen zutreffen. setEvaluator.custom=Nutze Formel "%EVALUATOR%". setEvaluator.or=Nutze ODER Operator. Tor wird sich öffnen, wenn eine Bedingung zutrifft. +setState.disabled=Dieses Tor wird derzeit nicht von Big Doors Opener verwaltet. +setState.enabled=Dieses Tor wird nunr von Big Doors Opener verwaltet. stayOpen.message=Das Tor wird für mindestens %SECONDS% sekunden offen sein, wenn es geöffnet wurde. syntax.amount=Anzahl syntax.closeTime=Schließzeit @@ -136,16 +152,19 @@ syntax.conditionValues=Bedingungs Argumente syntax.customEvaluator=Evaluierungs Formel syntax.doorId=TorId syntax.evaluationType=Evaluatierungs Form +syntax.mobType=mob typ syntax.openTime=Öffnungszeit syntax.player=Spieler syntax.proximityForm=AnnäherungsForm syntax.seconds=Sekunden syntax.sourceDoor=HerkunftsTorId +syntax.state=status syntax.targetDoor=ZielTorId syntax.weatherType=WetterTyp tabcomplete.consumed=Verbraucht tabcomplete.dimensions=Größe tabcomplete.doorId= +tabcomplete.doorPermission=torBerechtigung tabcomplete.forceState=Erzwinge Zustand tabcomplete.permissionNode=eigene.permissionNode.node tabcomplete.regionName=Region Name @@ -156,11 +175,3 @@ unregister.message=Tor %DOOR_NAME% wurde entfernt. warning.chainIsEmpty=Dieses Tor hat derzeit keine Bedingungen. Der Zustand wird sich nicht verändern. Vielleicht möchtest du sie lieber entfernen. warning.valueNotInEvaluator=Der Bedingung %VALUE% fehlt in der aktuellen Formel. Sie wird derzeit keinerlei Auswirkungen haben. warning.valueStillUsed=Die Bedingung %VALUE% wird noch in der Formel benutzt. Der berechnete Zustand wird eventuell nicht korrekt sein. -setCondition.mythicMob=MythicMob Bedingung gesetzt. -conditionDesc.owner=Owner -conditionDesc.user=User -conditionDesc.editor=Editor -conditionDesc.doorPermission=Zugriffslevel: -tabcomplete.doorPermission=torBerechtigung -error.invalidAccessLevel=Das eingegebene Zugriffslevel ist ungültig. -setCondition.doorPermission=Permission wurde auf DoorPermission gesetzt. diff --git a/src/main/resources/messages_en_US.properties b/src/main/resources/messages_en_US.properties index 79854b4..4ddddf5 100644 --- a/src/main/resources/messages_en_US.properties +++ b/src/main/resources/messages_en_US.properties @@ -3,7 +3,9 @@ cloneDoor.message=Cloned door %SOURCE% to %TARGET%. conditionDesc.clear=Clear conditionDesc.close=Close at: conditionDesc.consumed=Items consumed: +conditionDesc.doorPermission=Access Level: conditionDesc.downfall=Downfall +conditionDesc.editor=Editor conditionDesc.evaluator=Evaluator conditionDesc.forceState=Force State: conditionDesc.item=Item: @@ -13,6 +15,7 @@ conditionDesc.minPoint=Min Point: conditionDesc.mythicMob=Mythic Mob: conditionDesc.open=Open at: conditionDesc.openWhen=Open when: +conditionDesc.owner=Owner conditionDesc.permissionNode=Permission: conditionDesc.proximityForm=Form: conditionDesc.proximityForm.cuboid=Cuboid @@ -32,6 +35,7 @@ conditionDesc.type.region=Region (%NAME%) conditionDesc.type.simpleRegion=Simple Region (%NAME%) conditionDesc.type.time=Time (%NAME%) conditionDesc.type.weather=Weather (%NAME%) +conditionDesc.user=User conditionDesc.world=World: copyCondition.copiedAll=Copied all conditions from %SOURCE% to %TARGET%. copyCondition.copiedSingle=Copied condition %CONDITION% from %SOURCE% to %TARGET%. @@ -40,6 +44,7 @@ error.conditionNotSet=This condition is not set. error.doorNotFound=Door not found. error.doorNotRegistered=This door is not registered. error.executionFailed=Could not execute evaluator "%ERROR%". +error.invalidAccessLevel=The entered access level is invalid. error.invalidAmount=Invalid amount. error.invalidArguments=Invalid arguments.\nSyntax: %SYNTAX% error.invalidBoolean=Invalid boolean value. @@ -48,19 +53,23 @@ error.invalidCommand=This command does not exist. error.invalidConditionType=Invalid condition type. error.invalidEvaluationType=This is not a valid evaluation type. error.invalidForm=Invalid form. +error.invalidMob=Invalid mob type error.invalidNumber=Invalid number. error.invalidOpenTime=Invalid open time. error.invalidOperator="%ERROR%" is not a valid operator. error.invalidRange=The entered value is invalid. Value must be between %MIN% and %MAX%. +error.invalidState=Invalid State error.invalidSyntax="%ERROR%" is not valid syntax. error.invalidVariable="%ERROR%" is not a valid variable. error.invalidVector=Invalid Vector. error.invalidWeatherType=Invalid weather type. +error.mythicMob=MythicMobs is currently not active. error.noEvaluatorFound=No evaluator was found. Please enter one. error.noItemConditionSet=No item condition is set for this door. error.nonBooleanResult=Result is not a boolean "%ERROR%". error.notAllowedFromConsole=This command can not be executed via console. -error.permissionNode=You do not have the permissionNode to do this. (%PERMISSION%) +error.notYourDoor=This is not your door. +error.permission=You do not have the permission to do this. (%PERMISSION%) error.placeholderNotFound=Placeholder API is currently not active. error.playerNotFound=Player not found. error.regionNotFound=Region not found. @@ -94,9 +103,12 @@ info.info=Info: info.item=Item: info.location=Location: info.mythicmob=Mythic Mobs: -info.permissionNode=Permission: +info.permission=Permission: info.placeholder=Placeholder: info.remove=remove +info.state=State: +info.state.disabled=disabled +info.state.enabled=enabled info.stayOpen=Stay open: info.time=Time: info.weather=Weather: @@ -107,16 +119,18 @@ reload.completed=Reload complete. removeCondition.item=Item condition removed. removeCondition.location=Location condition removed. removeCondition.mythicMob=Mythic Mobs condition removed. -removeCondition.permissionNode=Permission condition removed. +removeCondition.permission=Permission condition removed. removeCondition.placeholder=Placeholder condition removed. removeCondition.time=Time condition removed. removeCondition.weather=Weather condition removed. +setCondition.doorPermission=Permission set to Door Permission. setCondition.firstPoint=Please click on the first point. setCondition.itemBlockRegistered=Item condition set to Item Block. setCondition.itemClick=Item condition set to Item Click. setCondition.itemHolding=Item condition set to Item Holding. setCondition.itemOwning=Item condition set to Item Owning. setCondition.itemblock=Please click on a block which should be the keyhole. +setCondition.mythicMob=MythicMob condition set. setCondition.permissionNode=Permission condition set. setCondition.placeholder=Placeholder condition set. setCondition.proximity=Location condition set to Proximity. @@ -128,6 +142,8 @@ setCondition.weather=Weather condition set.\nOpen at: %OPEN% setEvaluator.and=Using AND operator. Door will open if all conditions are true. setEvaluator.custom=Using custom evaluator "%EVALUATOR%". setEvaluator.or=Using OR operator. Door will open if one condition is true. +setState.disabled=Door is currently not managed by Big Doors Opener. +setState.enabled=Door is now managed by Big Doors Opener. stayOpen.message=The door will stay open for at least %SECONDS% seconds when opened. syntax.amount=amount syntax.closeTime=closeTime @@ -136,16 +152,19 @@ syntax.conditionValues=conditionValues syntax.customEvaluator=customEvaluator syntax.doorId=doorId syntax.evaluationType=evaluationType +syntax.mobType=mob type syntax.openTime=openTime syntax.player=player syntax.proximityForm=proximityForm syntax.seconds=seconds syntax.sourceDoor=sourceDoorId +syntax.state=state syntax.targetDoor=targetDoorId syntax.weatherType=weatherType tabcomplete.consumed=consumed tabcomplete.dimensions=dimensions tabcomplete.doorId=doorId +tabcomplete.doorPermission=doorPermission tabcomplete.forceState=forceState tabcomplete.permissionNode=own.permissionNode.node tabcomplete.regionName=region name @@ -156,11 +175,3 @@ unregister.message=Door %DOOR_NAME% unregistered. warning.chainIsEmpty=The door has no conditions set. The door will not change its state. Maybe you want to unregister it instead. warning.valueNotInEvaluator=The condition %VALUE% is missing in the evaluator. It will not have any influence on the door state yet. warning.valueStillUsed=The condition %VALUE% is still present in the evaluator. The evaluation will probably not work till it is removed. -setCondition.mythicMob=MythicMob condition set. -conditionDesc.owner=Owner -conditionDesc.user=User -conditionDesc.editor=Editor -conditionDesc.doorPermission=Access Level: -tabcomplete.doorPermission=doorPermission -error.invalidAccessLevel=The entered access level is invalid. -setCondition.doorPermission=Permission set to Door Permission. diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 2c408ce..faa0611 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -2,7 +2,7 @@ name: ${project.name} description: ${project.description} author: Hadde version: ${project.version} -main: de.eldoria.bigdoorsopener.BigDoorsOpener +main: de.eldoria.bigdoorsopener.core.BigDoorsOpener website: www.spigotmc.org/resources/80805/ api-version: 1.13 depend: [BigDoors]