Skip to content

Commit

Permalink
feat: add placeholder api conditions support
Browse files Browse the repository at this point in the history
Allows admins to select specific clauses for when a portal can be used / not be used.
  • Loading branch information
TreemanKing committed Dec 29, 2024
1 parent 750fcf0 commit 35ed596
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 0 deletions.
3 changes: 3 additions & 0 deletions lang/src/main/resources/lang/en_GB.lang
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 4 additions & 0 deletions spigot/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -88,6 +89,8 @@ public void onEnable() {

this.portalsCore.registerPortalCommand("import",
new ImportPortalSubCommand());

registerPlaceholderAPI();
}

private void checkAndCreateConfig() {
Expand Down Expand Up @@ -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());
}
}
}
Original file line number Diff line number Diff line change
@@ -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) {

}
}
1 change: 1 addition & 0 deletions spigot/src/main/templates/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 35ed596

Please sign in to comment.