mirror of
https://github.com/PlaceholderAPI/PlaceholderAPI
synced 2026-04-08 02:02:27 +02:00
Merge branch 'hytale' into hytale-curseforge
This commit is contained in:
@@ -7,7 +7,7 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group = "at.helpch"
|
group = "at.helpch"
|
||||||
version = "1.0.7-CurseForge"
|
version = "1.0.8-CurseForge"
|
||||||
|
|
||||||
description = "An awesome placeholder provider!"
|
description = "An awesome placeholder provider!"
|
||||||
|
|
||||||
@@ -42,6 +42,10 @@ tasks {
|
|||||||
eachFile { expand("version" to project.version) }
|
eachFile { expand("version" to project.version) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
withType<Javadoc> {
|
||||||
|
isFailOnError = false
|
||||||
|
}
|
||||||
|
|
||||||
withType<ShadowJar> {
|
withType<ShadowJar> {
|
||||||
archiveClassifier.set("hytale")
|
archiveClassifier.set("hytale")
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ public final class PlaceholderAPIConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Map<String, Object> expansions() {
|
public ConcurrentHashMap<String, Object> expansions() {
|
||||||
return expansions;
|
return expansions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import at.helpch.placeholderapi.PlaceholderAPIPlugin;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementing this interface allows {@link at.helpch.placeholderapi.expansion.PlaceholderExpansion PlaceholderExpansions}
|
* Implementing this interface allows {@link at.helpch.placeholderapi.expansion.PlaceholderExpansion PlaceholderExpansions}
|
||||||
@@ -43,20 +44,31 @@ import java.util.Map;
|
|||||||
* @author Ryan McCarthy
|
* @author Ryan McCarthy
|
||||||
*/
|
*/
|
||||||
public interface Configurable<T> {
|
public interface Configurable<T> {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
Class<T> provideConfigType();
|
Class<T> provideConfigType();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
T provideDefault();
|
T provideDefault();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@NotNull
|
@NotNull
|
||||||
default T getConfig() {
|
default T getConfig() {
|
||||||
if (this instanceof PlaceholderExpansion exp) {
|
if (!(this instanceof PlaceholderExpansion exp)) {
|
||||||
return (T) PlaceholderAPIPlugin.instance().configManager().config().expansions().computeIfAbsent(exp.getIdentifier(), s -> provideDefault());
|
return provideDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
return provideDefault();
|
final ConcurrentHashMap<String, Object> expansionConfigs = PlaceholderAPIPlugin.instance().configManager().config().expansions();
|
||||||
|
final String key = exp.getIdentifier();
|
||||||
|
|
||||||
|
final Object existing = expansionConfigs.get(key);
|
||||||
|
if (existing != null) {
|
||||||
|
return (T) existing;
|
||||||
|
}
|
||||||
|
|
||||||
|
final T def = provideDefault();
|
||||||
|
final Object conf = expansionConfigs.putIfAbsent(key, def);
|
||||||
|
|
||||||
|
return (T) (conf != null ? conf : def);
|
||||||
}
|
}
|
||||||
|
|
||||||
// /**
|
// /**
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ import java.util.Locale;
|
|||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
|
||||||
import at.helpch.placeholderapi.expansion.PlaceholderExpansion;
|
import at.helpch.placeholderapi.expansion.PlaceholderExpansion;
|
||||||
import com.hypixel.hytale.server.core.entity.entities.Player;
|
|
||||||
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
import com.hypixel.hytale.server.core.universe.PlayerRef;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -38,98 +37,113 @@ public final class CharsReplacer implements Replacer {
|
|||||||
this.closure = closure;
|
this.closure = closure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Translates placeholders within the provided text using a high-performance
|
||||||
|
* character-scanning approach.
|
||||||
|
* * <p>The method identifies placeholders delimited by the defined {@link Closure}
|
||||||
|
* (e.g., %identifier_params% or {identifier_params}). If a placeholder is
|
||||||
|
* successfully identified, the provided lookup function is used to fetch the
|
||||||
|
* corresponding {@link PlaceholderExpansion}.</p>
|
||||||
|
*
|
||||||
|
* @param text The raw text containing potential placeholders to be replaced.
|
||||||
|
* @param player The {@link PlayerRef} to contextually parse the placeholders against.
|
||||||
|
* May be {@code null} if no player context is available.
|
||||||
|
* @param lookup A function that maps a lowercase identifier string to a registered
|
||||||
|
* {@link PlaceholderExpansion}.
|
||||||
|
* @return A string with all valid placeholders replaced by their respective values.
|
||||||
|
* Returns the original text if no placeholders are found.
|
||||||
|
*/
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public String apply(@NotNull final String text, @Nullable final PlayerRef player,
|
public String apply(@NotNull final String text, @Nullable final PlayerRef player,
|
||||||
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
|
@NotNull final Function<String, @Nullable PlaceholderExpansion> lookup) {
|
||||||
final char[] chars = text.toCharArray();
|
final char head = closure.head;
|
||||||
final StringBuilder builder = new StringBuilder(text.length());
|
int startPlaceholder = text.indexOf(head);
|
||||||
|
|
||||||
final StringBuilder identifier = new StringBuilder();
|
if (startPlaceholder == -1) {
|
||||||
final StringBuilder parameters = new StringBuilder();
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < chars.length; i++) {
|
final int length = text.length();
|
||||||
final char l = chars[i];
|
final StringBuilder builder = new StringBuilder(length + (length >> 3));
|
||||||
|
int cursor = 0;
|
||||||
|
|
||||||
if (l != closure.head || i + 1 >= chars.length) {
|
final char tail = closure.tail;
|
||||||
builder.append(l);
|
|
||||||
|
loop: do {
|
||||||
|
// Append plain text preceding the placeholder
|
||||||
|
if (startPlaceholder > cursor) {
|
||||||
|
builder.append(text, cursor, startPlaceholder);
|
||||||
|
}
|
||||||
|
|
||||||
|
final int endPlaceholder = text.indexOf(tail, startPlaceholder + 1);
|
||||||
|
|
||||||
|
if (endPlaceholder == -1) {
|
||||||
|
builder.append(text, startPlaceholder, length);
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int underscoreIndex = -1;
|
||||||
|
|
||||||
|
for (int i = startPlaceholder + 1; i < endPlaceholder; i++) {
|
||||||
|
final char current = text.charAt(i);
|
||||||
|
|
||||||
|
if (current == ' ' && underscoreIndex == -1) {
|
||||||
|
// Invalid placeholder (contains space before _).
|
||||||
|
// Treat the opening symbol as literal text and search for the next one.
|
||||||
|
builder.append(head);
|
||||||
|
cursor = startPlaceholder + 1;
|
||||||
|
startPlaceholder = text.indexOf(head, cursor);
|
||||||
|
|
||||||
|
// Safety check: If no more placeholders exist, break to finalize
|
||||||
|
if (startPlaceholder == -1) {
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
continue loop;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current == '_' && underscoreIndex == -1) {
|
||||||
|
underscoreIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (underscoreIndex == -1) {
|
||||||
|
builder.append(text, startPlaceholder, endPlaceholder + 1);
|
||||||
|
cursor = endPlaceholder + 1;
|
||||||
|
startPlaceholder = text.indexOf(head, cursor);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
boolean identified = false;
|
String identifier = text.substring(startPlaceholder + 1, underscoreIndex);
|
||||||
boolean invalid = true;
|
String parameters = "";
|
||||||
boolean hadSpace = false;
|
|
||||||
|
|
||||||
while (++i < chars.length) {
|
if (underscoreIndex + 1 < endPlaceholder) {
|
||||||
final char p = chars[i];
|
parameters = text.substring(underscoreIndex + 1, endPlaceholder);
|
||||||
|
|
||||||
if (p == ' ' && !identified) {
|
|
||||||
hadSpace = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (p == closure.tail) {
|
|
||||||
invalid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (p == '_' && !identified) {
|
|
||||||
identified = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (identified) {
|
|
||||||
parameters.append(p);
|
|
||||||
} else {
|
|
||||||
identifier.append(p);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final String identifierString = identifier.toString();
|
final PlaceholderExpansion expansion = lookup.apply(identifier.toLowerCase(Locale.ROOT));
|
||||||
final String lowercaseIdentifierString = identifierString.toLowerCase(Locale.ROOT);
|
String replacement = null;
|
||||||
final String parametersString = parameters.toString();
|
|
||||||
|
|
||||||
identifier.setLength(0);
|
if (expansion != null) {
|
||||||
parameters.setLength(0);
|
replacement = expansion.onPlaceholderRequest(player, parameters);
|
||||||
|
|
||||||
if (invalid) {
|
|
||||||
builder.append(closure.head).append(identifierString);
|
|
||||||
|
|
||||||
if (identified) {
|
|
||||||
builder.append('_').append(parametersString);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hadSpace) {
|
|
||||||
builder.append(' ');
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final PlaceholderExpansion placeholder = lookup.apply(lowercaseIdentifierString);
|
if (replacement != null) {
|
||||||
if (placeholder == null) {
|
builder.append(replacement);
|
||||||
builder.append(closure.head).append(identifierString);
|
} else {
|
||||||
|
// Fallback: Restore original placeholder format
|
||||||
if (identified) {
|
builder.append(head).append(identifier);
|
||||||
builder.append('_');
|
builder.append('_').append(parameters);
|
||||||
}
|
builder.append(tail);
|
||||||
|
|
||||||
builder.append(parametersString).append(closure.tail);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final String replacement = placeholder.onPlaceholderRequest(player, parametersString);
|
cursor = endPlaceholder + 1;
|
||||||
if (replacement == null) {
|
startPlaceholder = text.indexOf(head, cursor);
|
||||||
builder.append(closure.head).append(identifierString);
|
|
||||||
|
|
||||||
if (identified) {
|
} while (startPlaceholder != -1);
|
||||||
builder.append('_');
|
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(parametersString).append(closure.tail);
|
if (cursor < length) {
|
||||||
continue;
|
builder.append(text, cursor, length);
|
||||||
}
|
|
||||||
|
|
||||||
builder.append(replacement);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
"Description": "An awesome placeholder provider",
|
"Description": "An awesome placeholder provider",
|
||||||
"Authors": [{"Name": "HelpChat"}],
|
"Authors": [{"Name": "HelpChat"}],
|
||||||
"Website": "https://placeholderapi.com",
|
"Website": "https://placeholderapi.com",
|
||||||
"ServerVersion": "*",
|
"ServerVersion": "2026.03.26-89796e57b",
|
||||||
"Dependencies": {},
|
"Dependencies": {},
|
||||||
"OptionalDependencies": {},
|
"OptionalDependencies": {},
|
||||||
"DisabledByDefault": false,
|
"DisabledByDefault": false,
|
||||||
|
|||||||
Reference in New Issue
Block a user