diff --git a/lang/src/main/resources/lang/en_GB.lang b/lang/src/main/resources/lang/en_GB.lang index 8b0f0d32..9ea026b1 100644 --- a/lang/src/main/resources/lang/en_GB.lang +++ b/lang/src/main/resources/lang/en_GB.lang @@ -189,6 +189,9 @@ tag.triggerblock.description=Sets the trigger block/s of the portal. Comma separ tag.command.description=Sets a command on the post activation of the portal. Comma separated or multi tag. tag.portalEvent.description=Triggers the portal from portal events rather than the player entering the portal. (survival nether portal) tag.message.description=Sets the message to be displayed when the portal is activated +tag.conditions.description=Sets the conditions for the portal to be activated +tag.conditions.fail=The conditions to activate this portal have not been met +tag.conditions.invalid=The conditions are invalid tag.cooldown.fail= The cooldown must be a number. tag.command.nopermission= You do not have permission to create a command at %1$s command level diff --git a/spigot/build.gradle b/spigot/build.gradle index 11cb35d7..3a1b1083 100644 --- a/spigot/build.gradle +++ b/spigot/build.gradle @@ -9,6 +9,7 @@ repositories { maven { url "https://repo.maven.apache.org/maven2" } maven { url "https://hub.spigotmc.org/nexus/content/repositories/snapshots/" } maven { url 'https://papermc.io/repo/repository/maven-public/' } + maven { url 'https://repo.extendedclip.com/releases/'} } // includeLibs just says to include the library in the final jar @@ -23,6 +24,9 @@ dependencies { implementation "com.mojang:authlib:3.5.41" // Be careful to only use what you need to from paper, otherwise it will become incompatible with spigot. // compileOnly 'com.destroystokyo.paper:paper-api:1.16.5-R0.1-SNAPSHOT' + + // Soft dependencies + compileOnly 'me.clip:placeholderapi:2.11.6' } tasks.named('compileJava') { diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java index 9416556f..abab4042 100644 --- a/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/AdvancedPortalsPlugin.java @@ -16,6 +16,7 @@ import com.sekwah.advancedportals.spigot.importer.ConfigAccessor; import com.sekwah.advancedportals.spigot.importer.LegacyImporter; import com.sekwah.advancedportals.spigot.metrics.Metrics; +import com.sekwah.advancedportals.spigot.tags.ConditionsTag; import com.sekwah.advancedportals.spigot.warpeffects.SpigotWarpEffects; import java.io.File; import java.util.regex.Matcher; @@ -88,6 +89,8 @@ public void onEnable() { this.portalsCore.registerPortalCommand("import", new ImportPortalSubCommand()); + + registerPlaceholderAPI(); } private void checkAndCreateConfig() { @@ -124,4 +127,10 @@ private void checkAndCreateConfig() { public void onDisable() { this.portalsCore.onDisable(); } + + public void registerPlaceholderAPI() { + if (this.getServer().getPluginManager().getPlugin("PlaceholderAPI") != null) { + AdvancedPortalsCore.getInstance().getTagRegistry().registerTag(new ConditionsTag()); + } + } } diff --git a/spigot/src/main/java/com/sekwah/advancedportals/spigot/tags/ConditionsTag.java b/spigot/src/main/java/com/sekwah/advancedportals/spigot/tags/ConditionsTag.java new file mode 100644 index 00000000..fa275565 --- /dev/null +++ b/spigot/src/main/java/com/sekwah/advancedportals/spigot/tags/ConditionsTag.java @@ -0,0 +1,147 @@ +package com.sekwah.advancedportals.spigot.tags; + +import com.sekwah.advancedportals.core.connector.containers.PlayerContainer; +import com.sekwah.advancedportals.core.registry.TagTarget; +import com.sekwah.advancedportals.core.util.InfoLogger; +import com.sekwah.advancedportals.core.util.Lang; +import com.sekwah.advancedportals.core.warphandler.ActivationData; +import com.sekwah.advancedportals.core.warphandler.Tag; +import com.sekwah.advancedportals.shadowed.inject.Inject; +import me.clip.placeholderapi.PlaceholderAPI; +import org.bukkit.Bukkit; +import org.bukkit.entity.Player; + +public class ConditionsTag implements Tag.Activation, Tag.Split, Tag.Creation { + + @Inject + private InfoLogger infoLogger; + + @Override + public boolean preActivated(TagTarget target, PlayerContainer player, ActivationData activeData, String[] argData) { + + for (String condition : argData) { + if (!checkConditions(condition, Bukkit.getPlayer(player.getUUID()))) { + player.sendMessage(Lang.getNegativePrefix() + Lang.translate("tag.conditions.fail")); + return false; + } + } + + return true; + } + + @Override + public void postActivated(TagTarget target, PlayerContainer player, ActivationData activationData, String[] argData) { + + } + + @Override + public boolean activated(TagTarget target, PlayerContainer player, ActivationData activationData, String[] argData) { + return false; + } + + @Override + public TagType[] getTagTypes() { + return new TagType[] { TagType.PORTAL }; + } + + @Override + public String getName() { + return "conditions"; + } + + @Override + public String[] getAliases() { + return new String[0]; + } + + @Override + public String description() { + return Lang.translate("tag.conditions.description"); + } + + private boolean checkConditions(String condition, Player player) { + // Remove whitespaces before splitting the condition + String trimmedCondition = condition.replaceAll("\\s+", ""); + + // Check if the condition contains a valid operator + if (!trimmedCondition.matches(".*(<=|>=|<|>|==).*")) { + // Log a warning or handle the case where the condition format is invalid + infoLogger.warning("Invalid operator: " + condition); + return false; + } + + // Split the condition into placeholder and value parts + String[] parts = trimmedCondition.split("<=|>=|<|>|=="); + + if (parts.length == 2) { + // Trim to remove any leading/trailing whitespaces + String placeholder = parts[0].trim(); + String actualValue = PlaceholderAPI.setPlaceholders(player, placeholder); + String restOfCondition = parts[1].trim(); + + // Preserve the operator + String operator = condition.substring(placeholder.length(), condition.length() - restOfCondition.length()).trim(); + + return performComparison(actualValue, operator, restOfCondition); + } else { + // Log a warning or handle the case where the condition format is invalid + infoLogger.warning("Invalid condition format: " + condition); + return false; + } + } + + private boolean performComparison(String actualValue, String operator, String expectedValue) { + if (isNumeric(actualValue) && isNumeric(expectedValue)) { + // Numeric comparison + double actualNumeric = Double.parseDouble(actualValue); + double expectedNumeric = Double.parseDouble(expectedValue); + + return switch (operator) { + case "==" -> actualNumeric == expectedNumeric; + case "<" -> actualNumeric < expectedNumeric; + case ">" -> actualNumeric > expectedNumeric; + case "<=" -> actualNumeric <= expectedNumeric; + case ">=" -> actualNumeric >= expectedNumeric; + default -> false; // Unsupported operator + }; + } else if (isBoolean(actualValue) && isBoolean(expectedValue)) { + // Boolean comparison + boolean actualBoolean = Boolean.parseBoolean(actualValue); + boolean expectedBoolean = Boolean.parseBoolean(expectedValue); + + return actualBoolean == expectedBoolean; + } else { + // String comparison + return actualValue.equals(expectedValue); + } + } + + private boolean isNumeric(String str) { + try { + Double.parseDouble(str); + return true; + } catch (NumberFormatException e) { + return false; + } + } + + private boolean isBoolean(String str) { + return str.equalsIgnoreCase("true") || str.equalsIgnoreCase("false"); + } + + @Override + public boolean created(TagTarget target, PlayerContainer player, String[] argData) { + for (String condition : argData) { + if (!checkConditions(condition, Bukkit.getPlayer(player.getUUID()))) { + player.sendMessage(Lang.getNegativePrefix() + Lang.translate("tag.conditions.invalid")); + return false; + } + } + return true; + } + + @Override + public void destroyed(TagTarget target, PlayerContainer player, String[] argData) { + + } +} diff --git a/spigot/src/main/templates/plugin.yml b/spigot/src/main/templates/plugin.yml index afad8ada..d20a6cc0 100644 --- a/spigot/src/main/templates/plugin.yml +++ b/spigot/src/main/templates/plugin.yml @@ -4,6 +4,7 @@ version: ${pluginVersion} author: sekwah41 description: An advanced portals plugin for bukkit. api-version: 1.13 +softdepend: ["PlaceholderAPI"] commands: portal: description: The main command for the advanced portals