All source projects
MrUltimateLibrary Source
Standalone source project / 68 files
MrUltimateLibrary is the backbone of all my plugins; it offers features that facilitate plugin creation, maintenance, and updates.
java
MrUltimateLibrary/src/main/java/eu/mrneznamy/mrultimatelibrary/config/MrLibConfigMerger.java
JAVA · Read-only source
package eu.mrneznamy.mrultimatelibrary.config;
import eu.mrneznamy.mrultimatelibrary.utils.MrLibConsoleSayer;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.configuration.file.YamlConfiguration;
import org.bukkit.plugin.java.JavaPlugin;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.*;
/**
* Merges remote configuration with local user data
* Preserves user's custom values while adding new structure from remote
*/
public class MrLibConfigMerger {
private final JavaPlugin plugin;
public MrLibConfigMerger(JavaPlugin plugin) {
this.plugin = plugin;
}
/**
* Merges remote config with local config
* - Preserves all user data
* - Adds new sections from remote
* - Updates comments from remote
*
* @param localFile Local config file (user's data)
* @param remoteFile Remote config file (downloaded from web)
* @param configName Name of config (for logging)
*/
public void mergeConfigs(File localFile, File remoteFile, String configName) {
try {
if (!localFile.exists()) {
Files.copy(remoteFile.toPath(), localFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
MrLibConsoleSayer.MrSay_Success("[" + plugin.getName() + "] Created " + configName + " from remote");
return;
}
File backupFolder = new File(plugin.getDataFolder(), "backupFiles");
String timestamp = new java.text.SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new java.util.Date());
File backupFile = new File(backupFolder, configName + ".pre-merge-backup." + timestamp);
File parentDir = backupFile.getParentFile();
if (parentDir != null && !parentDir.exists()) {
parentDir.mkdirs();
}
Files.copy(localFile.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
MrLibConsoleSayer.MrSay_Info("[" + plugin.getName() + "] Backed up " + configName + " to backupFiles/" + backupFile.getName());
YamlConfiguration localConfig = YamlConfiguration.loadConfiguration(localFile);
YamlConfiguration remoteConfig = YamlConfiguration.loadConfiguration(remoteFile);
YamlConfiguration mergedConfig = new YamlConfiguration();
Set<String> allPaths = new HashSet<>();
allPaths.addAll(getAllPaths(localConfig));
allPaths.addAll(getAllPaths(remoteConfig));
for (String path : allPaths) {
if (localConfig.contains(path) && !localConfig.isConfigurationSection(path)) {
mergedConfig.set(path, localConfig.get(path));
} else if (remoteConfig.contains(path) && !remoteConfig.isConfigurationSection(path)) {
mergedConfig.set(path, remoteConfig.get(path));
}
}
if (remoteConfig.contains("MrLibCore-Configs-Version")) {
mergedConfig.set("MrLibCore-Configs-Version", remoteConfig.get("MrLibCore-Configs-Version"));
} else {
String versionKey = configName.replace(".yml", "") + "-version";
if (remoteConfig.contains(versionKey)) {
mergedConfig.set(versionKey, remoteConfig.get(versionKey));
}
}
mergedConfig.save(localFile);
MrLibConsoleSayer.MrSay_Success("[" + plugin.getName() + "] Merged " + configName + " - preserved user data, added new structure");
} catch (Exception e) {
MrLibConsoleSayer.MrSay_Error("[" + plugin.getName() + "] Failed to merge " + configName + ": " + e.getMessage());
e.printStackTrace();
}
}
/**
* Smart merge for plugin-specific configs
* Knows which sections to preserve completely (like user's sell chests)
*/
public void smartMerge(File localFile, File remoteFile, String configName) {
try {
if (!localFile.exists()) {
Files.copy(remoteFile.toPath(), localFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
MrLibConsoleSayer.MrSay_Success("[" + plugin.getName() + "] Created " + configName + " from remote");
return;
}
File backupFolder = new File(plugin.getDataFolder(), "backupFiles");
String timestamp = new java.text.SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new java.util.Date());
File backupFile = new File(backupFolder, configName + ".pre-merge-backup." + timestamp);
File parentDir = backupFile.getParentFile();
if (parentDir != null && !parentDir.exists()) {
parentDir.mkdirs();
}
Files.copy(localFile.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
YamlConfiguration localConfig = YamlConfiguration.loadConfiguration(localFile);
YamlConfiguration remoteConfig = YamlConfiguration.loadConfiguration(remoteFile);
YamlConfiguration mergedConfig = new YamlConfiguration();
Set<String> preserveSections = getPreserveSections(configName);
Set<String> updateSections = getUpdateSections(configName);
for (String section : preserveSections) {
if (localConfig.contains(section)) {
copySection(localConfig, mergedConfig, section);
}
}
for (String section : updateSections) {
if (remoteConfig.contains(section)) {
if (localConfig.contains(section)) {
mergeSection(localConfig, remoteConfig, mergedConfig, section);
} else {
copySection(remoteConfig, mergedConfig, section);
}
}
}
for (String key : localConfig.getKeys(false)) {
if (!mergedConfig.contains(key)) {
if (localConfig.isConfigurationSection(key)) {
copySection(localConfig, mergedConfig, key);
} else {
mergedConfig.set(key, localConfig.get(key));
}
}
}
if (remoteConfig.contains("MrLibCore-Configs-Version")) {
mergedConfig.set("MrLibCore-Configs-Version", remoteConfig.get("MrLibCore-Configs-Version"));
} else {
String versionKey = configName.replace(".yml", "") + "-version";
if (remoteConfig.contains(versionKey)) {
mergedConfig.set(versionKey, remoteConfig.get(versionKey));
}
}
mergedConfig.save(localFile);
MrLibConsoleSayer.MrSay_Success("[" + plugin.getName() + "] Smart merged " + configName);
} catch (Exception e) {
MrLibConsoleSayer.MrSay_Error("[" + plugin.getName() + "] Failed to smart merge " + configName + ": " + e.getMessage());
e.printStackTrace();
}
}
/**
* Special merge for messages.yml
* ONLY adds new message keys, NEVER changes existing ones
* This preserves user's translations, custom colors, etc.
*/
public void mergeMessagesOnly(File localFile, File remoteFile, String configName) {
try {
if (!localFile.exists()) {
Files.copy(remoteFile.toPath(), localFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
MrLibConsoleSayer.MrSay_Success("[" + plugin.getName() + "] Created " + configName + " from remote");
return;
}
File backupFolder = new File(plugin.getDataFolder(), "backupFiles");
String timestamp = new java.text.SimpleDateFormat("yyyy-MM-dd_HH-mm-ss").format(new java.util.Date());
File backupFile = new File(backupFolder, configName + ".pre-merge-backup." + timestamp);
File parentDir = backupFile.getParentFile();
if (parentDir != null && !parentDir.exists()) {
parentDir.mkdirs();
}
Files.copy(localFile.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
YamlConfiguration localConfig = YamlConfiguration.loadConfiguration(localFile);
YamlConfiguration remoteConfig = YamlConfiguration.loadConfiguration(remoteFile);
YamlConfiguration mergedConfig = new YamlConfiguration();
Set<String> allKeys = new HashSet<>();
allKeys.addAll(getAllPaths(localConfig));
allKeys.addAll(getAllPaths(remoteConfig));
for (String key : allKeys) {
if (localConfig.contains(key)) {
mergedConfig.set(key, localConfig.get(key));
} else if (remoteConfig.contains(key)) {
mergedConfig.set(key, remoteConfig.get(key));
}
}
if (remoteConfig.contains("MrLibCore-Configs-Version")) {
mergedConfig.set("MrLibCore-Configs-Version", remoteConfig.get("MrLibCore-Configs-Version"));
} else {
String versionKey = configName.replace(".yml", "") + "-version";
if (remoteConfig.contains(versionKey)) {
mergedConfig.set(versionKey, remoteConfig.get(versionKey));
}
}
mergedConfig.save(localFile);
} catch (Exception e) {
MrLibConsoleSayer.MrSay_Error("[" + plugin.getName() + "] Failed to merge messages: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Get sections that should be preserved completely (user's custom data)
*/
private Set<String> getPreserveSections(String configName) {
Set<String> sections = new HashSet<>();
if (plugin.getName().equals("MrSellChests") && configName.equals("config.yml")) {
sections.add("SellChests");
sections.add("MrSellChests.SellChests");
sections.add("SettingsMenu");
sections.add("MrSellChests.SettingsMenu");
}
if (plugin.getName().equals("MrUltimateShop") && configName.equals("config.yml")) {
sections.add("ChestShops.Menu");
sections.add("MrUltimateShop.ChestShops.Menu");
}
return sections;
}
/**
* Get sections that should be updated from remote (plugin structure)
*/
private Set<String> getUpdateSections(String configName) {
Set<String> sections = new HashSet<>();
if (plugin.getName().equals("MrSellChests") && configName.equals("config.yml")) {
sections.add("MrSellChests.Database");
sections.add("MrSellChests.Holograms");
sections.add("MrSellChests.SellPrices");
sections.add("MrSellChests.Economy");
sections.add("MrSellChests.Sell-Message");
sections.add("MrSellChests.OfflineSell");
}
if (plugin.getName().equals("MrUltimateFishing") && configName.equals("config.yml")) {
sections.add("MrUltimateFishing.Database");
sections.add("MrUltimateFishing.HologramProvider");
sections.add("MrUltimateFishing.UpdateInterval");
sections.add("MrUltimateFishing.Fishing");
sections.add("MrUltimateFishing.Leveling");
sections.add("MrUltimateFishing.Economy");
sections.add("MrUltimateFishing.Player-Data");
sections.add("MrUltimateFishing.Debug");
sections.add("MrUltimateFishing.Fallback");
sections.add("MrUltimateFishing.General");
sections.add("MrUltimateFishing.Upgrades");
sections.add("MrUltimateFishing.CustomDrops");
sections.add("MrUltimateFishing.Totem");
sections.add("MrUltimateFishing.CustomEnchants");
}
if (plugin.getName().equals("MrUltimateFishing") && configName.equals("messages.yml")) {
sections.add("MrUltimateFishing.Items");
sections.add("MrUltimateFishing.menu-keys");
}
return sections;
}
/**
* Copy entire section from source to target
*/
private void copySection(YamlConfiguration source, YamlConfiguration target, String path) {
if (source.isConfigurationSection(path)) {
ConfigurationSection section = source.getConfigurationSection(path);
if (section != null) {
for (String key : section.getKeys(true)) {
String fullPath = path + "." + key;
if (!source.isConfigurationSection(fullPath)) {
target.set(fullPath, source.get(fullPath));
}
}
}
} else {
target.set(path, source.get(path));
}
}
/**
* Merge section: keep user values, add new keys from remote
*/
private void mergeSection(YamlConfiguration local, YamlConfiguration remote, YamlConfiguration merged, String path) {
ConfigurationSection localSection = local.getConfigurationSection(path);
ConfigurationSection remoteSection = remote.getConfigurationSection(path);
if (localSection == null && remoteSection == null) {
return;
}
Set<String> allKeys = new HashSet<>();
if (localSection != null) {
allKeys.addAll(localSection.getKeys(true));
}
if (remoteSection != null) {
allKeys.addAll(remoteSection.getKeys(true));
}
for (String key : allKeys) {
String fullPath = path + "." + key;
if (local.contains(fullPath) && !local.isConfigurationSection(fullPath)) {
merged.set(fullPath, local.get(fullPath));
} else if (remote.contains(fullPath) && !remote.isConfigurationSection(fullPath)) {
merged.set(fullPath, remote.get(fullPath));
}
}
}
/**
* Get all paths in config (including nested)
*/
private Set<String> getAllPaths(YamlConfiguration config) {
Set<String> paths = new HashSet<>();
for (String key : config.getKeys(true)) {
if (!config.isConfigurationSection(key)) {
paths.add(key);
}
}
return paths;
}
}
404 linesGNU GENERAL PUBLIC LICENSE · Version 3, 29 June 2007 · UTF-8 · Read only