Fixed the loading of the Serialized configs

This commit is contained in:
nossr50 2019-03-12 04:21:46 -07:00
parent 77b4ade885
commit a8bf6357aa
6 changed files with 247 additions and 50 deletions

View File

@ -3,6 +3,7 @@ package com.gmail.nossr50.config;
import com.gmail.nossr50.config.collectionconfigs.RepairConfig;
import com.gmail.nossr50.config.collectionconfigs.SalvageConfig;
import com.gmail.nossr50.config.experience.ExperienceConfig;
import com.gmail.nossr50.config.hocon.SerializedConfigLoader;
import com.gmail.nossr50.config.hocon.database.ConfigDatabase;
import com.gmail.nossr50.config.party.ItemWeightConfig;
import com.gmail.nossr50.config.skills.alchemy.PotionConfig;
@ -59,7 +60,7 @@ public final class ConfigManager {
/* CONFIG INSTANCES */
private ConfigDatabase configDatabase;
private SerializedConfigLoader<ConfigDatabase> configDatabase;
private MainConfig mainConfig;
private FishingTreasureConfig fishingTreasureConfig;
private ExcavationTreasureConfig excavationTreasureConfig;
@ -90,7 +91,7 @@ public final class ConfigManager {
// I'm pretty these are supposed to be done in a specific order, so don't rearrange them willy nilly
//TODO: Not sure about the order of MainConfig
configDatabase = new ConfigDatabase();
configDatabase = new SerializedConfigLoader<>(ConfigDatabase.class, "database_settings.conf", null);
mainConfig = new MainConfig();
fishingTreasureConfig = new FishingTreasureConfig();
@ -304,5 +305,5 @@ public final class ConfigManager {
return experienceMapManager;
}
public ConfigDatabase getConfigDatabase() { return configDatabase; }
public ConfigDatabase getConfigDatabase() { return configDatabase.getConfig(); }
}

View File

@ -0,0 +1,224 @@
package com.gmail.nossr50.config.hocon;
import com.gmail.nossr50.config.ConfigConstants;
import com.gmail.nossr50.mcMMO;
import ninja.leaping.configurate.ConfigurationOptions;
import ninja.leaping.configurate.ValueType;
import ninja.leaping.configurate.commented.CommentedConfigurationNode;
import ninja.leaping.configurate.commented.SimpleCommentedConfigurationNode;
import ninja.leaping.configurate.hocon.HoconConfigurationLoader;
import ninja.leaping.configurate.objectmapping.ObjectMapper;
import ninja.leaping.configurate.objectmapping.ObjectMappingException;
import ninja.leaping.configurate.util.ConfigurationNodeWalker;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Iterator;
import java.util.Objects;
/*
* This file is part of GriefPrevention, licensed under the MIT License (MIT).
*
* Copyright (c) bloodmc
* Copyright (c) contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/*
* The code here has been modified from its source
*/
/**
* Handles loading serialized configs with configurate
* @param <T> the class type of the config
*/
public class SerializedConfigLoader<T> {
private static final String CONFIG_HEADER = "Configuration files are now in the HOCON file format!\n" +
"\nHOCON is a lot less strict than YAML, so don't worry about the number of spaces and such!\n" +
"\nIt is recommended that you use a nice text editor to view and edit these files" +
"\n On Windows I recommend VS Code (Free by Microsoft) https://code.visualstudio.com/" +
"\n On Linux I recommend nvim (Free) https://neovim.io/\n" +
"\nIf you need help with the configuration files, feel free to come ask for support in our discord!" +
"\nOfficial mcMMO Discord - https://discord.gg/bJ7pFS9\n" +
"\nYou can also consult the new official wiki" +
"\nhttps://mcmmo.org/wiki - Keep in mind the wiki is a WIP and may not have information about everything in mcMMO!";
private static final ConfigurationOptions LOADER_OPTIONS = ConfigurationOptions.defaults().setHeader(CONFIG_HEADER);
private static final String ROOT_NODE_ADDRESS = "mcMMO";
private final Path path;
/**
* The parent configuration - values are inherited from this
*/
private final SerializedConfigLoader parent;
/**
* The loader (mapped to a file) used to read/write the config to disk
*/
private HoconConfigurationLoader loader;
/**
* A node representation of "whats actually in the file".
*/
private CommentedConfigurationNode fileData = SimpleCommentedConfigurationNode.root(LOADER_OPTIONS);
/**
* A node representation of {@link #fileData}, merged with the data of {@link #parent}.
*/
private CommentedConfigurationNode data = SimpleCommentedConfigurationNode.root(LOADER_OPTIONS);
/**
* The mapper instance used to populate the config instance
*/
private ObjectMapper<T>.BoundInstance configMapper;
public SerializedConfigLoader(Class<T> clazz, String fileName, SerializedConfigLoader parent) {
this.parent = parent;
this.path = getPathFromFileName(fileName);
try {
Files.createDirectories(path.getParent());
if (Files.notExists(path)) {
Files.createFile(path);
}
this.loader = HoconConfigurationLoader.builder().setPath(path).build();
this.configMapper = ObjectMapper.forClass(clazz).bindToNew();
reload();
save();
} catch (Exception e) {
mcMMO.p.getLogger().severe("Failed to initialize config - "+path.toString());
e.printStackTrace();
}
}
private Path getPathFromFileName(String fileName)
{
File configFile = new File(ConfigConstants.getConfigFolder(), fileName);
return configFile.toPath();
}
public T getConfig() {
return this.configMapper.getInstance();
}
public boolean save() {
try {
// save from the mapped object --> node
CommentedConfigurationNode saveNode = SimpleCommentedConfigurationNode.root(LOADER_OPTIONS);
this.configMapper.serialize(saveNode.getNode(ROOT_NODE_ADDRESS));
// before saving this config, remove any values already declared with the same value on the parent
if (this.parent != null) {
removeDuplicates(saveNode);
}
// merge the values we need to write with the ones already declared in the file
saveNode.mergeValuesFrom(this.fileData);
// save the data to disk
this.loader.save(saveNode);
return true;
} catch (IOException | ObjectMappingException e) {
mcMMO.p.getLogger().severe("Failed to save configuration - "+path.toString());
e.printStackTrace();
return false;
}
}
public void reload() {
try {
// load settings from file
CommentedConfigurationNode loadedNode = this.loader.load();
// store "what's in the file" separately in memory
this.fileData = loadedNode;
// make a copy of the file data
this.data = this.fileData.copy();
// merge with settings from parent
if (this.parent != null) {
this.parent.reload();
this.data.mergeValuesFrom(this.parent.data);
}
// populate the config object
populateInstance();
} catch (Exception e) {
mcMMO.p.getLogger().severe("Failed to load configuration - "+path.toString());
e.printStackTrace();
}
}
private void populateInstance() throws ObjectMappingException {
this.configMapper.populate(this.data.getNode(ROOT_NODE_ADDRESS));
}
/**
* Traverses the given {@code root} config node, removing any values which
* are also present and set to the same value on this configs "parent".
*
* @param root The node to process
*/
private void removeDuplicates(CommentedConfigurationNode root) {
if (this.parent == null) {
throw new IllegalStateException("parent is null");
}
Iterator<ConfigurationNodeWalker.VisitedNode<CommentedConfigurationNode>> it = ConfigurationNodeWalker.DEPTH_FIRST_POST_ORDER.walkWithPath(root);
while (it.hasNext()) {
ConfigurationNodeWalker.VisitedNode<CommentedConfigurationNode> next = it.next();
CommentedConfigurationNode node = next.getNode();
// remove empty maps
if (node.hasMapChildren()) {
if (node.getChildrenMap().isEmpty()) {
node.setValue(null);
}
continue;
}
// ignore list values
if (node.getParent() != null && node.getParent().getValueType() == ValueType.LIST) {
continue;
}
// if the node already exists in the parent config, remove it
CommentedConfigurationNode parentValue = this.parent.data.getNode(next.getPath().getArray());
if (Objects.equals(node.getValue(), parentValue.getValue())) {
node.setValue(null);
}
}
}
public CommentedConfigurationNode getRootNode() {
return this.data.getNode(ROOT_NODE_ADDRESS);
}
public Path getPath() {
return this.path;
}
}

View File

@ -1,45 +1,17 @@
package com.gmail.nossr50.config.hocon.database;
import com.gmail.nossr50.config.Config;
import com.gmail.nossr50.config.ConfigConstants;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ConfigSerializable
public class ConfigDatabase extends Config {
public ConfigDatabase() {
super("mysql", ConfigConstants.getDataFolder(), ConfigConstants.RELATIVE_PATH_CONFIG_DIR,
true,true, false, true);
initFullConfig(); //Load Config
}
public class ConfigDatabase {
/*
* CONFIG NODES
*/
@Setting(value = "MySQL", comment = "Settings for using MySQL or MariaDB database")
private UserConfigSectionMySQL userConfigSectionMySQL;
/*
* CLASS OVERRIDES
*/
@Override
public void unload() {
}
/**
* The version of this config
*
* @return
*/
@Override
public double getConfigVersion() {
return 1;
}
private UserConfigSectionMySQL userConfigSectionMySQL = new UserConfigSectionMySQL();
/*
* GETTER BOILERPLATE

View File

@ -1,6 +1,5 @@
package com.gmail.nossr50.config.hocon.database;
import com.gmail.nossr50.config.hocon.ConfigSection;
import ninja.leaping.configurate.objectmapping.Setting;
import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ -13,8 +12,6 @@ public class UserConfigSectionDatabase {
@Setting(value = "Table_Prefix", comment = "The Prefix that will be used for tables in your DB")
private String tablePrefix = "mcmmo_";
/*
* GETTER BOILERPLATE
*/

View File

@ -11,13 +11,13 @@ public class UserConfigSectionMySQL {
private boolean enabled = true;
@Setting(value = "User", comment = "Your MySQL User Settings")
private UserConfigSectionUser userConfigSectionUser;
private UserConfigSectionUser userConfigSectionUser = new UserConfigSectionUser();
@Setting(value = "Database", comment = "Database settings for MySQL/MariaDB")
private UserConfigSectionDatabase userConfigSectionDatabase;
private UserConfigSectionDatabase userConfigSectionDatabase = new UserConfigSectionDatabase();
@Setting(value = "Server", comment = "Your MySQL/MariaDB server settings.")
private UserConfigSectionServer userConfigSectionServer;
private UserConfigSectionServer userConfigSectionServer = new UserConfigSectionServer();
/*
* GETTER BOILERPLATE
@ -59,11 +59,11 @@ public class UserConfigSectionMySQL {
switch (poolIdentifier)
{
case LOAD:
return userConfigSectionServer.getUserConfigSectionMaxPoolSize().getLoad();
return userConfigSectionServer.getUserConfigSectionMaxConnections().getLoad();
case SAVE:
return userConfigSectionServer.getUserConfigSectionMaxPoolSize().getSave();
return userConfigSectionServer.getUserConfigSectionMaxConnections().getSave();
case MISC:
return userConfigSectionServer.getUserConfigSectionMaxPoolSize().getMisc();
return userConfigSectionServer.getUserConfigSectionMaxConnections().getMisc();
default:
return 20;
}

View File

@ -6,22 +6,25 @@ import ninja.leaping.configurate.objectmapping.serialize.ConfigSerializable;
@ConfigSerializable
public class UserConfigSectionServer {
@Setting(value = "Use_SSL", comment = "Enables SSL for MySQL/MariaDB connections, newer versions of MySQL will spam your console if you aren't using SSL." +
" It is recommended that you turn this on if you are using a newer version of MySQL," +
" if you run into issues with SSL not being supported, turn this off.")
@Setting(value = "Use_SSL", comment = "Enables SSL for MySQL/MariaDB connections." +
"\nIf your SQL server supports SSL, it is recommended to have it on but not necessary." +
"\nIf you run into any issues involving SSL, its best to just turn this off.")
private boolean useSSL = true;
@Setting(value = "Server_Port", comment = "Your MySQL/MariaDB server port")
@Setting(value = "Server_Port", comment = "Your MySQL/MariaDB server port" +
"\nThe default port is typically 3306 for MySQL, but every server configuration is different!")
private int serverPort = 3306;
@Setting(value = "Server_Address", comment = "The address for your MySQL/MariaDB server")
@Setting(value = "Server_Address", comment = "The address for your MySQL/MariaDB server" +
"If the MySQL server is hosted on the same machine, you can use the localhost alias")
private String serverAddress = "localhost";
@Setting(value = "Max_Connections", comment = "This setting is the max simultaneous MySQL/MariaDB connections allowed at a time, this needs to be high enough to support multiple player logins in quick succession")
private UserConfigSectionMaxConnections userConfigSectionMaxConnections;
@Setting(value = "Max_Connections", comment = "This setting is the max simultaneous MySQL/MariaDB connections allowed at a time." +
"\nThis needs to be high enough to support multiple player logins in quick succession, it is recommended that you do not lower these values")
private UserConfigSectionMaxConnections userConfigSectionMaxConnections = new UserConfigSectionMaxConnections();
@Setting(value = "Max_Pool_Size", comment = "This setting is the max size of the pool of cached connections that we hold at any given time.")
private UserConfigSectionMaxPoolSize userConfigSectionMaxPoolSize;
private UserConfigSectionMaxPoolSize userConfigSectionMaxPoolSize = new UserConfigSectionMaxPoolSize();
/*
* GETTER BOILERPLATE