mirror of
https://github.com/PlaceholderAPI/PlaceholderAPI
synced 2025-11-17 11:19:40 +01:00
we're really getting somewhere!@1
who the fuck decided to use 2 space instead of 4
This commit is contained in:
@@ -28,6 +28,7 @@ dependencies {
|
|||||||
implementation("net.kyori:adventure-platform-bukkit:4.4.1")
|
implementation("net.kyori:adventure-platform-bukkit:4.4.1")
|
||||||
|
|
||||||
//compileOnly("org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT")
|
//compileOnly("org.spigotmc:spigot-api:1.21-R0.1-SNAPSHOT")
|
||||||
|
compileOnly("io.papermc.paper:paper-api:1.21.10-R0.1-SNAPSHOT")
|
||||||
compileOnly("dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT")
|
compileOnly("dev.folia:folia-api:1.20.1-R0.1-SNAPSHOT")
|
||||||
compileOnlyApi("org.jetbrains:annotations:23.0.0")
|
compileOnlyApi("org.jetbrains:annotations:23.0.0")
|
||||||
|
|
||||||
@@ -92,7 +93,12 @@ tasks {
|
|||||||
archiveClassifier.set("")
|
archiveClassifier.set("")
|
||||||
|
|
||||||
relocate("org.bstats", "me.clip.placeholderapi.metrics")
|
relocate("org.bstats", "me.clip.placeholderapi.metrics")
|
||||||
relocate("net.kyori", "me.clip.placeholderapi.libs.kyori")
|
// relocate("net.kyori", "me.clip.placeholderapi.libs.kyori") {
|
||||||
|
// exclude("me/clip/placeholderapi/PAPIComponents.java")
|
||||||
|
// exclude("me/clip/placeholderapi/commands/TestCommand.java")
|
||||||
|
// }
|
||||||
|
|
||||||
|
destinationDirectory = file("server/1.21/plugins/")
|
||||||
|
|
||||||
exclude("META-INF/versions/**")
|
exclude("META-INF/versions/**")
|
||||||
}
|
}
|
||||||
|
|||||||
121
src/main/java/me/clip/placeholderapi/PAPIComponents.java
Normal file
121
src/main/java/me/clip/placeholderapi/PAPIComponents.java
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
package me.clip.placeholderapi;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
import me.clip.placeholderapi.expansion.Relational;
|
||||||
|
import me.clip.placeholderapi.replacer.ExactReplacer;
|
||||||
|
import me.clip.placeholderapi.replacer.Replacer;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.bukkit.entity.Player;
|
||||||
|
import org.checkerframework.checker.units.qual.N;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public final class PAPIComponents {
|
||||||
|
private static final Replacer EXACT_REPLACER = new ExactReplacer();
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Component setPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
||||||
|
// TODO: explore a custom TextReplacementRenderer which doesn't use regex for performance benefits i.e. merge CharsReplacer with kyori TextReplacementRenderer
|
||||||
|
return component.replaceText(config -> config.match(PlaceholderAPI.PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
||||||
|
builder.content(EXACT_REPLACER.apply(result.group(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static List<Component> setPlaceholders(final OfflinePlayer player, @NotNull final List<Component> components) {
|
||||||
|
return components.stream().map(component -> setPlaceholders(player, component)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Component setPlaceholders(final Player player, @NotNull final Component component) {
|
||||||
|
return setPlaceholders((OfflinePlayer) player, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static List<Component> setPlaceholders(final Player player, @NotNull final List<Component> components) {
|
||||||
|
return setPlaceholders((OfflinePlayer) player, components);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Component setBracketPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
||||||
|
return component.replaceText(config -> config.match(PlaceholderAPI.BRACKET_PLACEHOLDER_PATTERN).replacement((result, builder) ->
|
||||||
|
builder.content(EXACT_REPLACER.apply(result.group(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static List<Component> setBracketPlaceholders(final OfflinePlayer player, @NotNull final List<Component> components) {
|
||||||
|
return components.stream().map(component -> setBracketPlaceholders(player, component)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static Component setBracketPlaceholders(final Player player, @NotNull final Component component) {
|
||||||
|
return setBracketPlaceholders((OfflinePlayer) player, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static List<Component> setBracketPlaceholders(final Player player, @NotNull final List<Component> components) {
|
||||||
|
return setBracketPlaceholders((OfflinePlayer) player, components);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static Component setRelationalPlaceholders(Player one, Player two, Component component) {
|
||||||
|
// return component.replaceText(config -> config.match(PlaceholderAPI.RELATIONAL_PLACEHOLDER_PATTERN).replacement((result, builder) -> {
|
||||||
|
//
|
||||||
|
// final String format = result.group(2);
|
||||||
|
// final int index = format.indexOf("_");
|
||||||
|
//
|
||||||
|
// if (index <= 0 || index >= format.length()) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// String identifier = format.substring(0, index).toLowerCase(Locale.ROOT);
|
||||||
|
// String params = format.substring(index + 1);
|
||||||
|
// final PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance()
|
||||||
|
// .getLocalExpansionManager().getExpansion(identifier);
|
||||||
|
//
|
||||||
|
// if (!(expansion instanceof Relational)) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// final String value = ((Relational) expansion).onPlaceholderRequest(one, two, params);
|
||||||
|
//
|
||||||
|
// if (value != null) {
|
||||||
|
// text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value));
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// }));
|
||||||
|
//
|
||||||
|
// final Matcher matcher = PlaceholderAPI.RELATIONAL_PLACEHOLDER_PATTERN.matcher(text);
|
||||||
|
//
|
||||||
|
// while (matcher.find()) {
|
||||||
|
// final String format = matcher.group(2);
|
||||||
|
// final int index = format.indexOf("_");
|
||||||
|
//
|
||||||
|
// if (index <= 0 || index >= format.length()) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// String identifier = format.substring(0, index).toLowerCase(Locale.ROOT);
|
||||||
|
// String params = format.substring(index + 1);
|
||||||
|
// final PlaceholderExpansion expansion = PlaceholderAPIPlugin.getInstance()
|
||||||
|
// .getLocalExpansionManager().getExpansion(identifier);
|
||||||
|
//
|
||||||
|
// if (!(expansion instanceof Relational)) {
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// final String value = ((Relational) expansion).onPlaceholderRequest(one, two, params);
|
||||||
|
//
|
||||||
|
// if (value != null) {
|
||||||
|
// text = text.replaceAll(Pattern.quote(matcher.group()), Matcher.quoteReplacement(value));
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// return text;
|
||||||
|
// }
|
||||||
|
}
|
||||||
@@ -34,9 +34,8 @@ import me.clip.placeholderapi.expansion.manager.LocalExpansionManager;
|
|||||||
import me.clip.placeholderapi.replacer.CharsReplacer;
|
import me.clip.placeholderapi.replacer.CharsReplacer;
|
||||||
import me.clip.placeholderapi.replacer.Replacer;
|
import me.clip.placeholderapi.replacer.Replacer;
|
||||||
import me.clip.placeholderapi.replacer.Replacer.Closure;
|
import me.clip.placeholderapi.replacer.Replacer.Closure;
|
||||||
|
import me.clip.placeholderapi.replacer.ExactReplacer;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
import net.kyori.adventure.text.Component;
|
|
||||||
import net.kyori.adventure.text.TextReplacementConfig;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.bukkit.entity.Player;
|
import org.bukkit.entity.Player;
|
||||||
import org.bukkit.plugin.Plugin;
|
import org.bukkit.plugin.Plugin;
|
||||||
@@ -48,23 +47,18 @@ public final class PlaceholderAPI {
|
|||||||
private static final Replacer REPLACER_PERCENT = new CharsReplacer(Closure.PERCENT);
|
private static final Replacer REPLACER_PERCENT = new CharsReplacer(Closure.PERCENT);
|
||||||
private static final Replacer REPLACER_BRACKET = new CharsReplacer(Closure.BRACKET);
|
private static final Replacer REPLACER_BRACKET = new CharsReplacer(Closure.BRACKET);
|
||||||
|
|
||||||
private static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]");
|
static final Pattern PLACEHOLDER_PATTERN = Pattern.compile("[%]([^%]+)[%]");
|
||||||
private static final Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[{]([^{}]+)[}]");
|
static final Pattern BRACKET_PLACEHOLDER_PATTERN = Pattern.compile("[{]([^{}]+)[}]");
|
||||||
private static final Pattern RELATIONAL_PLACEHOLDER_PATTERN = Pattern
|
static final Pattern RELATIONAL_PLACEHOLDER_PATTERN = Pattern
|
||||||
.compile("[%](rel_)([^%]+)[%]");
|
.compile("[%](rel_)([^%]+)[%]");
|
||||||
|
|
||||||
|
private static final Replacer TEST = new ExactReplacer();
|
||||||
|
|
||||||
private PlaceholderAPI() {
|
private PlaceholderAPI() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Current API ===
|
// === Current API ===
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public static Component setComponentPlaceholders(final OfflinePlayer player, @NotNull final Component component) {
|
|
||||||
// change charsreplacer to custom that returns component instead of string - this is going to suck mega
|
|
||||||
return component.replaceText(config -> config.match(PLACEHOLDER_PATTERN).replacement((result, builder) -> builder.content(REPLACER_PERCENT.apply(builder.content(), player, PlaceholderAPIPlugin.getInstance().getLocalExpansionManager()::getExpansion))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Translates all placeholders into their corresponding values.
|
* Translates all placeholders into their corresponding values.
|
||||||
* <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
|
* <br>The pattern of a valid placeholder is {@literal %<identifier>_<params>%}.
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.Arrays;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommandRouter;
|
import me.clip.placeholderapi.commands.PlaceholderCommandRouter;
|
||||||
|
import me.clip.placeholderapi.commands.TestCommand;
|
||||||
import me.clip.placeholderapi.configuration.PlaceholderAPIConfig;
|
import me.clip.placeholderapi.configuration.PlaceholderAPIConfig;
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import me.clip.placeholderapi.expansion.Version;
|
import me.clip.placeholderapi.expansion.Version;
|
||||||
@@ -157,6 +158,7 @@ public final class PlaceholderAPIPlugin extends JavaPlugin {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
|
registerCommand("test", new TestCommand());
|
||||||
setupCommand();
|
setupCommand();
|
||||||
setupMetrics();
|
setupMetrics();
|
||||||
setupExpansions();
|
setupExpansions();
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
public abstract class PlaceholderHook {
|
public abstract class PlaceholderHook {
|
||||||
@Deprecated
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String onRequest(final OfflinePlayer player, @NotNull final String params) {
|
public String onRequest(final OfflinePlayer player, @NotNull final String params) {
|
||||||
if (player != null && player.isOnline()) {
|
if (player != null && player.isOnline()) {
|
||||||
@@ -39,16 +38,8 @@ public abstract class PlaceholderHook {
|
|||||||
return onPlaceholderRequest(null, params);
|
return onPlaceholderRequest(null, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public String onPlaceholderRequest(final Player player, @NotNull final String params) {
|
public String onPlaceholderRequest(final Player player, @NotNull final String params) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public Component onPlaceholderComponentRequest(final OfflinePlayer player, @NotNull final String params) {
|
|
||||||
final String result = onRequest(player, params);
|
|
||||||
|
|
||||||
return result == null ? null : Component.text(result);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,12 @@ package me.clip.placeholderapi.commands;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ package me.clip.placeholderapi.commands;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -30,6 +31,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.impl.cloud.CommandECloud;
|
import me.clip.placeholderapi.commands.impl.cloud.CommandECloud;
|
||||||
import me.clip.placeholderapi.commands.impl.local.CommandDump;
|
import me.clip.placeholderapi.commands.impl.local.CommandDump;
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package me.clip.placeholderapi.commands;
|
||||||
|
|
||||||
|
import io.papermc.paper.command.brigadier.BasicCommand;
|
||||||
|
import io.papermc.paper.command.brigadier.CommandSourceStack;
|
||||||
|
import me.clip.placeholderapi.PAPIComponents;
|
||||||
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
|
import net.kyori.adventure.text.Component;
|
||||||
|
import net.kyori.adventure.text.event.HoverEvent;
|
||||||
|
import net.kyori.adventure.text.event.HoverEventSource;
|
||||||
|
import net.kyori.adventure.text.format.TextColor;
|
||||||
|
import net.kyori.adventure.text.minimessage.MiniMessage;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
|
||||||
|
public class TestCommand implements BasicCommand {
|
||||||
|
private static final MiniMessage MINI = MiniMessage.miniMessage();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(final CommandSourceStack commandSourceStack, final String[] strings) {
|
||||||
|
// final Component component = Component.text("Woo! Test: %player_name%").color(TextColor.color(50, 168, 82)).hoverEvent(HoverEvent.showText(Component.text("OMG %player_gamemode%")));
|
||||||
|
final Component component = Component.text("Woo! Test: %player_name%");
|
||||||
|
|
||||||
|
String ser = MINI.serialize(component);
|
||||||
|
System.out.println(ser);
|
||||||
|
|
||||||
|
commandSourceStack.getSender().sendMessage(
|
||||||
|
PAPIComponents.setPlaceholders((OfflinePlayer) commandSourceStack.getSender(), component)
|
||||||
|
);
|
||||||
|
|
||||||
|
long tmp = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < 100000; ++i) {
|
||||||
|
PAPIComponents.setPlaceholders((OfflinePlayer) commandSourceStack.getSender(), component);
|
||||||
|
}
|
||||||
|
commandSourceStack.getSender().sendMessage(String.valueOf(System.currentTimeMillis() - tmp));
|
||||||
|
|
||||||
|
tmp = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < 100000; ++i) {
|
||||||
|
PlaceholderAPI.setPlaceholders((OfflinePlayer) commandSourceStack.getSender(), "Woo! Test: %player_name%");
|
||||||
|
}
|
||||||
|
commandSourceStack.getSender().sendMessage(String.valueOf(System.currentTimeMillis() - tmp));
|
||||||
|
|
||||||
|
tmp = System.currentTimeMillis();
|
||||||
|
for (int i = 0; i < 100000; ++i) {
|
||||||
|
final String serr = MINI.serialize(component);
|
||||||
|
final String repl = PlaceholderAPI.setPlaceholders((OfflinePlayer) commandSourceStack.getSender(), serr);
|
||||||
|
MINI.deserialize(repl);
|
||||||
|
}
|
||||||
|
commandSourceStack.getSender().sendMessage(String.valueOf(System.currentTimeMillis() - tmp));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.cloud;
|
package me.clip.placeholderapi.commands.impl.cloud;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ package me.clip.placeholderapi.commands.impl.cloud;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||||
|
|||||||
@@ -25,12 +25,14 @@ import com.google.common.collect.ImmutableSet;
|
|||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.primitives.Ints;
|
import com.google.common.primitives.Ints;
|
||||||
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.configuration.ExpansionSort;
|
import me.clip.placeholderapi.configuration.ExpansionSort;
|
||||||
|
|||||||
@@ -21,9 +21,11 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.cloud;
|
package me.clip.placeholderapi.commands.impl.cloud;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.cloud;
|
package me.clip.placeholderapi.commands.impl.cloud;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.cloud;
|
package me.clip.placeholderapi.commands.impl.cloud;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.expansion.manager.CloudExpansionManager;
|
import me.clip.placeholderapi.expansion.manager.CloudExpansionManager;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.cloud;
|
package me.clip.placeholderapi.commands.impl.cloud;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
@@ -28,6 +29,7 @@ import java.util.Objects;
|
|||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ package me.clip.placeholderapi.commands.impl.local;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPI;
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.local;
|
package me.clip.placeholderapi.commands.impl.local;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.local;
|
package me.clip.placeholderapi.commands.impl.local;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPI;
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
|
|||||||
@@ -21,9 +21,11 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.local;
|
package me.clip.placeholderapi.commands.impl.local;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPI;
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import java.util.List;
|
|||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPI;
|
import me.clip.placeholderapi.PlaceholderAPI;
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.local;
|
package me.clip.placeholderapi.commands.impl.local;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import org.bukkit.command.CommandSender;
|
import org.bukkit.command.CommandSender;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.commands.impl.local;
|
package me.clip.placeholderapi.commands.impl.local;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
import me.clip.placeholderapi.commands.PlaceholderCommand;
|
||||||
import me.clip.placeholderapi.util.Msg;
|
import me.clip.placeholderapi.util.Msg;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ package me.clip.placeholderapi.events;
|
|||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import org.bukkit.event.Event;
|
import org.bukkit.event.Event;
|
||||||
import org.bukkit.event.HandlerList;
|
import org.bukkit.event.HandlerList;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ package me.clip.placeholderapi.expansion.cloud;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.clip.placeholderapi.util.TimeUtil;
|
import me.clip.placeholderapi.util.TimeUtil;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ import com.google.common.io.Resources;
|
|||||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@@ -50,6 +51,7 @@ import java.util.function.Function;
|
|||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collector;
|
import java.util.stream.Collector;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
import me.clip.placeholderapi.expansion.cloud.CloudExpansion;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ package me.clip.placeholderapi.expansion.manager;
|
|||||||
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -38,6 +39,7 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
import java.util.concurrent.locks.ReentrantLock;
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import me.clip.placeholderapi.events.ExpansionRegisterEvent;
|
import me.clip.placeholderapi.events.ExpansionRegisterEvent;
|
||||||
import me.clip.placeholderapi.events.ExpansionUnregisterEvent;
|
import me.clip.placeholderapi.events.ExpansionUnregisterEvent;
|
||||||
@@ -213,6 +215,7 @@ public final class LocalExpansionManager implements Listener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attempt to register a {@link PlaceholderExpansion}
|
* Attempt to register a {@link PlaceholderExpansion}
|
||||||
|
*
|
||||||
* @param expansion the expansion to register
|
* @param expansion the expansion to register
|
||||||
* @return if the expansion was registered
|
* @return if the expansion was registered
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ package me.clip.placeholderapi.replacer;
|
|||||||
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
@@ -43,6 +44,8 @@ public final class CharsReplacer implements Replacer {
|
|||||||
public String apply(@NotNull final String text, @Nullable final OfflinePlayer player,
|
public String apply(@NotNull final String text, @Nullable final OfflinePlayer player,
|
||||||
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
|
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
|
||||||
final char[] chars = text.toCharArray();
|
final char[] chars = text.toCharArray();
|
||||||
|
// Woo! Hlello %player_name%
|
||||||
|
// Woo! GHsda PiggyPiglet
|
||||||
final StringBuilder builder = new StringBuilder(text.length());
|
final StringBuilder builder = new StringBuilder(text.length());
|
||||||
|
|
||||||
final StringBuilder identifier = new StringBuilder();
|
final StringBuilder identifier = new StringBuilder();
|
||||||
|
|||||||
@@ -1,303 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of adventure, licensed under the MIT License.
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017-2025 KyoriPowered
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
package me.clip.placeholderapi.replacer;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.BiFunction;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.regex.MatchResult;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
|
||||||
import net.kyori.adventure.text.*;
|
|
||||||
import net.kyori.adventure.text.event.HoverEvent;
|
|
||||||
import net.kyori.adventure.text.format.Style;
|
|
||||||
import net.kyori.adventure.text.renderer.ComponentRenderer;
|
|
||||||
import org.bukkit.OfflinePlayer;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A renderer performing a replacement on every {@link TextComponent} element of a component tree.
|
|
||||||
*/
|
|
||||||
final class ComponentCharsReplacer implements ComponentRenderer<ComponentCharsReplacer.State> {
|
|
||||||
//static final TextReplacementRenderer INSTANCE = new TextReplacementRenderer();
|
|
||||||
private final OfflinePlayer player;
|
|
||||||
private final Function<String, @Nullable PlaceholderExpansion> lookup;
|
|
||||||
private static final Closure CLOSURE = Closure.PERCENT;
|
|
||||||
|
|
||||||
enum Closure {
|
|
||||||
BRACKET('{', '}'),
|
|
||||||
PERCENT('%', '%');
|
|
||||||
|
|
||||||
|
|
||||||
public final char head, tail;
|
|
||||||
|
|
||||||
Closure(final char head, final char tail) {
|
|
||||||
this.head = head;
|
|
||||||
this.tail = tail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public ComponentCharsReplacer(@Nullable final OfflinePlayer player,
|
|
||||||
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
|
|
||||||
this.player = player;
|
|
||||||
this.lookup = lookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Component render(final Component component, final State state) {
|
|
||||||
if (!state.running) return component;
|
|
||||||
final boolean prevFirstMatch = state.firstMatch;
|
|
||||||
state.firstMatch = true;
|
|
||||||
|
|
||||||
final List<Component> oldChildren = component.children();
|
|
||||||
final int oldChildrenSize = oldChildren.size();
|
|
||||||
Style oldStyle = component.style();
|
|
||||||
List<Component> children = null;
|
|
||||||
Component modified = component;
|
|
||||||
// replace the component itself
|
|
||||||
if (component instanceof TextComponent) {
|
|
||||||
TextComponent tc = (TextComponent) component;
|
|
||||||
final String content = tc.content();
|
|
||||||
|
|
||||||
final char[] chars = content.toCharArray();
|
|
||||||
final StringBuilder identifier = new StringBuilder();
|
|
||||||
final StringBuilder parameters = new StringBuilder();
|
|
||||||
|
|
||||||
final Map<List<Integer>, Component> replacements = new HashMap<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
|
||||||
final char l = chars[i];
|
|
||||||
|
|
||||||
if (l != CLOSURE.head || i + 1 >= chars.length) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean identified = false;
|
|
||||||
boolean invalid = true;
|
|
||||||
boolean hadSpace = false;
|
|
||||||
|
|
||||||
while (++i < chars.length) {
|
|
||||||
final char p = chars[i];
|
|
||||||
|
|
||||||
if (p == ' ' && !identified) {
|
|
||||||
hadSpace = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == CLOSURE.tail) {
|
|
||||||
invalid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == '_' && !identified) {
|
|
||||||
identified = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (identified) {
|
|
||||||
parameters.append(p);
|
|
||||||
} else {
|
|
||||||
identifier.append(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final String identifierString = identifier.toString();
|
|
||||||
final String lowerIdentifiedString = identifierString.toLowerCase();
|
|
||||||
final String parametersString = parameters.toString();
|
|
||||||
|
|
||||||
identifier.setLength(0);
|
|
||||||
parameters.setLength(0);
|
|
||||||
|
|
||||||
if (invalid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
replacements.put(Lists.newArrayList(i, i + identifierString.length() + parametersString.length()), lookup.apply(lowerIdentifiedString).onPlaceholderComponentRequest(player, parametersString));
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// do something with our replacements
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
final Matcher matcher = state.pattern.matcher(content);
|
|
||||||
int replacedUntil = 0; // last index handled
|
|
||||||
while (matcher.find()) {
|
|
||||||
final PatternReplacementResult result = state.continuer.shouldReplace(matcher, ++state.matchCount, state.replaceCount);
|
|
||||||
|
|
||||||
if (matcher.start() == 0) {
|
|
||||||
// if we're a full match, modify the component directly
|
|
||||||
if (matcher.end() == content.length()) {
|
|
||||||
final ComponentLike replacement = state.replacement.apply(matcher, Component.text().content(matcher.group())
|
|
||||||
.style(component.style()));
|
|
||||||
|
|
||||||
modified = replacement == null ? Component.empty() : replacement.asComponent();
|
|
||||||
|
|
||||||
if (modified.style().hoverEvent() != null) {
|
|
||||||
oldStyle = oldStyle.hoverEvent(null); // Remove original hover if it has been replaced completely
|
|
||||||
}
|
|
||||||
|
|
||||||
// merge style of the match into this component to prevent unexpected loss of style
|
|
||||||
modified = modified.style(modified.style().merge(component.style(), Style.Merge.Strategy.IF_ABSENT_ON_TARGET));
|
|
||||||
|
|
||||||
if (children == null) { // Prepare children
|
|
||||||
children = new ArrayList<>(oldChildrenSize + modified.children().size());
|
|
||||||
children.addAll(modified.children());
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// otherwise, work on a child of the root node
|
|
||||||
modified = Component.text("", component.style());
|
|
||||||
final ComponentLike child = state.replacement.apply(matcher, Component.text().content(matcher.group()));
|
|
||||||
if (child != null) {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize + 1);
|
|
||||||
}
|
|
||||||
children.add(child.asComponent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize + 2);
|
|
||||||
}
|
|
||||||
if (state.firstMatch) {
|
|
||||||
// truncate parent to content before match
|
|
||||||
modified = ((TextComponent) component).content(content.substring(0, matcher.start()));
|
|
||||||
} else if (replacedUntil < matcher.start()) {
|
|
||||||
children.add(Component.text(content.substring(replacedUntil, matcher.start())));
|
|
||||||
}
|
|
||||||
final ComponentLike builder = state.replacement.apply(matcher, Component.text().content(matcher.group()));
|
|
||||||
if (builder != null) {
|
|
||||||
children.add(builder.asComponent());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
state.replaceCount++;
|
|
||||||
state.firstMatch = false;
|
|
||||||
replacedUntil = matcher.end();
|
|
||||||
}
|
|
||||||
if (replacedUntil < content.length()) {
|
|
||||||
// append trailing content
|
|
||||||
if (replacedUntil > 0) {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize);
|
|
||||||
}
|
|
||||||
children.add(Component.text(content.substring(replacedUntil)));
|
|
||||||
}
|
|
||||||
// otherwise, we haven't modified the component, so nothing to change
|
|
||||||
}
|
|
||||||
} else if (modified instanceof TranslatableComponent) { // get TranslatableComponent with() args
|
|
||||||
final List<TranslationArgument> args = ((TranslatableComponent) modified).arguments();
|
|
||||||
List<TranslationArgument> newArgs = null;
|
|
||||||
for (int i = 0, size = args.size(); i < size; i++) {
|
|
||||||
final TranslationArgument original = args.get(i);
|
|
||||||
final TranslationArgument replaced = original.value() instanceof Component ? TranslationArgument.component(this.render((Component) original.value(), state)) : original;
|
|
||||||
if (replaced != original) {
|
|
||||||
if (newArgs == null) {
|
|
||||||
newArgs = new ArrayList<>(size);
|
|
||||||
if (i > 0) {
|
|
||||||
newArgs.addAll(args.subList(0, i));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newArgs != null) {
|
|
||||||
newArgs.add(replaced);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (newArgs != null) {
|
|
||||||
modified = ((TranslatableComponent) modified).arguments(newArgs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Only visit children if we're running
|
|
||||||
if (state.running) {
|
|
||||||
// hover event
|
|
||||||
if (state.replaceInsideHoverEvents) {
|
|
||||||
final HoverEvent<?> event = oldStyle.hoverEvent();
|
|
||||||
if (event != null) {
|
|
||||||
final HoverEvent<?> rendered = event.withRenderedValue(this, state);
|
|
||||||
if (event != rendered) {
|
|
||||||
modified = modified.style(s -> s.hoverEvent(rendered));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Children
|
|
||||||
boolean first = true;
|
|
||||||
for (int i = 0; i < oldChildrenSize; i++) {
|
|
||||||
final Component child = oldChildren.get(i);
|
|
||||||
final Component replaced = this.render(child, state);
|
|
||||||
if (replaced != child) {
|
|
||||||
if (children == null) {
|
|
||||||
children = new ArrayList<>(oldChildrenSize);
|
|
||||||
}
|
|
||||||
if (first) {
|
|
||||||
children.addAll(oldChildren.subList(0, i));
|
|
||||||
}
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
if (children != null) {
|
|
||||||
children.add(replaced);
|
|
||||||
first = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// we're not visiting children, re-add original children if necessary
|
|
||||||
if (children != null) {
|
|
||||||
children.addAll(oldChildren);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.firstMatch = prevFirstMatch;
|
|
||||||
// Update the modified component with new children
|
|
||||||
if (children != null) {
|
|
||||||
return modified.children(children);
|
|
||||||
}
|
|
||||||
return modified;
|
|
||||||
}
|
|
||||||
|
|
||||||
static final class State {
|
|
||||||
final Pattern pattern;
|
|
||||||
final BiFunction<MatchResult, TextComponent.Builder, @Nullable ComponentLike> replacement;
|
|
||||||
final TextReplacementConfig.Condition continuer;
|
|
||||||
final boolean replaceInsideHoverEvents;
|
|
||||||
boolean running = true;
|
|
||||||
int matchCount = 0;
|
|
||||||
int replaceCount = 0;
|
|
||||||
boolean firstMatch = true;
|
|
||||||
|
|
||||||
State(final Pattern pattern, final BiFunction<MatchResult, TextComponent.Builder, @Nullable ComponentLike> replacement, final TextReplacementConfig.Condition continuer, final boolean replaceInsideHoverEvents) {
|
|
||||||
this.pattern = pattern;
|
|
||||||
this.replacement = replacement;
|
|
||||||
this.continuer = continuer;
|
|
||||||
this.replaceInsideHoverEvents = replaceInsideHoverEvents;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
package me.clip.placeholderapi.replacer;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
import net.kyori.adventure.text.*;
|
||||||
|
import net.kyori.adventure.text.format.Style;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
|
public final class ComponentReplacer {
|
||||||
|
public Component replace(Component component, OfflinePlayer player, Function<String, PlaceholderExpansion> function) {
|
||||||
|
Component modified = component;
|
||||||
|
|
||||||
|
final List<Component> oldChildren = component.children();
|
||||||
|
final int oldChildrenSize = oldChildren.size();
|
||||||
|
List<Component> children = null;
|
||||||
|
|
||||||
|
if (component instanceof TextComponent) {
|
||||||
|
TextComponent tc = (TextComponent) component;
|
||||||
|
final String content = tc.content();
|
||||||
|
|
||||||
|
final char[] chars = content.toCharArray();
|
||||||
|
|
||||||
|
final StringBuilder identifier = new StringBuilder();
|
||||||
|
final StringBuilder parameters = new StringBuilder();
|
||||||
|
|
||||||
|
for (int i = 0; i < chars.length; i++) {
|
||||||
|
final char l = chars[i];
|
||||||
|
|
||||||
|
if (l != '%' || i + 1 >= chars.length) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final int start = i;
|
||||||
|
|
||||||
|
boolean identified = false;
|
||||||
|
boolean invalid = true;
|
||||||
|
|
||||||
|
while (++i < chars.length) {
|
||||||
|
final char p = chars[i];
|
||||||
|
|
||||||
|
if (p == ' ' && !identified) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == '%') {
|
||||||
|
invalid = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == '_' && !identified) {
|
||||||
|
identified = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (identified) {
|
||||||
|
parameters.append(p);
|
||||||
|
} else {
|
||||||
|
identifier.append(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final String identifierString = identifier.toString();
|
||||||
|
final String lowercaseIdentifierString = identifierString.toLowerCase(Locale.ROOT);
|
||||||
|
final String parametersString = parameters.toString();
|
||||||
|
|
||||||
|
identifier.setLength(0);
|
||||||
|
parameters.setLength(0);
|
||||||
|
|
||||||
|
if (invalid) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final PlaceholderExpansion expansion = function.apply(lowercaseIdentifierString);
|
||||||
|
|
||||||
|
if (expansion == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String placeholderValue = expansion.onRequest(player, parametersString);
|
||||||
|
|
||||||
|
if (placeholderValue == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start == 0) {
|
||||||
|
// if we're a full match, modify the component directly
|
||||||
|
if (i == content.length() - 1) {
|
||||||
|
final ComponentLike replacement = Component.text(placeholderValue).style(component.style());
|
||||||
|
|
||||||
|
modified = replacement.asComponent();
|
||||||
|
Style modStyle = modified.style();
|
||||||
|
|
||||||
|
if (modStyle.hoverEvent() != null) {
|
||||||
|
Object hoverValue = modStyle.hoverEvent().value();
|
||||||
|
|
||||||
|
if (hoverValue instanceof Component) {
|
||||||
|
final Component replacedHoverComponent = replace((Component) hoverValue, player, function);
|
||||||
|
|
||||||
|
if (replacedHoverComponent != hoverValue) {
|
||||||
|
modified.style();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (modStyle.clickEvent() != null) {
|
||||||
|
String clickValue =
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (component instanceof TranslatableComponent) {
|
||||||
|
TranslatableComponent tc = (TranslatableComponent) component;
|
||||||
|
final List<TranslationArgument> args = tc.arguments();
|
||||||
|
List<TranslationArgument> newArgs = null;
|
||||||
|
for (int i = 0, size = args.size(); i < size; i++) {
|
||||||
|
final TranslationArgument original = args.get(i);
|
||||||
|
TranslationArgument replacement = original instanceof Component ? TranslationArgument.component(replace((Component) original, player, function)) : original;
|
||||||
|
|
||||||
|
if (original != replacement) {
|
||||||
|
if (newArgs == null) {
|
||||||
|
newArgs = new ArrayList<>(size);
|
||||||
|
|
||||||
|
if (i > 0) {
|
||||||
|
newArgs.addAll(args.subList(0, i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newArgs != null) {
|
||||||
|
newArgs.add(replacement);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newArgs != null) {
|
||||||
|
modified = ((TranslatableComponent) modified).arguments(newArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return modified;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
package me.clip.placeholderapi.replacer;
|
||||||
|
|
||||||
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
|
import org.bukkit.OfflinePlayer;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class ExactReplacer implements Replacer {
|
||||||
|
private static final Pattern DELIMITER = Pattern.compile("_");
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public String apply(@NotNull String text, @Nullable final OfflinePlayer player,
|
||||||
|
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
|
||||||
|
text = text.substring(1, text.length() - 1);
|
||||||
|
final String[] parts = DELIMITER.split(text);
|
||||||
|
final PlaceholderExpansion expansion;
|
||||||
|
|
||||||
|
if (parts.length == 0) {
|
||||||
|
expansion = lookup.apply(text);
|
||||||
|
} else {
|
||||||
|
expansion = lookup.apply(parts[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (expansion == null) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String params;
|
||||||
|
|
||||||
|
if (text.endsWith("_")) {
|
||||||
|
params = "";
|
||||||
|
} else {
|
||||||
|
params = text.substring(text.indexOf('_') + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String result = expansion.onRequest(player, params);
|
||||||
|
|
||||||
|
if (result == null) {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,6 +21,7 @@
|
|||||||
package me.clip.placeholderapi.replacer;
|
package me.clip.placeholderapi.replacer;
|
||||||
|
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import org.bukkit.OfflinePlayer;
|
import org.bukkit.OfflinePlayer;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import static java.util.stream.IntStream.range;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ package me.clip.placeholderapi.util;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
import me.clip.placeholderapi.PlaceholderAPIPlugin;
|
||||||
import org.bukkit.Bukkit;
|
import org.bukkit.Bukkit;
|
||||||
import org.bukkit.ChatColor;
|
import org.bukkit.ChatColor;
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ commands:
|
|||||||
placeholderapi:
|
placeholderapi:
|
||||||
description: "PlaceholderAPI Command"
|
description: "PlaceholderAPI Command"
|
||||||
aliases: ["papi"]
|
aliases: ["papi"]
|
||||||
|
test:
|
||||||
|
description: "yes"
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
placeholderapi.*:
|
placeholderapi.*:
|
||||||
|
|||||||
Reference in New Issue
Block a user