mirror of
https://github.com/NoCheatPlus/NoCheatPlus.git
synced 2024-09-27 14:13:11 +02:00
Fix faulty config notifications.
The per-config-path notifications would keep showing up, even if you removed the paths, then run 'ncp reload', then alter any of them and run 'ncp reload'. To fix this, the configversion.created value is set to the current build, if no config warnings are there - which is the same, as what the notification suggests as an alternative to removing the paths and running 'ncp reload'. To do this, isConfigUpToDate had to be moved from Updates to ConfigManager, which makes more sense anyway. In addition the 'created' and saved 'values' are set to the biggest thing found, instead of the prehistoric static value. Further a negative 'created' value will not be overridden anymore, allowing to silence the config notifications forever. Not necessarily recommended for the general case, but it can be useful/necessary with maintained blueprints, e.g. with administering multiple servers. One of the next steps will be to remove the DefaultConfig.buildNumber in favor of setting a build number for each and every path added. All provided we don't run into nasty issues here. Another follow up could be to create an extra registry/config log file and write all the values there, and only print the first 5 in ingame chat.
This commit is contained in:
parent
4b9e7c9fe3
commit
3d73a54fcd
@ -18,14 +18,18 @@ import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
import org.bukkit.configuration.MemoryConfiguration;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
|
||||
import fr.neatmonster.nocheatplus.actions.ActionFactory;
|
||||
import fr.neatmonster.nocheatplus.logging.StaticLog;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
|
||||
/**
|
||||
* Central location for everything that's described in the configuration file(s).<br>
|
||||
@ -205,6 +209,9 @@ public class ConfigManager {
|
||||
// Try to obtain and parse the global configuration file.
|
||||
final File globalFile = new File(plugin.getDataFolder(), "config.yml");
|
||||
final ConfigFile defaultConfig = new DefaultConfig();
|
||||
final int maxBuildContained = Math.max(DefaultConfig.buildNumber,
|
||||
defaultConfig.getMaxLastChangedBuildNumber());
|
||||
// TODO: Detect changes to the configuration (only save back if necessary.).
|
||||
PathUtils.processPaths(globalFile, "global config", false);
|
||||
final ConfigFile globalConfig = new ConfigFile();
|
||||
globalConfig.setDefaults(defaultConfig);
|
||||
@ -215,11 +222,21 @@ public class ConfigManager {
|
||||
// Quick shallow ugly fix: only save back if loading was successful.
|
||||
try {
|
||||
if (globalConfig.getBoolean(ConfPaths.SAVEBACKCONFIG)){
|
||||
boolean overrideCreated = false;
|
||||
if (!globalConfig.contains(ConfPaths.CONFIGVERSION_CREATED)){
|
||||
// Workaround.
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_CREATED, DefaultConfig.buildNumber);
|
||||
overrideCreated = true;
|
||||
}
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_SAVED, DefaultConfig.buildNumber);
|
||||
if (!overrideCreated && globalConfig.getInt(ConfPaths.CONFIGVERSION_CREATED, 0) >= 0
|
||||
&& ConfigManager.isConfigUpToDate(globalConfig) == null) {
|
||||
// Workaround: Update the created build number, to not warn on further changes.
|
||||
overrideCreated = true;
|
||||
}
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_SAVED, maxBuildContained);
|
||||
if (overrideCreated) {
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_CREATED, maxBuildContained);
|
||||
}
|
||||
// TODO: Only save back if really changed?
|
||||
globalConfig.save(globalFile);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
@ -235,8 +252,8 @@ public class ConfigManager {
|
||||
globalConfig.options().header("This configuration was auto-generated by NoCheatPlus.");
|
||||
globalConfig.options().copyHeader(true);
|
||||
try {
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_CREATED, DefaultConfig.buildNumber);
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_SAVED, DefaultConfig.buildNumber);
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_CREATED, maxBuildContained);
|
||||
globalConfig.set(ConfPaths.CONFIGVERSION_SAVED, maxBuildContained);
|
||||
globalConfig.save(globalFile);
|
||||
} catch (final Exception e) {
|
||||
StaticLog.logSevere(e);
|
||||
@ -271,7 +288,9 @@ public class ConfigManager {
|
||||
worldConfig.load(worldFile);
|
||||
newWorldsMap.put(worldEntry.getKey(), worldConfig);
|
||||
try{
|
||||
if (worldConfig.getBoolean(ConfPaths.SAVEBACKCONFIG)) worldConfig.save(worldFile);
|
||||
if (worldConfig.getBoolean(ConfPaths.SAVEBACKCONFIG)) {
|
||||
worldConfig.save(worldFile);
|
||||
}
|
||||
} catch (final Exception e){
|
||||
StaticLog.logSevere("Couldn't save back world-specific configuration for " + worldEntry.getKey() + " (see exception below).");
|
||||
StaticLog.logSevere(e);
|
||||
@ -288,6 +307,68 @@ public class ConfigManager {
|
||||
isInitialized = true;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param globalConfig
|
||||
* @return null if everything is fine, a string with a message stating problems otherwise.
|
||||
*/
|
||||
public static String isConfigUpToDate(ConfigFile globalConfig) {
|
||||
Object created_o = globalConfig.get(ConfPaths.CONFIGVERSION_CREATED);
|
||||
int buildCreated = -1;
|
||||
if (created_o != null && created_o instanceof Integer) {
|
||||
buildCreated = ((Integer) created_o).intValue();
|
||||
}
|
||||
// Silence version checking with a value < 0.
|
||||
if (buildCreated < 0) {
|
||||
return null;
|
||||
}
|
||||
final int maxBuildContained = Math.max(DefaultConfig.buildNumber,
|
||||
globalConfig.getMaxLastChangedBuildNumber());
|
||||
// Legacy build number comparison.
|
||||
if (buildCreated < DefaultConfig.buildNumber) {
|
||||
// Potentially outdated Configuration.
|
||||
return "Your configuration might be outdated.\n" + "Some settings could have changed, you should regenerate it!";
|
||||
}
|
||||
else if (buildCreated > maxBuildContained) {
|
||||
// Installed an older version of NCP.
|
||||
return "Your configuration seems to be created by a newer plugin version.\n" + "Some settings could have changed, you should regenerate it!";
|
||||
}
|
||||
// So far so good... test individual paths.
|
||||
final List<String> problems = new LinkedList<String>();
|
||||
final ConfigFile defaultConfig = new DefaultConfig();
|
||||
final Map<String, Integer> lastChangedBuildNumbers = defaultConfig.getLastChangedBuildNumbers();
|
||||
// TODO: Consider some behavior for entire nodes ?
|
||||
for (final Entry<String, Integer> entry : lastChangedBuildNumbers.entrySet()) {
|
||||
final int defaultBuild = entry.getValue();
|
||||
if (defaultBuild <= buildCreated) {
|
||||
// Ignore, might've been changed on purpose.
|
||||
continue;
|
||||
}
|
||||
final String path = entry.getKey();
|
||||
final Object defaultValue = defaultConfig.get(path);
|
||||
if (defaultValue instanceof ConfigurationSection) {
|
||||
problems.add("Changed with build " + defaultBuild + ", can not handle entire configuration sections yet: " + path);
|
||||
continue;
|
||||
}
|
||||
final Object currentValue = globalConfig.get(path);
|
||||
if (currentValue == null || defaultValue == null) {
|
||||
// To be handled elsewhere (@Moved / whatever).
|
||||
continue;
|
||||
}
|
||||
if (defaultBuild > buildCreated && !defaultValue.equals(currentValue)) {
|
||||
problems.add("Changed with build " + defaultBuild + ": " + path);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!problems.isEmpty()) {
|
||||
problems.add(0, "The following configuration default values have changed:");
|
||||
problems.add("(Remove/update individual values or set configversion.created to " + maxBuildContained + " to ignore all, then reload the configuration with the 'ncp reload' command.)");
|
||||
return StringUtil.join(problems, "\n");
|
||||
}
|
||||
// No errors could be determined (or versions coudl not be determined): ignore.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Informal test if the init method completed (no details are reflected).
|
||||
* @return
|
||||
|
@ -346,8 +346,14 @@ public class RawConfigFile extends YamlConfiguration {
|
||||
*
|
||||
* @param path
|
||||
* @param value
|
||||
* Must be greater than zero.
|
||||
* @throws IllegalArgumentException
|
||||
* If the value is equal to or smaller than zero.
|
||||
*/
|
||||
public void setLastChangedBuildNumber(String path, int value) {
|
||||
if (value <= 0) {
|
||||
throw new IllegalArgumentException("Build number must be greater than zero. Got " + value + " for path: " + path);
|
||||
}
|
||||
lastChangedBuildNumbers.put(path, value);
|
||||
}
|
||||
|
||||
@ -363,4 +369,20 @@ public class RawConfigFile extends YamlConfiguration {
|
||||
return lastChangedBuildNumbers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the maximum of all last-changed-build-number values, stored for
|
||||
* individual paths (default to 0).
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public int getMaxLastChangedBuildNumber() {
|
||||
int max = 0;
|
||||
for (Integer v : lastChangedBuildNumbers.values()) {
|
||||
if (v != null) {
|
||||
max = Math.max(max, v);
|
||||
}
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -121,7 +121,6 @@ import fr.neatmonster.nocheatplus.players.DataManager;
|
||||
import fr.neatmonster.nocheatplus.players.PlayerData;
|
||||
import fr.neatmonster.nocheatplus.players.PlayerMessageSender;
|
||||
import fr.neatmonster.nocheatplus.stats.Counters;
|
||||
import fr.neatmonster.nocheatplus.updates.Updates;
|
||||
import fr.neatmonster.nocheatplus.utilities.ColorUtil;
|
||||
import fr.neatmonster.nocheatplus.utilities.OnDemandTickListener;
|
||||
import fr.neatmonster.nocheatplus.utilities.ReflectionUtil;
|
||||
@ -1194,7 +1193,7 @@ public class NoCheatPlus extends JavaPlugin implements NoCheatPlusAPI {
|
||||
* @param config
|
||||
*/
|
||||
private void setInstanceMembers(final ConfigFile config) {
|
||||
configProblems = Updates.isConfigUpToDate(config);
|
||||
configProblems = ConfigManager.isConfigUpToDate(config);
|
||||
useSubscriptions = config.getBoolean(ConfPaths.LOGGING_BACKEND_INGAMECHAT_SUBSCRIPTIONS);
|
||||
clearExemptionsOnJoin = config.getBoolean(ConfPaths.COMPATIBILITY_EXEMPTIONS_REMOVE_JOIN);
|
||||
clearExemptionsOnLeave = config.getBoolean(ConfPaths.COMPATIBILITY_EXEMPTIONS_REMOVE_LEAVE);
|
||||
|
@ -14,80 +14,8 @@
|
||||
*/
|
||||
package fr.neatmonster.nocheatplus.updates;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.bukkit.configuration.ConfigurationSection;
|
||||
|
||||
import fr.neatmonster.nocheatplus.config.ConfPaths;
|
||||
import fr.neatmonster.nocheatplus.config.ConfigFile;
|
||||
import fr.neatmonster.nocheatplus.config.DefaultConfig;
|
||||
import fr.neatmonster.nocheatplus.utilities.StringUtil;
|
||||
|
||||
public class Updates {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param globalConfig
|
||||
* @return null if everything is fine, a string with a message stating problems otherwise.
|
||||
*/
|
||||
public static String isConfigUpToDate(ConfigFile globalConfig) {
|
||||
Object created_o = globalConfig.get(ConfPaths.CONFIGVERSION_CREATED);
|
||||
int buildCreated = -1;
|
||||
if (created_o != null && created_o instanceof Integer) {
|
||||
buildCreated = ((Integer) created_o).intValue();
|
||||
}
|
||||
if (buildCreated < 0) {
|
||||
return null;
|
||||
}
|
||||
if (buildCreated < DefaultConfig.buildNumber) {
|
||||
// Potentially outdated Configuration.
|
||||
return "Your configuration might be outdated.\n" + "Some settings could have changed, you should regenerate it!";
|
||||
}
|
||||
else if (buildCreated > DefaultConfig.buildNumber) {
|
||||
// Installed an older version of NCP.
|
||||
return "Your configuration seems to be created by a newer plugin version.\n" + "Some settings could have changed, you should regenerate it!";
|
||||
}
|
||||
// So far so good... test individual paths.
|
||||
final List<String> problems = new LinkedList<String>();
|
||||
final ConfigFile defaultConfig = new DefaultConfig();
|
||||
final Map<String, Integer> lastChangedBuildNumbers = defaultConfig.getLastChangedBuildNumbers();
|
||||
int maxBuild = DefaultConfig.buildNumber;
|
||||
// TODO: Consider some behavior for entire nodes ?
|
||||
for (final Entry<String, Integer> entry : lastChangedBuildNumbers.entrySet()) {
|
||||
final int defaultBuild = entry.getValue();
|
||||
if (defaultBuild <= buildCreated) {
|
||||
// Ignore, might've been changed on purpose.
|
||||
continue;
|
||||
}
|
||||
final String path = entry.getKey();
|
||||
final Object defaultValue = defaultConfig.get(path);
|
||||
if (defaultValue instanceof ConfigurationSection) {
|
||||
problems.add("Changed with build " + defaultBuild + ", can not handle entire configuration sections yet: " + path);
|
||||
continue;
|
||||
}
|
||||
final Object currentValue = globalConfig.get(path);
|
||||
if (currentValue == null || defaultValue == null) {
|
||||
// To be handled elsewhere (@Moved / whatever).
|
||||
continue;
|
||||
}
|
||||
if (defaultBuild > buildCreated && !defaultValue.equals(currentValue)) {
|
||||
problems.add("Changed with build " + defaultBuild + ": " + path);
|
||||
maxBuild = Math.max(defaultBuild, maxBuild);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!problems.isEmpty()) {
|
||||
problems.add(0, "The following configuration default values have changed:");
|
||||
problems.add("(Remove/update individual values or set configversion.created to " + maxBuild + " to ignore all, then reload the configuration with the 'ncp reload' command.)");
|
||||
return StringUtil.join(problems, "\n");
|
||||
}
|
||||
// No errors could be determined (or versions coudl not be determined): ignore.
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* To be called from an async task.
|
||||
* @param versionString Current version string (getDescription().getVersion()).
|
||||
|
Loading…
Reference in New Issue
Block a user