Configuration refactoring, convert symbols.yml to custom-placeholders.yml

This commit is contained in:
filoghost 2021-02-19 21:37:56 +01:00
parent 40e1967d20
commit acd83a6fe6
40 changed files with 845 additions and 687 deletions

View File

@ -6,6 +6,7 @@
package me.filoghost.holographicdisplays;
import me.filoghost.fcommons.BaseJavaPlugin;
import me.filoghost.fcommons.config.exception.ConfigException;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.reflection.ReflectUtils;
import me.filoghost.holographicdisplays.api.internal.BackendAPI;
@ -13,9 +14,9 @@ import me.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker;
import me.filoghost.holographicdisplays.bridge.protocollib.ProtocolLibHook;
import me.filoghost.holographicdisplays.bridge.protocollib.current.ProtocolLibHookImpl;
import me.filoghost.holographicdisplays.commands.HologramCommandManager;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.disk.Configuration;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.UnicodeSymbols;
import me.filoghost.holographicdisplays.disk.upgrade.LegacySymbolsUpgrader;
import me.filoghost.holographicdisplays.listener.MainListener;
import me.filoghost.holographicdisplays.nms.interfaces.NMSManager;
import me.filoghost.holographicdisplays.object.DefaultBackendAPI;
@ -71,12 +72,20 @@ public class HolographicDisplays extends BaseJavaPlugin {
System.setProperty("HolographicDisplaysLoaded", "true");
instance = this;
dataFolderPath = getDataFolder().toPath();
ConfigManager configManager = new ConfigManager(dataFolderPath);
// Run only once at startup, before anything else.
try {
LegacySymbolsUpgrader.run(configManager);
} catch (ConfigException e) {
Log.warning("Couldn't convert symbols file", e);
}
// Load placeholders.yml.
UnicodeSymbols.load(this);
configManager.reloadCustomPlaceholders();
// Load the configuration.
Configuration.load(this);
configManager.reloadMainConfig();
if (Configuration.updateNotification) {
UpdateChecker.run(this, 75097, (String newVersion) -> {
@ -119,7 +128,7 @@ public class HolographicDisplays extends BaseJavaPlugin {
}
// Initialize other static classes.
HologramDatabase.loadYamlFile(this);
configManager.reloadHologramDatabase();
BungeeServerTracker.restartTask(Configuration.bungeeRefreshSeconds);
// Start repeating tasks.
@ -132,7 +141,7 @@ public class HolographicDisplays extends BaseJavaPlugin {
"This can be caused by edits to plugin.yml or other plugins.");
}
commandManager = new HologramCommandManager();
commandManager = new HologramCommandManager(configManager);
commandManager.register(this);
mainListener = new MainListener(nmsManager);
@ -143,7 +152,8 @@ public class HolographicDisplays extends BaseJavaPlugin {
new MetricsLite(this, pluginID);
// Holograms are loaded later, when the worlds are ready.
Bukkit.getScheduler().runTask(this, new StartupLoadHologramsTask());
Bukkit.getScheduler().runTask(this,
new StartupLoadHologramsTask(configManager.getHologramDatabase().getHolograms()));
// Enable the API.
BackendAPI.setImplementation(new DefaultBackendAPI());

View File

@ -17,7 +17,6 @@ import java.io.IOException;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
public class BungeeServerTracker {
@ -146,12 +145,12 @@ public class BungeeServerTracker {
if (Configuration.pingerEnable) {
Bukkit.getScheduler().runTaskAsynchronously(HolographicDisplays.getInstance(), () -> {
for (Entry<String, ServerAddress> entry : Configuration.pingerServers.entrySet()) {
BungeeServerInfo serverInfo = getOrCreateServerInfo(entry.getKey());
for (ServerAddress serverAddress : Configuration.pingerServers) {
BungeeServerInfo serverInfo = getOrCreateServerInfo(serverAddress.getName());
boolean displayOffline = false;
try {
PingResponse data = ServerPinger.fetchData(entry.getValue(), Configuration.pingerTimeout);
PingResponse data = ServerPinger.fetchData(serverAddress, Configuration.pingerTimeout);
if (data.isOnline()) {
serverInfo.setOnline(true);
@ -164,13 +163,13 @@ public class BungeeServerTracker {
} catch (SocketTimeoutException e) {
displayOffline = true;
} catch (UnknownHostException e) {
Log.warning("Couldn't fetch data from " + entry.getKey() + "(" + entry.getValue().toString() + "): unknown host address.");
Log.warning("Couldn't fetch data from " + serverAddress + ": unknown host address.");
displayOffline = true;
} catch (IOException e) {
displayOffline = true;
} catch (Throwable t) {
displayOffline = true;
Log.warning("Couldn't fetch data from " + entry.getKey() + "(" + entry.getValue().toString() + ")", t);
Log.warning("Couldn't fetch data from " + serverAddress, t);
}
if (displayOffline) {

View File

@ -31,6 +31,7 @@ import me.filoghost.holographicdisplays.commands.subs.RemovelineCommand;
import me.filoghost.holographicdisplays.commands.subs.SetlineCommand;
import me.filoghost.holographicdisplays.commands.subs.TeleportCommand;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@ -47,28 +48,28 @@ public class HologramCommandManager extends SubCommandManager {
private final HelpCommand helpCommand;
public HologramCommandManager() {
public HologramCommandManager(ConfigManager configManager) {
setName("holograms");
subCommands = new ArrayList<>();
subCommandsByClass = new HashMap<>();
registerSubCommand(new AddlineCommand());
registerSubCommand(new CreateCommand());
registerSubCommand(new DeleteCommand());
registerSubCommand(new AddlineCommand(configManager));
registerSubCommand(new CreateCommand(configManager));
registerSubCommand(new DeleteCommand(configManager));
registerSubCommand(new EditCommand());
registerSubCommand(new ListCommand());
registerSubCommand(new NearCommand());
registerSubCommand(new TeleportCommand());
registerSubCommand(new MovehereCommand());
registerSubCommand(new AlignCommand());
registerSubCommand(new CopyCommand());
registerSubCommand(new ReloadCommand());
registerSubCommand(new MovehereCommand(configManager));
registerSubCommand(new AlignCommand(configManager));
registerSubCommand(new CopyCommand(configManager));
registerSubCommand(new ReloadCommand(configManager));
registerSubCommand(new RemovelineCommand());
registerSubCommand(new SetlineCommand());
registerSubCommand(new InsertlineCommand());
registerSubCommand(new ReadtextCommand());
registerSubCommand(new ReadimageCommand());
registerSubCommand(new RemovelineCommand(configManager));
registerSubCommand(new SetlineCommand(configManager));
registerSubCommand(new InsertlineCommand(configManager));
registerSubCommand(new ReadtextCommand(configManager));
registerSubCommand(new ReadimageCommand(configManager));
registerSubCommand(new InfoCommand());
registerSubCommand(new DebugCommand());

View File

@ -10,7 +10,7 @@ import me.filoghost.fcommons.command.validation.CommandValidate;
import me.filoghost.holographicdisplays.HolographicDisplays;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.HologramLineParser;
import me.filoghost.holographicdisplays.disk.HologramLineParseException;
import me.filoghost.holographicdisplays.disk.HologramLoadException;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.NamedHologramManager;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
@ -24,7 +24,7 @@ public class HologramCommandValidate {
public static CraftHologramLine parseHologramLine(NamedHologram hologram, String serializedLine, boolean validateMaterial) throws CommandException {
try {
return HologramLineParser.parseLine(hologram, serializedLine, validateMaterial);
} catch (HologramLineParseException e) {
} catch (HologramLoadException e) {
throw new CommandException(Utils.formatExceptionMessage(e));
}
}

View File

@ -10,7 +10,7 @@ import me.filoghost.fcommons.command.validation.CommandException;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.event.NamedHologramEditedEvent;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
@ -19,11 +19,15 @@ import org.bukkit.command.CommandSender;
public class AddlineCommand extends LineEditingCommand {
public AddlineCommand() {
private final ConfigManager configManager;
public AddlineCommand(ConfigManager configManager) {
super("addline");
setMinArgs(2);
setUsageArgs("<hologram> <text>");
setDescription("Adds a line to an existing hologram.");
this.configManager = configManager;
}
@Override
@ -35,8 +39,8 @@ public class AddlineCommand extends LineEditingCommand {
hologram.getLinesUnsafe().add(line);
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
Bukkit.getPluginManager().callEvent(new NamedHologramEditedEvent(hologram));
sender.sendMessage(Colors.PRIMARY + "Line added!");

View File

@ -11,18 +11,22 @@ import me.filoghost.fcommons.command.validation.CommandValidate;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.HologramSubCommand;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.object.NamedHologram;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
public class AlignCommand extends HologramSubCommand {
public AlignCommand() {
private final ConfigManager configManager;
public AlignCommand(ConfigManager configManager) {
super("align");
setMinArgs(3);
setUsageArgs("<X | Y | Z | XZ> <hologram> <referenceHologram>");
setDescription("Aligns the first hologram to the second, in the specified axis.");
this.configManager = configManager;
}
@Override
@ -52,8 +56,8 @@ public class AlignCommand extends HologramSubCommand {
hologram.despawnEntities();
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
sender.sendMessage(Colors.PRIMARY + "Hologram \"" + hologram.getName() + "\" aligned to the hologram \"" + referenceHologram.getName() + "\" on the " + axis.toUpperCase() + " axis.");
}

View File

@ -10,18 +10,22 @@ import me.filoghost.fcommons.command.validation.CommandException;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.HologramSubCommand;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
import org.bukkit.command.CommandSender;
public class CopyCommand extends HologramSubCommand {
public CopyCommand() {
private final ConfigManager configManager;
public CopyCommand(ConfigManager configManager) {
super("copy");
setMinArgs(2);
setUsageArgs("<fromHologram> <toHologram>");
setDescription("Copies the contents of a hologram into another one.");
this.configManager = configManager;
}
@Override
@ -31,14 +35,14 @@ public class CopyCommand extends HologramSubCommand {
toHologram.clearLines();
for (CraftHologramLine line : fromHologram.getLinesUnsafe()) {
CraftHologramLine clonedLine = HologramCommandValidate.parseHologramLine(toHologram, HologramDatabase.serializeHologramLine(line), false);
CraftHologramLine clonedLine = HologramCommandValidate.parseHologramLine(toHologram, line.getSerializedConfigValue(), false);
toHologram.getLinesUnsafe().add(clonedLine);
}
toHologram.refreshAll();
HologramDatabase.saveHologram(toHologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(toHologram);
configManager.saveHologramDatabase();
sender.sendMessage(Colors.PRIMARY + "Hologram \"" + fromHologram.getName() + "\" copied into hologram \"" + toHologram.getName() + "\"!");
}

View File

@ -12,7 +12,7 @@ import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.HologramSubCommand;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.NamedHologramManager;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
@ -23,7 +23,9 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
public class CreateCommand extends HologramSubCommand {
public CreateCommand() {
private final ConfigManager configManager;
public CreateCommand(ConfigManager configManager) {
super("create");
setMinArgs(1);
setUsageArgs("<hologramName> [text]");
@ -31,6 +33,8 @@ public class CreateCommand extends HologramSubCommand {
"Creates a new hologram with the given name, that must",
"be alphanumeric. The name will be used as reference to",
"that hologram for editing commands.");
this.configManager = configManager;
}
@SuppressWarnings("deprecation")
@ -68,8 +72,8 @@ public class CreateCommand extends HologramSubCommand {
NamedHologramManager.addHologram(hologram);
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
Location look = player.getLocation();
look.setPitch(90);
player.teleport(look, TeleportCause.PLUGIN);

View File

@ -10,18 +10,22 @@ import me.filoghost.fcommons.command.validation.CommandException;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.HologramSubCommand;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.NamedHologramManager;
import org.bukkit.command.CommandSender;
public class DeleteCommand extends HologramSubCommand {
public DeleteCommand() {
private final ConfigManager configManager;
public DeleteCommand(ConfigManager configManager) {
super("delete", "remove");
setMinArgs(1);
setUsageArgs("<hologram>");
setDescription("Deletes a hologram. Cannot be undone.");
this.configManager = configManager;
}
@Override
@ -30,9 +34,10 @@ public class DeleteCommand extends HologramSubCommand {
hologram.delete();
NamedHologramManager.removeHologram(hologram);
HologramDatabase.deleteHologram(hologram.getName());
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().removeHologram(hologram);
configManager.saveHologramDatabase();
sender.sendMessage(Colors.PRIMARY + "You deleted the hologram '" + hologram.getName() + "'.");
}

View File

@ -10,7 +10,6 @@ import me.filoghost.fcommons.command.validation.CommandException;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.Messages;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
import org.bukkit.command.CommandSender;
@ -33,7 +32,7 @@ public class InfoCommand extends LineEditingCommand {
int index = 0;
for (CraftHologramLine line : hologram.getLinesUnsafe()) {
sender.sendMessage(Colors.SECONDARY + Colors.BOLD + (++index) + Colors.SECONDARY_SHADOW + ". " + Colors.SECONDARY + HologramDatabase.serializeHologramLine(line));
sender.sendMessage(Colors.SECONDARY + Colors.BOLD + (++index) + Colors.SECONDARY_SHADOW + ". " + Colors.SECONDARY + line.getSerializedConfigValue());
}
EditCommand.sendQuickEditCommands(context, hologram);
}

View File

@ -12,7 +12,7 @@ import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.Messages;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.event.NamedHologramEditedEvent;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
@ -21,7 +21,9 @@ import org.bukkit.command.CommandSender;
public class InsertlineCommand extends LineEditingCommand {
public InsertlineCommand() {
private final ConfigManager configManager;
public InsertlineCommand(ConfigManager configManager) {
super("insertline");
setMinArgs(3);
setUsageArgs("<hologram> <lineNumber> <text>");
@ -29,6 +31,8 @@ public class InsertlineCommand extends LineEditingCommand {
"Inserts a line after the specified index.",
"If the index is 0, the line will be put before",
"the first line of the hologram.");
this.configManager = configManager;
}
@Override
@ -45,8 +49,8 @@ public class InsertlineCommand extends LineEditingCommand {
hologram.getLinesUnsafe().add(insertAfter, line);
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
Bukkit.getPluginManager().callEvent(new NamedHologramEditedEvent(hologram));

View File

@ -11,7 +11,7 @@ import me.filoghost.fcommons.command.validation.CommandValidate;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.HologramSubCommand;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.object.NamedHologram;
import org.bukkit.Location;
import org.bukkit.command.CommandSender;
@ -20,12 +20,15 @@ import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
public class MovehereCommand extends HologramSubCommand {
private final ConfigManager configManager;
public MovehereCommand() {
public MovehereCommand(ConfigManager configManager) {
super("movehere");
setMinArgs(1);
setUsageArgs("<hologram>");
setDescription("Moves a hologram to your location.");
this.configManager = configManager;
}
@Override
@ -37,8 +40,8 @@ public class MovehereCommand extends HologramSubCommand {
hologram.despawnEntities();
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
Location to = player.getLocation();
to.setPitch(90);
player.teleport(to, TeleportCause.PLUGIN);

View File

@ -12,12 +12,12 @@ import me.filoghost.fcommons.command.validation.CommandValidate;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.Messages;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.event.NamedHologramEditedEvent;
import me.filoghost.holographicdisplays.image.ImageMessage;
import me.filoghost.holographicdisplays.image.ImageReadException;
import me.filoghost.holographicdisplays.image.ImageReader;
import me.filoghost.holographicdisplays.image.ImageTooWideException;
import me.filoghost.holographicdisplays.image.ImageReadException;
import me.filoghost.holographicdisplays.image.ImageMessage;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftTextLine;
import org.bukkit.Bukkit;
@ -35,10 +35,14 @@ import java.util.List;
public class ReadimageCommand extends LineEditingCommand {
public ReadimageCommand() {
private final ConfigManager configManager;
public ReadimageCommand(ConfigManager configManager) {
super("readimage", "image");
setMinArgs(3);
setUsageArgs("<hologram> <imageWithExtension> <width>");
this.configManager = configManager;
}
@Override
@ -120,8 +124,8 @@ public class ReadimageCommand extends LineEditingCommand {
Messages.sendTip(sender, "The image has a very low height. You can increase it by increasing the width, it will scale automatically.");
}
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
if (append) {
sender.sendMessage(Colors.PRIMARY + "The image was appended int the end of the hologram!");

View File

@ -11,9 +11,9 @@ import me.filoghost.fcommons.command.validation.CommandException;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.commands.Messages;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.HologramLineParseException;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.disk.HologramLineParser;
import me.filoghost.holographicdisplays.disk.HologramLoadException;
import me.filoghost.holographicdisplays.event.NamedHologramEditedEvent;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
@ -31,10 +31,14 @@ import java.util.List;
public class ReadtextCommand extends LineEditingCommand {
public ReadtextCommand() {
private final ConfigManager configManager;
public ReadtextCommand(ConfigManager configManager) {
super("readtext", "readlines");
setMinArgs(2);
setUsageArgs("<hologram> <fileWithExtension>");
this.configManager = configManager;
}
@Override
@ -71,7 +75,7 @@ public class ReadtextCommand extends LineEditingCommand {
try {
CraftHologramLine line = HologramLineParser.parseLine(hologram, serializedLines.get(i), true);
linesToAdd.add(line);
} catch (HologramLineParseException e) {
} catch (HologramLoadException e) {
throw new CommandException("Error at line " + (i + 1) + ": " + e.getMessage());
}
}
@ -80,8 +84,8 @@ public class ReadtextCommand extends LineEditingCommand {
hologram.getLinesUnsafe().addAll(linesToAdd);
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
if (isImageExtension(FileUtils.getExtension(fileName))) {
Messages.sendWarning(sender, "The read file has an image's extension. If it is an image, you should use /" + context.getRootLabel() + " readimage.");

View File

@ -13,10 +13,10 @@ import me.filoghost.holographicdisplays.bridge.bungeecord.BungeeServerTracker;
import me.filoghost.holographicdisplays.commands.HologramSubCommand;
import me.filoghost.holographicdisplays.commands.Messages;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.disk.Configuration;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.HologramConfig;
import me.filoghost.holographicdisplays.disk.HologramLoadException;
import me.filoghost.holographicdisplays.disk.UnicodeSymbols;
import me.filoghost.holographicdisplays.event.HolographicDisplaysReloadEvent;
import me.filoghost.holographicdisplays.object.CraftHologram;
import me.filoghost.holographicdisplays.object.NamedHologram;
@ -26,26 +26,28 @@ import me.filoghost.holographicdisplays.placeholder.PlaceholdersManager;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import java.util.Set;
public class ReloadCommand extends HologramSubCommand {
public ReloadCommand() {
private final ConfigManager configManager;
public ReloadCommand(ConfigManager configManager) {
super("reload");
setDescription("Reloads the holograms from the database.");
this.configManager = configManager;
}
@Override
public void execute(CommandSender sender, String[] args, SubCommandContext context) {
long startMillis = System.currentTimeMillis();
UnicodeSymbols.load(HolographicDisplays.getInstance());
Configuration.load(HolographicDisplays.getInstance());
configManager.reloadCustomPlaceholders();
configManager.reloadMainConfig();
BungeeServerTracker.resetTrackedServers();
BungeeServerTracker.restartTask(Configuration.bungeeRefreshSeconds);
HologramDatabase.loadYamlFile(HolographicDisplays.getInstance());
configManager.reloadHologramDatabase();
try {
AnimationsRegister.loadAnimations(HolographicDisplays.getInstance());
} catch (Exception e) {
@ -55,15 +57,12 @@ public class ReloadCommand extends HologramSubCommand {
PlaceholdersManager.untrackAll();
NamedHologramManager.clearAll();
Set<String> savedHolograms = HologramDatabase.getHolograms();
if (savedHolograms != null && savedHolograms.size() > 0) {
for (String singleSavedHologram : savedHolograms) {
try {
NamedHologram singleHologramEntity = HologramDatabase.loadHologram(singleSavedHologram);
NamedHologramManager.addHologram(singleHologramEntity);
} catch (HologramLoadException e) {
Messages.sendWarning(sender, Utils.formatExceptionMessage(e));
}
for (HologramConfig hologramConfig : configManager.getHologramDatabase().getHolograms()) {
try {
NamedHologram hologram = hologramConfig.createHologram();
NamedHologramManager.addHologram(hologram);
} catch (HologramLoadException e) {
Messages.sendWarning(sender, Utils.formatExceptionMessage(e));
}
}

View File

@ -10,7 +10,7 @@ import me.filoghost.fcommons.command.validation.CommandException;
import me.filoghost.fcommons.command.validation.CommandValidate;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.event.NamedHologramEditedEvent;
import me.filoghost.holographicdisplays.object.NamedHologram;
import org.bukkit.Bukkit;
@ -18,11 +18,15 @@ import org.bukkit.command.CommandSender;
public class RemovelineCommand extends LineEditingCommand {
public RemovelineCommand() {
private final ConfigManager configManager;
public RemovelineCommand(ConfigManager configManager) {
super("removeline");
setMinArgs(2);
setUsageArgs("<hologram> <lineNumber>");
setDescription("Removes a line from a hologram.");
this.configManager = configManager;
}
@Override
@ -39,8 +43,8 @@ public class RemovelineCommand extends LineEditingCommand {
hologram.removeLine(index);
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
Bukkit.getPluginManager().callEvent(new NamedHologramEditedEvent(hologram));
sender.sendMessage(Colors.PRIMARY + "Line " + lineNumber + " removed!");

View File

@ -11,7 +11,7 @@ import me.filoghost.fcommons.command.validation.CommandValidate;
import me.filoghost.holographicdisplays.Colors;
import me.filoghost.holographicdisplays.commands.HologramCommandValidate;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import me.filoghost.holographicdisplays.event.NamedHologramEditedEvent;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
@ -20,11 +20,15 @@ import org.bukkit.command.CommandSender;
public class SetlineCommand extends LineEditingCommand {
public SetlineCommand() {
private final ConfigManager configManager;
public SetlineCommand(ConfigManager configManager) {
super("setline");
setMinArgs(3);
setUsageArgs("<hologram> <lineNumber> <newText>");
setDescription("Changes a line of a hologram.");
this.configManager = configManager;
}
@Override
@ -42,8 +46,8 @@ public class SetlineCommand extends LineEditingCommand {
hologram.getLinesUnsafe().set(index, line);
hologram.refreshAll();
HologramDatabase.saveHologram(hologram);
HologramDatabase.trySaveToDisk();
configManager.getHologramDatabase().addOrUpdate(hologram);
configManager.saveHologramDatabase();
Bukkit.getPluginManager().callEvent(new NamedHologramEditedEvent(hologram));
sender.sendMessage(Colors.PRIMARY + "Line " + lineNumber + " changed!");

View File

@ -0,0 +1,97 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.config.BaseConfigManager;
import me.filoghost.fcommons.config.Config;
import me.filoghost.fcommons.config.ConfigErrors;
import me.filoghost.fcommons.config.ConfigLoader;
import me.filoghost.fcommons.config.FileConfig;
import me.filoghost.fcommons.config.exception.ConfigException;
import me.filoghost.fcommons.config.mapped.MappedConfigLoader;
import me.filoghost.fcommons.logging.Log;
import java.nio.file.Path;
public class ConfigManager extends BaseConfigManager {
private final MappedConfigLoader<MainConfigModel> mainConfigLoader;
private final ConfigLoader databaseConfigLoader;
private final ConfigLoader placeholdersConfigLoader;
private final HologramDatabase hologramDatabase;
public ConfigManager(Path rootDataFolder) {
super(rootDataFolder);
this.mainConfigLoader = getMappedConfigLoader("config.yml", MainConfigModel.class);
this.databaseConfigLoader = getConfigLoader("database.yml");
this.placeholdersConfigLoader = getConfigLoader("custom-placeholders.yml");
this.hologramDatabase = new HologramDatabase();
}
public void reloadMainConfig() {
MainConfigModel mainConfig;
try {
mainConfig = mainConfigLoader.init();
} catch (ConfigException e) {
logConfigInitException(mainConfigLoader.getFile(), e);
mainConfig = new MainConfigModel(); // Fallback: use default values
}
Configuration.load(mainConfig);
}
public void reloadHologramDatabase() {
Config databaseConfig;
try {
databaseConfig = databaseConfigLoader.init();
} catch (ConfigException e) {
logConfigInitException(databaseConfigLoader.getFile(), e);
databaseConfig = new Config(); // Fallback: empty config
}
hologramDatabase.reloadFromConfig(databaseConfig);
}
public void saveHologramDatabase() {
try {
databaseConfigLoader.save(hologramDatabase.saveToConfig());
} catch (ConfigException e) {
logConfigSaveException(databaseConfigLoader.getFile(), e);
}
}
public HologramDatabase getHologramDatabase() {
return hologramDatabase;
}
public void reloadCustomPlaceholders() {
FileConfig placeholdersConfig;
try {
placeholdersConfig = placeholdersConfigLoader.init();
} catch (ConfigException e) {
logConfigInitException(placeholdersConfigLoader.getFile(), e);
placeholdersConfig = new FileConfig(placeholdersConfigLoader.getFile()); // Fallback: empty config
}
CustomPlaceholders.load(placeholdersConfig);
}
private void logConfigInitException(Path file, ConfigException e) {
Log.severe("error while initializing config file \"" + formatPath(file) + "\"", e);
}
private void logConfigSaveException(Path file, ConfigException e) {
Log.severe("error while saving config file \"" + formatPath(file) + "\"", e);
}
private String formatPath(Path path) {
return ConfigErrors.formatPath(getRootDataFolder(), path);
}
}

View File

@ -1,47 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
import java.util.Arrays;
public enum ConfigNode {
SPACE_BETWEEN_LINES("space-between-lines", 0.02),
QUICK_EDIT_COMMANDS("quick-edit-commands", true),
IMAGES_SYMBOL("images.symbol", "[x]"),
TRANSPARENCY_SPACE("images.transparency.space", " [|] "),
TRANSPARENCY_COLOR("images.transparency.color", "&7"),
UPDATE_NOTIFICATION("update-notification", true),
BUNGEE_REFRESH_SECONDS("bungee.refresh-seconds", 3),
BUNGEE_USE_REDIS_BUNGEE("bungee.use-RedisBungee", false),
BUNGEE_USE_FULL_PINGER("bungee.pinger.enable", false),
BUNGEE_PINGER_TIMEOUT("bungee.pinger.timeout", 500),
BUNGEE_PINGER_OFFLINE_MOTD("bungee.pinger.offline-motd", "&cOffline, couldn't get the MOTD."),
BUNGEE_PINGER_ONLINE_FORMAT("bungee.pinger.status.online", "&aOnline"),
BUNGEE_PINGER_OFFLINE_FORMAT("bungee.pinger.status.offline", "&cOffline"),
BUNGEE_PINGER_TRIM_MOTD("bungee.pinger.motd-remove-leading-trailing-spaces", true),
BUNGEE_PINGER_SERVERS("bungee.pinger.servers", Arrays.asList("hub: 127.0.0.1:25565", "survival: 127.0.0.1:25566", "minigames: 127.0.0.1:25567")),
TIME_FORMAT("time.format", "H:mm"),
TIME_ZONE("time.zone", "GMT+1"),
DEBUG("debug", false);
private final String path;
private final Object value;
ConfigNode(String path, Object defaultValue) {
this.path = path;
value = defaultValue;
}
public String getPath() {
return path;
}
public Object getDefaultValue() {
return value;
}
}

View File

@ -11,213 +11,154 @@
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.Strings;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.common.DebugLogger;
import org.bukkit.ChatColor;
import org.bukkit.configuration.InvalidConfigurationException;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.io.IOException;
import java.time.DateTimeException;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.HashMap;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Just a bunch of static variables to hold the settings.
* Useful for fast access.
*/
public class Configuration {
public static double spaceBetweenLines;
public static boolean quickEditCommands;
public static DateTimeFormatter timeFormat;
public static boolean updateNotification;
public static String imageSymbol;
public static String transparencySymbol;
public static boolean updateNotification;
public static ChatColor transparencyColor;
public static DateTimeFormatter timeFormat;
public static int bungeeRefreshSeconds;
public static boolean useRedisBungee;
public static boolean pingerEnable;
public static int pingerTimeout;
public static String pingerOfflineMotd;
public static String pingerStatusOnline;
public static String pingerStatusOffline;
public static boolean pingerTrimMotd;
public static Map<String, ServerAddress> pingerServers;
public static List<ServerAddress> pingerServers;
public static void load(MainConfigModel config) {
spaceBetweenLines = config.spaceBetweenLines;
quickEditCommands = config.quickEditCommands;
timeFormat = parseTimeFormatter(config.timeFormat, config.timeZone);
updateNotification = config.updateNotification;
public static void load(Plugin plugin) {
File configFile = new File(plugin.getDataFolder(), "config.yml");
if (!configFile.exists()) {
plugin.getDataFolder().mkdirs();
plugin.saveResource("config.yml", true);
}
imageSymbol = StringConverter.toReadableFormat(config.imageSymbol);
transparencySymbol = StringConverter.toReadableFormat(config.transparencySymbol);
transparencyColor = parseTransparencyColor(config.transparencyColor);
YamlConfiguration config = new YamlConfiguration();
try {
config.load(configFile);
} catch (InvalidConfigurationException e) {
e.printStackTrace();
Log.warning("The configuration is not a valid YAML file! Please check it with a tool like http://yaml-online-parser.appspot.com/");
return;
} catch (IOException e) {
e.printStackTrace();
Log.warning("I/O error while reading the configuration. Was the file in use?");
return;
} catch (Exception e) {
e.printStackTrace();
Log.warning("Unhandled exception while reading the configuration!");
return;
}
boolean needsSave = false;
for (ConfigNode node : ConfigNode.values()) {
if (!config.isSet(node.getPath())) {
needsSave = true;
config.set(node.getPath(), node.getDefaultValue());
}
}
// Check the old values.
List<String> nodesToRemove = Arrays.asList(
"vertical-spacing",
"time-format",
"bungee-refresh-seconds",
"using-RedisBungee",
"bungee-online-format",
"bungee-offline-format",
"precise-hologram-movement"
);
for (String oldNode : nodesToRemove) {
if (config.isSet(oldNode)) {
config.set(oldNode, null);
needsSave = true;
}
}
if (needsSave) {
config.options().header(String.join("\n",
".",
". Read the tutorial at: http://dev.bukkit.org/bukkit-plugins/holographic-displays/",
".",
". Plugin created by filoghost.",
"."));
config.options().copyHeader(true);
try {
config.save(configFile);
} catch (IOException e) {
e.printStackTrace();
Log.warning("I/O error while saving the configuration. Was the file in use?");
}
}
spaceBetweenLines = config.getDouble(ConfigNode.SPACE_BETWEEN_LINES.getPath());
quickEditCommands = config.getBoolean(ConfigNode.QUICK_EDIT_COMMANDS.getPath());
updateNotification = config.getBoolean(ConfigNode.UPDATE_NOTIFICATION.getPath());
imageSymbol = StringConverter.toReadableFormat(config.getString(ConfigNode.IMAGES_SYMBOL.getPath()));
transparencySymbol = StringConverter.toReadableFormat(config.getString(ConfigNode.TRANSPARENCY_SPACE.getPath()));
bungeeRefreshSeconds = config.getInt(ConfigNode.BUNGEE_REFRESH_SECONDS.getPath());
useRedisBungee = config.getBoolean(ConfigNode.BUNGEE_USE_REDIS_BUNGEE.getPath());
pingerEnable = config.getBoolean(ConfigNode.BUNGEE_USE_FULL_PINGER.getPath());
pingerTimeout = config.getInt(ConfigNode.BUNGEE_PINGER_TIMEOUT.getPath());
pingerTrimMotd = config.getBoolean(ConfigNode.BUNGEE_PINGER_TRIM_MOTD.getPath());
pingerOfflineMotd = StringConverter.toReadableFormat(config.getString(ConfigNode.BUNGEE_PINGER_OFFLINE_MOTD.getPath()));
pingerStatusOnline = StringConverter.toReadableFormat(config.getString(ConfigNode.BUNGEE_PINGER_ONLINE_FORMAT.getPath()));
pingerStatusOffline = StringConverter.toReadableFormat(config.getString(ConfigNode.BUNGEE_PINGER_OFFLINE_FORMAT.getPath()));
if (pingerTimeout <= 0) {
pingerTimeout = 100;
} else if (pingerTimeout >= 10000) {
pingerTimeout = 10000;
}
pingerServers = new HashMap<>();
bungeeRefreshSeconds = parseBungeeRefreshInterval(config.bungeeRefreshSeconds);
useRedisBungee = config.useRedisBungee;
pingerEnable = config.pingerEnable;
pingerTimeout = parsePingerTimeout(config.pingerTimeout);
pingerOfflineMotd = StringConverter.toReadableFormat(config.pingerOfflineMotd);
pingerStatusOnline = StringConverter.toReadableFormat(config.pingerStatusOnline);
pingerStatusOffline = StringConverter.toReadableFormat(config.pingerStatusOffline);
pingerTrimMotd = config.pingerTrimMotd;
pingerServers = new ArrayList<>();
if (pingerEnable) {
for (String singleServer : config.getStringList(ConfigNode.BUNGEE_PINGER_SERVERS.getPath())) {
String[] nameAndAddress = singleServer.split(":", 2);
if (nameAndAddress.length < 2) {
Log.warning("The server info \"" + singleServer + "\" is not valid. There should be a name and an address, separated by a colon.");
continue;
for (String singleServer : config.pingerServers) {
ServerAddress serverAddress = parseServerAddress(singleServer);
if (serverAddress != null) {
pingerServers.add(serverAddress);
}
String name = nameAndAddress[0].trim();
String address = nameAndAddress[1].replace(" ", "");
String ip;
int port;
if (address.contains(":")) {
String[] ipAndPort = address.split(":", 2);
ip = ipAndPort[0];
try {
port = Integer.parseInt(ipAndPort[1]);
} catch (NumberFormatException e) {
Log.warning("Invalid port number in the server info \"" + singleServer + "\".");
continue;
}
} else {
ip = address;
port = 25565; // The default Minecraft port.
}
pingerServers.put(name, new ServerAddress(ip, port));
}
}
DebugLogger.setDebugEnabled(config.getBoolean(ConfigNode.DEBUG.getPath()));
DebugLogger.setDebugEnabled(config.debug);
}
String tempColor = config.getString(ConfigNode.TRANSPARENCY_COLOR.getPath()).replace('&', ChatColor.COLOR_CHAR);
boolean foundColor = false;
for (ChatColor chatColor : ChatColor.values()) {
if (chatColor.toString().equals(tempColor)) {
Configuration.transparencyColor = chatColor;
foundColor = true;
}
}
if (!foundColor) {
Configuration.transparencyColor = ChatColor.GRAY;
Log.warning("You didn't set a valid chat color for transparency in the configuration, light gray (&7) will be used.");
}
private static DateTimeFormatter parseTimeFormatter(String pattern, String timeZone) {
DateTimeFormatter timeFormat;
try {
timeFormat = DateTimeFormatter.ofPattern(config.getString(ConfigNode.TIME_FORMAT.getPath()));
timeFormat = DateTimeFormatter.ofPattern(pattern);
} catch (IllegalArgumentException ex) {
timeFormat = DateTimeFormatter.ofPattern("H:mm");
Log.warning("Time format not valid in the configuration, using the default.");
}
try {
timeFormat = timeFormat.withZone(ZoneId.of(config.getString(ConfigNode.TIME_ZONE.getPath())));
timeFormat = timeFormat.withZone(ZoneId.of(timeZone));
} catch (DateTimeException e) {
Log.warning("Time zone not valid in the configuration, using the default.");
}
if (bungeeRefreshSeconds < 1) {
Log.warning("The minimum interval for pinging BungeeCord's servers is 1 second. It has been automatically set.");
bungeeRefreshSeconds = 1;
return timeFormat;
}
private static ChatColor parseTransparencyColor(String transparencyColor) {
transparencyColor = transparencyColor.replace('&', ChatColor.COLOR_CHAR);
for (ChatColor chatColor : ChatColor.values()) {
if (chatColor.toString().equals(transparencyColor)) {
return chatColor;
}
}
if (bungeeRefreshSeconds > 60) {
Log.warning("You didn't set a valid chat color for transparency in the configuration, light gray (&7) will be used.");
return ChatColor.GRAY;
}
private static int parseBungeeRefreshInterval(int interval) {
if (interval < 1) {
Log.warning("The minimum interval for pinging BungeeCord's servers is 1 second. It has been automatically set.");
return 1;
} else if (interval > 60) {
Log.warning("The maximum interval for pinging BungeeCord's servers is 60 seconds. It has been automatically set.");
bungeeRefreshSeconds = 60;
return 60;
} else {
return interval;
}
}
private static int parsePingerTimeout(int timeout) {
if (timeout < 100) {
Log.warning("The minimum timeout for pinging BungeeCord's servers is 100 milliseconds. It has been automatically set.");
return 100;
} else if (timeout > 10000) {
Log.warning("The maximum timeout for pinging BungeeCord's servers is 10000 milliseconds. It has been automatically set.");
return 10000;
} else {
return timeout;
}
}
private static ServerAddress parseServerAddress(String singleServer) {
String[] nameAndAddress = Strings.splitAndTrim(singleServer, ":", 2);
if (nameAndAddress.length < 2) {
Log.warning("The server info \"" + singleServer + "\" is not valid. There should be a name and an address, separated by a colon.");
return null;
}
String name = nameAndAddress[0];
String address = nameAndAddress[1];
String ip;
int port;
if (address.contains(":")) {
String[] ipAndPort = Strings.splitAndTrim(address, ":", 2);
ip = ipAndPort[0];
try {
port = Integer.parseInt(ipAndPort[1]);
} catch (NumberFormatException e) {
Log.warning("Invalid port number in the server info \"" + singleServer + "\".");
return null;
}
} else {
ip = address;
port = 25565; // The default Minecraft port.
}
return new ServerAddress(name, ip, port);
}
}

View File

@ -0,0 +1,55 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.Colors;
import me.filoghost.fcommons.config.ConfigSection;
import me.filoghost.fcommons.config.FileConfig;
import me.filoghost.fcommons.logging.Log;
import java.util.ArrayList;
import java.util.List;
public class CustomPlaceholders {
private static final List<StaticPlaceholder> placeholders = new ArrayList<>();
public static void load(FileConfig config) {
placeholders.clear();
ConfigSection placeholdersSection = config.getConfigSection("placeholders");
if (placeholdersSection == null) {
return;
}
for (String placeholder : placeholdersSection.getKeys()) {
String replacement = Colors.addColors(placeholdersSection.getString(placeholder));
if (replacement == null) {
return;
}
if (placeholder.length() == 0) {
Log.warning("Error in \"" + config.getSourceFile() + "\": placeholder cannot be empty (skipped).");
continue;
}
if (placeholder.length() > 100) {
Log.warning("Error in \"" + config.getSourceFile() + "\": placeholder cannot be longer than 100 character (" + placeholder + ").");
continue;
}
placeholders.add(new StaticPlaceholder(placeholder, replacement));
}
}
public static String replaceStaticPlaceholders(String text) {
for (StaticPlaceholder staticPlaceholder : placeholders) {
text = text.replace(staticPlaceholder.getIdentifier(), staticPlaceholder.getReplacement());
}
return text;
}
}

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.Strings;
import me.filoghost.fcommons.config.ConfigSection;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class HologramConfig {
private static final DecimalFormat LOCATION_NUMBER_FORMAT
= new DecimalFormat("0.000", DecimalFormatSymbols.getInstance(Locale.ROOT));
private final String name;
private final List<String> serializedLines;
private final String serializedLocation;
public HologramConfig(String name, ConfigSection configSection) {
this.name = name;
this.serializedLines = configSection.getStringList("lines");
this.serializedLocation = configSection.getString("location");
}
public HologramConfig(NamedHologram hologram) {
this.name = hologram.getName();
this.serializedLines = new ArrayList<>();
for (CraftHologramLine line : hologram.getLinesUnsafe()) {
serializedLines.add(line.getSerializedConfigValue());
}
this.serializedLocation = serializeLocation(hologram.getLocation());
}
public ConfigSection toConfigSection() {
ConfigSection configSection = new ConfigSection();
configSection.setStringList("lines", serializedLines);
configSection.setString("location", serializedLocation);
return configSection;
}
public NamedHologram createHologram() throws HologramLoadException {
if (serializedLines == null || serializedLines.size() == 0) {
throw new HologramLoadException("hologram \"" + name + "\" was found, but it contained no lines");
}
if (serializedLocation == null) {
throw new HologramLoadException("hologram \"" + name + "\" doesn't have a location set");
}
Location location = deserializeLocation(serializedLocation);
NamedHologram hologram = new NamedHologram(location, name);
for (String serializedLine : serializedLines) {
try {
CraftHologramLine line = HologramLineParser.parseLine(hologram, serializedLine, false);
hologram.getLinesUnsafe().add(line);
} catch (HologramLoadException e) {
// Rethrow with more details
throw new HologramLoadException("hologram \"" + hologram.getName() + "\" has an invalid line: " + e.getMessage(), e);
}
}
return hologram;
}
private String serializeLocation(Location loc) {
return loc.getWorld().getName()
+ ", " + LOCATION_NUMBER_FORMAT.format(loc.getX())
+ ", " + LOCATION_NUMBER_FORMAT.format(loc.getY())
+ ", " + LOCATION_NUMBER_FORMAT.format(loc.getZ());
}
private Location deserializeLocation(String serializedLocation) throws HologramLoadException {
String[] parts = Strings.splitAndTrim(serializedLocation, ",");
if (parts.length != 4) {
throw new HologramLoadException("hologram \"" + name + "\" has an invalid location format:"
+ " it must be \"world, x, y, z\"");
}
try {
String worldName = parts[0];
double x = Double.parseDouble(parts[1]);
double y = Double.parseDouble(parts[2]);
double z = Double.parseDouble(parts[3]);
World world = Bukkit.getWorld(worldName);
if (world == null) {
throw new HologramLoadException("hologram \"" + name + "\""
+ " was in the world \"" + worldName + "\" but it wasn't loaded");
}
return new Location(world, x, y, z);
} catch (NumberFormatException ex) {
throw new HologramLoadException("hologram \"" + name + "\""
+ " has an invalid location format: invalid number");
}
}
public String getName() {
return name;
}
}

View File

@ -5,108 +5,64 @@
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.fcommons.config.Config;
import me.filoghost.fcommons.config.ConfigSection;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.line.CraftHologramLine;
import org.bukkit.Location;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.FileConfiguration;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.Plugin;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map.Entry;
public class HologramDatabase {
private static File file;
private static FileConfiguration config;
private final LinkedHashMap<String, HologramConfig> hologramConfigs;
public static void loadYamlFile(Plugin plugin) {
file = new File(plugin.getDataFolder(), "database.yml");
if (!file.exists()) {
plugin.getDataFolder().mkdirs();
plugin.saveResource("database.yml", true);
}
config = YamlConfiguration.loadConfiguration(file);
public HologramDatabase() {
this.hologramConfigs = new LinkedHashMap<>();
}
public static NamedHologram loadHologram(String name) throws HologramNotFoundException, LocationFormatException, LocationWorldNotLoadedException, HologramLineParseException {
ConfigurationSection configSection = config.getConfigurationSection(name);
public void reloadFromConfig(Config config) {
hologramConfigs.clear();
if (configSection == null) {
throw new HologramNotFoundException("hologram \"" + name + "\" not found, skipping it");
}
List<String> lines = configSection.getStringList("lines");
String locationString = configSection.getString("location");
if (lines == null || locationString == null || lines.size() == 0) {
throw new HologramNotFoundException("hologram \"" + name + "\" was found, but it contained no lines");
}
Location loc = LocationSerializer.locationFromString(name, locationString);
NamedHologram hologram = new NamedHologram(loc, name);
for (String line : lines) {
try {
hologram.getLinesUnsafe().add(HologramLineParser.parseLine(hologram, line, false));
} catch (HologramLineParseException e) {
throw new HologramLineParseException("hologram \"" + hologram.getName() + "\" has an invalid line: " + e.getMessage(), e.getCause());
for (String hologramName : config.getKeys()) {
ConfigSection hologramSection = config.getConfigSection(hologramName);
if (hologramSection == null) {
continue;
}
}
return hologram;
}
public static String serializeHologramLine(CraftHologramLine line) {
return line.getSerializedConfigValue();
}
public static void deleteHologram(String name) {
config.set(name, null);
}
public static void saveHologram(NamedHologram hologram) {
List<String> serializedLines = new ArrayList<>();
for (CraftHologramLine line : hologram.getLinesUnsafe()) {
serializedLines.add(serializeHologramLine(line));
}
ConfigurationSection hologramSection = getOrCreateSection(hologram.getName());
hologramSection.set("location", LocationSerializer.locationToString(hologram.getLocation()));
hologramSection.set("lines", serializedLines);
}
public static Set<String> getHolograms() {
return config.getKeys(false);
}
private static ConfigurationSection getOrCreateSection(String name) {
if (config.isConfigurationSection(name)) {
return config.getConfigurationSection(name);
} else {
return config.createSection(name);
HologramConfig hologramConfig = new HologramConfig(hologramName, hologramSection);
hologramConfigs.put(hologramConfig.getName(), hologramConfig);
}
}
public static void saveToDisk() throws IOException {
if (config != null && file != null) {
config.save(file);
public Config saveToConfig() {
Config config = new Config();
for (Entry<String, HologramConfig> entry : hologramConfigs.entrySet()) {
config.setConfigSection(entry.getKey(), entry.getValue().toConfigSection());
}
config.setHeader(
"",
"Please do NOT edit this file manually if possible.",
""
);
return config;
}
public static void trySaveToDisk() {
try {
saveToDisk();
} catch (IOException ex) {
Log.severe("Unable to save database.yml to disk!", ex);
}
public Collection<HologramConfig> getHolograms() {
return hologramConfigs.values();
}
public void addOrUpdate(NamedHologram hologram) {
HologramConfig hologramConfig = new HologramConfig(hologram);
hologramConfigs.put(hologram.getName(), hologramConfig);
}
public void removeHologram(NamedHologram hologram) {
hologramConfigs.remove(hologram.getName());
}
}

View File

@ -1,18 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
public class HologramLineParseException extends HologramLoadException {
public HologramLineParseException(String message) {
super(message);
}
public HologramLineParseException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -19,12 +19,13 @@ import org.bukkit.inventory.ItemStack;
public class HologramLineParser {
private static final String ICON_PREFIX = "icon:";
public static CraftHologramLine parseLine(NamedHologram hologram, String serializedLine, boolean checkMaterialValidity) throws HologramLineParseException {
public static CraftHologramLine parseLine(NamedHologram hologram, String serializedLine, boolean checkMaterialValidity) throws HologramLoadException {
CraftHologramLine hologramLine;
if (serializedLine.toLowerCase().startsWith("icon:")) {
String serializedIcon = serializedLine.substring("icon:".length());
if (serializedLine.toLowerCase().startsWith(ICON_PREFIX)) {
String serializedIcon = serializedLine.substring(ICON_PREFIX.length());
ItemStack icon = parseItemStack(serializedIcon, checkMaterialValidity);
hologramLine = new CraftItemLine(hologram, icon);
@ -42,7 +43,7 @@ public class HologramLineParser {
@SuppressWarnings("deprecation")
private static ItemStack parseItemStack(String serializedItem, boolean checkMaterialValidity) throws HologramLineParseException {
private static ItemStack parseItemStack(String serializedItem, boolean checkMaterialValidity) throws HologramLoadException {
serializedItem = serializedItem.trim();
// Parse json
@ -69,7 +70,7 @@ public class HologramLineParser {
try {
dataValue = (short) Integer.parseInt(materialAndDataValue[1]);
} catch (NumberFormatException e) {
throw new HologramLineParseException("data value \"" + materialAndDataValue[1] + "\" is not a valid number");
throw new HologramLoadException("data value \"" + materialAndDataValue[1] + "\" is not a valid number");
}
materialName = materialAndDataValue[0];
} else {
@ -79,7 +80,7 @@ public class HologramLineParser {
Material material = MaterialsHelper.matchMaterial(materialName);
if (material == null) {
if (checkMaterialValidity) {
throw new HologramLineParseException("\"" + materialName + "\" is not a valid material");
throw new HologramLoadException("\"" + materialName + "\" is not a valid material");
}
material = Material.BEDROCK;
}
@ -92,9 +93,9 @@ public class HologramLineParser {
MojangsonParser.parse(nbtString);
Bukkit.getUnsafe().modifyItemStack(itemStack, nbtString);
} catch (MojangsonParseException e) {
throw new HologramLineParseException("invalid NBT data, " + e.getMessage());
throw new HologramLoadException("invalid NBT data, " + e.getMessage());
} catch (Throwable t) {
throw new HologramLineParseException("unexpected exception while parsing NBT data", t);
throw new HologramLoadException("unexpected exception while parsing NBT data", t);
}
}

View File

@ -1,14 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
public class HologramNotFoundException extends HologramLoadException {
public HologramNotFoundException(String message) {
super(message);
}
}

View File

@ -1,14 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
public class LocationFormatException extends HologramLoadException {
public LocationFormatException(String message) {
super(message);
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.Strings;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;
public class LocationSerializer {
private static DecimalFormat numberFormat = new DecimalFormat("0.000", DecimalFormatSymbols.getInstance(Locale.ROOT));
public static Location locationFromString(String hologramName, String serializedLocation) throws LocationWorldNotLoadedException, LocationFormatException {
if (serializedLocation == null) {
throw new LocationFormatException("hologram \"" + hologramName + "\" doesn't have a location set");
}
String[] parts = Strings.splitAndTrim(serializedLocation, ",");
if (parts.length != 4) {
throw new LocationFormatException("hologram \"" + hologramName + "\" has an invalid location format:"
+ " it must be \"world, x, y, z\"");
}
try {
String worldName = parts[0];
double x = Double.parseDouble(parts[1]);
double y = Double.parseDouble(parts[2]);
double z = Double.parseDouble(parts[3]);
World world = Bukkit.getWorld(worldName);
if (world == null) {
throw new LocationWorldNotLoadedException("hologram \"" + hologramName + "\""
+ " was in the world \"" + worldName + "\" but it wasn't loaded");
}
return new Location(world, x, y, z);
} catch (NumberFormatException ex) {
throw new LocationFormatException("hologram \"" + hologramName + "\""
+ " has an invalid location format: invalid number");
}
}
public static String locationToString(Location loc) {
return (loc.getWorld().getName() + ", " + numberFormat.format(loc.getX()) + ", " + numberFormat.format(loc.getY()) + ", " + numberFormat.format(loc.getZ()));
}
}

View File

@ -1,14 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
public class LocationWorldNotLoadedException extends HologramLoadException {
public LocationWorldNotLoadedException(String message) {
super(message);
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.config.Config;
import me.filoghost.fcommons.config.mapped.ConfigPath;
import me.filoghost.fcommons.config.mapped.MappedConfig;
import java.util.Arrays;
import java.util.List;
public class MainConfigModel implements MappedConfig {
@ConfigPath("space-between-lines")
double spaceBetweenLines = 0.02;
@ConfigPath("quick-edit-commands")
boolean quickEditCommands = true;
@ConfigPath("images.symbol")
String imageSymbol = "[x]";
@ConfigPath("images.transparency.space")
String transparencySymbol = " [|] ";
@ConfigPath("images.transparency.color")
String transparencyColor = "&7";
@ConfigPath("bungee.refresh-seconds")
int bungeeRefreshSeconds = 3;
@ConfigPath("bungee.use-RedisBungee")
boolean useRedisBungee = false;
@ConfigPath("bungee.pinger.enable")
boolean pingerEnable = false;
@ConfigPath("bungee.pinger.timeout")
int pingerTimeout = 500;
@ConfigPath("bungee.pinger.offline-motd")
String pingerOfflineMotd = "&cOffline, couldn't get the MOTD";
@ConfigPath("bungee.pinger.status.online")
String pingerStatusOnline = "&aOnline";
@ConfigPath("bungee.pinger.status.offline")
String pingerStatusOffline = "&cOffline";
@ConfigPath("bungee.pinger.motd-remove-leading-trailing-spaces")
boolean pingerTrimMotd = true;
@ConfigPath("bungee.pinger.servers")
List<String> pingerServers = Arrays.asList("hub: 127.0.0.1:25565", "games: 127.0.0.1:25566");
@ConfigPath("time.format")
String timeFormat = "H:mm";
@ConfigPath("time.zone")
String timeZone = "GMT+1";
@ConfigPath("update-notification")
boolean updateNotification = true;
@ConfigPath("debug")
boolean debug = false;
@Override
public List<String> getHeader() {
return Arrays.asList(
"",
"Plugin page: https://dev.bukkit.org/projects/holographic-displays",
"",
"Created by filoghost.",
""
);
}
@Override
public boolean beforeSave(Config rawConfig) {
List<String> pathsToRemove = Arrays.asList(
"vertical-spacing",
"time-format",
"bungee-refresh-seconds",
"using-RedisBungee",
"bungee-online-format",
"bungee-offline-format",
"precise-hologram-movement"
);
boolean modified = false;
for (String path : pathsToRemove) {
if (rawConfig.get(path) != null) {
rawConfig.remove(path);
modified = true;
}
}
return modified;
}
}

View File

@ -7,14 +7,20 @@ package me.filoghost.holographicdisplays.disk;
public class ServerAddress {
private String name;
private String ip;
private int port;
public ServerAddress(String ip, int port) {
public ServerAddress(String name, String ip, int port) {
this.name = name;
this.ip = ip;
this.port = port;
}
public String getName() {
return name;
}
public String getAddress() {
return ip;
}
@ -25,7 +31,7 @@ public class ServerAddress {
@Override
public String toString() {
return ip + ":" + port;
return name + " (" + ip + ":" + port + ")";
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
public class StaticPlaceholder {
private final String identifier;
private final String replacement;
public StaticPlaceholder(String identifier, String replacement) {
this.identifier = identifier;
this.replacement = replacement;
}
public String getIdentifier() {
return identifier;
}
public String getReplacement() {
return replacement;
}
}

View File

@ -20,7 +20,7 @@ public class StringConverter {
return null;
}
input = UnicodeSymbols.placeholdersToSymbols(input);
input = CustomPlaceholders.replaceStaticPlaceholders(input);
input = Colors.addColors(input);
return input;
}

View File

@ -1,103 +0,0 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.HolographicDisplays;
import org.apache.commons.lang.StringEscapeUtils;
import org.bukkit.plugin.Plugin;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class UnicodeSymbols {
private static Map<String, String> placeholders = new HashMap<>();
public static void load(Plugin plugin) {
placeholders.clear();
Path file = HolographicDisplays.getDataFolderPath().resolve("symbols.yml");
if (!Files.isRegularFile(file)) {
plugin.saveResource("symbols.yml", true);
}
List<String> lines;
try {
lines = Files.readAllLines(file);
} catch (IOException e) {
Log.warning("I/O error while reading symbols.yml. Was the file in use?", e);
return;
} catch (Exception e) {
Log.warning("Unhandled exception while reading symbols.yml!", e);
return;
}
for (String line : lines) {
// Comment or empty line.
if (line.length() == 0 || line.startsWith("#")) {
continue;
}
if (!line.contains(":")) {
Log.warning("Unable to parse a line(" + line + ") from symbols.yml: it must contain ':' to separate the placeholder and the replacement.");
continue;
}
int indexOf = line.indexOf(':');
String placeholder = unquote(line.substring(0, indexOf).trim());
String replacement = StringEscapeUtils.unescapeJava(unquote(line.substring(indexOf + 1).trim()));
if (placeholder.isEmpty() || replacement.isEmpty()) {
Log.warning("Unable to parse a line(" + line + ") from symbols.yml: the placeholder and the replacement must have both at least 1 character.");
continue;
}
if (placeholder.length() > 30) {
Log.warning("Unable to parse a line(" + line + ") from symbols.yml: the placeholder cannot be longer than 30 characters.");
continue;
}
placeholders.put(placeholder, replacement);
}
}
protected static String placeholdersToSymbols(String input) {
for (Entry<String, String> entry : placeholders.entrySet()) {
input = input.replace(entry.getKey(), entry.getValue());
}
return input;
}
private static String unquote(String input) {
if (input.length() < 2) {
// Cannot be quoted.
return input;
}
if (input.startsWith("'") && input.endsWith("'")) {
return input.substring(1, input.length() - 1);
} else if (input.startsWith("\"") && input.endsWith("\"")) {
return input.substring(1, input.length() - 1);
}
return input;
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (C) filoghost and contributors
*
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package me.filoghost.holographicdisplays.disk.upgrade;
import me.filoghost.fcommons.Strings;
import me.filoghost.fcommons.config.Config;
import me.filoghost.fcommons.config.ConfigErrors;
import me.filoghost.fcommons.config.ConfigLoader;
import me.filoghost.fcommons.config.exception.ConfigLoadException;
import me.filoghost.fcommons.config.exception.ConfigSaveException;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.disk.ConfigManager;
import org.apache.commons.lang.StringEscapeUtils;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
public class LegacySymbolsUpgrader {
public static void run(ConfigManager configManager) throws ConfigLoadException, ConfigSaveException {
Path oldFile = configManager.getRootDataFolder().resolve("symbols.yml");
ConfigLoader newConfigLoader = configManager.getConfigLoader("custom-placeholders.yml");
Path newFile = newConfigLoader.getFile();
if (!Files.isRegularFile(oldFile)) {
return; // Old file doesn't exist, ignore upgrade
}
if (Files.isRegularFile(newFile)) {
return; // Already created, do not override
}
Config newConfig = new Config();
List<String> lines;
try {
lines = Files.readAllLines(oldFile);
} catch (IOException e) {
throw new ConfigLoadException(ConfigErrors.readIOException, e);
}
for (String line : lines) {
// Comment or empty line
if (line.isEmpty() || line.startsWith("#")) {
continue;
}
// Ignore bad line
if (!line.contains(":")) {
Log.warning("Couldn't convert invalid line in " + oldFile.getFileName() + ": " + line);
continue;
}
String[] parts = Strings.splitAndTrim(line, ":", 2);
String placeholder = unquote(parts[0]);
String replacement = StringEscapeUtils.unescapeJava(unquote(parts[1]));
newConfig.setString("placeholders." + placeholder, replacement);
}
try {
Files.move(oldFile, oldFile.resolveSibling("symbols.yml.backup"));
} catch (IOException e) {
Log.warning("Couldn't rename " + oldFile.getFileName(), e);
}
newConfigLoader.save(newConfig);
}
private static String unquote(String input) {
if (input.length() < 2) {
// Too short, cannot be a quoted string
return input;
}
if (input.startsWith("'") && input.endsWith("'")) {
return input.substring(1, input.length() - 1);
} else if (input.startsWith("\"") && input.endsWith("\"")) {
return input.substring(1, input.length() - 1);
}
return input;
}
}

View File

@ -7,30 +7,33 @@ package me.filoghost.holographicdisplays.task;
import me.filoghost.fcommons.logging.Log;
import me.filoghost.holographicdisplays.common.Utils;
import me.filoghost.holographicdisplays.disk.HologramDatabase;
import me.filoghost.holographicdisplays.disk.HologramConfig;
import me.filoghost.holographicdisplays.disk.HologramLoadException;
import me.filoghost.holographicdisplays.object.NamedHologram;
import me.filoghost.holographicdisplays.object.NamedHologramManager;
import java.util.Set;
import java.util.Collection;
public class StartupLoadHologramsTask implements Runnable {
private Collection<HologramConfig> hologramConfigsToLoad;
public StartupLoadHologramsTask(Collection<HologramConfig> hologramConfigsToLoad) {
this.hologramConfigsToLoad = hologramConfigsToLoad;
}
@Override
public void run() {
Set<String> savedHologramsNames = HologramDatabase.getHolograms();
if (savedHologramsNames != null) {
for (String hologramName : savedHologramsNames) {
try {
NamedHologram namedHologram = HologramDatabase.loadHologram(hologramName);
NamedHologramManager.addHologram(namedHologram);
namedHologram.refreshAll();
} catch (HologramLoadException e) {
Log.warning(Utils.formatExceptionMessage(e));
} catch (Exception e) {
Log.warning("Unexpected exception while loading the hologram \"" + hologramName + "\"."
+ " Please contact the developer.", e);
}
for (HologramConfig hologramConfig : hologramConfigsToLoad) {
try {
NamedHologram hologram = hologramConfig.createHologram();
NamedHologramManager.addHologram(hologram);
hologram.refreshAll();
} catch (HologramLoadException e) {
Log.warning(Utils.formatExceptionMessage(e));
} catch (Exception e) {
Log.warning("Unexpected exception while loading the hologram \"" + hologramConfig.getName() + "\"."
+ " Please contact the developer.", e);
}
}
}

View File

@ -1,20 +0,0 @@
#.
#. Read the tutorial at: http://dev.bukkit.org/bukkit-plugins/holographic-displays/
#.
#. Plugin created by filoghost.
#.
space-between-lines: 0.02
quick-edit-commands: true
images:
symbol: '[x]'
transparency:
space: ' [|] '
color: '&7'
bungee:
refresh-seconds: 3
use-RedisBungee: false
time:
format: H:mm
zone: GMT+1
update-notification: true
debug: false

View File

@ -0,0 +1,14 @@
#
# This is the configuration file for custom placeholders.
# Dynamic placeholders are {online}, {max_players}...
#
# You can use these to avoid repeating text multiple times,
# and edit it from a single location.
#
# Another use would be for defining colors, symbols, or text decorations.
#
placeholders:
'{custom_placeholder}': 'This is a custom placeholder.'
'{primary_color}': '&b'
'{secondary_color}': '&7'
'{separator}': '&8&m '

View File

@ -1,3 +0,0 @@
#.
#. Please do NOT edit this file manually.
#.

View File

@ -1,14 +0,0 @@
#
# This is the configuration file for static placeholders.
# Dynamic placeholders are {online}, {max_players}, ...
# Static placeholders are symbols.
#
# List of unicode symbols: http://www.fileformat.info/info/unicode/index.htm
#
[x]: \u2588
[/]: \u258C
[.]: \u2591
[..]: \u2592
[...]: \u2593
[p]: \u2022
[|]: \u23B9