mirror of
https://github.com/filoghost/HolographicDisplays.git
synced 2024-11-15 23:15:10 +01:00
Improve and refactor individual placeholders
This commit is contained in:
parent
5543edd47b
commit
eeec178e65
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.api.placeholder;
|
||||
|
||||
/**
|
||||
* @since 1
|
||||
*/
|
||||
public interface IndividualPlaceholder extends IndividualPlaceholderReplacer {
|
||||
|
||||
/**
|
||||
* @since 1
|
||||
*/
|
||||
int getRefreshIntervalTicks();
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.api.placeholder;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @since 1
|
||||
*/
|
||||
public interface IndividualPlaceholderFactory {
|
||||
|
||||
/**
|
||||
* @since 1
|
||||
*/
|
||||
@Nullable IndividualPlaceholder getPlaceholder(@Nullable String argument);
|
||||
|
||||
}
|
@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.api.placeholder;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* @since 1
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface IndividualPlaceholderReplacer {
|
||||
|
||||
/**
|
||||
* @since 1
|
||||
*/
|
||||
@Nullable String getReplacement(@NotNull Player player, @Nullable String argument);
|
||||
|
||||
}
|
@ -41,11 +41,22 @@ public class DefaultHolographicDisplaysAPI implements HolographicDisplaysAPI {
|
||||
|
||||
@Override
|
||||
public void registerPlaceholder(@NotNull String identifier, int refreshIntervalTicks, @NotNull PlaceholderReplacer replacer) {
|
||||
Preconditions.notNull(identifier, "identifier");
|
||||
Preconditions.notEmpty(identifier, "identifier");
|
||||
for (char c : identifier.toCharArray()) {
|
||||
Preconditions.checkArgument(isValidIdentifierCharacter(c), "identifier contains invalid character '" + c + "'");
|
||||
}
|
||||
Preconditions.checkArgument(refreshIntervalTicks >= 0, "refreshIntervalTicks should be positive");
|
||||
Preconditions.notNull(replacer, "replacer");
|
||||
|
||||
placeholderRegistry.registerReplacer(plugin, identifier, refreshIntervalTicks, replacer);
|
||||
placeholderRegistry.registerGlobalPlaceholderReplacer(plugin, identifier, refreshIntervalTicks, replacer);
|
||||
}
|
||||
|
||||
private boolean isValidIdentifierCharacter(char c) {
|
||||
return ('a' <= c && c <= 'z')
|
||||
|| ('A' <= c && c <= 'Z')
|
||||
|| ('0' <= c && c <= '9')
|
||||
|| c == '-'
|
||||
|| c == '_';
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -31,7 +31,10 @@ import me.filoghost.holographicdisplays.object.api.APIHologram;
|
||||
import me.filoghost.holographicdisplays.object.api.APIHologramManager;
|
||||
import me.filoghost.holographicdisplays.object.internal.InternalHologram;
|
||||
import me.filoghost.holographicdisplays.object.internal.InternalHologramManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderTracker;
|
||||
import me.filoghost.holographicdisplays.placeholder.TickClock;
|
||||
import me.filoghost.holographicdisplays.placeholder.TickingTask;
|
||||
import me.filoghost.holographicdisplays.placeholder.internal.AnimationRegistry;
|
||||
import me.filoghost.holographicdisplays.placeholder.internal.DefaultPlaceholders;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderRegistry;
|
||||
@ -52,7 +55,7 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
private APIHologramManager apiHologramManager;
|
||||
private BungeeServerTracker bungeeServerTracker;
|
||||
private AnimationRegistry animationRegistry;
|
||||
private PlaceholderManager placeholderManager;
|
||||
private PlaceholderRegistry placeholderRegistry;
|
||||
|
||||
@Override
|
||||
public void onCheckedEnable() throws PluginEnableException {
|
||||
@ -94,12 +97,15 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
throw new PluginEnableException(e, "Couldn't initialize the NMS manager.");
|
||||
}
|
||||
|
||||
configManager = new ConfigManager(getDataFolder().toPath());
|
||||
bungeeServerTracker = new BungeeServerTracker(this);
|
||||
animationRegistry = new AnimationRegistry();
|
||||
placeholderManager = new PlaceholderManager();
|
||||
configManager = new ConfigManager(getDataFolder().toPath());
|
||||
internalHologramManager = new InternalHologramManager(nmsManager, placeholderManager);
|
||||
apiHologramManager = new APIHologramManager(nmsManager, placeholderManager);
|
||||
placeholderRegistry = new PlaceholderRegistry();
|
||||
TickClock tickClock = new TickClock();
|
||||
PlaceholderTracker placeholderTracker = new PlaceholderTracker(placeholderRegistry, tickClock);
|
||||
PlaceholderLineTracker placeholderLineTracker = new PlaceholderLineTracker(placeholderTracker);
|
||||
internalHologramManager = new InternalHologramManager(nmsManager, placeholderLineTracker);
|
||||
apiHologramManager = new APIHologramManager(nmsManager, placeholderLineTracker);
|
||||
|
||||
PrintableErrorCollector errorCollector = new PrintableErrorCollector();
|
||||
|
||||
@ -109,14 +115,15 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
} catch (ConfigException e) {
|
||||
errorCollector.add(e, "couldn't automatically convert symbols file to the new format");
|
||||
}
|
||||
|
||||
load(true, errorCollector);
|
||||
|
||||
ProtocolLibHook.setup(this, nmsManager, this, errorCollector);
|
||||
PlaceholderAPIHook.setup();
|
||||
|
||||
placeholderManager.startUpdaterTask(this);
|
||||
|
||||
load(true, errorCollector);
|
||||
|
||||
ProtocolLibHook.setup(this, nmsManager, this, placeholderLineTracker, errorCollector);
|
||||
PlaceholderAPIHook.setup();
|
||||
|
||||
TickingTask tickingTask = new TickingTask(tickClock, placeholderLineTracker);
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(this, tickingTask, 0, 1);
|
||||
|
||||
HologramCommandManager commandManager = new HologramCommandManager(configManager, internalHologramManager, nmsManager);
|
||||
commandManager.register(this);
|
||||
|
||||
@ -127,14 +134,9 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
registerListener(updateNotificationListener);
|
||||
|
||||
// Enable the APIs
|
||||
HolographicDisplaysAPIProvider.setImplementation(new DefaultHolographicDisplaysAPIProvider(
|
||||
apiHologramManager,
|
||||
nmsManager,
|
||||
placeholderManager.getPlaceholderRegistry()));
|
||||
enableLegacyAPI(
|
||||
apiHologramManager,
|
||||
nmsManager,
|
||||
placeholderManager.getPlaceholderRegistry());
|
||||
HolographicDisplaysAPIProvider.setImplementation(
|
||||
new DefaultHolographicDisplaysAPIProvider(apiHologramManager, nmsManager, placeholderRegistry));
|
||||
enableLegacyAPI(apiHologramManager, nmsManager, placeholderRegistry);
|
||||
|
||||
// Register bStats metrics
|
||||
int pluginID = 3123;
|
||||
@ -157,7 +159,7 @@ public class HolographicDisplays extends FCommonsPlugin implements ProtocolPacke
|
||||
}
|
||||
|
||||
public void load(boolean deferHologramsCreation, ErrorCollector errorCollector) {
|
||||
DefaultPlaceholders.resetAndRegister(placeholderManager.getPlaceholderRegistry(), animationRegistry, bungeeServerTracker);
|
||||
DefaultPlaceholders.resetAndRegister(placeholderRegistry, animationRegistry, bungeeServerTracker);
|
||||
|
||||
internalHologramManager.clearAll();
|
||||
|
||||
|
@ -84,7 +84,7 @@ class MetadataHelper {
|
||||
}
|
||||
|
||||
|
||||
public WrappedWatchableObject getCustomNameWacthableObject(WrappedDataWatcher metadata) {
|
||||
public WrappedWatchableObject getCustomNameWatchableObject(WrappedDataWatcher metadata) {
|
||||
return metadata.getWatchableObject(customNameIndex);
|
||||
}
|
||||
|
||||
|
@ -22,11 +22,8 @@ import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.core.nms.ProtocolPacketSettings;
|
||||
import me.filoghost.holographicdisplays.core.nms.entity.NMSArmorStand;
|
||||
import me.filoghost.holographicdisplays.core.nms.entity.NMSEntity;
|
||||
import me.filoghost.holographicdisplays.placeholder.RelativePlaceholder;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholdersUpdateTask;
|
||||
import me.filoghost.holographicdisplays.placeholder.TrackedLine;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.StringWithPlaceholders;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderRegistry;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.TrackedLine;
|
||||
import me.filoghost.holographicdisplays.util.NMSVersion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
@ -36,10 +33,14 @@ class PacketListener extends PacketAdapter {
|
||||
private final NMSManager nmsManager;
|
||||
private final MetadataHelper metadataHelper;
|
||||
private final ProtocolPacketSettings packetSettings;
|
||||
PlaceholdersUpdateTask placeholdersUpdateTask;
|
||||
PlaceholderRegistry placeholderRegistry;
|
||||
private final PlaceholderLineTracker placeholderLineTracker;
|
||||
|
||||
PacketListener(Plugin plugin, NMSManager nmsManager, MetadataHelper metadataHelper, ProtocolPacketSettings packetSettings) {
|
||||
PacketListener(
|
||||
Plugin plugin,
|
||||
NMSManager nmsManager,
|
||||
MetadataHelper metadataHelper,
|
||||
ProtocolPacketSettings packetSettings,
|
||||
PlaceholderLineTracker placeholderLineTracker) {
|
||||
super(PacketAdapter.params()
|
||||
.plugin(plugin)
|
||||
.types(
|
||||
@ -54,6 +55,7 @@ class PacketListener extends PacketAdapter {
|
||||
this.nmsManager = nmsManager;
|
||||
this.metadataHelper = metadataHelper;
|
||||
this.packetSettings = packetSettings;
|
||||
this.placeholderLineTracker = placeholderLineTracker;
|
||||
}
|
||||
|
||||
public void registerListener() {
|
||||
@ -117,9 +119,9 @@ class PacketListener extends PacketAdapter {
|
||||
return;
|
||||
}
|
||||
|
||||
String customNameWithRelativePlaceholders = replaceRelativePlaceholders(textLine, customName, player);
|
||||
String customNameWithIndividualPlaceholders = replaceIndividualPlaceholders(textLine, customName, player);
|
||||
|
||||
if (customNameWithRelativePlaceholders.equals(customName)) {
|
||||
if (customNameWithIndividualPlaceholders.equals(customName)) {
|
||||
return; // No need to modify packets, custom name doesn't need changes
|
||||
}
|
||||
|
||||
@ -133,36 +135,26 @@ class PacketListener extends PacketAdapter {
|
||||
} else {
|
||||
WrapperPlayServerSpawnEntityLiving spawnEntityPacket = new WrapperPlayServerSpawnEntityLiving(packet.deepClone());
|
||||
packetWrapper = spawnEntityPacket;
|
||||
customNameWatchableObject = metadataHelper.getCustomNameWacthableObject(spawnEntityPacket.getMetadata());
|
||||
customNameWatchableObject = metadataHelper.getCustomNameWatchableObject(spawnEntityPacket.getMetadata());
|
||||
}
|
||||
|
||||
if (customNameWatchableObject == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object customNameNMSObject = nmsManager.createCustomNameNMSObject(customNameWithRelativePlaceholders);
|
||||
Object customNameNMSObject = nmsManager.createCustomNameNMSObject(customNameWithIndividualPlaceholders);
|
||||
metadataHelper.setCustomNameNMSObject(customNameWatchableObject, customNameNMSObject);
|
||||
event.setPacket(packetWrapper.getHandle());
|
||||
}
|
||||
}
|
||||
|
||||
private String replaceRelativePlaceholders(StandardTextLine textLine, String text, Player player) {
|
||||
TrackedLine trackedLine = placeholdersUpdateTask.getTrackedLine(textLine);
|
||||
private String replaceIndividualPlaceholders(StandardTextLine textLine, String text, Player player) {
|
||||
TrackedLine trackedLine = placeholderLineTracker.getTrackedLine(textLine);
|
||||
if (trackedLine == null) {
|
||||
return text;
|
||||
}
|
||||
|
||||
if (trackedLine.containsRelativePlaceholders()) {
|
||||
StringWithPlaceholders textWithPlaceholders = new StringWithPlaceholders(text);
|
||||
textWithPlaceholders.replacePlaceholders(placeholderOccurrence -> {
|
||||
RelativePlaceholder relativePlaceholder = placeholderRegistry.findRelative(placeholderOccurrence);
|
||||
if (relativePlaceholder != null) {
|
||||
return relativePlaceholder.getReplacement(player);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
text = trackedLine.replaceIndividualPlaceholders(player);
|
||||
|
||||
if (PlaceholderAPIHook.isEnabled() && PlaceholderAPIHook.containsPlaceholders(text)) {
|
||||
text = PlaceholderAPIHook.replacePlaceholders(player, text);
|
||||
|
@ -12,6 +12,7 @@ import me.filoghost.holographicdisplays.core.Utils;
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardHologram;
|
||||
import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.core.nms.ProtocolPacketSettings;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import me.filoghost.holographicdisplays.util.VersionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Location;
|
||||
@ -26,7 +27,12 @@ public class ProtocolLibHook {
|
||||
private static boolean enabled;
|
||||
private static PacketSender packetSender;
|
||||
|
||||
public static void setup(Plugin plugin, NMSManager nmsManager, ProtocolPacketSettings packetSettings, ErrorCollector errorCollector) {
|
||||
public static void setup(
|
||||
Plugin plugin,
|
||||
NMSManager nmsManager,
|
||||
ProtocolPacketSettings packetSettings,
|
||||
PlaceholderLineTracker placeholderLineTracker,
|
||||
ErrorCollector errorCollector) {
|
||||
if (!Bukkit.getPluginManager().isPluginEnabled("ProtocolLib")) {
|
||||
return;
|
||||
}
|
||||
@ -42,21 +48,21 @@ public class ProtocolLibHook {
|
||||
String versionNumbers = versionNumbersMatcher.group();
|
||||
|
||||
if (!VersionUtils.isVersionGreaterEqual(versionNumbers, "4.4")) {
|
||||
errorCollector.add("detected old unsupported version of ProtocolLib, support disabled."
|
||||
errorCollector.add("detected old unsupported version of ProtocolLib, support disabled."
|
||||
+ " You must use ProtocolLib 4.4.0 or higher");
|
||||
return;
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
errorCollector.add(e, "could not detect ProtocolLib version (" + e.getMessage() + "),"
|
||||
errorCollector.add(e, "could not detect ProtocolLib version (" + e.getMessage() + "),"
|
||||
+ " enabling support anyway and hoping for the best");
|
||||
}
|
||||
|
||||
try {
|
||||
MetadataHelper metadataHelper = new MetadataHelper();
|
||||
new PacketListener(plugin, nmsManager, metadataHelper, packetSettings).registerListener();
|
||||
new PacketListener(plugin, nmsManager, metadataHelper, packetSettings, placeholderLineTracker).registerListener();
|
||||
packetSender = new PacketSender(metadataHelper);
|
||||
Log.info("Enabled player relative placeholders with ProtocolLib.");
|
||||
Log.info("Enabled per-player placeholders with ProtocolLib.");
|
||||
} catch (Exception e) {
|
||||
errorCollector.add(e, "failed to load ProtocolLib support, is it updated?");
|
||||
return;
|
||||
|
@ -71,7 +71,11 @@ public class V2HologramsAPIProvider extends HologramsAPIProvider {
|
||||
boolean alreadyRegistered = placeholderRegistry.isRegisteredIdentifier(plugin, textPlaceholder);
|
||||
|
||||
if (!alreadyRegistered) {
|
||||
placeholderRegistry.registerReplacer(plugin, textPlaceholder, refreshIntervalTicks, argument -> replacer.update());
|
||||
placeholderRegistry.registerGlobalPlaceholderReplacer(
|
||||
plugin,
|
||||
textPlaceholder,
|
||||
refreshIntervalTicks,
|
||||
argument -> replacer.update());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
@ -11,7 +11,7 @@ import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
import me.filoghost.holographicdisplays.legacy.api.v2.V2HologramAdapter;
|
||||
import me.filoghost.holographicdisplays.object.base.BaseHologram;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -36,8 +36,8 @@ public class APIHologram extends BaseHologram<APIHologramLine> implements Hologr
|
||||
Plugin plugin,
|
||||
NMSManager nmsManager,
|
||||
APIHologramManager apiHologramManager,
|
||||
PlaceholderManager placeholderManager) {
|
||||
super(source, nmsManager, placeholderManager);
|
||||
PlaceholderLineTracker placeholderLineTracker) {
|
||||
super(source, nmsManager, placeholderLineTracker);
|
||||
Preconditions.notNull(plugin, "plugin");
|
||||
this.plugin = plugin;
|
||||
this.apiHologramManager = apiHologramManager;
|
||||
|
@ -8,7 +8,7 @@ package me.filoghost.holographicdisplays.object.api;
|
||||
import me.filoghost.holographicdisplays.api.Hologram;
|
||||
import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.object.base.BaseHologramManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
@ -20,15 +20,15 @@ import java.util.List;
|
||||
public class APIHologramManager extends BaseHologramManager<APIHologram> {
|
||||
|
||||
private final NMSManager nmsManager;
|
||||
private final PlaceholderManager placeholderManager;
|
||||
private final PlaceholderLineTracker placeholderLineTracker;
|
||||
|
||||
public APIHologramManager(NMSManager nmsManager, PlaceholderManager placeholderManager) {
|
||||
public APIHologramManager(NMSManager nmsManager, PlaceholderLineTracker placeholderLineTracker) {
|
||||
this.nmsManager = nmsManager;
|
||||
this.placeholderManager = placeholderManager;
|
||||
this.placeholderLineTracker = placeholderLineTracker;
|
||||
}
|
||||
|
||||
public APIHologram createHologram(Location source, Plugin plugin) {
|
||||
APIHologram hologram = new APIHologram(source, plugin, nmsManager, this, placeholderManager);
|
||||
APIHologram hologram = new APIHologram(source, plugin, nmsManager, this, placeholderLineTracker);
|
||||
super.addHologram(hologram);
|
||||
return hologram;
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ import me.filoghost.holographicdisplays.core.hologram.StandardHologram;
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardHologramLine;
|
||||
import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.disk.Configuration;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.World;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@ -23,14 +23,14 @@ import java.util.List;
|
||||
public abstract class BaseHologram<T extends StandardHologramLine> extends BaseHologramComponent implements StandardHologram {
|
||||
|
||||
private final NMSManager nmsManager;
|
||||
private final PlaceholderManager placeholderManager;
|
||||
private final PlaceholderLineTracker placeholderLineTracker;
|
||||
private final List<T> lines;
|
||||
private final List<T> unmodifiableLinesView;
|
||||
|
||||
private boolean deleted;
|
||||
|
||||
public BaseHologram(Location location, NMSManager nmsManager, PlaceholderManager placeholderManager) {
|
||||
this.placeholderManager = placeholderManager;
|
||||
public BaseHologram(Location location, NMSManager nmsManager, PlaceholderLineTracker placeholderLineTracker) {
|
||||
this.placeholderLineTracker = placeholderLineTracker;
|
||||
Preconditions.notNull(location, "location");
|
||||
this.setLocation(location);
|
||||
this.nmsManager = nmsManager;
|
||||
@ -42,8 +42,8 @@ public abstract class BaseHologram<T extends StandardHologramLine> extends BaseH
|
||||
return nmsManager;
|
||||
}
|
||||
|
||||
protected final PlaceholderManager getPlaceholderManager() {
|
||||
return placeholderManager;
|
||||
protected final PlaceholderLineTracker getPlaceholderLineTracker() {
|
||||
return placeholderLineTracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -11,7 +11,7 @@ import me.filoghost.holographicdisplays.core.hologram.StandardHologram;
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardHologramLine;
|
||||
import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.core.nms.SpawnFailedException;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import org.bukkit.World;
|
||||
|
||||
public abstract class BaseHologramLine extends BaseHologramComponent implements StandardHologramLine {
|
||||
@ -34,8 +34,8 @@ public abstract class BaseHologramLine extends BaseHologramComponent implements
|
||||
return hologram.getNMSManager();
|
||||
}
|
||||
|
||||
protected final PlaceholderManager getPlaceholderManager() {
|
||||
return hologram.getPlaceholderManager();
|
||||
protected final PlaceholderLineTracker getPlaceholderLineTracker() {
|
||||
return hologram.getPlaceholderLineTracker();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -34,7 +34,7 @@ public abstract class BaseTextLine extends BaseTouchableLine implements Standard
|
||||
|
||||
if (textEntity != null) {
|
||||
textEntity.setCustomNameNMS(text);
|
||||
getPlaceholderManager().updateTracking(this);
|
||||
getPlaceholderLineTracker().onTextLineChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -48,7 +48,7 @@ public abstract class BaseTextLine extends BaseTouchableLine implements Standard
|
||||
textEntity.setCustomNameNMS(text);
|
||||
}
|
||||
|
||||
getPlaceholderManager().updateTracking(this);
|
||||
getPlaceholderLineTracker().onTextLineChange(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -8,7 +8,7 @@ package me.filoghost.holographicdisplays.object.internal;
|
||||
import me.filoghost.holographicdisplays.HolographicDisplays;
|
||||
import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.object.base.BaseHologram;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
@ -18,8 +18,8 @@ public class InternalHologram extends BaseHologram<InternalHologramLine> {
|
||||
|
||||
private final String name;
|
||||
|
||||
protected InternalHologram(Location source, String name, NMSManager nmsManager, PlaceholderManager placeholderManager) {
|
||||
super(source, nmsManager, placeholderManager);
|
||||
protected InternalHologram(Location source, String name, NMSManager nmsManager, PlaceholderLineTracker placeholderLineTracker) {
|
||||
super(source, nmsManager, placeholderLineTracker);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
|
@ -7,21 +7,21 @@ package me.filoghost.holographicdisplays.object.internal;
|
||||
|
||||
import me.filoghost.holographicdisplays.core.nms.NMSManager;
|
||||
import me.filoghost.holographicdisplays.object.base.BaseHologramManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderManager;
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
import org.bukkit.Location;
|
||||
|
||||
public class InternalHologramManager extends BaseHologramManager<InternalHologram> {
|
||||
|
||||
private final NMSManager nmsManager;
|
||||
private final PlaceholderManager placeholderManager;
|
||||
private final PlaceholderLineTracker placeholderLineTracker;
|
||||
|
||||
public InternalHologramManager(NMSManager nmsManager, PlaceholderManager placeholderManager) {
|
||||
public InternalHologramManager(NMSManager nmsManager, PlaceholderLineTracker placeholderLineTracker) {
|
||||
this.nmsManager = nmsManager;
|
||||
this.placeholderManager = placeholderManager;
|
||||
this.placeholderLineTracker = placeholderLineTracker;
|
||||
}
|
||||
|
||||
public InternalHologram createHologram(Location source, String name) {
|
||||
InternalHologram hologram = new InternalHologram(source, name, nmsManager, placeholderManager);
|
||||
InternalHologram hologram = new InternalHologram(source, name, nmsManager, placeholderLineTracker);
|
||||
super.addHologram(hologram);
|
||||
return hologram;
|
||||
}
|
||||
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardTextLine;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderRegistry;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
public class PlaceholderManager {
|
||||
|
||||
private final PlaceholderRegistry placeholderRegistry;
|
||||
private final PlaceholdersUpdateTask placeholdersUpdateTask;
|
||||
|
||||
public PlaceholderManager() {
|
||||
this.placeholderRegistry = new PlaceholderRegistry();
|
||||
PlaceholdersReplacementTracker placeholdersReplacementTracker = new PlaceholdersReplacementTracker(placeholderRegistry);
|
||||
this.placeholdersUpdateTask = new PlaceholdersUpdateTask(placeholdersReplacementTracker, placeholderRegistry);
|
||||
|
||||
placeholderRegistry.setChangeListener(placeholdersReplacementTracker::clearOutdatedSources);
|
||||
}
|
||||
|
||||
public PlaceholderRegistry getPlaceholderRegistry() {
|
||||
return placeholderRegistry;
|
||||
}
|
||||
|
||||
public void startUpdaterTask(Plugin plugin) {
|
||||
Bukkit.getScheduler().scheduleSyncRepeatingTask(plugin, placeholdersUpdateTask, 0, 1);
|
||||
}
|
||||
|
||||
public void updateTracking(StandardTextLine line) {
|
||||
placeholdersUpdateTask.updateTracking(line);
|
||||
}
|
||||
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import me.filoghost.holographicdisplays.api.placeholder.Placeholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderFactory;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderOccurrence;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderExpansion;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderRegistry;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class PlaceholdersReplacementTracker {
|
||||
|
||||
private final PlaceholderRegistry registry;
|
||||
private final Map<PlaceholderOccurrence, ReplacementHolder> currentReplacements;
|
||||
|
||||
public PlaceholdersReplacementTracker(PlaceholderRegistry registry) {
|
||||
this.registry = registry;
|
||||
// Use WeakHashMap to ensure that when a PlaceholderOccurrence is no longer referenced in other objects
|
||||
// the corresponding entry is removed from the map automatically.
|
||||
this.currentReplacements = new WeakHashMap<>();
|
||||
}
|
||||
|
||||
public void clearOutdatedSources() {
|
||||
// Remove entries whose placeholder expansion sources are outdated
|
||||
currentReplacements.entrySet().removeIf(entry -> {
|
||||
PlaceholderOccurrence placeholderOccurrence = entry.getKey();
|
||||
PlaceholderExpansion currentSource = entry.getValue().source;
|
||||
PlaceholderExpansion newSource = registry.findBestMatch(placeholderOccurrence);
|
||||
|
||||
return !Objects.equals(currentSource, newSource);
|
||||
});
|
||||
}
|
||||
|
||||
public @Nullable String getOrUpdateReplacement(PlaceholderOccurrence placeholderOccurrence, long currentTick)
|
||||
throws PlaceholderException {
|
||||
ReplacementHolder replacementHolder = currentReplacements.get(placeholderOccurrence);
|
||||
|
||||
if (replacementHolder == null) {
|
||||
replacementHolder = createReplacementHolder(placeholderOccurrence);
|
||||
currentReplacements.put(placeholderOccurrence, replacementHolder);
|
||||
}
|
||||
|
||||
try {
|
||||
replacementHolder.refreshIfNeeded(placeholderOccurrence, currentTick);
|
||||
} catch (Throwable t) {
|
||||
throw new PlaceholderException(t, replacementHolder.source);
|
||||
}
|
||||
|
||||
return replacementHolder.currentReplacement;
|
||||
}
|
||||
|
||||
private ReplacementHolder createReplacementHolder(PlaceholderOccurrence placeholderOccurrence) throws PlaceholderException {
|
||||
PlaceholderExpansion placeholderExpansion = registry.findBestMatch(placeholderOccurrence);
|
||||
Placeholder placeholder;
|
||||
|
||||
if (placeholderExpansion != null) {
|
||||
PlaceholderFactory placeholderFactory = placeholderExpansion.getPlaceholderFactory();
|
||||
try {
|
||||
placeholder = placeholderFactory.getPlaceholder(placeholderOccurrence.getArgument());
|
||||
} catch (Throwable t) {
|
||||
throw new PlaceholderException(t, placeholderExpansion);
|
||||
}
|
||||
} else {
|
||||
placeholder = null;
|
||||
}
|
||||
|
||||
return new ReplacementHolder(placeholderExpansion, placeholder);
|
||||
}
|
||||
|
||||
|
||||
private static class ReplacementHolder {
|
||||
|
||||
final PlaceholderExpansion source;
|
||||
final Placeholder placeholder;
|
||||
|
||||
String currentReplacement;
|
||||
long lastUpdateTick = -1;
|
||||
|
||||
ReplacementHolder(PlaceholderExpansion source, Placeholder placeholder) {
|
||||
this.source = source;
|
||||
this.placeholder = placeholder;
|
||||
}
|
||||
|
||||
public void refreshIfNeeded(PlaceholderOccurrence placeholderOccurrence, long currentTick) {
|
||||
if (needsRefresh(currentTick)) {
|
||||
currentReplacement = placeholder.getReplacement(placeholderOccurrence.getArgument());
|
||||
lastUpdateTick = currentTick;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean needsRefresh(long currentTick) {
|
||||
if (placeholder == null || lastUpdateTick == currentTick) {
|
||||
return false; // No need to refresh
|
||||
}
|
||||
|
||||
if (lastUpdateTick == -1) {
|
||||
return true; // Force at least the initial refresh
|
||||
}
|
||||
|
||||
return currentTick - lastUpdateTick >= placeholder.getRefreshIntervalTicks();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import me.filoghost.fcommons.logging.Log;
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardTextLine;
|
||||
import me.filoghost.holographicdisplays.core.nms.entity.NMSArmorStand;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderOccurrence;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.StringWithPlaceholders;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderExpansion;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderRegistry;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class PlaceholdersUpdateTask implements Runnable {
|
||||
|
||||
private final PlaceholdersReplacementTracker placeholdersReplacementTracker;
|
||||
private final PlaceholderRegistry placeholderRegistry;
|
||||
private final Map<StandardTextLine, TrackedLine> trackedLines;
|
||||
private final Map<PlaceholderExpansion, Long> lastErrorLogByPlaceholderExpansion;
|
||||
|
||||
private long currentTick;
|
||||
|
||||
public PlaceholdersUpdateTask(PlaceholdersReplacementTracker placeholdersReplacementTracker, PlaceholderRegistry placeholderRegistry) {
|
||||
this.placeholdersReplacementTracker = placeholdersReplacementTracker;
|
||||
this.placeholderRegistry = placeholderRegistry;
|
||||
this.trackedLines = new LinkedHashMap<>();
|
||||
this.lastErrorLogByPlaceholderExpansion = new WeakHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Iterator<TrackedLine> iterator = trackedLines.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
TrackedLine trackedLine = iterator.next();
|
||||
|
||||
if (trackedLine.shouldBeUntracked()) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
trackedLine.updateNameWithPlaceholders();
|
||||
}
|
||||
|
||||
currentTick++;
|
||||
}
|
||||
|
||||
public TrackedLine getTrackedLine(StandardTextLine line) {
|
||||
return trackedLines.get(line);
|
||||
}
|
||||
|
||||
public void updateTracking(StandardTextLine line) {
|
||||
TrackedLine trackedLine = createTrackedLineIfNeeded(line);
|
||||
|
||||
if (trackedLine != null) {
|
||||
trackedLines.put(line, trackedLine);
|
||||
trackedLine.updateNameWithPlaceholders();
|
||||
} else {
|
||||
TrackedLine untrackedLine = trackedLines.remove(line);
|
||||
if (untrackedLine != null) {
|
||||
untrackedLine.restoreOriginalName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable TrackedLine createTrackedLineIfNeeded(StandardTextLine textLine) {
|
||||
if (!textLine.isAllowPlaceholders()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String text = textLine.getText();
|
||||
if (text == null || text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NMSArmorStand entity = textLine.getNMSArmorStand();
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringWithPlaceholders textWithPlaceholders = new StringWithPlaceholders(text);
|
||||
if (!textWithPlaceholders.containsPlaceholders()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TrackedLine(this, placeholderRegistry, textLine, entity, textWithPlaceholders);
|
||||
}
|
||||
|
||||
protected String getCurrentReplacement(PlaceholderOccurrence placeholderOccurrence) {
|
||||
try {
|
||||
return placeholdersReplacementTracker.getOrUpdateReplacement(placeholderOccurrence, currentTick);
|
||||
} catch (PlaceholderException e) {
|
||||
handleException(e);
|
||||
return "[Error]";
|
||||
}
|
||||
}
|
||||
|
||||
private void handleException(PlaceholderException exception) {
|
||||
PlaceholderExpansion placeholderExpansion = exception.getPlaceholderExpansion();
|
||||
|
||||
Long lastErrorLog = lastErrorLogByPlaceholderExpansion.get(placeholderExpansion);
|
||||
if (lastErrorLog != null && currentTick - lastErrorLog < 20) {
|
||||
return; // Avoid spamming the console too frequently
|
||||
}
|
||||
lastErrorLogByPlaceholderExpansion.put(placeholderExpansion, currentTick);
|
||||
|
||||
Log.warning("The placeholder \"" + placeholderExpansion.getIdentifier() + "\""
|
||||
+ " registered by the plugin " + placeholderExpansion.getPluginName()
|
||||
+ " generated an exception."
|
||||
+ " Please contact the author of " + placeholderExpansion.getPluginName(),
|
||||
exception.getCause());
|
||||
}
|
||||
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public interface RelativePlaceholder {
|
||||
|
||||
String getReplacement(Player player);
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderExpansion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class StandardPlaceholder {
|
||||
|
||||
private final @NotNull PlaceholderExpansion source;
|
||||
|
||||
protected StandardPlaceholder(@NotNull PlaceholderExpansion source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
public final @NotNull PlaceholderExpansion getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
public boolean isIndividual() {
|
||||
return source.isIndividual();
|
||||
}
|
||||
|
||||
public final int getRefreshIntervalTicks() throws PlaceholderException {
|
||||
try {
|
||||
return doGetRefreshIntervalTicks();
|
||||
} catch (Throwable t) {
|
||||
throw new PlaceholderException(t, getSource());
|
||||
}
|
||||
}
|
||||
|
||||
public final @Nullable String getReplacement(Player player, @Nullable String argument) throws PlaceholderException {
|
||||
try {
|
||||
return doGetReplacement(player, argument);
|
||||
} catch (Throwable t) {
|
||||
throw new PlaceholderException(t, getSource());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Below methods may use externally provided objects which can throw any exception
|
||||
*/
|
||||
|
||||
protected abstract int doGetRefreshIntervalTicks() throws Throwable;
|
||||
|
||||
protected abstract @Nullable String doGetReplacement(Player player, @Nullable String argument) throws Throwable;
|
||||
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
public class TickClock {
|
||||
|
||||
private long currentTick;
|
||||
|
||||
public void incrementTick() {
|
||||
currentTick++;
|
||||
}
|
||||
|
||||
public long getCurrentTick() {
|
||||
return currentTick;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.tracking.PlaceholderLineTracker;
|
||||
|
||||
public class TickingTask implements Runnable {
|
||||
|
||||
private final TickClock tickClock;
|
||||
private final PlaceholderLineTracker placeholderLineTracker;
|
||||
|
||||
public TickingTask(TickClock tickClock, PlaceholderLineTracker placeholderLineTracker) {
|
||||
this.tickClock = tickClock;
|
||||
this.placeholderLineTracker = placeholderLineTracker;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
tickClock.incrementTick();
|
||||
placeholderLineTracker.updateEntitiesWithGlobalPlaceholders();
|
||||
}
|
||||
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder;
|
||||
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardTextLine;
|
||||
import me.filoghost.holographicdisplays.core.nms.entity.NMSArmorStand;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.StringWithPlaceholders;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderRegistry;
|
||||
|
||||
public class TrackedLine {
|
||||
|
||||
private final PlaceholdersUpdateTask placeholdersUpdateTask;
|
||||
private final PlaceholderRegistry placeholderRegistry;
|
||||
private final StandardTextLine textLine;
|
||||
private final NMSArmorStand entity;
|
||||
private final StringWithPlaceholders nameWithPlaceholders;
|
||||
private final boolean containsRelativePlaceholders;
|
||||
|
||||
TrackedLine(PlaceholdersUpdateTask placeholdersUpdateTask, PlaceholderRegistry placeholderRegistry, StandardTextLine textLine, NMSArmorStand entity, StringWithPlaceholders nameWithPlaceholders) {
|
||||
this.placeholdersUpdateTask = placeholdersUpdateTask;
|
||||
this.placeholderRegistry = placeholderRegistry;
|
||||
this.textLine = textLine;
|
||||
this.entity = entity;
|
||||
this.nameWithPlaceholders = nameWithPlaceholders;
|
||||
this.containsRelativePlaceholders = nameWithPlaceholders.containsPlaceholdersMatching(
|
||||
occurrence -> this.placeholderRegistry.findRelative(occurrence) != null
|
||||
);
|
||||
}
|
||||
|
||||
void updateNameWithPlaceholders() {
|
||||
String newName = nameWithPlaceholders.replacePlaceholders(placeholdersUpdateTask::getCurrentReplacement);
|
||||
entity.setCustomNameNMS(newName);
|
||||
}
|
||||
|
||||
void restoreOriginalName() {
|
||||
if (!entity.isDeadNMS()) {
|
||||
entity.setCustomNameNMS(textLine.getText());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsRelativePlaceholders() {
|
||||
return containsRelativePlaceholders;
|
||||
}
|
||||
|
||||
public boolean shouldBeUntracked() {
|
||||
return entity.isDeadNMS();
|
||||
}
|
||||
|
||||
}
|
@ -30,7 +30,7 @@ public class DefaultPlaceholders {
|
||||
HolographicDisplays plugin = HolographicDisplays.getInstance();
|
||||
placeholderRegistry.unregisterAll(plugin);
|
||||
|
||||
placeholderRegistry.register(plugin, "rainbow", new AnimationPlaceholder(4, toStringList(
|
||||
placeholderRegistry.registerGlobalPlaceholder(plugin, "rainbow", new AnimationPlaceholder(4, toStringList(
|
||||
ChatColor.RED,
|
||||
ChatColor.GOLD,
|
||||
ChatColor.YELLOW,
|
||||
@ -39,17 +39,17 @@ public class DefaultPlaceholders {
|
||||
ChatColor.LIGHT_PURPLE
|
||||
)));
|
||||
|
||||
placeholderRegistry.registerReplacer(plugin, "time", 10, (argument) -> {
|
||||
placeholderRegistry.registerGlobalPlaceholderReplacer(plugin, "time", 10, (argument) -> {
|
||||
return Configuration.timeFormat.format(Instant.now());
|
||||
});
|
||||
|
||||
placeholderRegistry.registerFactory(plugin, "animation", animationRegistry);
|
||||
placeholderRegistry.registerGlobalPlaceholderFactory(plugin, "animation", animationRegistry);
|
||||
|
||||
placeholderRegistry.registerFactory(plugin, "world", new WorldPlayersPlaceholderFactory());
|
||||
placeholderRegistry.registerGlobalPlaceholderFactory(plugin, "world", new WorldPlayersPlaceholderFactory());
|
||||
|
||||
placeholderRegistry.registerFactory(plugin, "online", new OnlinePlayersPlaceholderFactory(bungeeServerTracker));
|
||||
placeholderRegistry.registerGlobalPlaceholderFactory(plugin, "online", new OnlinePlayersPlaceholderFactory(bungeeServerTracker));
|
||||
|
||||
placeholderRegistry.registerReplacer(plugin, "max_players", 20, (serverName) -> {
|
||||
placeholderRegistry.registerGlobalPlaceholderReplacer(plugin, "max_players", 20, (serverName) -> {
|
||||
if (serverName == null) {
|
||||
// No argument specified, return max players of this server
|
||||
return String.valueOf(Bukkit.getMaxPlayers());
|
||||
@ -62,7 +62,7 @@ public class DefaultPlaceholders {
|
||||
return String.valueOf(bungeeServerTracker.getCurrentServerInfo(serverName).getMaxPlayers());
|
||||
});
|
||||
|
||||
placeholderRegistry.registerReplacer(plugin, "status", 20, (serverName) -> {
|
||||
placeholderRegistry.registerGlobalPlaceholderReplacer(plugin, "status", 20, (serverName) -> {
|
||||
if (serverName == null) {
|
||||
return NO_SERVER_SPECIFIED_ERROR;
|
||||
}
|
||||
@ -79,7 +79,7 @@ public class DefaultPlaceholders {
|
||||
}
|
||||
});
|
||||
|
||||
placeholderRegistry.registerReplacer(plugin, "motd", 20, (serverName) -> {
|
||||
placeholderRegistry.registerGlobalPlaceholderReplacer(plugin, "motd", 20, (serverName) -> {
|
||||
if (serverName == null) {
|
||||
return NO_SERVER_SPECIFIED_ERROR;
|
||||
}
|
||||
@ -91,7 +91,7 @@ public class DefaultPlaceholders {
|
||||
return bungeeServerTracker.getCurrentServerInfo(serverName).getMotdLine1();
|
||||
});
|
||||
|
||||
placeholderRegistry.registerReplacer(plugin, "motd2", 20, (serverName) -> {
|
||||
placeholderRegistry.registerGlobalPlaceholderReplacer(plugin, "motd2", 20, (serverName) -> {
|
||||
if (serverName == null) {
|
||||
return NO_SERVER_SPECIFIED_ERROR;
|
||||
}
|
||||
@ -102,6 +102,14 @@ public class DefaultPlaceholders {
|
||||
|
||||
return bungeeServerTracker.getCurrentServerInfo(serverName).getMotdLine2();
|
||||
});
|
||||
|
||||
placeholderRegistry.registerIndividualPlaceholderReplacer(plugin, "player", Integer.MAX_VALUE, (player, argument) -> {
|
||||
return player.getName();
|
||||
});
|
||||
|
||||
placeholderRegistry.registerIndividualPlaceholderReplacer(plugin, "displayName", 20, (player, argument) -> {
|
||||
return player.getDisplayName();
|
||||
});
|
||||
}
|
||||
|
||||
private static List<String> toStringList(ChatColor... colors) {
|
||||
|
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.parsing;
|
||||
|
||||
@FunctionalInterface
|
||||
public interface PlaceholderReplaceFunction {
|
||||
|
||||
String getReplacement(PlaceholderOccurrence placeholderOccurrence);
|
||||
|
||||
}
|
@ -9,7 +9,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class StringWithPlaceholders {
|
||||
@ -22,14 +21,24 @@ public class StringWithPlaceholders {
|
||||
|
||||
public StringWithPlaceholders(String string) {
|
||||
this.string = string;
|
||||
this.stringParts = toStringParts(string);
|
||||
this.stringParts = splitToParts(string);
|
||||
}
|
||||
|
||||
private StringWithPlaceholders(String string, List<StringPart> stringParts) {
|
||||
this.string = string;
|
||||
this.stringParts = stringParts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return string;
|
||||
}
|
||||
|
||||
public boolean containsPlaceholders() {
|
||||
return stringParts != null;
|
||||
}
|
||||
|
||||
public boolean containsPlaceholdersMatching(Predicate<PlaceholderOccurrence> filter) {
|
||||
public boolean anyMatch(Predicate<PlaceholderOccurrence> filter) {
|
||||
if (stringParts == null) {
|
||||
return false;
|
||||
}
|
||||
@ -37,7 +46,7 @@ public class StringWithPlaceholders {
|
||||
for (StringPart stringPart : stringParts) {
|
||||
if (stringPart instanceof PlaceholderStringPart) {
|
||||
PlaceholderStringPart placeholderStringPart = (PlaceholderStringPart) stringPart;
|
||||
if (filter.test(placeholderStringPart.content)) {
|
||||
if (filter.test(placeholderStringPart.placeholderOccurrence)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -46,7 +55,51 @@ public class StringWithPlaceholders {
|
||||
return false;
|
||||
}
|
||||
|
||||
public String replacePlaceholders(Function<PlaceholderOccurrence, String> replaceFunction) {
|
||||
public StringWithPlaceholders partiallyReplacePlaceholders(PlaceholderReplaceFunction replaceFunction) {
|
||||
if (!containsPlaceholders()) {
|
||||
return this;
|
||||
}
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
StringBuilder fullOutput = new StringBuilder();
|
||||
List<StringPart> newStringParts = null; // Lazy initialization
|
||||
|
||||
for (StringPart part : stringParts) {
|
||||
if (part instanceof PlaceholderStringPart) {
|
||||
PlaceholderStringPart placeholderStringPart = (PlaceholderStringPart) part;
|
||||
String replacement = replaceFunction.getReplacement(placeholderStringPart.placeholderOccurrence);
|
||||
if (replacement != null) {
|
||||
output.append(replacement);
|
||||
fullOutput.append(replacement);
|
||||
} else {
|
||||
// Placeholder was not replaced, may be replaced later
|
||||
if (newStringParts == null) {
|
||||
newStringParts = new ArrayList<>();
|
||||
}
|
||||
// Append leading literal string, if present
|
||||
if (output.length() > 0) {
|
||||
newStringParts.add(new LiteralStringPart(output.toString()));
|
||||
output.setLength(0);
|
||||
}
|
||||
newStringParts.add(placeholderStringPart);
|
||||
output.append(placeholderStringPart.nonReplacedString);
|
||||
fullOutput.append(placeholderStringPart.nonReplacedString);
|
||||
}
|
||||
} else {
|
||||
LiteralStringPart literalStringPart = (LiteralStringPart) part;
|
||||
output.append(literalStringPart.literalString);
|
||||
fullOutput.append(literalStringPart.literalString);
|
||||
}
|
||||
}
|
||||
|
||||
if (output.length() > 0 && newStringParts != null) {
|
||||
newStringParts.add(new LiteralStringPart(output.toString()));
|
||||
}
|
||||
|
||||
return new StringWithPlaceholders(fullOutput.toString(), newStringParts);
|
||||
}
|
||||
|
||||
public String replacePlaceholders(PlaceholderReplaceFunction replaceFunction) {
|
||||
if (!containsPlaceholders()) {
|
||||
return string;
|
||||
}
|
||||
@ -59,7 +112,7 @@ public class StringWithPlaceholders {
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
private @Nullable List<StringPart> toStringParts(String string) {
|
||||
private @Nullable List<StringPart> splitToParts(String string) {
|
||||
int placeholderStartIndex = -1;
|
||||
int lastAppendIndex = 0;
|
||||
List<StringPart> stringParts = null; // Lazy initialization
|
||||
@ -116,7 +169,7 @@ public class StringWithPlaceholders {
|
||||
|
||||
private interface StringPart {
|
||||
|
||||
String getValue(Function<PlaceholderOccurrence, String> placeholderReplaceFunction);
|
||||
String getValue(PlaceholderReplaceFunction placeholderReplaceFunction);
|
||||
|
||||
}
|
||||
|
||||
@ -130,7 +183,7 @@ public class StringWithPlaceholders {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Function<PlaceholderOccurrence, String> placeholderReplaceFunction) {
|
||||
public String getValue(PlaceholderReplaceFunction placeholderReplaceFunction) {
|
||||
return literalString;
|
||||
}
|
||||
|
||||
@ -139,22 +192,22 @@ public class StringWithPlaceholders {
|
||||
|
||||
private static class PlaceholderStringPart implements StringPart {
|
||||
|
||||
private final PlaceholderOccurrence content;
|
||||
private final String unparsedString;
|
||||
private final PlaceholderOccurrence placeholderOccurrence;
|
||||
private final String nonReplacedString;
|
||||
|
||||
PlaceholderStringPart(PlaceholderOccurrence parsedContent, String unparsedString) {
|
||||
this.content = parsedContent;
|
||||
this.unparsedString = unparsedString;
|
||||
PlaceholderStringPart(PlaceholderOccurrence placeholderOccurrence, String nonReplacedString) {
|
||||
this.placeholderOccurrence = placeholderOccurrence;
|
||||
this.nonReplacedString = nonReplacedString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getValue(Function<PlaceholderOccurrence, String> placeholderReplaceFunction) {
|
||||
String replacement = placeholderReplaceFunction.apply(content);
|
||||
public String getValue(PlaceholderReplaceFunction placeholderReplaceFunction) {
|
||||
String replacement = placeholderReplaceFunction.getReplacement(placeholderOccurrence);
|
||||
if (replacement != null) {
|
||||
return replacement;
|
||||
} else {
|
||||
// If no replacement is provided, leave the unparsed placeholder string
|
||||
return unparsedString;
|
||||
return nonReplacedString;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.registry;
|
||||
|
||||
import me.filoghost.holographicdisplays.api.placeholder.Placeholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderFactory;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.StandardPlaceholder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class GlobalPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
private final PlaceholderFactory placeholderFactory;
|
||||
|
||||
GlobalPlaceholderExpansion(Plugin plugin, String identifier, PlaceholderFactory placeholderFactory) {
|
||||
super(plugin, identifier);
|
||||
this.placeholderFactory = placeholderFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndividual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable StandardPlaceholder createPlaceholder(String argument) throws PlaceholderException {
|
||||
Placeholder placeholder;
|
||||
try {
|
||||
placeholder = placeholderFactory.getPlaceholder(argument);
|
||||
} catch (Throwable t) {
|
||||
throw new PlaceholderException(t, this);
|
||||
}
|
||||
|
||||
if (placeholder != null) {
|
||||
return new GlobalStandardPlaceholder(placeholder, this);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class GlobalStandardPlaceholder extends StandardPlaceholder {
|
||||
|
||||
private final @NotNull Placeholder placeholder;
|
||||
|
||||
GlobalStandardPlaceholder(@NotNull Placeholder placeholder, @NotNull GlobalPlaceholderExpansion source) {
|
||||
super(source);
|
||||
this.placeholder = placeholder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doGetRefreshIntervalTicks() {
|
||||
return placeholder.getRefreshIntervalTicks();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable String doGetReplacement(Player player, @Nullable String argument) {
|
||||
return placeholder.getReplacement(argument);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.registry;
|
||||
|
||||
import me.filoghost.holographicdisplays.api.placeholder.IndividualPlaceholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.IndividualPlaceholderFactory;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.StandardPlaceholder;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class IndividualPlaceholderExpansion extends PlaceholderExpansion {
|
||||
|
||||
private final IndividualPlaceholderFactory placeholderFactory;
|
||||
|
||||
IndividualPlaceholderExpansion(Plugin plugin, String identifier, IndividualPlaceholderFactory placeholderFactory) {
|
||||
super(plugin, identifier);
|
||||
this.placeholderFactory = placeholderFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIndividual() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @Nullable StandardPlaceholder createPlaceholder(String argument) throws PlaceholderException {
|
||||
IndividualPlaceholder placeholder;
|
||||
try {
|
||||
placeholder = placeholderFactory.getPlaceholder(argument);
|
||||
} catch (Throwable t) {
|
||||
throw new PlaceholderException(t, this);
|
||||
}
|
||||
|
||||
if (placeholder != null) {
|
||||
return new IndividualStandardPlaceholder(placeholder, this);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class IndividualStandardPlaceholder extends StandardPlaceholder {
|
||||
|
||||
private final @NotNull IndividualPlaceholder placeholder;
|
||||
|
||||
IndividualStandardPlaceholder(@NotNull IndividualPlaceholder placeholder, @NotNull IndividualPlaceholderExpansion source) {
|
||||
super(source);
|
||||
this.placeholder = placeholder;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int doGetRefreshIntervalTicks() {
|
||||
return placeholder.getRefreshIntervalTicks();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @Nullable String doGetReplacement(Player player, @Nullable String argument) {
|
||||
return placeholder.getReplacement(player, argument);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -5,37 +5,21 @@
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.registry;
|
||||
|
||||
import me.filoghost.fcommons.Preconditions;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderFactory;
|
||||
import me.filoghost.holographicdisplays.placeholder.StandardPlaceholder;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderIdentifier;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PluginName;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class PlaceholderExpansion {
|
||||
public abstract class PlaceholderExpansion {
|
||||
|
||||
private final PluginName pluginName;
|
||||
private final PlaceholderIdentifier identifier;
|
||||
private final PlaceholderFactory placeholderFactory;
|
||||
|
||||
public PlaceholderExpansion(Plugin plugin, String identifier, PlaceholderFactory placeholderFactory) {
|
||||
Preconditions.notNull(plugin, "plugin");
|
||||
Preconditions.notEmpty(identifier, "identifier");
|
||||
for (char c : identifier.toCharArray()) {
|
||||
Preconditions.checkArgument(isValidIdentifierCharacter(c), "identifier contains invalid character '" + c + "'");
|
||||
}
|
||||
Preconditions.notNull(placeholderFactory, "placeholderFactory");
|
||||
|
||||
public PlaceholderExpansion(Plugin plugin, String identifier) {
|
||||
this.pluginName = new PluginName(plugin);
|
||||
this.identifier = new PlaceholderIdentifier(identifier);
|
||||
this.placeholderFactory = placeholderFactory;
|
||||
}
|
||||
|
||||
private boolean isValidIdentifierCharacter(char c) {
|
||||
return ('a' <= c && c <= 'z')
|
||||
|| ('A' <= c && c <= 'Z')
|
||||
|| ('0' <= c && c <= '9')
|
||||
|| c == '-'
|
||||
|| c == '_';
|
||||
}
|
||||
|
||||
public PluginName getPluginName() {
|
||||
@ -46,8 +30,8 @@ public class PlaceholderExpansion {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public PlaceholderFactory getPlaceholderFactory() {
|
||||
return placeholderFactory;
|
||||
}
|
||||
public abstract boolean isIndividual();
|
||||
|
||||
public abstract @Nullable StandardPlaceholder createPlaceholder(String argument) throws PlaceholderException;
|
||||
|
||||
}
|
||||
|
@ -8,55 +8,63 @@ package me.filoghost.holographicdisplays.placeholder.registry;
|
||||
import com.google.common.collect.HashBasedTable;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Table;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.IndividualPlaceholderFactory;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.IndividualPlaceholderReplacer;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.Placeholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderFactory;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderReplacer;
|
||||
import me.filoghost.holographicdisplays.placeholder.RelativePlaceholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.IndividualPlaceholder;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderIdentifier;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderOccurrence;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PluginName;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlaceholderRegistry {
|
||||
|
||||
private final Table<PlaceholderIdentifier, PluginName, PlaceholderExpansion> placeholderExpansions;
|
||||
private final Map<PlaceholderIdentifier, RelativePlaceholder> relativePlaceholders;
|
||||
private Runnable changeListener;
|
||||
|
||||
public PlaceholderRegistry() {
|
||||
this.placeholderExpansions = HashBasedTable.create();
|
||||
relativePlaceholders = new HashMap<>();
|
||||
registerRelative("player", Player::getName);
|
||||
registerRelative("displayName", Player::getDisplayName);
|
||||
}
|
||||
|
||||
public void setChangeListener(Runnable changeListener) {
|
||||
this.changeListener = changeListener;
|
||||
}
|
||||
|
||||
public void registerIndividualPlaceholderReplacer(Plugin plugin, String identifier, int refreshIntervalTicks, IndividualPlaceholderReplacer placeholderReplacer) {
|
||||
registerIndividualPlaceholder(plugin, identifier, new SimpleIndividualPlaceholder(refreshIntervalTicks, placeholderReplacer));
|
||||
}
|
||||
|
||||
public void registerRelative(String identifier, RelativePlaceholder relativePlaceholder) {
|
||||
relativePlaceholders.put(new PlaceholderIdentifier(identifier), relativePlaceholder);
|
||||
public void registerIndividualPlaceholder(Plugin plugin, String identifier, IndividualPlaceholder placeholder) {
|
||||
registerIndividualPlaceholderFactory(plugin, identifier, (String argument) -> placeholder);
|
||||
}
|
||||
|
||||
public void registerReplacer(Plugin plugin, String identifier, int refreshIntervalTicks, PlaceholderReplacer placeholderReplacer) {
|
||||
register(plugin, identifier, new SimplePlaceholder(refreshIntervalTicks, placeholderReplacer));
|
||||
public void registerIndividualPlaceholderFactory(Plugin plugin, String identifier, IndividualPlaceholderFactory factory) {
|
||||
PlaceholderExpansion expansion = new IndividualPlaceholderExpansion(plugin, identifier, factory);
|
||||
registerExpansion(expansion);
|
||||
}
|
||||
|
||||
public void registerGlobalPlaceholderReplacer(Plugin plugin, String identifier, int refreshIntervalTicks, PlaceholderReplacer placeholderReplacer) {
|
||||
registerGlobalPlaceholder(plugin, identifier, new SimpleGlobalPlaceholder(refreshIntervalTicks, placeholderReplacer));
|
||||
}
|
||||
|
||||
public void register(Plugin plugin, String identifier, Placeholder placeholder) {
|
||||
registerFactory(plugin, identifier, new SingletonPlaceholderFactory(placeholder));
|
||||
public void registerGlobalPlaceholder(Plugin plugin, String identifier, Placeholder placeholder) {
|
||||
registerGlobalPlaceholderFactory(plugin, identifier, (String argument) -> placeholder);
|
||||
}
|
||||
|
||||
public void registerFactory(Plugin plugin, String identifier, PlaceholderFactory placeholderFactory) {
|
||||
PlaceholderExpansion expansion = new PlaceholderExpansion(plugin, identifier, placeholderFactory);
|
||||
public void registerGlobalPlaceholderFactory(Plugin plugin, String identifier, PlaceholderFactory factory) {
|
||||
PlaceholderExpansion expansion = new GlobalPlaceholderExpansion(plugin, identifier, factory);
|
||||
registerExpansion(expansion);
|
||||
}
|
||||
|
||||
private void registerExpansion(PlaceholderExpansion expansion) {
|
||||
placeholderExpansions.put(expansion.getIdentifier(), expansion.getPluginName(), expansion);
|
||||
|
||||
|
||||
changeListener.run();
|
||||
}
|
||||
|
||||
@ -72,7 +80,7 @@ public class PlaceholderRegistry {
|
||||
changeListener.run();
|
||||
}
|
||||
|
||||
public @Nullable PlaceholderExpansion findBestMatch(PlaceholderOccurrence textOccurrence) {
|
||||
public @Nullable PlaceholderExpansion find(PlaceholderOccurrence textOccurrence) {
|
||||
PluginName pluginName = textOccurrence.getPluginName();
|
||||
PlaceholderIdentifier identifier = textOccurrence.getIdentifier();
|
||||
|
||||
@ -101,9 +109,4 @@ public class PlaceholderRegistry {
|
||||
return placeholderExpansions.contains(new PlaceholderIdentifier(identifier), new PluginName(plugin));
|
||||
}
|
||||
|
||||
public @Nullable RelativePlaceholder findRelative(PlaceholderOccurrence textOccurrence) {
|
||||
PlaceholderIdentifier identifier = textOccurrence.getIdentifier();
|
||||
return relativePlaceholders.get(identifier);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,18 +5,15 @@
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.registry;
|
||||
|
||||
import me.filoghost.fcommons.Preconditions;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.Placeholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderReplacer;
|
||||
|
||||
class SimplePlaceholder implements Placeholder {
|
||||
class SimpleGlobalPlaceholder implements Placeholder {
|
||||
|
||||
private final int refreshIntervalTicks;
|
||||
private final PlaceholderReplacer placeholderReplacer;
|
||||
|
||||
SimplePlaceholder(int refreshIntervalTicks, PlaceholderReplacer placeholderReplacer) {
|
||||
Preconditions.checkArgument(refreshIntervalTicks >= 0, "refreshIntervalTicks cannot be negative");
|
||||
Preconditions.notNull(placeholderReplacer, "placeholderReplacer");
|
||||
SimpleGlobalPlaceholder(int refreshIntervalTicks, PlaceholderReplacer placeholderReplacer) {
|
||||
this.refreshIntervalTicks = refreshIntervalTicks;
|
||||
this.placeholderReplacer = placeholderReplacer;
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.registry;
|
||||
|
||||
import me.filoghost.holographicdisplays.api.placeholder.IndividualPlaceholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.IndividualPlaceholderReplacer;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class SimpleIndividualPlaceholder implements IndividualPlaceholder {
|
||||
|
||||
private final int refreshIntervalTicks;
|
||||
private final IndividualPlaceholderReplacer placeholderReplacer;
|
||||
|
||||
SimpleIndividualPlaceholder(int refreshIntervalTicks, IndividualPlaceholderReplacer placeholderReplacer) {
|
||||
this.refreshIntervalTicks = refreshIntervalTicks;
|
||||
this.placeholderReplacer = placeholderReplacer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRefreshIntervalTicks() {
|
||||
return refreshIntervalTicks;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getReplacement(@NotNull Player player, @Nullable String argument) {
|
||||
return placeholderReplacer.getReplacement(player, argument);
|
||||
}
|
||||
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.registry;
|
||||
|
||||
import me.filoghost.fcommons.Preconditions;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.Placeholder;
|
||||
import me.filoghost.holographicdisplays.api.placeholder.PlaceholderFactory;
|
||||
|
||||
class SingletonPlaceholderFactory implements PlaceholderFactory {
|
||||
|
||||
private final Placeholder placeholder;
|
||||
|
||||
SingletonPlaceholderFactory(Placeholder placeholder) {
|
||||
Preconditions.notNull(placeholder, "placeholder");
|
||||
this.placeholder = placeholder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Placeholder getPlaceholder(String argument) {
|
||||
return placeholder;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.fcommons.logging.Log;
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.TickClock;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderExpansion;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
class PlaceholderExceptionHandler {
|
||||
|
||||
private final TickClock tickClock;
|
||||
private final Map<PlaceholderExpansion, Long> lastErrorLogByPlaceholderExpansion;
|
||||
|
||||
PlaceholderExceptionHandler(TickClock tickClock) {
|
||||
this.tickClock = tickClock;
|
||||
this.lastErrorLogByPlaceholderExpansion = new WeakHashMap<>();
|
||||
}
|
||||
|
||||
void handle(PlaceholderException exception) {
|
||||
PlaceholderExpansion placeholderExpansion = exception.getPlaceholderExpansion();
|
||||
Long lastErrorLog = lastErrorLogByPlaceholderExpansion.get(placeholderExpansion);
|
||||
long currentTick = tickClock.getCurrentTick();
|
||||
|
||||
if (lastErrorLog != null && currentTick - lastErrorLog < 20) {
|
||||
return; // Avoid spamming the console too frequently
|
||||
}
|
||||
|
||||
lastErrorLogByPlaceholderExpansion.put(placeholderExpansion, currentTick);
|
||||
|
||||
Log.warning("The placeholder \"" + placeholderExpansion.getIdentifier() + "\""
|
||||
+ " registered by the plugin " + placeholderExpansion.getPluginName()
|
||||
+ " generated an exception."
|
||||
+ " Please contact the author of " + placeholderExpansion.getPluginName(),
|
||||
exception.getCause());
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardTextLine;
|
||||
import me.filoghost.holographicdisplays.core.nms.entity.NMSArmorStand;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.StringWithPlaceholders;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class PlaceholderLineTracker {
|
||||
|
||||
private final PlaceholderTracker replacementTracker;
|
||||
private final Map<StandardTextLine, TrackedLine> trackedLines;
|
||||
|
||||
public PlaceholderLineTracker(PlaceholderTracker replacementTracker) {
|
||||
this.replacementTracker = replacementTracker;
|
||||
this.trackedLines = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
public void updateEntitiesWithGlobalPlaceholders() {
|
||||
Iterator<TrackedLine> iterator = trackedLines.values().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
TrackedLine trackedLine = iterator.next();
|
||||
|
||||
if (trackedLine.shouldBeUntracked()) {
|
||||
iterator.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
trackedLine.updateEntityWithGlobalPlaceholders();
|
||||
}
|
||||
}
|
||||
|
||||
public void onTextLineChange(StandardTextLine line) {
|
||||
TrackedLine trackedLine = createTrackedLineIfNeeded(line);
|
||||
|
||||
if (trackedLine != null) {
|
||||
trackedLines.put(line, trackedLine);
|
||||
trackedLine.updateEntityWithGlobalPlaceholders(); // Update placeholders instantly to avoid flashing the non-replaced text
|
||||
} else {
|
||||
TrackedLine untrackedLine = trackedLines.remove(line);
|
||||
if (untrackedLine != null) {
|
||||
untrackedLine.restoreOriginalName();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private @Nullable TrackedLine createTrackedLineIfNeeded(StandardTextLine textLine) {
|
||||
if (!textLine.isAllowPlaceholders()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String text = textLine.getText();
|
||||
if (text == null || text.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NMSArmorStand entity = textLine.getNMSArmorStand();
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
StringWithPlaceholders textWithPlaceholders = new StringWithPlaceholders(text);
|
||||
if (!textWithPlaceholders.containsPlaceholders()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new TrackedLine(replacementTracker, textLine, entity, textWithPlaceholders);
|
||||
}
|
||||
|
||||
public TrackedLine getTrackedLine(StandardTextLine line) {
|
||||
return trackedLines.get(line);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.StandardPlaceholder;
|
||||
import me.filoghost.holographicdisplays.placeholder.TickClock;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderOccurrence;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.StringWithPlaceholders;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderExpansion;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderRegistry;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class PlaceholderTracker {
|
||||
|
||||
private final PlaceholderRegistry registry;
|
||||
private final TickClock tickClock;
|
||||
private final PlaceholderExceptionHandler exceptionHandler;
|
||||
|
||||
// Use WeakHashMap to ensure that when a PlaceholderOccurrence is no longer referenced in other objects
|
||||
// the corresponding entry is removed from the map automatically.
|
||||
private final WeakHashMap<PlaceholderOccurrence, TrackedPlaceholder> activePlaceholders;
|
||||
|
||||
public PlaceholderTracker(PlaceholderRegistry registry, TickClock tickClock) {
|
||||
this.registry = registry;
|
||||
this.tickClock = tickClock;
|
||||
this.exceptionHandler = new PlaceholderExceptionHandler(tickClock);
|
||||
this.activePlaceholders = new WeakHashMap<>();
|
||||
|
||||
registry.setChangeListener(this::onRegistryChange);
|
||||
}
|
||||
|
||||
private void onRegistryChange() {
|
||||
// Remove entries whose placeholder expansion sources are outdated
|
||||
activePlaceholders.entrySet().removeIf(entry -> {
|
||||
PlaceholderOccurrence placeholderOccurrence = entry.getKey();
|
||||
PlaceholderExpansion currentSource = entry.getValue().getSource();
|
||||
PlaceholderExpansion newSource = registry.find(placeholderOccurrence);
|
||||
|
||||
return !Objects.equals(currentSource, newSource);
|
||||
});
|
||||
}
|
||||
|
||||
public @Nullable String updateAndGetGlobalReplacement(PlaceholderOccurrence placeholderOccurrence) {
|
||||
return updateAndGetReplacement(placeholderOccurrence, null, false);
|
||||
}
|
||||
|
||||
public @Nullable String updateAndGetIndividualReplacement(PlaceholderOccurrence placeholderOccurrence, Player player) {
|
||||
return updateAndGetReplacement(placeholderOccurrence, player, true);
|
||||
}
|
||||
|
||||
private @Nullable String updateAndGetReplacement(PlaceholderOccurrence placeholderOccurrence, Player player, boolean individual) {
|
||||
try {
|
||||
TrackedPlaceholder trackedPlaceholder = getTrackedPlaceholder(placeholderOccurrence);
|
||||
if (trackedPlaceholder.isIndividual() == individual) {
|
||||
return trackedPlaceholder.updateAndGetReplacement(player, tickClock.getCurrentTick());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (PlaceholderException e) {
|
||||
exceptionHandler.handle(e);
|
||||
return "[Error]";
|
||||
}
|
||||
}
|
||||
|
||||
private @NotNull TrackedPlaceholder getTrackedPlaceholder(PlaceholderOccurrence placeholderOccurrence) throws PlaceholderException {
|
||||
TrackedPlaceholder trackedPlaceholder = activePlaceholders.get(placeholderOccurrence);
|
||||
|
||||
if (trackedPlaceholder == null) {
|
||||
trackedPlaceholder = createTrackedPlaceholder(placeholderOccurrence);
|
||||
activePlaceholders.put(placeholderOccurrence, trackedPlaceholder);
|
||||
}
|
||||
|
||||
return trackedPlaceholder;
|
||||
}
|
||||
|
||||
private TrackedPlaceholder createTrackedPlaceholder(PlaceholderOccurrence placeholderOccurrence) throws PlaceholderException {
|
||||
PlaceholderExpansion placeholderExpansion = registry.find(placeholderOccurrence);
|
||||
StandardPlaceholder placeholder;
|
||||
|
||||
if (placeholderExpansion != null) {
|
||||
placeholder = placeholderExpansion.createPlaceholder(placeholderOccurrence.getArgument());
|
||||
} else {
|
||||
placeholder = null;
|
||||
}
|
||||
|
||||
if (placeholder == null) {
|
||||
return new TrackedNullPlaceholder(placeholderExpansion);
|
||||
} else if (placeholder.isIndividual()) {
|
||||
return new TrackedIndividualPlaceholder(placeholder, placeholderOccurrence);
|
||||
} else {
|
||||
return new TrackedGlobalPlaceholder(placeholder, placeholderOccurrence);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean containsIndividualPlaceholders(StringWithPlaceholders nameWithPlaceholders) {
|
||||
return nameWithPlaceholders.anyMatch(occurrence -> {
|
||||
PlaceholderExpansion placeholderExpansion = registry.find(occurrence);
|
||||
return placeholderExpansion != null && placeholderExpansion.isIndividual();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.StandardPlaceholder;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderOccurrence;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class ReplacementHolder {
|
||||
|
||||
private final @NotNull StandardPlaceholder placeholder;
|
||||
private final @NotNull PlaceholderOccurrence placeholderOccurrence;
|
||||
|
||||
private @Nullable String currentReplacement;
|
||||
private long lastUpdateTick = -1;
|
||||
|
||||
ReplacementHolder(@NotNull StandardPlaceholder placeholder, @NotNull PlaceholderOccurrence placeholderOccurrence) {
|
||||
this.placeholder = placeholder;
|
||||
this.placeholderOccurrence = placeholderOccurrence;
|
||||
}
|
||||
|
||||
@Nullable String updateAndGet(Player player, long currentTick) throws PlaceholderException {
|
||||
if (needsRefresh(currentTick)) {
|
||||
currentReplacement = placeholder.getReplacement(player, placeholderOccurrence.getArgument());
|
||||
lastUpdateTick = currentTick;
|
||||
}
|
||||
return currentReplacement;
|
||||
}
|
||||
|
||||
private boolean needsRefresh(long currentTick) throws PlaceholderException {
|
||||
if (lastUpdateTick == currentTick) {
|
||||
return false; // No need to refresh
|
||||
}
|
||||
|
||||
if (lastUpdateTick == -1) {
|
||||
return true; // Force at least the initial refresh
|
||||
}
|
||||
|
||||
return currentTick - lastUpdateTick >= placeholder.getRefreshIntervalTicks();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.StandardPlaceholder;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderOccurrence;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class TrackedGlobalPlaceholder extends TrackedPlaceholder {
|
||||
|
||||
private final ReplacementHolder replacementHolder;
|
||||
|
||||
TrackedGlobalPlaceholder(@NotNull StandardPlaceholder placeholder, @NotNull PlaceholderOccurrence placeholderOccurrence) {
|
||||
super(placeholder.getSource());
|
||||
this.replacementHolder = new ReplacementHolder(placeholder, placeholderOccurrence);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isIndividual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable String updateAndGetReplacement(Player player, long currentTick) throws PlaceholderException {
|
||||
return replacementHolder.updateAndGet(player, currentTick);
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.StandardPlaceholder;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderOccurrence;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
class TrackedIndividualPlaceholder extends TrackedPlaceholder {
|
||||
|
||||
private final @NotNull StandardPlaceholder placeholder;
|
||||
private final @NotNull PlaceholderOccurrence placeholderOccurrence;
|
||||
private final WeakHashMap<Player, ReplacementHolder> replacementHolderByPlayer;
|
||||
|
||||
TrackedIndividualPlaceholder(@NotNull StandardPlaceholder placeholder, @NotNull PlaceholderOccurrence placeholderOccurrence) {
|
||||
super(placeholder.getSource());
|
||||
this.placeholder = placeholder;
|
||||
this.placeholderOccurrence = placeholderOccurrence;
|
||||
this.replacementHolderByPlayer = new WeakHashMap<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isIndividual() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable String updateAndGetReplacement(Player player, long currentTick) throws PlaceholderException {
|
||||
return replacementHolderByPlayer
|
||||
.computeIfAbsent(player, key -> new ReplacementHolder(placeholder, placeholderOccurrence))
|
||||
.updateAndGet(player, currentTick);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.core.hologram.StandardTextLine;
|
||||
import me.filoghost.holographicdisplays.core.nms.entity.NMSArmorStand;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.PlaceholderReplaceFunction;
|
||||
import me.filoghost.holographicdisplays.placeholder.parsing.StringWithPlaceholders;
|
||||
import org.bukkit.entity.Player;
|
||||
|
||||
public class TrackedLine {
|
||||
|
||||
private final PlaceholderTracker placeholderTracker;
|
||||
private final StandardTextLine textLine;
|
||||
private final NMSArmorStand entity;
|
||||
private final StringWithPlaceholders textWithPlaceholders;
|
||||
private final boolean containsIndividualPlaceholders;
|
||||
private final PlaceholderReplaceFunction globalReplaceFunction;
|
||||
|
||||
private StringWithPlaceholders textWithGlobalReplacements;
|
||||
|
||||
TrackedLine(
|
||||
PlaceholderTracker placeholderTracker,
|
||||
StandardTextLine textLine,
|
||||
NMSArmorStand entity,
|
||||
StringWithPlaceholders textWithPlaceholders) {
|
||||
this.placeholderTracker = placeholderTracker;
|
||||
this.textLine = textLine;
|
||||
this.entity = entity;
|
||||
this.textWithPlaceholders = textWithPlaceholders;
|
||||
this.containsIndividualPlaceholders = placeholderTracker.containsIndividualPlaceholders(textWithPlaceholders);
|
||||
this.globalReplaceFunction = placeholderTracker::updateAndGetGlobalReplacement;
|
||||
}
|
||||
|
||||
void updateEntityWithGlobalPlaceholders() {
|
||||
textWithGlobalReplacements = textWithPlaceholders.partiallyReplacePlaceholders(globalReplaceFunction);
|
||||
entity.setCustomNameNMS(textWithGlobalReplacements.toString());
|
||||
}
|
||||
|
||||
public String replaceIndividualPlaceholders(Player player) {
|
||||
if (containsIndividualPlaceholders) {
|
||||
return textWithGlobalReplacements.replacePlaceholders((occurrence) ->
|
||||
placeholderTracker.updateAndGetIndividualReplacement(occurrence, player));
|
||||
} else {
|
||||
return textWithGlobalReplacements.toString();
|
||||
}
|
||||
}
|
||||
|
||||
void restoreOriginalName() {
|
||||
if (!entity.isDeadNMS()) {
|
||||
entity.setCustomNameNMS(textLine.getText());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean shouldBeUntracked() {
|
||||
return entity.isDeadNMS();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderExpansion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
class TrackedNullPlaceholder extends TrackedPlaceholder {
|
||||
|
||||
TrackedNullPlaceholder(@Nullable PlaceholderExpansion placeholderExpansion) {
|
||||
super(placeholderExpansion);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nullable String updateAndGetReplacement(Player player, long currentTick) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isIndividual() {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) filoghost and contributors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||
*/
|
||||
package me.filoghost.holographicdisplays.placeholder.tracking;
|
||||
|
||||
import me.filoghost.holographicdisplays.placeholder.PlaceholderException;
|
||||
import me.filoghost.holographicdisplays.placeholder.registry.PlaceholderExpansion;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
abstract class TrackedPlaceholder {
|
||||
|
||||
private final @Nullable PlaceholderExpansion source;
|
||||
|
||||
TrackedPlaceholder(@Nullable PlaceholderExpansion source) {
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
final @Nullable PlaceholderExpansion getSource() {
|
||||
return source;
|
||||
}
|
||||
|
||||
abstract boolean isIndividual();
|
||||
|
||||
abstract @Nullable String updateAndGetReplacement(Player player, long currentTick) throws PlaceholderException;
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user