Skip to content

Commit

Permalink
Improve configuration handling, readd ability to reload
Browse files Browse the repository at this point in the history
  • Loading branch information
RealTriassic committed Oct 12, 2024
1 parent e95b11e commit 91cc2dc
Show file tree
Hide file tree
Showing 9 changed files with 217 additions and 146 deletions.
69 changes: 39 additions & 30 deletions src/main/java/com/triassic/geyserdebuginfo/GeyserDebugInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

import com.triassic.geyserdebuginfo.command.commands.ReloadCommand;
import com.triassic.geyserdebuginfo.command.commands.ToggleCommand;
import com.triassic.geyserdebuginfo.configuration.ConfigurationLoader;
import com.triassic.geyserdebuginfo.configuration.Configuration;
import com.triassic.geyserdebuginfo.configuration.ConfigurationContainer;
import com.triassic.geyserdebuginfo.listener.PlayerJoinListener;
import com.triassic.geyserdebuginfo.manager.BossBarManager;
import com.triassic.geyserdebuginfo.manager.PlaceholderManager;
Expand All @@ -18,14 +18,19 @@
import org.geysermc.geyser.api.event.lifecycle.GeyserPreInitializeEvent;
import org.geysermc.geyser.api.event.lifecycle.GeyserShutdownEvent;
import org.geysermc.geyser.api.extension.Extension;
import org.geysermc.geyser.api.extension.ExtensionLogger;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;

