This commit is contained in:
PiggyPiglet
2026-02-20 21:06:02 +08:00
14 changed files with 190 additions and 161 deletions

View File

@@ -7,7 +7,7 @@ plugins {
} }
group = "at.helpch" group = "at.helpch"
version = "1.0.7-DEV-${System.getProperty("BUILD_NUMBER")}-CurseForge" version = "1.0.7-CurseForge"
description = "An awesome placeholder provider!" description = "An awesome placeholder provider!"
@@ -15,15 +15,13 @@ repositories {
mavenCentral() mavenCentral()
mavenLocal() mavenLocal()
maven { maven("https://maven.hytale.com/release/")
url = uri("https://repo.codemc.io/repository/hytale/")
}
} }
dependencies { dependencies {
implementation("org.yaml:snakeyaml:2.5") implementation("org.yaml:snakeyaml:2.5")
compileOnly("com.hypixel.hytale:Server:2026.01.17-4b0f30090") compileOnly("com.hypixel.hytale:Server:latest.release")
compileOnlyApi("org.jetbrains:annotations:23.0.0") compileOnlyApi("org.jetbrains:annotations:23.0.0")
} }

View File

@@ -2,6 +2,7 @@ package at.helpch.placeholderapi;
import at.helpch.placeholderapi.commands.PlaceholderCommandRouter; import at.helpch.placeholderapi.commands.PlaceholderCommandRouter;
import at.helpch.placeholderapi.configuration.ConfigManager; import at.helpch.placeholderapi.configuration.ConfigManager;
import at.helpch.placeholderapi.expansion.PlaceholderExpansion;
import at.helpch.placeholderapi.expansion.manager.CloudExpansionManager; import at.helpch.placeholderapi.expansion.manager.CloudExpansionManager;
import at.helpch.placeholderapi.expansion.manager.LocalExpansionManager; import at.helpch.placeholderapi.expansion.manager.LocalExpansionManager;
import at.helpch.placeholderapi.metrics.MetricsManager; import at.helpch.placeholderapi.metrics.MetricsManager;
@@ -78,6 +79,12 @@ public class PlaceholderAPIPlugin extends JavaPlugin {
configManager.setup(); configManager.setup();
localExpansionManager.load(sender); localExpansionManager.load(sender);
for (final PlaceholderExpansion expansion : localExpansionManager.getExpansions()) {
if (expansion.getExpansionType() == PlaceholderExpansion.Type.INTERNAL) {
// when the config gets reloaded, getConfig for internal expansions will return a map instead of the correct object
localExpansionManager.createConfig(expansion);
}
}
if (configManager.config().cloudEnabled()) { if (configManager.config().cloudEnabled()) {
cloudExpansionManager.load(); cloudExpansionManager.load();

View File

@@ -101,7 +101,7 @@ public final class PlaceholderCommandRouter extends AbstractCommand {
final PlaceholderCommand target = commands.get(search); final PlaceholderCommand target = commands.get(search);
if (target == null) { if (target == null) {
sender.sendMessage(Message.raw("Unknown command ").color(Color.RED).insert(Message.raw(search).color(Color.GRAY))); sender.sendMessage(Message.raw("Unknown command ").color(Color.RED).insert(Message.raw(search).color(Color.LIGHT_GRAY)));
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }

View File

@@ -78,9 +78,9 @@ public final class CommandECloud extends PlaceholderCommand {
if (params.isEmpty()) { if (params.isEmpty()) {
Message message = Message.empty() Message message = Message.empty()
.insert(Message.raw("PlaceholderAPI ").color(Color.CYAN).bold(true)) .insert(Message.raw("PlaceholderAPI ").color(Color.CYAN).bold(true))
.insert(Message.raw("- ").color(Color.DARK_GRAY)) .insert(Message.raw("- ").color(Color.GRAY))
.insert(Message.raw("eCloud Help Menu ").color(Color.GRAY)) .insert(Message.raw("eCloud Help Menu ").color(Color.LIGHT_GRAY))
.insert(Message.raw("-\n").color(Color.DARK_GRAY)); .insert(Message.raw("-\n").color(Color.GRAY));
final List<String[]> commands = List.of( final List<String[]> commands = List.of(
new String[]{"ecloud status", "View status of the eCloud"}, new String[]{"ecloud status", "View status of the eCloud"},
@@ -96,7 +96,7 @@ public final class CommandECloud extends PlaceholderCommand {
for (String[] command : commands) { for (String[] command : commands) {
message = message.insert(Message.raw("\n/papi ").color(Color.CYAN)) message = message.insert(Message.raw("\n/papi ").color(Color.CYAN))
.insert(Message.raw(command[0]).color(Color.WHITE)) .insert(Message.raw(command[0]).color(Color.WHITE))
.insert(Message.raw("\n " + command[1]).color(Color.GRAY)); .insert(Message.raw("\n " + command[1]).color(Color.LIGHT_GRAY));
} }
sender.sendMessage(message); sender.sendMessage(message);
@@ -128,7 +128,7 @@ public final class CommandECloud extends PlaceholderCommand {
final PlaceholderCommand target = commands.get(search); final PlaceholderCommand target = commands.get(search);
if (target == null) { if (target == null) {
sender.sendMessage(Message.raw("Unknown command ").color(Color.RED).insert(Message.raw("ecloud " + search).color(Color.GRAY))); sender.sendMessage(Message.raw("Unknown command ").color(Color.RED).insert(Message.raw("ecloud " + search).color(Color.LIGHT_GRAY)));
// Msg.msg(sender, "&cUnknown command &7ecloud " + search); // Msg.msg(sender, "&cUnknown command &7ecloud " + search);
return; return;
} }

View File

@@ -39,15 +39,14 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
private static final int PAGE_SIZE = 10; private static final int PAGE_SIZE = 10;
@NotNull @NotNull
private static final Function<CloudExpansion, String> EXPANSION_LATEST_VERSION = private static final Function<CloudExpansion, String> EXPANSION_LATEST_VERSION =
CloudExpansion::getLatestVersion; CloudExpansion::getLatestVersion;
@NotNull @NotNull
private static final Function<CloudExpansion, String> EXPANSION_CURRENT_VERSION = private static final Function<CloudExpansion, String> EXPANSION_CURRENT_VERSION =
expansion -> PlaceholderAPIPlugin.instance().localExpansionManager() expansion -> PlaceholderAPIPlugin.instance().localExpansionManager()
.findExpansionByName(expansion.getName()).map(PlaceholderExpansion::getVersion) .findExpansionByName(expansion.getName()).map(PlaceholderExpansion::getVersion)
.orElse("Unknown"); .orElse("Unknown");
@Unmodifiable @Unmodifiable
private static final Set<String> OPTIONS = Set.of("all", "installed"); private static final Set<String> OPTIONS = Set.of("all", "installed");
@@ -105,7 +104,7 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
return title return title
.insert(Message.raw(" Page").color(Color.CYAN)) .insert(Message.raw(" Page").color(Color.CYAN))
.insert(Message.raw(": ").color(Color.GRAY)) .insert(Message.raw(": ").color(Color.LIGHT_GRAY))
.insert(Message.raw(String.valueOf(page)).color(Color.GREEN)); .insert(Message.raw(String.valueOf(page)).color(Color.GREEN));
} }
@@ -118,7 +117,7 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
Message line = Message.empty(); Message line = Message.empty();
final int expansionNumber = index + ((page - 1) * PAGE_SIZE) + 1; final int expansionNumber = index + ((page - 1) * PAGE_SIZE) + 1;
line = line.insert(Message.raw(expansionNumber + ". ").color(Color.DARK_GRAY)); line = line.insert(Message.raw(expansionNumber + ". ").color(Color.GRAY));
final Color expansionColour; final Color expansionColour;
@@ -128,7 +127,7 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
if (expansion.hasExpansion()) { if (expansion.hasExpansion()) {
expansionColour = Color.GREEN; expansionColour = Color.GREEN;
} else { } else {
expansionColour = Color.GRAY; expansionColour = Color.LIGHT_GRAY;
} }
} }
@@ -175,7 +174,17 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
// right.clickEvent(ClickEvent.runCommand("/papi ecloud list " + target + " " + (page + 1))); // right.clickEvent(ClickEvent.runCommand("/papi ecloud list " + target + " " + (page + 1)));
// } // }
message = message.insert(Message.raw(" - " + page + " of " + limit + " - ").color(Color.GREEN)); message = message
.insert(Message.raw(" - ").color(Color.LIGHT_GRAY))
.insert(Message.raw(page + " of " + limit).color(Color.GREEN))
.insert(Message.raw(" - ").color(Color.LIGHT_GRAY))
.insert(Message.raw("[").color(Color.GRAY))
.insert(Message.raw("Available").color(Color.LIGHT_GRAY))
.insert(Message.raw(", ").color(Color.GRAY))
.insert(Message.raw("Installed").color(Color.GREEN))
.insert(Message.raw(", ").color(Color.GRAY))
.insert(Message.raw("Update Available").color(Color.YELLOW))
.insert(Message.raw("]").color(Color.GRAY));
} }
return message; return message;
@@ -220,7 +229,7 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
message = message.insert(Message.raw("\n")); message = message.insert(Message.raw("\n"));
final int separatorLength = Arrays.stream(widths).sum() + (columnCount * 2); final int separatorLength = Arrays.stream(widths).sum() + (columnCount * 2);
message = message.insert(Message.raw("-".repeat(separatorLength)).color(Color.DARK_GRAY)); message = message.insert(Message.raw("-".repeat(separatorLength)).color(Color.GRAY));
if (rows.size() > 1) { if (rows.size() > 1) {
message = message.insert(Message.raw("\n")); message = message.insert(Message.raw("\n"));
@@ -232,10 +241,10 @@ public final class CommandECloudExpansionList extends PlaceholderCommand {
final Color nameColor = expansion.shouldUpdate() final Color nameColor = expansion.shouldUpdate()
? Color.YELLOW ? Color.YELLOW
: (expansion.hasExpansion() ? Color.GREEN : Color.GRAY); : (expansion.hasExpansion() ? Color.GREEN : Color.LIGHT_GRAY);
final List<Color> rowColors = List.of( final List<Color> rowColors = List.of(
Color.DARK_GRAY, Color.GRAY,
nameColor, nameColor,
Color.WHITE, Color.WHITE,
expansion.getVersion().isVerified() ? Color.GREEN : Color.RED, expansion.getVersion().isVerified() ? Color.GREEN : Color.RED,

View File

@@ -75,7 +75,7 @@ public final class CommandECloudExpansionPlaceholders extends PlaceholderCommand
Message message = Message.raw(" ").color(Color.ORANGE) Message message = Message.raw(" ").color(Color.ORANGE)
.insert(Message.raw(String.valueOf(placeholders.size())).color(Color.ORANGE)) .insert(Message.raw(String.valueOf(placeholders.size())).color(Color.ORANGE))
.insert(Message.raw(" placeholders: ").color(Color.GRAY)); .insert(Message.raw(" placeholders: ").color(Color.LIGHT_GRAY));
for (int i = 0; i < partitions.size(); i++) { for (int i = 0; i < partitions.size(); i++) {
if (i == 0) { if (i == 0) {
@@ -86,7 +86,7 @@ public final class CommandECloudExpansionPlaceholders extends PlaceholderCommand
for (int j = 0; j < partition.size(); j++) { for (int j = 0; j < partition.size(); j++) {
message = message.insert(Message.raw(partition.get(j)).color(Color.GREEN)); message = message.insert(Message.raw(partition.get(j)).color(Color.GREEN));
if (j < partition.size() - 1) { if (j < partition.size() - 1) {
message = message.insert(Message.raw(", ").color(Color.GRAY)); message = message.insert(Message.raw(", ").color(Color.LIGHT_GRAY));
} }
} }

View File

@@ -51,9 +51,9 @@ public final class CommandECloudStatus extends PlaceholderCommand {
Message message = Message.raw("There are ").color(Color.CYAN) Message message = Message.raw("There are ").color(Color.CYAN)
.insert(Message.raw(String.valueOf(expansionCount)).color(Color.GREEN)) .insert(Message.raw(String.valueOf(expansionCount)).color(Color.GREEN))
.insert(Message.raw(" expansions available on the eCloud.\n").color(Color.CYAN)) .insert(Message.raw(" expansions available on the eCloud.\n").color(Color.CYAN))
.insert(Message.raw("A total of ").color(Color.GRAY)) .insert(Message.raw("A total of ").color(Color.LIGHT_GRAY))
.insert(Message.raw(String.valueOf(authorCount)).color(Color.WHITE)) .insert(Message.raw(String.valueOf(authorCount)).color(Color.WHITE))
.insert(Message.raw(" authors have contributed Hytale expansions to the eCloud.\n").color(Color.GRAY)); .insert(Message.raw(" authors have contributed Hytale expansions to the eCloud.\n").color(Color.LIGHT_GRAY));
if (updateCount > 0) { if (updateCount > 0) {
message = message message = message

View File

@@ -48,12 +48,12 @@ public final class CommandHelp extends PlaceholderCommand {
// final PluginDescriptionFile description = plugin.getDescription(); // final PluginDescriptionFile description = plugin.getDescription();
final Message message = Message.raw("PlaceholderAPI ").color(Color.CYAN).bold(true) final Message message = Message.raw("PlaceholderAPI ").color(Color.CYAN).bold(true)
.insert(Message.raw("- ").color(Color.DARK_GRAY).bold(false)) .insert(Message.raw("- ").color(Color.GRAY).bold(false))
.insert(Message.raw("Help Menu ").color(Color.WHITE).bold(false)) .insert(Message.raw("Help Menu ").color(Color.WHITE).bold(false))
.insert(Message.raw("- ").color(Color.DARK_GRAY).bold(false)) .insert(Message.raw("- ").color(Color.GRAY).bold(false))
.insert(Message.raw("(").color(Color.GRAY).bold(false)) .insert(Message.raw("(").color(Color.LIGHT_GRAY).bold(false))
.insert(Message.raw(description.getVersion().toString()).color(Color.WHITE).bold(false)) .insert(Message.raw(description.getVersion().toString()).color(Color.WHITE).bold(false))
.insert(Message.raw(")").color(Color.GRAY).bold(false)) .insert(Message.raw(")").color(Color.LIGHT_GRAY).bold(false))
.insert(Message.raw("\n")) .insert(Message.raw("\n"))
.insert(genCommandMsg("bcparse", "<me|--null|player name> <message>", "Parse a message with placeholders and broadcast it")) .insert(genCommandMsg("bcparse", "<me|--null|player name> <message>", "Parse a message with placeholders and broadcast it"))
.insert(genCommandMsg("cmdparse", "<me|player> <command with placeholders>", "Parse a message with relational placeholders")) .insert(genCommandMsg("cmdparse", "<me|player> <command with placeholders>", "Parse a message with relational placeholders"))
@@ -107,6 +107,6 @@ public final class CommandHelp extends PlaceholderCommand {
} }
return message return message
.insert(Message.raw("\n " + description).color(Color.gray).bold(false)); .insert(Message.raw("\n " + description).color(Color.LIGHT_GRAY).bold(false));
} }
} }

View File

@@ -59,15 +59,15 @@ public final class CommandInfo extends PlaceholderCommand {
} }
Message message = Message.empty() Message message = Message.empty()
.insert(Message.raw("Placeholder expansion info for:").color(Color.GRAY)) .insert(Message.raw("Placeholder expansion info for:").color(Color.LIGHT_GRAY))
.insert(Message.raw(expansion.getName() + "\n").color(Color.WHITE)) .insert(Message.raw(expansion.getName() + "\n").color(Color.WHITE))
.insert(Message.raw("Status: ").color(Color.GRAY)) .insert(Message.raw("Status: ").color(Color.LIGHT_GRAY))
.insert(Message.raw(expansion.isRegistered() ? "Registered" : "Not Registered").color(expansion.isRegistered() ? Color.GREEN : Color.RED)) .insert(Message.raw(expansion.isRegistered() ? "Registered" : "Not Registered").color(expansion.isRegistered() ? Color.GREEN : Color.RED))
.insert("\n"); .insert("\n");
final String author = expansion.getAuthor(); final String author = expansion.getAuthor();
if (author != null) { if (author != null) {
message = message.insert(Message.raw("Author: ").color(Color.GRAY)) message = message.insert(Message.raw("Author: ").color(Color.LIGHT_GRAY))
.insert(Message.raw(author + "\n").color(Color.WHITE)); .insert(Message.raw(author + "\n").color(Color.WHITE));
// builder.append("&7Author: &r") // builder.append("&7Author: &r")
// .append(author) // .append(author)
@@ -76,7 +76,7 @@ public final class CommandInfo extends PlaceholderCommand {
final String version = expansion.getVersion(); final String version = expansion.getVersion();
if (version != null) { if (version != null) {
message = message.insert(Message.raw("Version: ").color(Color.GRAY)) message = message.insert(Message.raw("Version: ").color(Color.LIGHT_GRAY))
.insert(Message.raw(version + "\n").color(Color.WHITE)); .insert(Message.raw(version + "\n").color(Color.WHITE));
// builder.append("&7Version: &r") // builder.append("&7Version: &r")
@@ -86,7 +86,7 @@ public final class CommandInfo extends PlaceholderCommand {
final String requiredPlugin = expansion.getRequiredPlugin(); final String requiredPlugin = expansion.getRequiredPlugin();
if (requiredPlugin != null) { if (requiredPlugin != null) {
message = message.insert(Message.raw("Requires plugin: ").color(Color.GRAY)) message = message.insert(Message.raw("Requires plugin: ").color(Color.LIGHT_GRAY))
.insert(Message.raw(requiredPlugin + '\n').color(Color.WHITE)); .insert(Message.raw(requiredPlugin + '\n').color(Color.WHITE));
// builder.append("&7Requires plugin: &r") // builder.append("&7Requires plugin: &r")
@@ -96,9 +96,9 @@ public final class CommandInfo extends PlaceholderCommand {
final List<String> placeholders = expansion.getPlaceholders(); final List<String> placeholders = expansion.getPlaceholders();
if (placeholders != null && !placeholders.isEmpty()) { if (placeholders != null && !placeholders.isEmpty()) {
message = message.insert(Message.raw("-- ").color(Color.DARK_GRAY)) message = message.insert(Message.raw("-- ").color(Color.GRAY))
.insert(Message.raw("Placeholders ").color(Color.GRAY)) .insert(Message.raw("Placeholders ").color(Color.LIGHT_GRAY))
.insert(Message.raw("--\n").color(Color.DARK_GRAY)); .insert(Message.raw("--\n").color(Color.GRAY));
// builder.append("&8&m-- &7Placeholders &8&m--&r") // builder.append("&8&m-- &7Placeholders &8&m--&r")
// .append('\n'); // .append('\n');

View File

@@ -58,9 +58,9 @@ public final class CommandList extends PlaceholderCommand {
// final List<List<String>> partitions = Lists // final List<List<String>> partitions = Lists
// .partition(identifiers.stream().sorted().collect(Collectors.toList()), 10); // .partition(identifiers.stream().sorted().collect(Collectors.toList()), 10);
Message message = Message.raw("A total of ").color(Color.GRAY) Message message = Message.raw("A total of ").color(Color.LIGHT_GRAY)
.insert(Message.raw(identifiers.size() + " ").color(Color.WHITE)) .insert(Message.raw(identifiers.size() + " ").color(Color.WHITE))
.insert(Message.raw("placeholder hook(s) are active: ").color(Color.GRAY)); .insert(Message.raw("placeholder hook(s) are active: ").color(Color.LIGHT_GRAY));
for (int i = 0; i < partitions.size(); ++i) { for (int i = 0; i < partitions.size(); ++i) {
final List<String> partition = partitions.get(i); final List<String> partition = partitions.get(i);
@@ -69,7 +69,7 @@ public final class CommandList extends PlaceholderCommand {
message = message.insert(Message.raw(partition.get(j)).color(Color.GREEN)); message = message.insert(Message.raw(partition.get(j)).color(Color.GREEN));
if (j != partition.size() - 1) { if (j != partition.size() - 1) {
message = message.insert(Message.raw(", ").color(Color.GRAY)); message = message.insert(Message.raw(", ").color(Color.LIGHT_GRAY));
} }
} }

View File

@@ -29,13 +29,17 @@ import at.helpch.placeholderapi.PlaceholderAPI;
import at.helpch.placeholderapi.PlaceholderAPIPlugin; import at.helpch.placeholderapi.PlaceholderAPIPlugin;
import at.helpch.placeholderapi.commands.PlaceholderCommand; import at.helpch.placeholderapi.commands.PlaceholderCommand;
import at.helpch.placeholderapi.expansion.PlaceholderExpansion; import at.helpch.placeholderapi.expansion.PlaceholderExpansion;
import com.hypixel.hytale.component.Ref;
import com.hypixel.hytale.component.Store;
import com.hypixel.hytale.server.core.Message; import com.hypixel.hytale.server.core.Message;
import com.hypixel.hytale.server.core.NameMatching; import com.hypixel.hytale.server.core.NameMatching;
import com.hypixel.hytale.server.core.command.system.CommandSender; import com.hypixel.hytale.server.core.command.system.CommandSender;
import com.hypixel.hytale.server.core.entity.Entity;
import com.hypixel.hytale.server.core.entity.entities.Player; 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 com.hypixel.hytale.server.core.universe.Universe; import com.hypixel.hytale.server.core.universe.Universe;
import com.hypixel.hytale.server.core.universe.world.World; import com.hypixel.hytale.server.core.universe.world.World;
import com.hypixel.hytale.server.core.universe.world.storage.EntityStore;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.Unmodifiable; import org.jetbrains.annotations.Unmodifiable;
@@ -94,7 +98,7 @@ public final class CommandParse extends PlaceholderCommand {
sender.sendMessage(Message.raw("You must provide a target and a message: ").color(Color.RED) sender.sendMessage(Message.raw("You must provide a target and a message: ").color(Color.RED)
.insert(Message.raw("/papi ").color(Color.CYAN)) .insert(Message.raw("/papi ").color(Color.CYAN))
.insert(Message.raw(command ? "cmdparse" : (broadcast ? "bcparse" : "parse")).color(Color.CYAN)) .insert(Message.raw(command ? "cmdparse" : (broadcast ? "bcparse" : "parse")).color(Color.CYAN))
.insert(Message.raw(" {target}").color(Color.GRAY)) .insert(Message.raw(" {target}").color(Color.LIGHT_GRAY))
.insert(Message.raw(" {message}").color(Color.GREEN))); .insert(Message.raw(" {message}").color(Color.GREEN)));
return; return;
} }
@@ -103,12 +107,12 @@ public final class CommandParse extends PlaceholderCommand {
if ("me".equalsIgnoreCase(params.getFirst())) { if ("me".equalsIgnoreCase(params.getFirst())) {
if (!(sender instanceof Player) && !(sender instanceof PlayerRef)) { if (!(sender instanceof Player) && !(sender instanceof PlayerRef)) {
sender.sendMessage(Message.raw("You must be a player to use ").color(Color.RED).insert(Message.raw("me").color(Color.GRAY)).insert(Message.raw(" as a target!").color(Color.RED))); sender.sendMessage(Message.raw("You must be a player to use ").color(Color.RED).insert(Message.raw("me").color(Color.LIGHT_GRAY)).insert(Message.raw(" as a target!").color(Color.RED)));
return; return;
} }
if (sender instanceof Player) { if (sender instanceof Player) {
player = ((Player) sender).getPlayerRef(); player = getPlayerRef((Player) sender);
} else { } else {
player = (PlayerRef) sender; player = (PlayerRef) sender;
} }
@@ -144,7 +148,7 @@ public final class CommandParse extends PlaceholderCommand {
if (params.size() < 3) { if (params.size() < 3) {
sender.sendMessage(Message.raw("You must supply two targets, and a message: ").color(Color.RED) sender.sendMessage(Message.raw("You must supply two targets, and a message: ").color(Color.RED)
.insert(Message.raw("/papi parserel ").color(Color.CYAN)) .insert(Message.raw("/papi parserel ").color(Color.CYAN))
.insert(Message.raw("{target one} {target two} ").color(Color.GRAY)) .insert(Message.raw("{target one} {target two} ").color(Color.LIGHT_GRAY))
.insert(Message.raw("{message}").color(Color.GREEN))); .insert(Message.raw("{message}").color(Color.GREEN)));
return; return;
} }
@@ -154,13 +158,13 @@ public final class CommandParse extends PlaceholderCommand {
if ("me".equalsIgnoreCase(params.get(0))) { if ("me".equalsIgnoreCase(params.get(0))) {
if (!(sender instanceof Player) && !(sender instanceof PlayerRef)) { if (!(sender instanceof Player) && !(sender instanceof PlayerRef)) {
sender.sendMessage(Message.raw("You must be a player to use ").color(Color.RED) sender.sendMessage(Message.raw("You must be a player to use ").color(Color.RED)
.insert(Message.raw("me").color(Color.GRAY)) .insert(Message.raw("me").color(Color.LIGHT_GRAY))
.insert(Message.raw(" as a target!").color(Color.RED))); .insert(Message.raw(" as a target!").color(Color.RED)));
return; return;
} }
if (sender instanceof Player) { if (sender instanceof Player) {
playerOne = ((Player) sender).getPlayerRef(); playerOne = getPlayerRef((Player) sender);
} else { } else {
playerOne = (PlayerRef) sender; playerOne = (PlayerRef) sender;
} }
@@ -177,12 +181,12 @@ public final class CommandParse extends PlaceholderCommand {
if ("me".equalsIgnoreCase(params.get(1))) { if ("me".equalsIgnoreCase(params.get(1))) {
if (!(sender instanceof Player) && !(sender instanceof PlayerRef)) { if (!(sender instanceof Player) && !(sender instanceof PlayerRef)) {
sender.sendMessage(Message.raw("You must be a player to use ").color(Color.RED).insert(Message.raw("me").color(Color.GRAY)).insert(Message.raw(" as a target!").color(Color.RED))); sender.sendMessage(Message.raw("You must be a player to use ").color(Color.RED).insert(Message.raw("me").color(Color.LIGHT_GRAY)).insert(Message.raw(" as a target!").color(Color.RED)));
return; return;
} }
if (sender instanceof Player) { if (sender instanceof Player) {
playerTwo = ((Player) sender).getPlayerRef(); playerTwo = getPlayerRef((Player) sender);
} else { } else {
playerTwo = (PlayerRef) sender; playerTwo = (PlayerRef) sender;
} }
@@ -276,4 +280,16 @@ public final class CommandParse extends PlaceholderCommand {
return Universe.get().getPlayerByUsername(name, NameMatching.EXACT); return Universe.get().getPlayerByUsername(name, NameMatching.EXACT);
} }
@Nullable
private static PlayerRef getPlayerRef(@NotNull final Player player) {
final Ref<EntityStore> ref = player.getReference();
if (ref == null || !ref.isValid()) {
return null;
}
final Store<EntityStore> store = ref.getStore();
return store.getComponent(ref, PlayerRef.getComponentType());
}
} }

View File

@@ -49,15 +49,15 @@ public final class CommandVersion extends PlaceholderCommand {
sender.sendMessage(Message.empty() sender.sendMessage(Message.empty()
.insert(Message.raw("PlaceholderAPI ").color(Color.CYAN).bold(true)) .insert(Message.raw("PlaceholderAPI ").color(Color.CYAN).bold(true))
.insert(Message.raw("(").color(Color.GRAY)) .insert(Message.raw("(").color(Color.LIGHT_GRAY))
.insert(Message.raw(description.getVersion().toString()).color(Color.WHITE)) .insert(Message.raw(description.getVersion().toString()).color(Color.WHITE))
.insert(Message.raw(")").color(Color.GRAY)) .insert(Message.raw(")").color(Color.LIGHT_GRAY))
.insert(Message.raw("\nAuthor: ").color(Color.GRAY)) .insert(Message.raw("\nAuthor: ").color(Color.LIGHT_GRAY))
.insert(Message.raw(description.getAuthors().stream().map(AuthorInfo::getName).collect(Collectors.joining(", "))).color(Color.WHITE)) .insert(Message.raw(description.getAuthors().stream().map(AuthorInfo::getName).collect(Collectors.joining(", "))).color(Color.WHITE))
.insert(Message.raw("\nPAPI Commands: ").color(Color.GRAY)) .insert(Message.raw("\nPAPI Commands: ").color(Color.LIGHT_GRAY))
.insert(Message.raw("/papi ").color(Color.CYAN)) .insert(Message.raw("/papi ").color(Color.CYAN))
.insert(Message.raw("help").color(Color.WHITE)) .insert(Message.raw("help").color(Color.WHITE))
.insert(Message.raw("\neCloud Commands: ").color(Color.GRAY)) .insert(Message.raw("\neCloud Commands: ").color(Color.LIGHT_GRAY))
.insert(Message.raw("/papi ").color(Color.CYAN)) .insert(Message.raw("/papi ").color(Color.CYAN))
.insert(Message.raw("ecloud").color(Color.WHITE))); .insert(Message.raw("ecloud").color(Color.WHITE)));

View File

@@ -220,21 +220,7 @@ public final class LocalExpansionManager /*implements Listener*/ {
public boolean register(@NotNull final PlaceholderExpansion expansion) { public boolean register(@NotNull final PlaceholderExpansion expansion) {
final String identifier = expansion.getIdentifier().toLowerCase(Locale.ROOT); final String identifier = expansion.getIdentifier().toLowerCase(Locale.ROOT);
if (expansion instanceof Configurable<?> configurable) { createConfig(expansion);
final PlaceholderAPIConfig config = configManager.config();
if (config.expansions() == null) {
config.expansions(new ConcurrentHashMap<>());
}
if (!config.expansions().containsKey(expansion.getIdentifier())) {
config.expansions().put(expansion.getIdentifier(), configurable.provideDefault());
configManager.save();
} else {
final Object expansionConfig = configManager.convertExpansion((Map<String, Object>) config.expansions().get(expansion.getIdentifier()), configurable.provideConfigType());
config.expansions().put(expansion.getIdentifier(), expansionConfig);
}
}
if (!expansion.canRegister()) { if (!expansion.canRegister()) {
return false; return false;
@@ -307,6 +293,33 @@ public final class LocalExpansionManager /*implements Listener*/ {
return true; return true;
} }
/**
* Creates and initializes the configuration for the provided {@link PlaceholderExpansion}.
* If the expansion implements the {@link Configurable} interface, this method ensures that
* the expansion's default configuration is registered and saved if it is not already present.
* If a configuration already exists, it converts and updates it using the provided configuration type.
*
* @param expansion the {@link PlaceholderExpansion} for which the configuration is being created
*/
@ApiStatus.Internal
public void createConfig(PlaceholderExpansion expansion) {
if (expansion instanceof Configurable<?> configurable) {
final PlaceholderAPIConfig config = configManager.config();
if (config.expansions() == null) {
config.expansions(new ConcurrentHashMap<>());
}
if (!config.expansions().containsKey(expansion.getIdentifier())) {
config.expansions().put(expansion.getIdentifier(), configurable.provideDefault());
configManager.save();
} else {
final Object expansionConfig = configManager.convertExpansion((Map<String, Object>) config.expansions().get(expansion.getIdentifier()), configurable.provideConfigType());
config.expansions().put(expansion.getIdentifier(), expansionConfig);
}
}
}
@ApiStatus.Internal @ApiStatus.Internal
public boolean unregister(@NotNull final PlaceholderExpansion expansion) { public boolean unregister(@NotNull final PlaceholderExpansion expansion) {
if (expansions.remove(expansion.getIdentifier().toLowerCase(Locale.ROOT)) == null) { if (expansions.remove(expansion.getIdentifier().toLowerCase(Locale.ROOT)) == null) {

View File

@@ -24,6 +24,7 @@ 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;
@@ -37,116 +38,101 @@ 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 head = closure.head; final char[] chars = text.toCharArray();
int startPlaceholder = text.indexOf(head); final StringBuilder builder = new StringBuilder(text.length());
if (startPlaceholder == -1) { final StringBuilder identifier = new StringBuilder();
return text; final StringBuilder parameters = new StringBuilder();
}
final int length = text.length(); for (int i = 0; i < chars.length; i++) {
final StringBuilder builder = new StringBuilder(length + (length >> 3)); final char l = chars[i];
int cursor = 0;
final char tail = closure.tail; if (l != closure.head || i + 1 >= chars.length) {
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 == ' ') {
// Invalid placeholder (contains space).
// 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;
} }
String identifier = text.substring(startPlaceholder + 1, underscoreIndex); boolean identified = false;
String parameters = ""; boolean invalid = true;
boolean hadSpace = false;
if (underscoreIndex + 1 < endPlaceholder) { while (++i < chars.length) {
parameters = text.substring(underscoreIndex + 1, endPlaceholder); final char p = chars[i];
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 PlaceholderExpansion expansion = lookup.apply(identifier.toLowerCase(Locale.ROOT)); final String identifierString = identifier.toString();
String replacement = null; final String lowercaseIdentifierString = identifierString.toLowerCase(Locale.ROOT);
final String parametersString = parameters.toString();
if (expansion != null) { identifier.setLength(0);
replacement = expansion.onPlaceholderRequest(player, parameters); parameters.setLength(0);
if (invalid) {
builder.append(closure.head).append(identifierString);
if (identified) {
builder.append('_').append(parametersString);
}
if (hadSpace) {
builder.append(' ');
}
continue;
} }
if (replacement != null) { final PlaceholderExpansion placeholder = lookup.apply(lowercaseIdentifierString);
builder.append(replacement); if (placeholder == null) {
} else { builder.append(closure.head).append(identifierString);
// Fallback: Restore original placeholder format
builder.append(head).append(identifier); if (identified) {
builder.append('_').append(parameters); builder.append('_');
builder.append(tail); }
builder.append(parametersString).append(closure.tail);
continue;
} }
cursor = endPlaceholder + 1; final String replacement = placeholder.onPlaceholderRequest(player, parametersString);
startPlaceholder = text.indexOf(head, cursor); if (replacement == null) {
builder.append(closure.head).append(identifierString);
} while (startPlaceholder != -1); if (identified) {
builder.append('_');
}
if (cursor < length) { builder.append(parametersString).append(closure.tail);
builder.append(text, cursor, length); continue;
}
builder.append(replacement);
} }
return builder.toString(); return builder.toString();
} }
} }