diff --git a/build.gradle b/build.gradle index 34f56a6..76732e6 100644 --- a/build.gradle +++ b/build.gradle @@ -37,6 +37,7 @@ dependencies { implementation "com.github.robertlit:SpigotResourcesAPI:2.0" implementation "net.kyori:adventure-platform-bukkit:4.3.0" implementation "com.github.retrooper.packetevents:spigot:2.0.0-SNAPSHOT" + implementation "space.arim.dazzleconf:dazzleconf-ext-snakeyaml:1.2.1" } group "lol.pyr" @@ -55,8 +56,12 @@ shadowJar { relocate "org.checkerframework", "lol.pyr.znpcsplus.lib.checkerframework" relocate "javax.annotation", "lol.pyr.znpcsplus.lib.javaxannotation" relocate "com.google", "lol.pyr.znpcsplus.lib.google" + relocate "com.github.retrooper.packetevents", "lol.pyr.znpcsplus.lib.packetevents.api" relocate "io.github.retrooper.packetevents", "lol.pyr.znpcsplus.lib.packetevents.impl" + + relocate "org.yaml.snakeyaml", "lol.pyr.znpcsplus.lib.snakeyaml" + relocate "space.arim.dazzleconf", "lol.pyr.znpcsplus.lib.dazzleconf" minimize() } diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java deleted file mode 100644 index 751c110..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/Configuration.java +++ /dev/null @@ -1,74 +0,0 @@ -package io.github.znetworkw.znpcservers.configuration; - -import com.google.gson.JsonElement; -import com.google.gson.JsonParser; -import com.google.gson.internal.$Gson$Types; -import io.github.znetworkw.znpcservers.utility.Utils; -import lol.pyr.znpcsplus.ZNPCsPlus; - -import java.io.IOException; -import java.io.Reader; -import java.io.Writer; -import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; -import java.nio.file.Path; -import java.util.Map; -import java.util.stream.Collectors; - -public class Configuration { - private static final Charset CHARSET = StandardCharsets.UTF_8; - private final String name; - private final Path path; - private final Map configurationValues; - public static final Configuration CONFIGURATION = new Configuration("config"); - public static final Configuration MESSAGES = new Configuration("messages"); - - protected Configuration(String name) { - this(name, ZNPCsPlus.PLUGIN_FOLDER.toPath().resolve(name + ".json")); - } - - private Configuration(String name, Path path) { - if (!path.getFileName().toString().endsWith(".json")) throw new IllegalStateException("Invalid configuration format for: " + path.getFileName()); - this.name = name; - this.path = path; - this.configurationValues = ConfigurationValue.VALUES_BY_NAME.get(name).stream().collect(Collectors.toMap((c) -> c, ConfigurationValue::getValue)); - this.onLoad(); - this.save(); - } - - protected void onLoad() { - try (Reader reader = Files.newBufferedReader(this.path, CHARSET)) { - JsonElement data = JsonParser.parseReader(reader); - if (data == null) return; - for(ConfigurationValue configValue : this.configurationValues.keySet()) { - boolean single = this.configurationValues.size() == 1; - JsonElement jsonElement = single ? data : (data.isJsonObject() ? data.getAsJsonObject().get(configValue.name()) : null); - if (jsonElement == null || jsonElement.isJsonNull()) continue; - if (!single && configValue.getPrimitiveType().isEnum()) this.configurationValues.put(configValue, ZNPCsPlus.GSON.fromJson(jsonElement, configValue.getPrimitiveType())); - else this.configurationValues.put(configValue, ZNPCsPlus.GSON.fromJson(jsonElement, $Gson$Types.newParameterizedTypeWithOwner(null, configValue.getValue().getClass(), configValue.getPrimitiveType()))); - } - } catch (NoSuchFileException ignored) { - } catch (IOException ex) { - throw new IllegalStateException("Failed to read configuration: " + this.name); - } - } - - public void save() { - try (Writer writer = Files.newBufferedWriter(this.path, CHARSET)) { - ZNPCsPlus.GSON.toJson(this.configurationValues.size() == 1 ? this.configurationValues.values().iterator().next() : this.configurationValues, writer); - } catch (IOException ex) { - throw new IllegalStateException("Failed to save configuration: " + this.name); - } - } - - @SuppressWarnings("unchecked") - public T getValue(ConfigurationValue configValue) { - return (T)this.configurationValues.get(configValue); - } - - public void sendMessage(org.bukkit.command.CommandSender sender, ConfigurationValue configValue, Object... replaces) { - sender.sendMessage(Utils.toColor(String.format(this.getValue(configValue), replaces))); - } -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java deleted file mode 100644 index 6b7500b..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationConstants.java +++ /dev/null @@ -1,8 +0,0 @@ -package io.github.znetworkw.znpcservers.configuration; - -public final class ConfigurationConstants { - public static final String SPACE_SYMBOL = Configuration.CONFIGURATION.getValue(ConfigurationValue.REPLACE_SYMBOL); - public static final boolean DEBUG_ENABLED = Configuration.CONFIGURATION.getValue(ConfigurationValue.DEBUG_ENABLED); - public static final int VIEW_DISTANCE = Configuration.CONFIGURATION.getValue(ConfigurationValue.VIEW_DISTANCE); - public static final boolean CHECK_FOR_UPDATES = Configuration.CONFIGURATION.getValue(ConfigurationValue.CHECK_FOR_UPDATES); -} diff --git a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java b/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java deleted file mode 100644 index b14cfef..0000000 --- a/src/main/java/io/github/znetworkw/znpcservers/configuration/ConfigurationValue.java +++ /dev/null @@ -1,77 +0,0 @@ -package io.github.znetworkw.znpcservers.configuration; - -import com.google.common.collect.ImmutableSet; -import io.github.znetworkw.znpcservers.utility.GuavaCollectors; - -import java.util.Arrays; -import java.util.Map; -import java.util.stream.Collectors; - -public enum ConfigurationValue { - VIEW_DISTANCE("config", 32, Integer.class), - REPLACE_SYMBOL("config", "-", String.class), - SAVE_NPCS_DELAY_SECONDS("config", 600, Integer.class), - MAX_PATH_LOCATIONS("config", 500, Integer.class), - DEBUG_ENABLED("config", false, Boolean.class), - LINE_SPACING("config", 0.3D, Double.class), - ANIMATION_RGB("config", false, Boolean.class), - CHECK_FOR_UPDATES("config", true, Boolean.class), - NO_PERMISSION("messages", "&cYou do not have permission to execute this command.", String.class), - SUCCESS("messages", "&aSuccess!", String.class), - INCORRECT_USAGE("messages", "&cThe arguments you specified are invalid. Type &f/znpcs&c for examples.", String.class), - COMMAND_NOT_FOUND("messages", "&cThe command you specified does not exist!", String.class), - COMMAND_ERROR("messages", "&cAn error occurred when executing this command. See console for more information.", String.class), - INVALID_NUMBER("messages", "&cThe ID you have specified is invalid. Please use positive integers only!", String.class), - NPC_NOT_FOUND("messages", "&cNo NPCs could be found with this ID!", String.class), - TOO_FEW_ARGUMENTS("messages", "&cThis command does not contain enough arguments. Type &f/znpcs&c or view our documentation for a list/examples of existing arguments.", String.class), - PATH_START("messages", "&aSuccess! Move to create a path for your NPC. When finished, type &f/znpcs path exit&c to exit path creation.", String.class), - EXIT_PATH("messages", "&cYou have exited path creation.", String.class), - PATH_FOUND("messages", "&cThere is already a path with this name.", String.class), - NPC_FOUND("messages", "&cThere is already an NPC with this ID.", String.class), - NO_PATH_FOUND("messages", "&cThe path you have specified does not exist.", String.class), - NO_SKIN_FOUND("messages", "&cThe skin username/URL you have specified does not exist or is invalid.", String.class), - NO_NPC_FOUND("messages", "&cThe NPC you have specified does not exist.", String.class), - NO_ACTION_FOUND("messages", "&cThis action does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing action types.", String.class), - METHOD_NOT_FOUND("messages", "&cThis method does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing methods.", String.class), - INVALID_NAME_LENGTH("messages", "&cThe name you specified either too short or long. Please enter a positive integer of (3 to 16) characters.", String.class), - UNSUPPORTED_ENTITY("messages", "&cThis entity type not available in your current server version.", String.class), - PATH_SET_INCORRECT_USAGE("messages", "&eUsage: &aset ", String.class), - ACTION_ADD_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), - ACTION_DELAY_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), - CONVERSATION_SET_INCORRECT_USAGE("messages", "&cUsage: ", String.class), - NO_CONVERSATION_FOUND("messages", "&cThe conversation you have specified does not exist!", String.class), - CONVERSATION_FOUND("messages", "&cThere is already a conversation with this name.", String.class), - INVALID_SIZE("messages", "&cThe position you have specified cannot exceed the limit.", String.class), - FETCHING_SKIN("messages", "&aFetching skin for name: &f%s&a. Please wait...", String.class), - CANT_GET_SKIN("messages", "&cCould not fetch skin for name: %s.", String.class), - GET_SKIN("messages", "&aSkin successfully fetched!", String.class), - NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class); - - public static final Map> VALUES_BY_NAME; - - static { - VALUES_BY_NAME = Arrays.stream(values()).collect(Collectors.groupingBy(ConfigurationValue::getConfigName, GuavaCollectors.toImmutableSet())); - } - - private final String configName; - private final Object value; - private final Class primitiveType; - - ConfigurationValue(String configName, Object value, Class primitiveType) { - this.configName = configName; - this.value = value; - this.primitiveType = primitiveType; - } - - public String getConfigName() { - return this.configName; - } - - public Object getValue() { - return this.value; - } - - public Class getPrimitiveType() { - return this.primitiveType; - } -} diff --git a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java index 2b30206..58d850c 100644 --- a/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java +++ b/src/main/java/lol/pyr/znpcsplus/ZNPCsPlus.java @@ -6,11 +6,11 @@ import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; import io.github.znetworkw.znpcservers.listeners.InventoryListener; import io.github.znetworkw.znpcservers.utility.BungeeUtils; import io.github.znetworkw.znpcservers.utility.SchedulerUtils; import io.github.znetworkw.znpcservers.utility.itemstack.ItemStackSerializer; +import lol.pyr.znpcsplus.config.Configs; import lol.pyr.znpcsplus.entity.EntityProperty; import lol.pyr.znpcsplus.entity.PacketLocation; import lol.pyr.znpcsplus.interaction.InteractionPacketListener; @@ -110,6 +110,9 @@ public class ZNPCsPlus extends JavaPlugin { PLUGIN_FOLDER.mkdirs(); PATH_FOLDER.mkdirs(); + log(ChatColor.WHITE + " * Loading configurations..."); + Configs.init(PLUGIN_FOLDER); + log(ChatColor.WHITE + " * Registering components..."); getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord"); new Metrics(this, PLUGIN_ID); @@ -122,13 +125,13 @@ public class ZNPCsPlus extends JavaPlugin { new InventoryListener(this); new SkinCacheCleanTask(this); new UserListener(this); - if (ConfigurationConstants.CHECK_FOR_UPDATES) new UpdateNotificationListener(this, new UpdateChecker(this)); + if (Configs.config().checkForUpdates()) new UpdateNotificationListener(this, new UpdateChecker(this)); enabled = true; log(ChatColor.WHITE + " * Loading complete! (" + (System.currentTimeMillis() - before) + "ms)"); log(""); - if (ConfigurationConstants.DEBUG_ENABLED) { + if (Configs.config().debugEnabled()) { int wrap = 20; int x = 0; int z = 0; diff --git a/src/main/java/lol/pyr/znpcsplus/config/Configs.java b/src/main/java/lol/pyr/znpcsplus/config/Configs.java new file mode 100644 index 0000000..b367878 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/config/Configs.java @@ -0,0 +1,58 @@ +package lol.pyr.znpcsplus.config; + +import lol.pyr.znpcsplus.ZNPCsPlus; +import space.arim.dazzleconf.ConfigurationFactory; +import space.arim.dazzleconf.ConfigurationOptions; +import space.arim.dazzleconf.error.ConfigFormatSyntaxException; +import space.arim.dazzleconf.error.InvalidConfigException; +import space.arim.dazzleconf.ext.snakeyaml.CommentMode; +import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlConfigurationFactory; +import space.arim.dazzleconf.ext.snakeyaml.SnakeYamlOptions; +import space.arim.dazzleconf.helper.ConfigurationHelper; + +import java.io.File; +import java.io.IOException; + +public class Configs { + private volatile static MainConfig config; + private static ConfigurationHelper configHelper; + + private volatile static MessageConfig messages; + private static ConfigurationHelper messagesHelper; + + private static ConfigurationHelper createHelper(Class configClass, File file) { + SnakeYamlOptions yamlOptions = new SnakeYamlOptions.Builder().commentMode(CommentMode.fullComments()).build(); + ConfigurationFactory configFactory = SnakeYamlConfigurationFactory.create(configClass, ConfigurationOptions.defaults(), yamlOptions); + return new ConfigurationHelper<>(file.getParentFile().toPath(), file.getName(), configFactory); + } + + public static void init(File pluginFolder) { + configHelper = createHelper(MainConfig.class, new File(pluginFolder, "config.yaml")); + messagesHelper = createHelper(MessageConfig.class, new File(pluginFolder, "messages.yaml")); + load(); + } + + public static void load() { + try { + config = configHelper.reloadConfigData(); + messages = messagesHelper.reloadConfigData(); + } catch (IOException e) { + ZNPCsPlus.LOGGER.severe("Couldn't open config file!"); + e.printStackTrace(); + } catch (ConfigFormatSyntaxException e) { + ZNPCsPlus.LOGGER.severe("Invalid config syntax!"); + e.printStackTrace(); + } catch (InvalidConfigException e) { + ZNPCsPlus.LOGGER.severe("Invalid config value!"); + e.printStackTrace(); + } + } + + public static MainConfig config() { + return config; + } + + public static MessageConfig messages() { + return messages; + } +} diff --git a/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java b/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java new file mode 100644 index 0000000..0bfe954 --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/config/MainConfig.java @@ -0,0 +1,24 @@ +package lol.pyr.znpcsplus.config; + +import space.arim.dazzleconf.annote.ConfKey; + +import static space.arim.dazzleconf.annote.ConfDefault.*; + +// TODO: Add comments to the values using @ConfComments() +public interface MainConfig { + @ConfKey("view-distance") + @DefaultInteger(32) + int viewDistance(); + + @ConfKey("line-spacing") + @DefaultDouble(0.3D) + double lineSpacing(); + + @ConfKey("debug-enabled") + @DefaultBoolean(false) + boolean debugEnabled(); + + @ConfKey("check-for-updates") + @DefaultBoolean(true) + boolean checkForUpdates(); +} diff --git a/src/main/java/lol/pyr/znpcsplus/config/MessageConfig.java b/src/main/java/lol/pyr/znpcsplus/config/MessageConfig.java new file mode 100644 index 0000000..757f6af --- /dev/null +++ b/src/main/java/lol/pyr/znpcsplus/config/MessageConfig.java @@ -0,0 +1,38 @@ +package lol.pyr.znpcsplus.config; + +/** + * (OLD CONFIGURATION) + * NO_PERMISSION("messages", "&cYou do not have permission to execute this command.", String.class), + * SUCCESS("messages", "&aSuccess!", String.class), + * INCORRECT_USAGE("messages", "&cThe arguments you specified are invalid. Type &f/znpcs&c for examples.", String.class), + * COMMAND_NOT_FOUND("messages", "&cThe command you specified does not exist!", String.class), + * COMMAND_ERROR("messages", "&cAn error occurred when executing this command. See console for more information.", String.class), + * INVALID_NUMBER("messages", "&cThe ID you have specified is invalid. Please use positive integers only!", String.class), + * NPC_NOT_FOUND("messages", "&cNo NPCs could be found with this ID!", String.class), + * TOO_FEW_ARGUMENTS("messages", "&cThis command does not contain enough arguments. Type &f/znpcs&c or view our documentation for a list/examples of existing arguments.", String.class), + * PATH_START("messages", "&aSuccess! Move to create a path for your NPC. When finished, type &f/znpcs path exit&c to exit path creation.", String.class), + * EXIT_PATH("messages", "&cYou have exited path creation.", String.class), + * PATH_FOUND("messages", "&cThere is already a path with this name.", String.class), + * NPC_FOUND("messages", "&cThere is already an NPC with this ID.", String.class), + * NO_PATH_FOUND("messages", "&cThe path you have specified does not exist.", String.class), + * NO_SKIN_FOUND("messages", "&cThe skin username/URL you have specified does not exist or is invalid.", String.class), + * NO_NPC_FOUND("messages", "&cThe NPC you have specified does not exist.", String.class), + * NO_ACTION_FOUND("messages", "&cThis action does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing action types.", String.class), + * METHOD_NOT_FOUND("messages", "&cThis method does not exist! Type &f/znpcs&c or view our documentation for a list/examples of existing methods.", String.class), + * INVALID_NAME_LENGTH("messages", "&cThe name you specified either too short or long. Please enter a positive integer of (3 to 16) characters.", String.class), + * UNSUPPORTED_ENTITY("messages", "&cThis entity type not available in your current server version.", String.class), + * PATH_SET_INCORRECT_USAGE("messages", "&eUsage: &aset ", String.class), + * ACTION_ADD_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), + * ACTION_DELAY_INCORRECT_USAGE("messages", "&eUsage: &a ", String.class), + * CONVERSATION_SET_INCORRECT_USAGE("messages", "&cUsage: ", String.class), + * NO_CONVERSATION_FOUND("messages", "&cThe conversation you have specified does not exist!", String.class), + * CONVERSATION_FOUND("messages", "&cThere is already a conversation with this name.", String.class), + * INVALID_SIZE("messages", "&cThe position you have specified cannot exceed the limit.", String.class), + * FETCHING_SKIN("messages", "&aFetching skin for name: &f%s&a. Please wait...", String.class), + * CANT_GET_SKIN("messages", "&cCould not fetch skin for name: %s.", String.class), + * GET_SKIN("messages", "&aSkin successfully fetched!", String.class), + * NOT_SUPPORTED_NPC_TYPE("messages", "&cThis NPC type doesn't exists or is not supported in your current server version.", String.class); + */ + +public interface MessageConfig { +} diff --git a/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java index 59a5d97..6a9f105 100644 --- a/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java +++ b/src/main/java/lol/pyr/znpcsplus/tasks/NPCVisibilityTask.java @@ -1,12 +1,13 @@ package lol.pyr.znpcsplus.tasks; -import io.github.znetworkw.znpcservers.configuration.ConfigurationConstants; +import lol.pyr.znpcsplus.config.Configs; import lol.pyr.znpcsplus.npc.NPC; import lol.pyr.znpcsplus.npc.NPCRegistry; import org.bukkit.Bukkit; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.util.NumberConversions; public class NPCVisibilityTask extends BukkitRunnable { public NPCVisibilityTask(Plugin plugin) { @@ -14,7 +15,7 @@ public class NPCVisibilityTask extends BukkitRunnable { } public void run() { - int distSq = ConfigurationConstants.VIEW_DISTANCE * ConfigurationConstants.VIEW_DISTANCE; + double distSq = NumberConversions.square(Configs.config().viewDistance()); for (NPC npc : NPCRegistry.all()) for (Player player : Bukkit.getOnlinePlayers()) { boolean inRange = (player.getWorld() == npc.getWorld() && player.getLocation().distanceSquared(npc.getLocation().toBukkitLocation(npc.getWorld())) <= distSq); if (!inRange && npc.isShown(player)) npc.hide(player);