public class GeyserDebugInfo implements Extension {

private File dataFolder;

@Getter
private Path dataFolder;
@Getter
private ExtensionLogger logger;
@Getter
private Configuration config;
@Getter
Expand All @@ -35,23 +40,34 @@ public class GeyserDebugInfo implements Extension {
@Getter
private PlaceholderManager placeholderManager;

/**
* Initializes the extension.
* Sets up the data folder, loads configuration,
* and registers event listeners.
*/
private ConfigurationContainer configContainer;

@Subscribe
public void onPostInitialize(GeyserPreInitializeEvent event) {
public void onPreInitialize(GeyserPreInitializeEvent event) {
long startTime = System.currentTimeMillis();

this.dataFolder = this.dataFolder().toFile();
if (!dataFolder.exists() && !dataFolder.mkdirs())
logger().error("Failed to create data folder " + dataFolder.getAbsolutePath());
this.logger = logger();
this.dataFolder = dataFolder();

try {
if (Files.notExists(dataFolder))
Files.createDirectories(dataFolder);
} catch (IOException e) {
logger.error("Failed to create data folder " + dataFolder.toAbsolutePath(), e);
extensionManager().disable(this);
return;
}

this.configContainer = new ConfigurationContainer(dataFolder, logger, Configuration.class);
this.config = configContainer.get();

this.config = new ConfigurationLoader(this)
.load(Configuration.class);
if (config == null) {
logger.error("Failed to load the configuration. Please check config.yml for issues.");
extensionManager().disable(this);
return;
}

this.playerDataManager = new PlayerDataManager(dataFolder, this.logger(), false);
this.playerDataManager = new PlayerDataManager(this.dataFolder().toFile(), logger(), false);
this.placeholderManager = new PlaceholderManager();
this.bossBarManager = new BossBarManager(this);
this.eventBus().register(new PlayerJoinListener(this));
Expand All @@ -66,15 +82,7 @@ public void onPostInitialize(GeyserPreInitializeEvent event) {
new TextModifierProvider()
).forEach(placeholderManager::registerProvider);

logger().info("Enabled in " + (System.currentTimeMillis() - startTime) + "ms");
}

/**
* Loads the configuration file from the specified data folder.
* This method attempts to load the configuration file and logs an error if the process fails.
*/
private void loadConfig() {

logger.info("Enabled in " + (System.currentTimeMillis() - startTime) + "ms");
}

/**
Expand All @@ -98,10 +106,11 @@ public void onShutdown(GeyserShutdownEvent event) {
playerDataManager.savePlayerData();
}

/**
* Reloads the configuration settings.
*/
public synchronized void reload() {
// TODO: add reloading for configuration.
public boolean reloadConfig() {
boolean reloaded = configContainer.reload();
if (reloaded)
this.config = configContainer.get();

return reloaded;
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.triassic.geyserdebuginfo.command.commands;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.command.CommandSource;
import com.triassic.geyserdebuginfo.GeyserDebugInfo;
import com.triassic.geyserdebuginfo.command.Command;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.command.CommandSource;

public class ReloadCommand implements Command {

Expand All @@ -29,7 +29,11 @@ public org.geysermc.geyser.api.command.Command createCommand() {
}

private void execute(@NonNull CommandSource commandSource, org.geysermc.geyser.api.command.Command command, @NonNull String[] strings) {
instance.reload();
commandSource.sendMessage("§aGeyserDebugInfo configuration has been reloaded.");
if (instance.reloadConfig()) {
commandSource.sendMessage("§aGeyserDebugInfo configuration has been reloaded.");
System.out.println(instance.getConfig().getConfigVersion());
} else {
commandSource.sendMessage("§cFailed to reload GeyserDebugInfo configuration, check console for details.");
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.triassic.geyserdebuginfo.command.commands;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.session.GeyserSession;
import com.triassic.geyserdebuginfo.GeyserDebugInfo;
import com.triassic.geyserdebuginfo.command.Command;
import com.triassic.geyserdebuginfo.manager.BossBarManager;
import com.triassic.geyserdebuginfo.manager.PlayerDataManager;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.geysermc.geyser.api.command.CommandSource;
import org.geysermc.geyser.entity.type.player.SessionPlayerEntity;
import org.geysermc.geyser.session.GeyserSession;

public class ToggleCommand implements Command {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,72 @@

import lombok.Getter;
import org.spongepowered.configurate.objectmapping.ConfigSerializable;
import org.spongepowered.configurate.objectmapping.meta.Comment;
import org.spongepowered.configurate.objectmapping.meta.Setting;

import java.util.Arrays;
import java.util.List;

@Getter
@ConfigSerializable
@SuppressWarnings("FieldMayBeFinal")
public class Configuration {

private long refreshInterval = 50;
private List<String> displayFormat = Arrays.asList(
"Geyser Debug Information",
"",
"%player_world%",
"",
"XYZ: %player_x% / %player_y% / %player_z%",
"Block: %player_x:floor% %player_y:floor% %player_z:floor% [%player_relative_x% %player_relative_y% %player_relative_z%]",
"Chunk: %player_chunk_x% %player_chunk_y% %player_chunk_z% [%player_global_x% %player_global_z% in %player_region_file%]",
"Facing: %player_facing% (%player_yaw% / %player_pitch%)"
);
@Setting("display")
private Display display = new Display();

@Setting("config-version")
@Comment("Used internally, do not change.")
private int configVersion = 1;

@Getter
@ConfigSerializable
public static class Display {

@Setting("actionbar")
private ActionBar actionBar = new ActionBar();

@Setting("bossbar")
private BossBar bossBar = new BossBar();

@Getter
@ConfigSerializable
public static class ActionBar {
@Setting("enabled")
private boolean enabled = true;

@Setting("visible-by-default")
private boolean visibleByDefault = false;

@Setting("refresh-interval")
private int refreshInterval = 50;

@Setting("text")
private String text = "%player_x% %player_y% %player_z%";
}

@Getter
@ConfigSerializable
public static class BossBar {
@Setting("enabled")
private boolean enabled = true;

@Setting("visible-by-default")
private boolean visibleByDefault = false;

@Setting("refresh-interval")
private int refreshInterval = 50;

@Setting("text")
private List<String> text = List.of(
"Geyser Debug Information",
"",
"%player_world%",
"",
"XYZ: %player_x% / %player_y% / %player_z%",
"Block: %player_x:floor% %player_y:floor% %player_z:floor% [%player_relative_x% %player_relative_y% %player_relative_z%]",
"Chunk: %player_chunk_x% %player_chunk_y% %player_chunk_z% [%player_global_x% %player_global_z% in %player_region_file%]",
"Facing: %player_facing% (%player_yaw% / %player_pitch%)"
);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package com.triassic.geyserdebuginfo.configuration;

import org.geysermc.geyser.api.extension.ExtensionLogger;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.configurate.CommentedConfigurationNode;
import org.spongepowered.configurate.yaml.NodeStyle;
import org.spongepowered.configurate.yaml.YamlConfigurationLoader;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.atomic.AtomicReference;

public class ConfigurationContainer {

private static final String HEADER = """
GeyserDebugInfo Configuration File
A Geyser extension that strives to provide F3-like debug information for Bedrock Edition players.
Report any issues on our GitHub repository:
https://github.com/RealTriassic/GeyserDebugInfo""";

private final Path configFile;
private final ExtensionLogger logger;
private final YamlConfigurationLoader loader;
private final Class<? extends Configuration> configClass;
private final AtomicReference<Configuration> config = new AtomicReference<>();

public ConfigurationContainer(
final Path dataFolder,
final ExtensionLogger logger,
final Class<? extends Configuration> configClass) {
this.logger = logger;
this.configClass = configClass;
this.configFile = dataFolder.resolve("config.yml");

this.loader = YamlConfigurationLoader.builder()
.indent(2)
.path(configFile)
.nodeStyle(NodeStyle.BLOCK)
.defaultOptions(options -> options
.shouldCopyDefaults(true)
.header(HEADER))
.build();

this.load();
}

/**
* Loads the configuration from the file.
* If loading fails, the previous configuration is retained.
*
* @return true if the configuration was loaded successfully, false otherwise.
*/
private boolean load() {
try {
final Configuration loadedConfig = loadConfig();
config.set(loadedConfig);
return true;
} catch (Throwable e) {
logger.error("Failed to load configuration", e);
return false;
}
}

/**
* Loads the configuration from the file and creates a new Configuration object.
*
* @return the loaded Configuration object.
* @throws IOException if an error occurs while reading or parsing the file.
*/
private Configuration loadConfig() throws IOException {
CommentedConfigurationNode node = loader.load();
Configuration loadedConfig = node.get(configClass);

if (Files.notExists(configFile)) {
node.set(configClass, loadedConfig);
loader.save(node);
}

return loadedConfig;
}

/**
* Reloads the configuration from the file.
* If reloading fails, the previous configuration is retained.
*
* @return true if the configuration was reloaded successfully, false otherwise.
*/
public boolean reload() {
return load();
}

@Nullable
public Configuration get() {
return config.get();
}
}
Loading

0 comments on commit 91cc2dc

Please sign in to comment.