Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,13 @@ public interface HologramConfiguration {
* @return The hologram visibility update interval in milliseconds.
*/
int getUpdateVisibilityInterval();

/**
* Returns the interval at which text holograms refresh dynamic text updates.
*
* @return The hologram text refresh interval in milliseconds.
*/
default int getHologramUpdateInterval() {
return 200;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.oliver.fancyholograms.api.hologram;

import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import de.oliver.fancyholograms.api.data.HologramData;
import de.oliver.fancyholograms.api.data.TextHologramData;
import de.oliver.fancyholograms.api.data.property.Visibility;
Expand All @@ -16,6 +18,7 @@
import org.lushplugins.chatcolorhandler.paper.PaperColor;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
* Abstract base class for creating, updating, and managing holograms.
Expand All @@ -40,6 +43,12 @@ public abstract class Hologram {
* Set of UUIDs of players to whom the hologram is currently shown.
*/
protected final @NotNull Set<UUID> viewers = new HashSet<>();
private static final UUID NULL_PLAYER_KEY = new UUID(0L, 0L);
private final Cache<UUID, Component> cachedTextPerPlayer = CacheBuilder.newBuilder()
.expireAfterWrite(1, TimeUnit.SECONDS)
.maximumSize(512)
.build();
private String lastRawText = "";

protected Hologram(@NotNull final HologramData data) {
this.data = data;
Expand Down Expand Up @@ -184,6 +193,7 @@ public final void updateHologram() {
* Use {@link #forceUpdate()} if this hologram is not registered to the HologramManager.
*/
public final void queueUpdate() {
clearTextCache();
data.setHasChanges(true);
}

Expand Down Expand Up @@ -355,13 +365,32 @@ public final Component getShownText(@Nullable final Player player) {
return null;
}

var text = String.join("\n", textData.getText());
final String rawText = String.join("\n", textData.getText());

if (!rawText.equals(lastRawText)) {
cachedTextPerPlayer.invalidateAll();
lastRawText = rawText;
}

if (Bukkit.isStopping()) {
return MiniMessage.miniMessage().deserialize(text);
return MiniMessage.miniMessage().deserialize(rawText);
}

final UUID cacheKey = player != null ? player.getUniqueId() : NULL_PLAYER_KEY;
final Component cached = cachedTextPerPlayer.getIfPresent(cacheKey);
if (cached != null) {
return cached;
}

return PaperColor.handler().translate(text, player);
final Component translated = PaperColor.handler().translate(rawText, player);
cachedTextPerPlayer.put(cacheKey, translated);
return translated;
}

@ApiStatus.Internal
public void clearTextCache() {
cachedTextPerPlayer.invalidateAll();
lastRawText = "";
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,21 @@ public final class FancyHologramsConfiguration implements HologramConfiguration
private static final String CONFIG_VISIBILITY_DISTANCE = "visibility_distance";
private static final String CONFIG_REGISTER_COMMANDS = "register_commands";
private static final String CONFIG_UPDATE_VISIBILITY_INTERVAL = "update_visibility_interval";
private static final String CONFIG_HOLOGRAM_UPDATE_INTERVAL = "performance.hologram_update_interval_ms";
private static final String CONFIG_REPORT_ERRORS_TO_SENTRY = "report_errors_to_sentry";
private static final String CONFIG_VERSION = "config_version";
private static final Map<String, List<String>> CONFIG_COMMENTS = Map.of(
CONFIG_VERSION, List.of("Config version, do not modify."),
CONFIG_AUTOSAVE_ENABLED, List.of("Whether autosave is enabled."),
CONFIG_AUTOSAVE_INTERVAL, List.of("The interval at which autosave is performed in minutes."),
CONFIG_SAVE_ON_CHANGED, List.of("Whether the plugin should save holograms when they are changed."),
CONFIG_LOG_LEVEL, List.of("The log level for the plugin (DEBUG, INFO, WARN, ERROR)."),
CONFIG_LOG_ON_WORLD_LOAD, List.of("Whether hologram loading should be logged on world loading. Disable this if you load worlds dynamically to prevent console spam."),
CONFIG_VERSION_NOTIFICATIONS, List.of("Whether the plugin should send notifications for new updates."),
CONFIG_VISIBILITY_DISTANCE, List.of("The default visibility distance for holograms."),
CONFIG_REGISTER_COMMANDS, List.of("Whether the plugin should register its commands."),
CONFIG_UPDATE_VISIBILITY_INTERVAL, List.of("The interval at which hologram visibility is updated in ticks.")
private static final Map<String, List<String>> CONFIG_COMMENTS = Map.ofEntries(
Map.entry(CONFIG_VERSION, List.of("Config version, do not modify.")),
Map.entry(CONFIG_AUTOSAVE_ENABLED, List.of("Whether autosave is enabled.")),
Map.entry(CONFIG_AUTOSAVE_INTERVAL, List.of("The interval at which autosave is performed in minutes.")),
Map.entry(CONFIG_SAVE_ON_CHANGED, List.of("Whether the plugin should save holograms when they are changed.")),
Map.entry(CONFIG_LOG_LEVEL, List.of("The log level for the plugin (DEBUG, INFO, WARN, ERROR).")),
Map.entry(CONFIG_LOG_ON_WORLD_LOAD, List.of("Whether hologram loading should be logged on world loading. Disable this if you load worlds dynamically to prevent console spam.")),
Map.entry(CONFIG_VERSION_NOTIFICATIONS, List.of("Whether the plugin should send notifications for new updates.")),
Map.entry(CONFIG_VISIBILITY_DISTANCE, List.of("The default visibility distance for holograms.")),
Map.entry(CONFIG_REGISTER_COMMANDS, List.of("Whether the plugin should register its commands.")),
Map.entry(CONFIG_UPDATE_VISIBILITY_INTERVAL, List.of("The interval at which hologram visibility is updated in ticks.")),
Map.entry(CONFIG_HOLOGRAM_UPDATE_INTERVAL, List.of("The interval at which text holograms refresh placeholder updates in milliseconds. Lower values are more responsive but use more CPU."))
);
/**
* Indicates whether autosave is enabled.
Expand Down Expand Up @@ -78,6 +80,10 @@ public final class FancyHologramsConfiguration implements HologramConfiguration
* The interval at which hologram visibility is updated.
*/
private int updateVisibilityInterval;
/**
* The interval at which text holograms refresh dynamic text updates.
*/
private int hologramUpdateInterval;

private void updateChecker(@NotNull FancyHolograms plugin, @NotNull FileConfiguration config) {
final int latestVersion = 1;
Expand Down Expand Up @@ -145,6 +151,7 @@ private void setOptions(@NotNull FileConfiguration config) {
defaultVisibilityDistance = (int) ConfigHelper.getOrDefault(config, CONFIG_VISIBILITY_DISTANCE, 20);
registerCommands = (boolean) ConfigHelper.getOrDefault(config, CONFIG_REGISTER_COMMANDS, true);
updateVisibilityInterval = (int) ConfigHelper.getOrDefault(config, CONFIG_UPDATE_VISIBILITY_INTERVAL, 20);
hologramUpdateInterval = Math.max(10, (int) ConfigHelper.getOrDefault(config, CONFIG_HOLOGRAM_UPDATE_INTERVAL, 200));

config.set(CONFIG_REPORT_ERRORS_TO_SENTRY, null);
}
Expand Down Expand Up @@ -209,4 +216,9 @@ public boolean isRegisterCommands() {
public int getUpdateVisibilityInterval() {
return updateVisibilityInterval;
}
}

@Override
public int getHologramUpdateInterval() {
return hologramUpdateInterval;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ void initializeTasks() {
for (final var hologram : this.getHolograms()) {
HologramData data = hologram.getData();
if (data.hasChanges()) {
if (data instanceof TextHologramData) {
hologram.clearTextCache();
}

hologram.forceUpdate();
hologram.refreshForViewersInWorld();
data.setHasChanges(false);
Expand Down Expand Up @@ -259,7 +263,7 @@ void initializeTasks() {
}
}
}
}, 50, 50, TimeUnit.MILLISECONDS);
}, 50, this.plugin.getHologramConfiguration().getHologramUpdateInterval(), TimeUnit.MILLISECONDS);
}

/**
Expand Down
Loading