Improves configuration migration, and fixes some issues
All checks were successful
EpicKnarvik97/Blacksmith/pipeline/head This commit looks good
All checks were successful
EpicKnarvik97/Blacksmith/pipeline/head This commit looks good
Fixes incorrect dropItems instead of dropItem key in config.yml Adds some missing dropper messages to config.yml Adds proper migration keys for all known configuration options Adds a modified version of Stargate's StargateYamlConfiguration to allow retaining comments during configuration migration. Fixes the annoying "[]" is not a valid repairable item Removes the use of data keys for the global configuration
This commit is contained in:
parent
8b8890c408
commit
757fcdf139
@ -13,6 +13,7 @@ import net.knarcraft.blacksmith.command.scrapper.ScrapperConfigCommand;
|
|||||||
import net.knarcraft.blacksmith.command.scrapper.ScrapperConfigTabCompleter;
|
import net.knarcraft.blacksmith.command.scrapper.ScrapperConfigTabCompleter;
|
||||||
import net.knarcraft.blacksmith.command.scrapper.ScrapperEditCommand;
|
import net.knarcraft.blacksmith.command.scrapper.ScrapperEditCommand;
|
||||||
import net.knarcraft.blacksmith.command.scrapper.ScrapperEditTabCompleter;
|
import net.knarcraft.blacksmith.command.scrapper.ScrapperEditTabCompleter;
|
||||||
|
import net.knarcraft.blacksmith.config.StargateYamlConfiguration;
|
||||||
import net.knarcraft.blacksmith.config.blacksmith.GlobalBlacksmithSettings;
|
import net.knarcraft.blacksmith.config.blacksmith.GlobalBlacksmithSettings;
|
||||||
import net.knarcraft.blacksmith.config.scrapper.GlobalScrapperSettings;
|
import net.knarcraft.blacksmith.config.scrapper.GlobalScrapperSettings;
|
||||||
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
import net.knarcraft.blacksmith.formatting.BlacksmithTranslatableMessage;
|
||||||
@ -21,15 +22,15 @@ import net.knarcraft.blacksmith.listener.PlayerListener;
|
|||||||
import net.knarcraft.blacksmith.manager.EconomyManager;
|
import net.knarcraft.blacksmith.manager.EconomyManager;
|
||||||
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
|
import net.knarcraft.blacksmith.trait.BlacksmithTrait;
|
||||||
import net.knarcraft.blacksmith.trait.ScrapperTrait;
|
import net.knarcraft.blacksmith.trait.ScrapperTrait;
|
||||||
|
import net.knarcraft.blacksmith.util.ConfigHelper;
|
||||||
import net.knarcraft.knarlib.formatting.StringFormatter;
|
import net.knarcraft.knarlib.formatting.StringFormatter;
|
||||||
import net.knarcraft.knarlib.formatting.TranslatableTimeUnit;
|
import net.knarcraft.knarlib.formatting.TranslatableTimeUnit;
|
||||||
import net.knarcraft.knarlib.formatting.Translator;
|
import net.knarcraft.knarlib.formatting.Translator;
|
||||||
import net.knarcraft.knarlib.property.ColorConversion;
|
|
||||||
import net.knarcraft.knarlib.util.FileHelper;
|
|
||||||
import net.knarcraft.knarlib.util.UpdateChecker;
|
import net.knarcraft.knarlib.util.UpdateChecker;
|
||||||
import org.bukkit.command.CommandExecutor;
|
import org.bukkit.command.CommandExecutor;
|
||||||
import org.bukkit.command.PluginCommand;
|
import org.bukkit.command.PluginCommand;
|
||||||
import org.bukkit.command.TabCompleter;
|
import org.bukkit.command.TabCompleter;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
import org.bukkit.configuration.file.FileConfiguration;
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.plugin.PluginDescriptionFile;
|
import org.bukkit.plugin.PluginDescriptionFile;
|
||||||
import org.bukkit.plugin.PluginManager;
|
import org.bukkit.plugin.PluginManager;
|
||||||
@ -40,9 +41,6 @@ import org.jetbrains.annotations.Nullable;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -50,11 +48,13 @@ import java.util.logging.Level;
|
|||||||
*/
|
*/
|
||||||
public class BlacksmithPlugin extends JavaPlugin {
|
public class BlacksmithPlugin extends JavaPlugin {
|
||||||
|
|
||||||
|
private static final String CONFIG_FILE_NAME = "config.yml";
|
||||||
private static BlacksmithPlugin instance;
|
private static BlacksmithPlugin instance;
|
||||||
private GlobalBlacksmithSettings blacksmithConfig;
|
private GlobalBlacksmithSettings blacksmithConfig;
|
||||||
private GlobalScrapperSettings scrapperConfig;
|
private GlobalScrapperSettings scrapperConfig;
|
||||||
private static Translator translator;
|
private static Translator translator;
|
||||||
private static StringFormatter stringFormatter;
|
private static StringFormatter stringFormatter;
|
||||||
|
private FileConfiguration configuration;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor required for MockBukkit
|
* Constructor required for MockBukkit
|
||||||
@ -107,8 +107,18 @@ public class BlacksmithPlugin extends JavaPlugin {
|
|||||||
this.reloadConfig();
|
this.reloadConfig();
|
||||||
blacksmithConfig.load();
|
blacksmithConfig.load();
|
||||||
scrapperConfig.load();
|
scrapperConfig.load();
|
||||||
translator.loadLanguages(this.getDataFolder(), "en",
|
translator.loadLanguages(this.getDataFolder(), "en", this.getConfiguration().getString(
|
||||||
this.getConfig().getString("language", "en"));
|
"language", "en"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the raw configuration
|
||||||
|
*
|
||||||
|
* @return <p>The raw configuration</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
public FileConfiguration getConfiguration() {
|
||||||
|
return this.configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -139,18 +149,23 @@ public class BlacksmithPlugin extends JavaPlugin {
|
|||||||
instance = this;
|
instance = this;
|
||||||
|
|
||||||
//Copy default config to disk
|
//Copy default config to disk
|
||||||
FileConfiguration fileConfiguration = this.getConfig();
|
|
||||||
this.saveDefaultConfig();
|
this.saveDefaultConfig();
|
||||||
if (fileConfiguration.getString("defaults.dropItem") != null) {
|
this.getConfig();
|
||||||
migrateConfig(fileConfiguration);
|
this.configuration = new StargateYamlConfiguration();
|
||||||
this.saveConfig();
|
try {
|
||||||
|
this.configuration.load(new File(getDataFolder(), CONFIG_FILE_NAME));
|
||||||
|
} catch (IOException | InvalidConfigurationException exception) {
|
||||||
|
getLogger().log(Level.SEVERE, exception.getMessage());
|
||||||
}
|
}
|
||||||
fileConfiguration.options().copyDefaults(true);
|
this.configuration.options().copyDefaults(true);
|
||||||
this.reloadConfig();
|
|
||||||
this.saveConfig();
|
|
||||||
|
|
||||||
// Initialize custom configuration files
|
// Initialize custom configuration files
|
||||||
initializeConfigurations(fileConfiguration);
|
this.reloadConfig();
|
||||||
|
if (this.configuration.getString("scrapper.defaults.dropItem") == null) {
|
||||||
|
ConfigHelper.migrateConfig(this.getDataFolder().getPath().replaceAll("\\\\", "/"), this.configuration);
|
||||||
|
this.reloadConfig();
|
||||||
|
}
|
||||||
|
initializeConfigurations(this.configuration);
|
||||||
|
|
||||||
//Set up Vault integration
|
//Set up Vault integration
|
||||||
if (!setUpVault()) {
|
if (!setUpVault()) {
|
||||||
@ -174,6 +189,28 @@ public class BlacksmithPlugin extends JavaPlugin {
|
|||||||
() -> this.getDescription().getVersion(), null);
|
() -> this.getDescription().getVersion(), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void reloadConfig() {
|
||||||
|
super.reloadConfig();
|
||||||
|
this.configuration = new StargateYamlConfiguration();
|
||||||
|
this.configuration.options().copyDefaults(true);
|
||||||
|
try {
|
||||||
|
this.configuration.load(new File(getDataFolder(), CONFIG_FILE_NAME));
|
||||||
|
} catch (IOException | InvalidConfigurationException exception) {
|
||||||
|
getLogger().log(Level.SEVERE, "Unable to load the configuration! Message: " + exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveConfig() {
|
||||||
|
super.saveConfig();
|
||||||
|
try {
|
||||||
|
this.configuration.save(new File(getDataFolder(), CONFIG_FILE_NAME));
|
||||||
|
} catch (IOException exception) {
|
||||||
|
getLogger().log(Level.SEVERE, "Unable to save the configuration! Message: " + exception.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes custom configuration and translation
|
* Initializes custom configuration and translation
|
||||||
*
|
*
|
||||||
@ -256,48 +293,4 @@ public class BlacksmithPlugin extends JavaPlugin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Changes all configuration values from the old name to the new name
|
|
||||||
*
|
|
||||||
* @param fileConfiguration <p>The config to read from and write to</p>
|
|
||||||
*/
|
|
||||||
private void migrateConfig(@NotNull FileConfiguration fileConfiguration) {
|
|
||||||
//Save the old config just in case something goes wrong
|
|
||||||
try {
|
|
||||||
fileConfiguration.save(getDataFolder() + "/config.yml.old");
|
|
||||||
} catch (IOException exception) {
|
|
||||||
BlacksmithPlugin.getInstance().getLogger().log(Level.SEVERE, Arrays.toString(exception.getStackTrace()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Read all available config migrations
|
|
||||||
Map<String, String> migrationFields = null;
|
|
||||||
try {
|
|
||||||
InputStream inputStream = FileHelper.getInputStreamForInternalFile("/config-migrations.txt");
|
|
||||||
if (inputStream != null) {
|
|
||||||
migrationFields = FileHelper.readKeyValuePairs(FileHelper.getBufferedReaderFromInputStream(inputStream),
|
|
||||||
"=", ColorConversion.NORMAL);
|
|
||||||
}
|
|
||||||
} catch (IOException exception) {
|
|
||||||
BlacksmithPlugin.getInstance().getLogger().log(Level.SEVERE, Arrays.toString(exception.getStackTrace()));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (migrationFields == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Replace old config names with the new ones
|
|
||||||
for (String key : migrationFields.keySet()) {
|
|
||||||
if (fileConfiguration.contains(key)) {
|
|
||||||
String newPath = migrationFields.get(key);
|
|
||||||
Object oldValue = fileConfiguration.get(key);
|
|
||||||
if (!newPath.trim().isEmpty()) {
|
|
||||||
fileConfiguration.set(newPath, oldValue);
|
|
||||||
}
|
|
||||||
fileConfiguration.set(key, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,246 @@
|
|||||||
|
package net.knarcraft.blacksmith.config;
|
||||||
|
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A YAML configuration which retains all comments
|
||||||
|
*
|
||||||
|
* <p>This configuration converts all comments to YAML values when loaded, which all start with comment_. When saved,
|
||||||
|
* those YAML values are converted to normal text comments. This ensures that the comments aren't removed by the
|
||||||
|
* YamlConfiguration during its parsing.</p>
|
||||||
|
*
|
||||||
|
* <p>Note: When retrieving a configuration section, that will include comments that start with "comment_". You should
|
||||||
|
* filter those before parsing input.</p>
|
||||||
|
*
|
||||||
|
* @author Kristian Knarvik
|
||||||
|
* @author Thorin
|
||||||
|
*/
|
||||||
|
public class StargateYamlConfiguration extends YamlConfiguration {
|
||||||
|
|
||||||
|
private static final String START_OF_COMMENT_LINE = "[HASHTAG]";
|
||||||
|
private static final String END_OF_COMMENT = "_endOfComment_";
|
||||||
|
private static final String START_OF_COMMENT = "comment_";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
protected String buildHeader() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@NotNull
|
||||||
|
public String saveToString() {
|
||||||
|
// Convert YAML comments to normal comments
|
||||||
|
return this.convertYAMLMappingsToComments(super.saveToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFromString(@NotNull String contents) throws InvalidConfigurationException {
|
||||||
|
// Convert normal comments to YAML comments to prevent them from disappearing
|
||||||
|
super.loadFromString(this.convertCommentsToYAMLMappings(contents));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a configuration section's keys, without any comment entries
|
||||||
|
*
|
||||||
|
* @param configurationSection <p>The configuration section to get keys for</p>
|
||||||
|
* @param deep <p>Whether to get keys for child elements as well</p>
|
||||||
|
* @return <p>The configuration section's keys, with comment entries removed</p>
|
||||||
|
*/
|
||||||
|
public static Set<String> getKeysWithoutComments(@NotNull ConfigurationSection configurationSection, boolean deep) {
|
||||||
|
Set<String> keys = new HashSet<>(configurationSection.getKeys(deep));
|
||||||
|
keys.removeIf(key -> key.matches(START_OF_COMMENT + "[0-9]+"));
|
||||||
|
return keys;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a file with comments, and recreates them into yaml mappings
|
||||||
|
*
|
||||||
|
* <p>A mapping follows this format: comment_{CommentNumber}: "The comment"
|
||||||
|
* This needs to be done as comments otherwise get removed using
|
||||||
|
* the {@link FileConfiguration#save(File)} method. The config
|
||||||
|
* needs to be saved if a config value has changed.</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private String convertCommentsToYAMLMappings(@NotNull String configString) {
|
||||||
|
StringBuilder yamlBuilder = new StringBuilder();
|
||||||
|
List<String> currentComment = new ArrayList<>();
|
||||||
|
int commentId = 0;
|
||||||
|
int previousIndentation = 0;
|
||||||
|
|
||||||
|
for (String line : configString.split("\n")) {
|
||||||
|
String trimmed = line.trim();
|
||||||
|
if (trimmed.startsWith("#")) {
|
||||||
|
// Store the indentation of the block
|
||||||
|
if (currentComment.isEmpty()) {
|
||||||
|
previousIndentation = getIndentation(line);
|
||||||
|
}
|
||||||
|
//Temporarily store the comment line
|
||||||
|
addComment(currentComment, trimmed);
|
||||||
|
} else {
|
||||||
|
addYamlString(yamlBuilder, currentComment, line, previousIndentation, commentId);
|
||||||
|
commentId++;
|
||||||
|
previousIndentation = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return yamlBuilder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a YAML string to the given string builder
|
||||||
|
*
|
||||||
|
* @param yamlBuilder <p>The string builder used for building YAML</p>
|
||||||
|
* @param currentComment <p>The comment to add as a YAML string</p>
|
||||||
|
* @param line <p>The current line</p>
|
||||||
|
* @param previousIndentation <p>The indentation of the current block comment</p>
|
||||||
|
* @param commentId <p>The id of the comment</p>
|
||||||
|
*/
|
||||||
|
private void addYamlString(@NotNull StringBuilder yamlBuilder, @NotNull List<String> currentComment,
|
||||||
|
@NotNull String line, int previousIndentation, int commentId) {
|
||||||
|
String trimmed = line.trim();
|
||||||
|
//Write the full formatted comment to the StringBuilder
|
||||||
|
if (!currentComment.isEmpty()) {
|
||||||
|
int indentation = trimmed.isEmpty() ? previousIndentation : getIndentation(line);
|
||||||
|
generateCommentYAML(yamlBuilder, currentComment, commentId, indentation);
|
||||||
|
currentComment.clear();
|
||||||
|
}
|
||||||
|
//Add the non-comment line assuming it isn't empty
|
||||||
|
if (!trimmed.isEmpty()) {
|
||||||
|
yamlBuilder.append(line).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the given comment to the given list
|
||||||
|
*
|
||||||
|
* @param commentParts <p>The list to add to</p>
|
||||||
|
* @param comment <p>The comment to add</p>
|
||||||
|
*/
|
||||||
|
private void addComment(@NotNull List<String> commentParts, @NotNull String comment) {
|
||||||
|
if (comment.startsWith("# ")) {
|
||||||
|
commentParts.add(comment.replaceFirst("# ", START_OF_COMMENT_LINE));
|
||||||
|
} else {
|
||||||
|
commentParts.add(comment.replaceFirst("#", START_OF_COMMENT_LINE));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a YAML-compatible string for one comment block
|
||||||
|
*
|
||||||
|
* @param yamlBuilder <p>The string builder to add the generated YAML to</p>
|
||||||
|
* @param commentLines <p>The lines of the comment to convert into YAML</p>
|
||||||
|
* @param commentId <p>The unique id of the comment</p>
|
||||||
|
* @param indentation <p>The indentation to add to every line</p>
|
||||||
|
*/
|
||||||
|
private void generateCommentYAML(@NotNull StringBuilder yamlBuilder, @NotNull List<String> commentLines,
|
||||||
|
int commentId, int indentation) {
|
||||||
|
String subIndentation = this.addIndentation(indentation + 2);
|
||||||
|
//Add the comment start marker
|
||||||
|
yamlBuilder.append(this.addIndentation(indentation)).append(START_OF_COMMENT).append(commentId).append(": |\n");
|
||||||
|
for (String commentLine : commentLines) {
|
||||||
|
//Add each comment line with the proper indentation
|
||||||
|
yamlBuilder.append(subIndentation).append(commentLine).append("\n");
|
||||||
|
}
|
||||||
|
//Add the comment end marker
|
||||||
|
yamlBuilder.append(subIndentation).append(subIndentation).append(END_OF_COMMENT).append("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the internal YAML mapping format to a readable config file
|
||||||
|
*
|
||||||
|
* <p>The internal YAML structure is converted to a string with the same format as a standard configuration file.
|
||||||
|
* The internal structure has comments in the format: START_OF_COMMENT + id + multi-line YAML string +
|
||||||
|
* END_OF_COMMENT.</p>
|
||||||
|
*
|
||||||
|
* @param yamlString <p>A string using the YAML format</p>
|
||||||
|
* @return <p>The corresponding comment string</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private String convertYAMLMappingsToComments(@NotNull String yamlString) {
|
||||||
|
StringBuilder finalText = new StringBuilder();
|
||||||
|
|
||||||
|
String[] lines = yamlString.split("\n");
|
||||||
|
for (int currentIndex = 0; currentIndex < lines.length; currentIndex++) {
|
||||||
|
String line = lines[currentIndex];
|
||||||
|
String possibleComment = line.trim();
|
||||||
|
|
||||||
|
if (possibleComment.startsWith(START_OF_COMMENT)) {
|
||||||
|
//Add an empty line before every comment block
|
||||||
|
finalText.append("\n");
|
||||||
|
currentIndex = readComment(finalText, lines, currentIndex + 1, getIndentation(line));
|
||||||
|
} else {
|
||||||
|
//Output the configuration key
|
||||||
|
finalText.append(line).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return finalText.toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fully reads a comment
|
||||||
|
*
|
||||||
|
* @param builder <p>The string builder to write to</p>
|
||||||
|
* @param lines <p>The lines to read from</p>
|
||||||
|
* @param startIndex <p>The index to start reading from</p>
|
||||||
|
* @param commentIndentation <p>The indentation of the read comment</p>
|
||||||
|
* @return <p>The index containing the next non-comment line</p>
|
||||||
|
*/
|
||||||
|
private int readComment(@NotNull StringBuilder builder, @NotNull String[] lines, int startIndex,
|
||||||
|
int commentIndentation) {
|
||||||
|
for (int currentIndex = startIndex; currentIndex < lines.length; currentIndex++) {
|
||||||
|
String line = lines[currentIndex];
|
||||||
|
String possibleComment = line.trim();
|
||||||
|
if (!line.contains(END_OF_COMMENT)) {
|
||||||
|
possibleComment = possibleComment.replace(START_OF_COMMENT_LINE, "");
|
||||||
|
builder.append(addIndentation(commentIndentation)).append("# ").append(possibleComment).append("\n");
|
||||||
|
} else {
|
||||||
|
return currentIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return startIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a string containing the given indentation
|
||||||
|
*
|
||||||
|
* @param indentationSpaces <p>The number spaces to use for indentation</p>
|
||||||
|
* @return <p>A string containing the number of spaces specified</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private String addIndentation(int indentationSpaces) {
|
||||||
|
return " ".repeat(Math.max(0, indentationSpaces));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the indentation (number of spaces) of the given line
|
||||||
|
*
|
||||||
|
* @param line <p>The line to get indentation of</p>
|
||||||
|
* @return <p>The number of spaces in the line's indentation</p>
|
||||||
|
*/
|
||||||
|
private int getIndentation(@NotNull String line) {
|
||||||
|
int spacesFound = 0;
|
||||||
|
for (char aCharacter : line.toCharArray()) {
|
||||||
|
if (aCharacter == ' ') {
|
||||||
|
spacesFound++;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return spacesFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,20 +1,21 @@
|
|||||||
package net.knarcraft.blacksmith.config.blacksmith;
|
package net.knarcraft.blacksmith.config.blacksmith;
|
||||||
|
|
||||||
import net.citizensnpcs.api.util.DataKey;
|
|
||||||
import net.citizensnpcs.api.util.YamlStorage;
|
|
||||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||||
import net.knarcraft.blacksmith.config.SettingValueType;
|
import net.knarcraft.blacksmith.config.SettingValueType;
|
||||||
import net.knarcraft.blacksmith.config.Settings;
|
import net.knarcraft.blacksmith.config.Settings;
|
||||||
|
import net.knarcraft.blacksmith.config.StargateYamlConfiguration;
|
||||||
import net.knarcraft.blacksmith.util.ConfigHelper;
|
import net.knarcraft.blacksmith.util.ConfigHelper;
|
||||||
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
import net.knarcraft.blacksmith.util.InputParsingHelper;
|
||||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.bukkit.enchantments.Enchantment;
|
import org.bukkit.enchantments.Enchantment;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -31,28 +32,21 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
private final Map<BlacksmithSetting, Object> settings = new HashMap<>();
|
private final Map<BlacksmithSetting, Object> settings = new HashMap<>();
|
||||||
private final List<Material> defaultReforgeAbleMaterials = new ArrayList<>();
|
private final List<Material> defaultReforgeAbleMaterials = new ArrayList<>();
|
||||||
private final List<Enchantment> defaultEnchantmentBlockList = new ArrayList<>();
|
private final List<Enchantment> defaultEnchantmentBlockList = new ArrayList<>();
|
||||||
|
private final BlacksmithPlugin instance;
|
||||||
private final YamlStorage defaultConfig;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new "Settings"
|
* Instantiates a new "Global Blacksmith Settings"
|
||||||
*
|
*
|
||||||
* @param plugin <p>A reference to the blacksmith plugin</p>
|
* @param instance <p>The blacksmith plugin to load and save configurations for</p>
|
||||||
*/
|
*/
|
||||||
public GlobalBlacksmithSettings(BlacksmithPlugin plugin) {
|
public GlobalBlacksmithSettings(BlacksmithPlugin instance) {
|
||||||
this.defaultConfig = new YamlStorage(new File(plugin.getDataFolder() + File.separator + "config.yml"),
|
this.instance = instance;
|
||||||
"Blacksmith Configuration\nWarning: The values under defaults are the values set for a " +
|
|
||||||
"blacksmith upon creation. To change any values for existing NPCs, edit the citizens NPC file.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all configuration values from the config file
|
* Loads all configuration values from the config file
|
||||||
*/
|
*/
|
||||||
public void load() {
|
public void load() {
|
||||||
// Load the config from disk
|
|
||||||
this.defaultConfig.load();
|
|
||||||
DataKey root = this.defaultConfig.getKey("");
|
|
||||||
|
|
||||||
// Just in case, clear existing values
|
// Just in case, clear existing values
|
||||||
this.settings.clear();
|
this.settings.clear();
|
||||||
this.materialBasePrices.clear();
|
this.materialBasePrices.clear();
|
||||||
@ -60,10 +54,10 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
this.enchantmentCosts.clear();
|
this.enchantmentCosts.clear();
|
||||||
|
|
||||||
// Load/Save settings
|
// Load/Save settings
|
||||||
loadSettings(root);
|
loadSettings();
|
||||||
|
|
||||||
// Save any modified values to disk
|
// Save any modified values to disk
|
||||||
this.defaultConfig.save();
|
instance.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -314,34 +308,51 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all global settings
|
* Loads all global settings
|
||||||
*
|
|
||||||
* @param root <p>The root node of all global settings</p>
|
|
||||||
*/
|
*/
|
||||||
private void loadSettings(DataKey root) {
|
private void loadSettings() {
|
||||||
|
instance.reloadConfig();
|
||||||
|
FileConfiguration configuration = instance.getConfiguration();
|
||||||
|
|
||||||
for (BlacksmithSetting blacksmithSetting : BlacksmithSetting.values()) {
|
for (BlacksmithSetting blacksmithSetting : BlacksmithSetting.values()) {
|
||||||
if (!root.keyExists(blacksmithSetting.getPath())) {
|
if (!configuration.contains(blacksmithSetting.getPath())) {
|
||||||
//If the setting does not exist in the config file, add it
|
//If the setting does not exist in the config file, add it
|
||||||
root.setRaw(blacksmithSetting.getPath(), blacksmithSetting.getDefaultValue());
|
configuration.set(blacksmithSetting.getPath(), blacksmithSetting.getDefaultValue());
|
||||||
} else {
|
} else {
|
||||||
//Set the setting to the value found in the path
|
//Set the setting to the value found in the path
|
||||||
settings.put(blacksmithSetting, root.getRaw(blacksmithSetting.getPath()));
|
settings.put(blacksmithSetting, configuration.get(blacksmithSetting.getPath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadReforgeAbleItems();
|
loadReforgeAbleItems();
|
||||||
loadEnchantmentBlockList();
|
loadEnchantmentBlockList();
|
||||||
|
|
||||||
//Load all base prices
|
//Load all base prices
|
||||||
loadBasePrices(root);
|
loadBasePrices(configuration);
|
||||||
|
|
||||||
//Load all per-durability-point prices
|
//Load all per-durability-point prices
|
||||||
loadPricesPerDurabilityPoint(root);
|
loadPricesPerDurabilityPoint(configuration);
|
||||||
|
|
||||||
//Load all enchantment prices
|
//Load all enchantment prices
|
||||||
DataKey enchantmentCostNode = root.getRelative(BlacksmithSetting.ENCHANTMENT_COST.getPath());
|
loadEnchantmentPrices(configuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads all prices for enchantments
|
||||||
|
*
|
||||||
|
* @param fileConfiguration <p>The configuration to read</p>
|
||||||
|
*/
|
||||||
|
private void loadEnchantmentPrices(@NotNull FileConfiguration fileConfiguration) {
|
||||||
|
ConfigurationSection enchantmentCostNode = fileConfiguration.getConfigurationSection(
|
||||||
|
getBase(BlacksmithSetting.ENCHANTMENT_COST.getPath()));
|
||||||
|
if (enchantmentCostNode == null) {
|
||||||
|
instance.getLogger().log(Level.WARNING, "Could not load enchantment prices. because the " +
|
||||||
|
"configuration section doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Map<String, String> relevantKeys = getRelevantKeys(enchantmentCostNode);
|
Map<String, String> relevantKeys = getRelevantKeys(enchantmentCostNode);
|
||||||
for (String key : relevantKeys.keySet()) {
|
for (String key : relevantKeys.keySet()) {
|
||||||
String enchantmentName = relevantKeys.get(key);
|
String enchantmentName = relevantKeys.get(key);
|
||||||
Enchantment enchantment = InputParsingHelper.matchEnchantment(enchantmentName);
|
Enchantment enchantment = InputParsingHelper.matchEnchantment(enchantmentName);
|
||||||
|
instance.getLogger().log(Level.WARNING, "loadEnchantmentPrices " + enchantmentName);
|
||||||
setItemPrice(this.enchantmentCosts, enchantmentName, enchantment, enchantmentCostNode.getDouble(key));
|
setItemPrice(this.enchantmentCosts, enchantmentName, enchantment, enchantmentCostNode.getDouble(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -349,10 +360,16 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
/**
|
/**
|
||||||
* Loads all prices per durability point for all materials
|
* Loads all prices per durability point for all materials
|
||||||
*
|
*
|
||||||
* @param root <p>The configuration root node to search from</p>
|
* @param fileConfiguration <p>The configuration to read</p>
|
||||||
*/
|
*/
|
||||||
private void loadPricesPerDurabilityPoint(DataKey root) {
|
private void loadPricesPerDurabilityPoint(@NotNull FileConfiguration fileConfiguration) {
|
||||||
DataKey basePerDurabilityPriceNode = root.getRelative(BlacksmithSetting.PRICE_PER_DURABILITY_POINT.getPath());
|
ConfigurationSection basePerDurabilityPriceNode = fileConfiguration.getConfigurationSection(
|
||||||
|
getBase(BlacksmithSetting.PRICE_PER_DURABILITY_POINT.getPath()));
|
||||||
|
if (basePerDurabilityPriceNode == null) {
|
||||||
|
instance.getLogger().log(Level.WARNING, "Could not load per durability prices. because the " +
|
||||||
|
"configuration section doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Map<String, String> relevantKeys = getRelevantKeys(basePerDurabilityPriceNode);
|
Map<String, String> relevantKeys = getRelevantKeys(basePerDurabilityPriceNode);
|
||||||
|
|
||||||
for (String key : relevantKeys.keySet()) {
|
for (String key : relevantKeys.keySet()) {
|
||||||
@ -371,10 +388,16 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
/**
|
/**
|
||||||
* Loads base prices for all materials
|
* Loads base prices for all materials
|
||||||
*
|
*
|
||||||
* @param root <p>The configuration root node to search from</p>
|
* @param fileConfiguration <p>The configuration to read</p>
|
||||||
*/
|
*/
|
||||||
private void loadBasePrices(DataKey root) {
|
private void loadBasePrices(@NotNull FileConfiguration fileConfiguration) {
|
||||||
DataKey basePriceNode = root.getRelative(BlacksmithSetting.BASE_PRICE.getPath());
|
ConfigurationSection basePriceNode = fileConfiguration.getConfigurationSection(
|
||||||
|
getBase(BlacksmithSetting.BASE_PRICE.getPath()));
|
||||||
|
if (basePriceNode == null) {
|
||||||
|
instance.getLogger().log(Level.WARNING, "Could not load base prices, because the configuration " +
|
||||||
|
"section doesn't exist");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Map<String, String> relevantKeys = getRelevantKeys(basePriceNode);
|
Map<String, String> relevantKeys = getRelevantKeys(basePriceNode);
|
||||||
|
|
||||||
for (String key : relevantKeys.keySet()) {
|
for (String key : relevantKeys.keySet()) {
|
||||||
@ -397,7 +420,7 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
* @param materialName <p>The material name to match</p>
|
* @param materialName <p>The material name to match</p>
|
||||||
* @param price <p>The price to set for the matched materials</p>
|
* @param price <p>The price to set for the matched materials</p>
|
||||||
*/
|
*/
|
||||||
private void setMatchedMaterialPrices(Map<Material, Double> prices, String materialName, double price) {
|
private void setMatchedMaterialPrices(@NotNull Map<Material, Double> prices, @NotNull String materialName, double price) {
|
||||||
String search = InputParsingHelper.regExIfy(materialName);
|
String search = InputParsingHelper.regExIfy(materialName);
|
||||||
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
|
for (Material material : ItemHelper.getAllReforgeAbleMaterials()) {
|
||||||
if (material.name().matches(search)) {
|
if (material.name().matches(search)) {
|
||||||
@ -414,31 +437,31 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
* @param item <p>The material parsed from the name</p>
|
* @param item <p>The material parsed from the name</p>
|
||||||
* @param price <p>The price to set</p>
|
* @param price <p>The price to set</p>
|
||||||
*/
|
*/
|
||||||
private <K> void setItemPrice(Map<K, Double> prices, String itemName, K item, double price) {
|
private <K> void setItemPrice(@NotNull Map<K, Double> prices, @NotNull String itemName, @Nullable K item,
|
||||||
|
double price) {
|
||||||
if (item != null) {
|
if (item != null) {
|
||||||
prices.put(item, price);
|
prices.put(item, price);
|
||||||
} else {
|
} else {
|
||||||
BlacksmithPlugin.getInstance().getLogger().log(Level.WARNING,
|
instance.getLogger().log(Level.WARNING, "Unable to find a material/enchantment matching " + itemName);
|
||||||
"Unable to find a material/enchantment matching " + itemName);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a map between relevant keys and their normalized name
|
* Gets a map between relevant keys and their normalized name
|
||||||
*
|
*
|
||||||
* @param rootKey <p>The root data key containing sub-keys</p>
|
* @param configurationSection <p>The configuration section to search</p>
|
||||||
* @return <p>Any sub-keys found that aren't the default</p>
|
* @return <p>Any sub-keys found that aren't the default</p>
|
||||||
*/
|
*/
|
||||||
private Map<String, String> getRelevantKeys(DataKey rootKey) {
|
@NotNull
|
||||||
|
private Map<String, String> getRelevantKeys(@NotNull ConfigurationSection configurationSection) {
|
||||||
Map<String, String> relevant = new HashMap<>();
|
Map<String, String> relevant = new HashMap<>();
|
||||||
for (DataKey dataKey : rootKey.getSubKeys()) {
|
for (String dataKey : StargateYamlConfiguration.getKeysWithoutComments(configurationSection, false)) {
|
||||||
String keyName = dataKey.name();
|
|
||||||
//Skip the default value
|
//Skip the default value
|
||||||
if (keyName.equals("default")) {
|
if (dataKey.equals("default")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
String normalizedName = keyName.toUpperCase().replace("-", "_");
|
String normalizedName = dataKey.toUpperCase().replace("-", "_");
|
||||||
relevant.put(keyName, normalizedName);
|
relevant.put(dataKey, normalizedName);
|
||||||
}
|
}
|
||||||
return relevant;
|
return relevant;
|
||||||
}
|
}
|
||||||
@ -449,7 +472,8 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
* @param normalizedName <p>The normalized name to un-normalize</p>
|
* @param normalizedName <p>The normalized name to un-normalize</p>
|
||||||
* @return <p>The un-normalized name</p>
|
* @return <p>The un-normalized name</p>
|
||||||
*/
|
*/
|
||||||
private String unNormalizeName(String normalizedName) {
|
@NotNull
|
||||||
|
private String unNormalizeName(@NotNull String normalizedName) {
|
||||||
return normalizedName.toLowerCase().replace("_", "-");
|
return normalizedName.toLowerCase().replace("_", "-");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,32 +505,66 @@ public class GlobalBlacksmithSettings implements Settings<BlacksmithSetting> {
|
|||||||
* Saves all current settings to the config file
|
* Saves all current settings to the config file
|
||||||
*/
|
*/
|
||||||
private void save() {
|
private void save() {
|
||||||
DataKey root = this.defaultConfig.getKey("");
|
FileConfiguration fileConfiguration = instance.getConfiguration();
|
||||||
|
|
||||||
//Save all default settings
|
//Save all default settings
|
||||||
for (BlacksmithSetting setting : BlacksmithSetting.values()) {
|
for (BlacksmithSetting setting : BlacksmithSetting.values()) {
|
||||||
root.setRaw(setting.getPath(), this.settings.get(setting));
|
fileConfiguration.set(setting.getPath(), this.settings.get(setting));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Save all base prices
|
//Save all base prices
|
||||||
DataKey basePriceNode = root.getRelative(BlacksmithSetting.BASE_PRICE.getPath());
|
ConfigurationSection basePriceNode = getAndCreateSection(fileConfiguration, getBase(BlacksmithSetting.BASE_PRICE.getPath()));
|
||||||
for (Material material : this.materialBasePrices.keySet()) {
|
for (Material material : this.materialBasePrices.keySet()) {
|
||||||
basePriceNode.setRaw(unNormalizeName(material.name()), this.materialBasePrices.get(material));
|
basePriceNode.set(unNormalizeName(material.name()), this.materialBasePrices.get(material));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Save all per-durability-point prices
|
//Save all per-durability-point prices
|
||||||
DataKey basePerDurabilityPriceNode = root.getRelative(BlacksmithSetting.PRICE_PER_DURABILITY_POINT.getPath());
|
ConfigurationSection basePerDurabilityPriceNode = getAndCreateSection(fileConfiguration, getBase(BlacksmithSetting.PRICE_PER_DURABILITY_POINT.getPath()));
|
||||||
for (Material material : this.materialPricePerDurabilityPoints.keySet()) {
|
for (Material material : this.materialPricePerDurabilityPoints.keySet()) {
|
||||||
basePerDurabilityPriceNode.setRaw(unNormalizeName(material.name()), this.materialPricePerDurabilityPoints.get(material));
|
basePerDurabilityPriceNode.set(unNormalizeName(material.name()), this.materialPricePerDurabilityPoints.get(material));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Load all enchantment prices
|
//Load all enchantment prices
|
||||||
DataKey enchantmentCostNode = root.getRelative(BlacksmithSetting.ENCHANTMENT_COST.getPath());
|
ConfigurationSection enchantmentCostNode = getAndCreateSection(fileConfiguration, getBase(BlacksmithSetting.ENCHANTMENT_COST.getPath()));
|
||||||
for (Enchantment enchantment : this.enchantmentCosts.keySet()) {
|
for (Enchantment enchantment : this.enchantmentCosts.keySet()) {
|
||||||
enchantmentCostNode.setRaw(unNormalizeName(enchantment.getKey().getKey()), this.enchantmentCosts.get(enchantment));
|
enchantmentCostNode.set(unNormalizeName(enchantment.getKey().getKey()), this.enchantmentCosts.get(enchantment));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Perform the actual save to disk
|
//Perform the actual save to disk
|
||||||
this.defaultConfig.save();
|
instance.saveConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a configuration section, creating it if necessary
|
||||||
|
*
|
||||||
|
* @param fileConfiguration <p>The file configuration to read</p>
|
||||||
|
* @param sectionPath <p>The path to the configuration section to get</p>
|
||||||
|
* @return <p>The configuration section</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private ConfigurationSection getAndCreateSection(@NotNull FileConfiguration fileConfiguration, @NotNull String sectionPath) {
|
||||||
|
ConfigurationSection configurationSection = fileConfiguration.getConfigurationSection(sectionPath);
|
||||||
|
if (configurationSection == null) {
|
||||||
|
fileConfiguration.createSection(sectionPath);
|
||||||
|
configurationSection = fileConfiguration.getConfigurationSection(sectionPath);
|
||||||
|
}
|
||||||
|
if (configurationSection == null) {
|
||||||
|
throw new RuntimeException("Unable to create configuration section!");
|
||||||
|
}
|
||||||
|
return configurationSection;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the base path of a configuration path pointing to a specific value
|
||||||
|
*
|
||||||
|
* @param configurationPath <p>The configuration path to get the base of</p>
|
||||||
|
* @return <p>The base configuration path</p>
|
||||||
|
*/
|
||||||
|
@NotNull
|
||||||
|
private String getBase(@NotNull String configurationPath) {
|
||||||
|
String[] parts = configurationPath.split("\\.");
|
||||||
|
String[] base = Arrays.copyOfRange(parts, 0, parts.length - 1);
|
||||||
|
return String.join(".", base);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,17 +1,15 @@
|
|||||||
package net.knarcraft.blacksmith.config.scrapper;
|
package net.knarcraft.blacksmith.config.scrapper;
|
||||||
|
|
||||||
import net.citizensnpcs.api.util.DataKey;
|
|
||||||
import net.citizensnpcs.api.util.YamlStorage;
|
|
||||||
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||||
import net.knarcraft.blacksmith.config.SettingValueType;
|
import net.knarcraft.blacksmith.config.SettingValueType;
|
||||||
import net.knarcraft.blacksmith.config.Settings;
|
import net.knarcraft.blacksmith.config.Settings;
|
||||||
import net.knarcraft.blacksmith.util.ConfigHelper;
|
import net.knarcraft.blacksmith.util.ConfigHelper;
|
||||||
import net.knarcraft.blacksmith.util.ItemHelper;
|
import net.knarcraft.blacksmith.util.ItemHelper;
|
||||||
import org.bukkit.Material;
|
import org.bukkit.Material;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -29,35 +27,29 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
|
|||||||
private final List<Material> defaultSalvageableMaterials = new ArrayList<>();
|
private final List<Material> defaultSalvageableMaterials = new ArrayList<>();
|
||||||
private final Map<Material, Set<Material>> ignoredSalvage = new HashMap<>();
|
private final Map<Material, Set<Material>> ignoredSalvage = new HashMap<>();
|
||||||
|
|
||||||
private final YamlStorage defaultConfig;
|
private final BlacksmithPlugin instance;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new "Settings"
|
* Instantiates a new "Settings"
|
||||||
*
|
*
|
||||||
* @param plugin <p>A reference to the blacksmith plugin</p>
|
* @param instance <p>A reference to the blacksmith plugin</p>
|
||||||
*/
|
*/
|
||||||
public GlobalScrapperSettings(BlacksmithPlugin plugin) {
|
public GlobalScrapperSettings(BlacksmithPlugin instance) {
|
||||||
this.defaultConfig = new YamlStorage(new File(plugin.getDataFolder() + File.separator + "config.yml"),
|
this.instance = instance;
|
||||||
"Scrapper Configuration\nWarning: The values under defaults are the values set for a " +
|
|
||||||
"scrapper upon creation. To change any values for existing NPCs, edit the citizens NPC file.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all configuration values from the config file
|
* Loads all configuration values from the config file
|
||||||
*/
|
*/
|
||||||
public void load() {
|
public void load() {
|
||||||
//Load the config from disk
|
|
||||||
this.defaultConfig.load();
|
|
||||||
DataKey root = this.defaultConfig.getKey("");
|
|
||||||
|
|
||||||
//Just in case, clear existing values
|
//Just in case, clear existing values
|
||||||
this.settings.clear();
|
this.settings.clear();
|
||||||
|
|
||||||
//Load/Save global settings
|
//Load/Save global settings
|
||||||
loadSettings(root);
|
loadSettings();
|
||||||
|
|
||||||
//Save any modified values to disk
|
//Save any modified values to disk
|
||||||
this.defaultConfig.save();
|
instance.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,17 +129,18 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads all global settings
|
* Loads all global settings
|
||||||
*
|
|
||||||
* @param root <p>The root node of all global settings</p>
|
|
||||||
*/
|
*/
|
||||||
private void loadSettings(DataKey root) {
|
private void loadSettings() {
|
||||||
|
instance.reloadConfig();
|
||||||
|
FileConfiguration configuration = instance.getConfiguration();
|
||||||
|
|
||||||
for (ScrapperSetting setting : ScrapperSetting.values()) {
|
for (ScrapperSetting setting : ScrapperSetting.values()) {
|
||||||
if (!root.keyExists(setting.getPath())) {
|
if (!configuration.contains(setting.getPath())) {
|
||||||
//If the setting does not exist in the config file, add it
|
//If the setting does not exist in the config file, add it
|
||||||
root.setRaw(setting.getPath(), setting.getDefaultValue());
|
configuration.set(setting.getPath(), setting.getDefaultValue());
|
||||||
} else {
|
} else {
|
||||||
//Set the setting to the value found in the path
|
//Set the setting to the value found in the path
|
||||||
this.settings.put(setting, root.getRaw(setting.getPath()));
|
this.settings.put(setting, configuration.get(setting.getPath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loadSalvageAbleItems();
|
loadSalvageAbleItems();
|
||||||
@ -158,14 +151,15 @@ public class GlobalScrapperSettings implements Settings<ScrapperSetting> {
|
|||||||
* Saves all current settings to the config file
|
* Saves all current settings to the config file
|
||||||
*/
|
*/
|
||||||
private void save() {
|
private void save() {
|
||||||
DataKey root = this.defaultConfig.getKey("");
|
FileConfiguration fileConfiguration = instance.getConfiguration();
|
||||||
|
|
||||||
//Save all default settings
|
//Save all default settings
|
||||||
for (ScrapperSetting setting : ScrapperSetting.values()) {
|
for (ScrapperSetting setting : ScrapperSetting.values()) {
|
||||||
root.setRaw(setting.getPath(), this.settings.get(setting));
|
fileConfiguration.set(setting.getPath(), this.settings.get(setting));
|
||||||
}
|
}
|
||||||
|
|
||||||
//Perform the actual save to disk
|
//Perform the actual save to disk
|
||||||
this.defaultConfig.save();
|
instance.saveConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -131,7 +131,7 @@ public enum ScrapperSetting implements Setting {
|
|||||||
* The message displayed if a player presents a different item after seeing the price to reforge an item
|
* The message displayed if a player presents a different item after seeing the price to reforge an item
|
||||||
*/
|
*/
|
||||||
ITEM_UNEXPECTEDLY_CHANGED_MESSAGE("itemChangedMessage", SettingValueType.STRING, "&cThat's not the item" +
|
ITEM_UNEXPECTEDLY_CHANGED_MESSAGE("itemChangedMessage", SettingValueType.STRING, "&cThat's not the item" +
|
||||||
" you wanted to reforge before!", "The message to display when presenting a different item than" +
|
" you wanted to salvage before!", "The message to display when presenting a different item than" +
|
||||||
" the one just evaluated", true, true),
|
" the one just evaluated", true, true),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,10 +1,23 @@
|
|||||||
package net.knarcraft.blacksmith.util;
|
package net.knarcraft.blacksmith.util;
|
||||||
|
|
||||||
|
import net.knarcraft.blacksmith.BlacksmithPlugin;
|
||||||
|
import net.knarcraft.blacksmith.config.StargateYamlConfiguration;
|
||||||
|
import net.knarcraft.knarlib.property.ColorConversion;
|
||||||
|
import net.knarcraft.knarlib.util.FileHelper;
|
||||||
|
import org.bukkit.configuration.ConfigurationSection;
|
||||||
|
import org.bukkit.configuration.MemorySection;
|
||||||
|
import org.bukkit.configuration.file.FileConfiguration;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A helper class for getting an object value as the correct type
|
* A helper class for getting an object value as the correct type
|
||||||
@ -94,4 +107,103 @@ public final class ConfigHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes all configuration values from the old name to the new name
|
||||||
|
*
|
||||||
|
* @param currentConfiguration <p>The current config to back up</p>
|
||||||
|
*/
|
||||||
|
public static void migrateConfig(@NotNull String dataFolderPath, @NotNull FileConfiguration currentConfiguration) {
|
||||||
|
BlacksmithPlugin instance = BlacksmithPlugin.getInstance();
|
||||||
|
|
||||||
|
//Save the old config just in case something goes wrong
|
||||||
|
try {
|
||||||
|
currentConfiguration.save(new File(dataFolderPath, "config.yml.old"));
|
||||||
|
} catch (IOException exception) {
|
||||||
|
instance.getLogger().log(Level.WARNING, "Unable to save old backup and do migration");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Load old and new configuration
|
||||||
|
instance.reloadConfig();
|
||||||
|
FileConfiguration oldConfiguration = instance.getConfig();
|
||||||
|
InputStream configStream = FileHelper.getInputStreamForInternalFile("/config.yml");
|
||||||
|
if (configStream == null) {
|
||||||
|
instance.getLogger().log(Level.SEVERE, "Could not migrate the configuration, as the internal " +
|
||||||
|
"configuration could not be read!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
YamlConfiguration newConfiguration = StargateYamlConfiguration.loadConfiguration(
|
||||||
|
FileHelper.getBufferedReaderFromInputStream(configStream));
|
||||||
|
|
||||||
|
//Read all available config migrations
|
||||||
|
Map<String, String> migrationFields;
|
||||||
|
try {
|
||||||
|
InputStream migrationStream = FileHelper.getInputStreamForInternalFile("/config-migrations.txt");
|
||||||
|
if (migrationStream == null) {
|
||||||
|
instance.getLogger().log(Level.SEVERE, "Could not migrate the configuration, as the internal migration paths could not be read!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
migrationFields = FileHelper.readKeyValuePairs(FileHelper.getBufferedReaderFromInputStream(migrationStream),
|
||||||
|
"=", ColorConversion.NORMAL);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
instance.getLogger().log(Level.WARNING, "Unable to load config migration file");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Replace old config names with the new ones
|
||||||
|
for (String key : migrationFields.keySet()) {
|
||||||
|
if (oldConfiguration.contains(key)) {
|
||||||
|
migrateProperty(migrationFields, key, oldConfiguration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all keys to the new config
|
||||||
|
for (String key : StargateYamlConfiguration.getKeysWithoutComments(oldConfiguration, true)) {
|
||||||
|
if (oldConfiguration.get(key) instanceof MemorySection) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
newConfiguration.set(key, oldConfiguration.get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
newConfiguration.save(new File(dataFolderPath, "config.yml"));
|
||||||
|
} catch (IOException exception) {
|
||||||
|
instance.getLogger().log(Level.WARNING, "Unable to save migrated config");
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.reloadConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Migrates one configuration property
|
||||||
|
*
|
||||||
|
* @param migrationFields <p>The configuration fields to be migrated</p>
|
||||||
|
* @param key <p>The key/path of the property to migrate</p>
|
||||||
|
* @param oldConfiguration <p>The original pre-migration configuration</p>
|
||||||
|
*/
|
||||||
|
private static void migrateProperty(@NotNull Map<String, String> migrationFields, @NotNull String key,
|
||||||
|
@NotNull FileConfiguration oldConfiguration) {
|
||||||
|
String newPath = migrationFields.get(key);
|
||||||
|
Object oldValue = oldConfiguration.get(key);
|
||||||
|
if (!newPath.trim().isEmpty()) {
|
||||||
|
if (oldConfiguration.isConfigurationSection(key)) {
|
||||||
|
// Copy each value of a configuration section
|
||||||
|
ConfigurationSection sourceSection = oldConfiguration.getConfigurationSection(key);
|
||||||
|
ConfigurationSection destinationSection = oldConfiguration.createSection(newPath);
|
||||||
|
if (sourceSection == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String path : StargateYamlConfiguration.getKeysWithoutComments(sourceSection, true)) {
|
||||||
|
destinationSection.set(path, sourceSection.get(path));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Copy the value to the new path
|
||||||
|
oldConfiguration.set(newPath, oldValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the old path's value
|
||||||
|
oldConfiguration.set(key, null);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ public final class ItemHelper {
|
|||||||
//Parse every material, and add to reforgeAble items
|
//Parse every material, and add to reforgeAble items
|
||||||
for (String item : itemList) {
|
for (String item : itemList) {
|
||||||
//Ignore ",,"
|
//Ignore ",,"
|
||||||
if (InputParsingHelper.isEmpty(item)) {
|
if (InputParsingHelper.isEmpty(item) || item.matches("\\[]")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,38 @@
|
|||||||
defaults=blacksmith.defaults
|
global.basePrice=blacksmith.global.basePrice
|
||||||
global=blacksmith.global
|
global.pricePerDurabilityPoint=blacksmith.global.pricePerDurabilityPoint
|
||||||
scrapper.defaults.delaysInSeconds.minimum=scrapper.defaults.minSalvageWaitTimeSeconds
|
global.enchantmentCost=blacksmith.global.enchantmentCost
|
||||||
scrapper.defaults.delaysInSeconds.maximum=scrapper.defaults.maxSalvageWaitTimeSeconds
|
global.useNaturalCost=blacksmith.global.useNaturalCost
|
||||||
scrapper.defaults.delaysInSeconds.salvageCoolDown=scrapper.defaults.salvageCoolDownSeconds
|
global.showExactTime=blacksmith.global.showExactTime
|
||||||
blacksmith.defaults.delaysInSeconds.minimum=blacksmith.defaults.minReforgeWaitTimeSeconds
|
global.chippedAnvilRepairCost=blacksmith.global.chippedAnvilReforgingCost
|
||||||
blacksmith.defaults.delaysInSeconds.maximum=blacksmith.defaults.maxReforgeWaitTimeSeconds
|
global.damagedAnvilRepairCost=blacksmith.global.damagedAnvilReforgingCost
|
||||||
blacksmith.defaults.delaysInSeconds.reforgeCoolDown=blacksmith.defaults.reforgeCoolDownSeconds
|
global.chippedAnvilReforgingCost=blacksmith.global.chippedAnvilReforgingCost
|
||||||
blacksmith.defaults.enchantmentBlocklist=blacksmith.defaults.enchantmentBlockList
|
global.damagedAnvilReforgingCost=blacksmith.global.damagedAnvilReforgingCost
|
||||||
|
global.disableMaterialLimitation=
|
||||||
|
defaults.dropItem=blacksmith.defaults.dropItem
|
||||||
|
defaults.reforgeAbleItems=blacksmith.defaults.reforgeAbleItems
|
||||||
|
defaults.disableCoolDown=
|
||||||
|
defaults.disableDelay=
|
||||||
|
defaults.failReforgeChance=blacksmith.defaults.failReforgeChance
|
||||||
|
defaults.extraEnchantmentChance=blacksmith.defaults.extraEnchantmentChance
|
||||||
|
defaults.maxEnchantments=blacksmith.defaults.maxEnchantments
|
||||||
|
defaults.delaysInSeconds.maximum=blacksmith.defaults.maxReforgeWaitTimeSeconds
|
||||||
|
defaults.delaysInSeconds.minimum=blacksmith.defaults.minReforgeWaitTimeSeconds
|
||||||
|
defaults.delaysInSeconds.reforgeCoolDown=blacksmith.defaults.reforgeCoolDownSeconds
|
||||||
|
defaults.delaysInSeconds.blacksmithTitle=
|
||||||
|
defaults.messages.busyPlayerMessage=blacksmith.defaults.messages.busyPlayerMessage
|
||||||
|
defaults.messages.busyReforgeMessage=blacksmith.defaults.messages.busyReforgeMessage
|
||||||
|
defaults.messages.coolDownUnexpiredMessage=blacksmith.defaults.messages.coolDownUnexpiredMessage
|
||||||
|
defaults.messages.costMessage=blacksmith.defaults.messages.costMessage
|
||||||
|
defaults.messages.failReforgeMessage=blacksmith.defaults.messages.failReforgeMessage
|
||||||
|
defaults.messages.insufficientFundsMessage=blacksmith.defaults.messages.insufficientFundsMessage
|
||||||
|
defaults.messages.invalidItemMessage=blacksmith.defaults.messages.invalidItemMessage
|
||||||
|
defaults.messages.itemChangedMessage=blacksmith.defaults.messages.itemChangedMessage
|
||||||
|
defaults.messages.startReforgeMessage=blacksmith.defaults.messages.startReforgeMessage
|
||||||
|
defaults.messages.successMessage=blacksmith.defaults.messages.successMessage
|
||||||
|
defaults.messages.notDamagedMessage=blacksmith.defaults.messages.notDamagedMessage
|
||||||
|
defaults.blacksmithTitle=blacksmith.defaults.blacksmithTitle
|
||||||
|
defaults.enchantmentBlocklist=blacksmith.defaults.enchantmentBlockList
|
||||||
|
defaults.repairAnvils=blacksmith.defaults.reforgeAnvils
|
||||||
|
defaults.repairAnvils=
|
||||||
|
defaults.reforgeAnvils=blacksmith.defaults.reforgeAnvils
|
||||||
|
defaults.failReforgeRemovesEnchantments=blacksmith.defaults.failReforgeRemovesEnchantments
|
@ -139,7 +139,7 @@ scrapper:
|
|||||||
defaults:
|
defaults:
|
||||||
|
|
||||||
# Whether the item will drop materials resulting from scrapping on the ground, instead of putting them into the user's inventory
|
# Whether the item will drop materials resulting from scrapping on the ground, instead of putting them into the user's inventory
|
||||||
dropItems: true
|
dropItem: true
|
||||||
|
|
||||||
# The chance to fail a salvage, thus destroying the item (0-100)
|
# The chance to fail a salvage, thus destroying the item (0-100)
|
||||||
failSalvageChance: 0
|
failSalvageChance: 0
|
||||||
@ -175,8 +175,8 @@ scrapper:
|
|||||||
# The message to display when the scrapper is still on a cool-down from the previous salvaging
|
# The message to display when the scrapper is still on a cool-down from the previous salvaging
|
||||||
coolDownUnexpiredMessage: "&cYou've already had your chance! Give me a break! I'll be ready {time}!"
|
coolDownUnexpiredMessage: "&cYou've already had your chance! Give me a break! I'll be ready {time}!"
|
||||||
|
|
||||||
# The message to display if the player tries to salvage an item the scrapper cannot salvage
|
# The message to display when holding an item the blacksmith is unable to reforge
|
||||||
cannotSalvageMessage: "&cI'm unable to salvage that item"
|
invalidItemMessage: "&cI'm sorry, but I'm a/an {title}, I don't know how to salvage that!"
|
||||||
|
|
||||||
# The message to display if salvaging the player's item would result in no salvage
|
# The message to display if salvaging the player's item would result in no salvage
|
||||||
tooDamagedForSalvageMessage: "&cThat item is too damaged to be salvaged into anything useful"
|
tooDamagedForSalvageMessage: "&cThat item is too damaged to be salvaged into anything useful"
|
||||||
@ -193,5 +193,8 @@ scrapper:
|
|||||||
# The message to display once the scrapper starts salvaging
|
# The message to display once the scrapper starts salvaging
|
||||||
startSalvageMessage: "&eOk, let's see what I can do..."
|
startSalvageMessage: "&eOk, let's see what I can do..."
|
||||||
|
|
||||||
# The message to display when holding an item the blacksmith is unable to reforge
|
# The message to display if the player is unable to pay the scrapper's fee
|
||||||
invalidItemMessage: "&cI'm sorry, but I'm a/an {title}, I don't know how to salvage that!"
|
insufficientFundsMessage: "&cYou don't have enough money to salvage an item!"
|
||||||
|
|
||||||
|
# The message to display when explaining the shown item's salvage cost
|
||||||
|
costMessage: "&eIt will cost &a{cost}&e to salvage that item! Click again to salvage!"
|
Loading…
Reference in New Issue
Block a user