mirror of
https://github.com/ViaVersion/ViaVersion.git
synced 2024-11-29 21:43:30 +01:00
Add config wrapper to update config
Configuration reads old config and moves it's values over to a new config copied from the resources directory. normally, when you save it would delete the comments, but they are written back in to the new config by this wrapper now people their config files will actually update
This commit is contained in:
parent
4a804bae7c
commit
6d95af3963
@ -24,9 +24,12 @@ import us.myles.ViaVersion.handlers.ViaVersionInitializer;
|
|||||||
import us.myles.ViaVersion.listeners.CommandBlockListener;
|
import us.myles.ViaVersion.listeners.CommandBlockListener;
|
||||||
import us.myles.ViaVersion.update.UpdateListener;
|
import us.myles.ViaVersion.update.UpdateListener;
|
||||||
import us.myles.ViaVersion.update.UpdateUtil;
|
import us.myles.ViaVersion.update.UpdateUtil;
|
||||||
|
import us.myles.ViaVersion.util.Configuration;
|
||||||
import us.myles.ViaVersion.util.ListWrapper;
|
import us.myles.ViaVersion.util.ListWrapper;
|
||||||
import us.myles.ViaVersion.util.ReflectionUtil;
|
import us.myles.ViaVersion.util.ReflectionUtil;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -36,6 +39,7 @@ import java.util.concurrent.Callable;
|
|||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
|
||||||
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
||||||
|
|
||||||
@ -64,7 +68,7 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
|||||||
@Override
|
@Override
|
||||||
public void onEnable() {
|
public void onEnable() {
|
||||||
ViaVersion.setInstance(this);
|
ViaVersion.setInstance(this);
|
||||||
saveDefaultConfig();
|
generateConfig();
|
||||||
if (System.getProperty("ViaVersion") != null) {
|
if (System.getProperty("ViaVersion") != null) {
|
||||||
getLogger().severe("ViaVersion is already loaded, we don't support reloads. Please reboot if you wish to update.");
|
getLogger().severe("ViaVersion is already loaded, we don't support reloads. Please reboot if you wish to update.");
|
||||||
getLogger().severe("Some features may not work.");
|
getLogger().severe("Some features may not work.");
|
||||||
@ -93,6 +97,28 @@ public class ViaVersionPlugin extends JavaPlugin implements ViaVersionAPI {
|
|||||||
getCommand("viaversion").setExecutor(new ViaVersionCommand(this));
|
getCommand("viaversion").setExecutor(new ViaVersionCommand(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void generateConfig() {
|
||||||
|
File file = new File(getDataFolder(), "config.yml");
|
||||||
|
if(file.exists()) {
|
||||||
|
// Update config options
|
||||||
|
Configuration oldConfig = new Configuration(file);
|
||||||
|
oldConfig.reload(false); // Load current options from config
|
||||||
|
file.delete(); // Delete old config
|
||||||
|
saveDefaultConfig(); // Generate new config
|
||||||
|
Configuration newConfig = new Configuration(file);
|
||||||
|
newConfig.reload(true); // Load default options
|
||||||
|
for(String key : oldConfig.getKeys(false)) {
|
||||||
|
// Set option in new config if exists
|
||||||
|
if(newConfig.contains(key)) {
|
||||||
|
newConfig.set(key, oldConfig.get(key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newConfig.save();
|
||||||
|
} else {
|
||||||
|
saveDefaultConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void injectPacketHandler() {
|
public void injectPacketHandler() {
|
||||||
try {
|
try {
|
||||||
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
Class<?> serverClazz = ReflectionUtil.nms("MinecraftServer");
|
||||||
|
246
src/main/java/us/myles/ViaVersion/util/Configuration.java
Normal file
246
src/main/java/us/myles/ViaVersion/util/Configuration.java
Normal file
@ -0,0 +1,246 @@
|
|||||||
|
package us.myles.ViaVersion.util;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import org.bukkit.Bukkit;
|
||||||
|
import org.bukkit.configuration.InvalidConfigurationException;
|
||||||
|
import org.bukkit.configuration.file.YamlConfiguration;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
public class Configuration extends YamlConfiguration {
|
||||||
|
private List<String> mainHeader = Lists.newArrayList();
|
||||||
|
private final Map<String, List<String>> headers = Maps.newConcurrentMap();
|
||||||
|
private final File file;
|
||||||
|
private boolean loadHeaders;
|
||||||
|
|
||||||
|
public Configuration(File file) {
|
||||||
|
this.file = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the main header displayed at top of config.
|
||||||
|
*
|
||||||
|
* @param header header
|
||||||
|
*/
|
||||||
|
public void mainHeader(String... header) {
|
||||||
|
mainHeader = Arrays.asList(header);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get main header displayed at top of config.
|
||||||
|
*
|
||||||
|
* @return header
|
||||||
|
*/
|
||||||
|
public List<String> mainHeader() {
|
||||||
|
return mainHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set option header.
|
||||||
|
*
|
||||||
|
* @param key of option (or section)
|
||||||
|
* @param header of option (or section)
|
||||||
|
*/
|
||||||
|
public void header(String key, String... header) {
|
||||||
|
// String value = Joiner.on('\n').join(header);
|
||||||
|
headers.put(key, Arrays.asList(header));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get header of option
|
||||||
|
*
|
||||||
|
* @param key of option (or section)
|
||||||
|
* @return Header
|
||||||
|
*/
|
||||||
|
public List<String> header(String key) {
|
||||||
|
return headers.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T get(String key, Class<T> type) {
|
||||||
|
return type.cast(get(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload config from file.
|
||||||
|
*/
|
||||||
|
public void reload() {
|
||||||
|
reload(headers.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reload config from file.
|
||||||
|
*
|
||||||
|
* @param loadHeaders Whether or not to load headers.
|
||||||
|
*/
|
||||||
|
public void reload(boolean loadHeaders) {
|
||||||
|
this.loadHeaders = loadHeaders;
|
||||||
|
try {
|
||||||
|
load(file);
|
||||||
|
} catch(Exception e) {
|
||||||
|
Bukkit.getLogger().log(Level.WARNING, "failed to reload file", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void loadFromString(String contents) throws InvalidConfigurationException {
|
||||||
|
if(!loadHeaders) {
|
||||||
|
super.loadFromString(contents);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder memoryData = new StringBuilder();
|
||||||
|
|
||||||
|
// Parse headers
|
||||||
|
final int indentLength = options().indent();
|
||||||
|
final String pathSeparator = Character.toString(options().pathSeparator());
|
||||||
|
int currentIndents = 0;
|
||||||
|
String key = "";
|
||||||
|
List<String> headers = Lists.newArrayList();
|
||||||
|
for(String line : contents.split("\n")) {
|
||||||
|
if(line.isEmpty()) continue; // Skip empty lines
|
||||||
|
int indent = getSuccessiveCharCount(line, ' ');
|
||||||
|
String subline = indent > 0 ? line.substring(indent) : line;
|
||||||
|
if(subline.startsWith("#")) {
|
||||||
|
if(subline.startsWith("#>")) {
|
||||||
|
String txt = subline.startsWith("#> ") ? subline.substring(3) : subline.substring(2);
|
||||||
|
mainHeader.add(txt);
|
||||||
|
continue; // Main header, handled by bukkit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add header to list
|
||||||
|
String txt = subline.startsWith("# ") ? subline.substring(2) : subline.substring(1);
|
||||||
|
headers.add(txt);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int indents = indent / indentLength;
|
||||||
|
if(indents <= currentIndents) {
|
||||||
|
// Remove last section of key
|
||||||
|
String[] array = key.split(Pattern.quote(pathSeparator));
|
||||||
|
int backspace = currentIndents - indents + 1;
|
||||||
|
key = join(array, options().pathSeparator(), 0, array.length - backspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new section to key
|
||||||
|
String separator = key.length() > 0 ? pathSeparator : "";
|
||||||
|
String lineKey = line.contains(":") ? line.split(Pattern.quote(":"))[0] : line;
|
||||||
|
key += separator + lineKey.substring(indent);
|
||||||
|
|
||||||
|
currentIndents = indents;
|
||||||
|
|
||||||
|
memoryData.append(line).append('\n');
|
||||||
|
if(!headers.isEmpty()) {
|
||||||
|
this.headers.put(key, headers);
|
||||||
|
headers = Lists.newArrayList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse remaining text
|
||||||
|
super.loadFromString(memoryData.toString());
|
||||||
|
|
||||||
|
// Clear bukkit header
|
||||||
|
options().header(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Save config to file
|
||||||
|
*/
|
||||||
|
public void save() {
|
||||||
|
if(headers.isEmpty() && mainHeader.isEmpty()) {
|
||||||
|
try {
|
||||||
|
super.save(file);
|
||||||
|
} catch(IOException e) {
|
||||||
|
Bukkit.getLogger().log(Level.WARNING, "Failed to save file", e);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Custom save
|
||||||
|
final int indentLength = options().indent();
|
||||||
|
final String pathSeparator = Character.toString(options().pathSeparator());
|
||||||
|
String content = saveToString();
|
||||||
|
StringBuilder fileData = new StringBuilder(buildHeader());
|
||||||
|
int currentIndents = 0;
|
||||||
|
String key = "";
|
||||||
|
for(String h : mainHeader) {
|
||||||
|
// Append main header to top of file
|
||||||
|
fileData.append("#> ").append(h).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
for(String line : content.split("\n")) {
|
||||||
|
if(line.isEmpty()) continue; // Skip empty lines
|
||||||
|
int indent = getSuccessiveCharCount(line, ' ');
|
||||||
|
int indents = indent / indentLength;
|
||||||
|
String indentText = indent > 0 ? line.substring(0, indent) : "";
|
||||||
|
if(indents <= currentIndents) {
|
||||||
|
// Remove last section of key
|
||||||
|
String[] array = key.split(Pattern.quote(pathSeparator));
|
||||||
|
int backspace = currentIndents - indents + 1;
|
||||||
|
key = join(array, options().pathSeparator(), 0, array.length - backspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add new section to key
|
||||||
|
String separator = key.length() > 0 ? pathSeparator : "";
|
||||||
|
String lineKey = line.contains(":") ? line.split(Pattern.quote(":"))[0] : line;
|
||||||
|
key += separator + lineKey.substring(indent);
|
||||||
|
|
||||||
|
currentIndents = indents;
|
||||||
|
|
||||||
|
List<String> header = headers.get(key);
|
||||||
|
String headerText = header != null ? addHeaderTags(header, indentText) : "";
|
||||||
|
fileData.append(headerText).append(line).append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write data to file
|
||||||
|
FileWriter writer = null;
|
||||||
|
try {
|
||||||
|
writer = new FileWriter(file);
|
||||||
|
writer.write(fileData.toString());
|
||||||
|
writer.flush();
|
||||||
|
} catch(IOException e) {
|
||||||
|
Bukkit.getLogger().log(Level.WARNING, "Failed to save file", e);
|
||||||
|
} finally {
|
||||||
|
if(writer != null) {
|
||||||
|
try {
|
||||||
|
writer.close();
|
||||||
|
} catch(IOException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String addHeaderTags(List<String> header, String indent) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for(String line : header) {
|
||||||
|
builder.append(indent).append("# ").append(line).append('\n');
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String join(String[] array, char joinChar, int start, int length) {
|
||||||
|
String[] copy = new String[length - start];
|
||||||
|
System.arraycopy(array, start, copy, 0, length - start);
|
||||||
|
return Joiner.on(joinChar).join(copy);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getSuccessiveCharCount(String text, char key) {
|
||||||
|
int count = 0;
|
||||||
|
for(int i = 0; i < text.length(); i++) {
|
||||||
|
if(text.charAt(i) == key) {
|
||||||
|
count += 1;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user