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