Skip to content

Commit

Permalink
Refactor placeholder registration
Browse files Browse the repository at this point in the history
Includes support for registering relational placeholders with PAPI
  • Loading branch information
APickledWalrus committed May 24, 2024
1 parent e493e38 commit fef82b9
Show file tree
Hide file tree
Showing 9 changed files with 239 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

import ch.njol.skript.Skript;
import io.github.apickledwalrus.skriptplaceholders.placeholder.PlaceholderPlugin;
import io.github.apickledwalrus.skriptplaceholders.placeholder.PlaceholderRegistry;
import org.bukkit.plugin.java.JavaPlugin;

import java.io.IOException;

public class SkriptPlaceholders extends JavaPlugin {

private static SkriptPlaceholders instance;
private PlaceholderRegistry registry;

public static SkriptPlaceholders getInstance() {
if (instance == null) {
throw new IllegalStateException("skript-placeholders has not been initialized yet.");
}
return instance;
}

@Override
public void onEnable() {
Expand All @@ -26,10 +35,17 @@ public void onEnable() {
getLogger().severe(e.toString());
getServer().getPluginManager().disablePlugin(this);
}

this.registry = new PlaceholderRegistry(this);
}

public static SkriptPlaceholders getInstance() {
return instance;
@Override
public void onDisable() {
instance = null;
}

public PlaceholderRegistry getRegistry() {
return registry;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@
import org.bukkit.OfflinePlayer;
import org.bukkit.plugin.Plugin;

import java.util.HashSet;
import java.util.Set;

/**
* A placeholder listener for placeholders created using {@link PlaceholderPlugin#MVDW_PLACEHOLDER_API}.
*/
public class MVdWPlaceholderAPIListener implements PlaceholderListener {

private final Plugin plugin;
private final PlaceholderEvaluator evaluator;
private final String placeholder;

public MVdWPlaceholderAPIListener(Plugin plugin, PlaceholderEvaluator evaluator, String placeholder) {
private final Set<PlaceholderEvaluator> evaluators = new HashSet<>();

public MVdWPlaceholderAPIListener(Plugin plugin, String placeholder) {
this.plugin = plugin;
this.evaluator = evaluator;
this.placeholder = placeholder;
}

Expand All @@ -26,7 +29,13 @@ public void registerListener() {
if (player == null) { // this is for an actual offline player
player = event.getOfflinePlayer();
}
return evaluator.evaluate(placeholder, player);
for (PlaceholderEvaluator evaluator : evaluators) {
String result = evaluator.evaluate(placeholder, player);;
if (result != null) {
return result;
}
}
return null;
});
}

Expand All @@ -35,4 +44,19 @@ public void unregisterListener() {
// TODO determine if this is possible
}

@Override
public void addEvaluator(PlaceholderEvaluator evaluator) {
evaluators.add(evaluator);
}

@Override
public void removeEvaluator(PlaceholderEvaluator evaluator) {
evaluators.remove(evaluator);
}

@Override
public boolean hasEvaluators() {
return !evaluators.isEmpty();
}

}
Original file line number Diff line number Diff line change
@@ -1,23 +1,28 @@
package io.github.apickledwalrus.skriptplaceholders.placeholder;

import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import me.clip.placeholderapi.expansion.Relational;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.HashSet;
import java.util.Set;

/**
* A placeholder listener for placeholders created using {@link PlaceholderPlugin#PLACEHOLDER_API}.
*/
public class PlaceholderAPIListener extends PlaceholderExpansion implements PlaceholderListener {
public class PlaceholderAPIListener extends PlaceholderExpansion implements Relational, PlaceholderListener {

private final Plugin plugin;
private final PlaceholderEvaluator evaluator;
private final String prefix;

public PlaceholderAPIListener(Plugin plugin, PlaceholderEvaluator evaluator, String prefix) {
private final Set<PlaceholderEvaluator> evaluators = new HashSet<>();

public PlaceholderAPIListener(Plugin plugin, String prefix) {
this.plugin = plugin;
this.evaluator = evaluator;
this.prefix = prefix;
}

Expand All @@ -43,7 +48,24 @@ public boolean persist() {

@Override
public @Nullable String onRequest(@Nullable OfflinePlayer player, @NotNull String identifier) {
return evaluator.evaluate(this.prefix + "_" + identifier, player);
for (PlaceholderEvaluator evaluator : evaluators) {
String result = evaluator.evaluate(this.prefix + "_" + identifier, player);
if (result != null) {
return result;
}
}
return null;
}

@Override
public @Nullable String onPlaceholderRequest(Player one, Player two, String identifier) {
for (PlaceholderEvaluator evaluator : evaluators) {
String result = evaluator.evaluateRelational(this.prefix + "_" + identifier, one, two);
if (result != null) {
return result;
}
}
return null;
}

@Override
Expand All @@ -56,4 +78,19 @@ public void unregisterListener() {
unregister();
}

@Override
public void addEvaluator(PlaceholderEvaluator evaluator) {
evaluators.add(evaluator);
}

@Override
public void removeEvaluator(PlaceholderEvaluator evaluator) {
evaluators.remove(evaluator);
}

@Override
public boolean hasEvaluators() {
return !evaluators.isEmpty();
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.apickledwalrus.skriptplaceholders.placeholder;

import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.jetbrains.annotations.Nullable;

/**
Expand All @@ -13,8 +14,17 @@ public interface PlaceholderEvaluator {
* @param placeholder The placeholder to evaluate.
* @param player The player to use for evaluating this placeholder.
* Can be null for placeholders that do not require such context.
* @return The value of the placeholder.
* @return The value of the placeholder, or null if it could not be evaluated.
*/
@Nullable String evaluate(String placeholder, @Nullable OfflinePlayer player);

/**
* A method to evaluate the value of a relational placeholder, which depends on two players.
* @param placeholder The placeholder to evaluate.
* @param one The first player to use for evaluating <code>placeholder</code>.
* @param two The second player to use for evaluating <code>placeholder</code>.
* @return The value of the placeholder, or null if it could not be evaluated.
*/
@Nullable String evaluateRelational(String placeholder, Player one, Player two);

}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/**
* A placeholder listener is responsible for registering, unregistering, and handling placeholder requests.
*/
public interface PlaceholderListener {
interface PlaceholderListener {

/**
* Registers this listener with the providing plugin.
Expand All @@ -15,4 +15,21 @@ public interface PlaceholderListener {
*/
void unregisterListener();

/**
* Adds an evaluator to be used when trying to evaluate a placeholder.
* @param evaluator The evaluator to add.
*/
void addEvaluator(PlaceholderEvaluator evaluator);

/**
* Removes an evaluator from this listener. It will no longer be used when trying to evaluate a placeholder.
* @param evaluator The evaluator to remove.
*/
void removeEvaluator(PlaceholderEvaluator evaluator);

/**
* @return Whether this listener has any evaluators.
*/
boolean hasEvaluators();

}
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package io.github.apickledwalrus.skriptplaceholders.placeholder;

import ch.njol.skript.Skript;
import io.github.apickledwalrus.skriptplaceholders.SkriptPlaceholders;
import org.apache.commons.lang.StringUtils;
import org.bukkit.OfflinePlayer;
import org.bukkit.entity.Player;
import org.bukkit.plugin.Plugin;
import org.jetbrains.annotations.Nullable;

import java.util.Arrays;
Expand Down Expand Up @@ -35,8 +35,8 @@ public enum PlaceholderPlugin {
}

@Override
public PlaceholderListener registerPlaceholder(PlaceholderEvaluator evaluator, String placeholder) {
PlaceholderListener listener = new PlaceholderAPIListener(SkriptPlaceholders.getInstance(), evaluator, placeholder);
PlaceholderListener registerPlaceholder(Plugin plugin, String placeholder) {
PlaceholderListener listener = new PlaceholderAPIListener(plugin, placeholder);
listener.registerListener();
return listener;
}
Expand Down Expand Up @@ -80,8 +80,8 @@ public boolean supportsRelationalPlaceholders() {
}

@Override
public PlaceholderListener registerPlaceholder(PlaceholderEvaluator evaluator, String placeholder) {
PlaceholderListener listener = new MVdWPlaceholderAPIListener(SkriptPlaceholders.getInstance(), evaluator, placeholder);
PlaceholderListener registerPlaceholder(Plugin plugin, String placeholder) {
PlaceholderListener listener = new MVdWPlaceholderAPIListener(plugin, placeholder);
listener.registerListener();
return listener;
}
Expand Down Expand Up @@ -145,10 +145,11 @@ public final boolean isInstalled() {

/**
* Registers a new placeholder with this plugin.
* @param plugin The plugin registering the placeholder.
* @param placeholder The name of the placeholder to register.
* @return The registered listener.
*/
public abstract PlaceholderListener registerPlaceholder(PlaceholderEvaluator evaluator, String placeholder);
abstract PlaceholderListener registerPlaceholder(Plugin plugin, String placeholder);

/**
* @param placeholder The placeholder to obtain the value of.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package io.github.apickledwalrus.skriptplaceholders.placeholder;

import org.bukkit.plugin.Plugin;

import java.util.HashMap;
import java.util.Map;

public class PlaceholderRegistry {

private final Plugin plugin;
private final Map<PlaceholderPlugin, PlaceholderRegister> registers = new HashMap<>();

public PlaceholderRegistry(Plugin plugin) {
this.plugin = plugin;
}

public void registerPlaceholder(PlaceholderPlugin plugin, String placeholder, PlaceholderEvaluator evaluator) {
PlaceholderRegister register = registers.computeIfAbsent(plugin, PlaceholderRegister::new);
register.registerPlaceholder(placeholder, evaluator);
}

public void unregisterPlaceholder(PlaceholderPlugin plugin, String placeholder, PlaceholderEvaluator evaluator) {
PlaceholderRegister register = registers.get(plugin);
if (register != null) {
register.unregisterPlaceholder(placeholder, evaluator);
}
}

private final class PlaceholderRegister {

private final PlaceholderPlugin plugin;
private final Map<String, PlaceholderListener> listeners = new HashMap<>();

public PlaceholderRegister(PlaceholderPlugin plugin) {
this.plugin = plugin;
}

public void registerPlaceholder(String placeholder, PlaceholderEvaluator evaluator) {
PlaceholderListener listener = listeners.computeIfAbsent(placeholder,
key -> plugin.registerPlaceholder(PlaceholderRegistry.this.plugin, key)
);
listener.addEvaluator(evaluator);
}

public void unregisterPlaceholder(String placeholder, PlaceholderEvaluator evaluator) {
PlaceholderListener listener = listeners.get(placeholder);
if (listener == null) {
return;
}
listener.removeEvaluator(evaluator);
if (!listener.hasEvaluators()) { // if this was the last evaluator, unregister the listener
listener.unregisterListener();
listeners.remove(placeholder);
}
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.github.apickledwalrus.skriptplaceholders.skript;

import org.bukkit.entity.Player;

/**
* An event to be used by Skript for passing context regarding relational placeholders during execution.
*/
public class RelationalPlaceholderEvent extends PlaceholderEvent {

private final Player other;

public RelationalPlaceholderEvent(String placeholder, Player player, Player other) {
super(placeholder, player);
this.other = other;
}

@Override
public Player getPlayer() {
//noinspection ConstantConditions - player is passed up as NotNull
return super.getPlayer().getPlayer();
}

public Player getOther() {
return other;
}

}
Loading

0 comments on commit fef82b9

Please sign in to comment.