256 lines
7.4 KiB
Java
256 lines
7.4 KiB
Java
package net.minecraft.server.dedicated;
|
|
|
|
import com.google.common.base.MoreObjects;
|
|
import com.mojang.logging.LogUtils;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
import java.io.InputStreamReader;
|
|
import java.io.Reader;
|
|
import java.io.Writer;
|
|
import java.nio.charset.CharacterCodingException;
|
|
import java.nio.charset.CharsetDecoder;
|
|
import java.nio.charset.CodingErrorAction;
|
|
import java.nio.charset.StandardCharsets;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.util.Objects;
|
|
import java.util.Properties;
|
|
import java.util.function.Function;
|
|
import java.util.function.IntFunction;
|
|
import java.util.function.Supplier;
|
|
import java.util.function.UnaryOperator;
|
|
import net.minecraft.core.RegistryAccess;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.slf4j.Logger;
|
|
|
|
public abstract class Settings<T extends Settings<T>> {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
protected final Properties properties;
|
|
|
|
public Settings(Properties properties) {
|
|
this.properties = properties;
|
|
}
|
|
|
|
public static Properties loadFromFile(Path path) {
|
|
try {
|
|
try {
|
|
InputStream inputStream = Files.newInputStream(path);
|
|
|
|
Properties var13;
|
|
try {
|
|
CharsetDecoder charsetDecoder = StandardCharsets.UTF_8
|
|
.newDecoder()
|
|
.onMalformedInput(CodingErrorAction.REPORT)
|
|
.onUnmappableCharacter(CodingErrorAction.REPORT);
|
|
Properties properties = new Properties();
|
|
properties.load(new InputStreamReader(inputStream, charsetDecoder));
|
|
var13 = properties;
|
|
} catch (Throwable var8) {
|
|
if (inputStream != null) {
|
|
try {
|
|
inputStream.close();
|
|
} catch (Throwable var6) {
|
|
var8.addSuppressed(var6);
|
|
}
|
|
}
|
|
|
|
throw var8;
|
|
}
|
|
|
|
if (inputStream != null) {
|
|
inputStream.close();
|
|
}
|
|
|
|
return var13;
|
|
} catch (CharacterCodingException var9) {
|
|
LOGGER.info("Failed to load properties as UTF-8 from file {}, trying ISO_8859_1", path);
|
|
Reader reader = Files.newBufferedReader(path, StandardCharsets.ISO_8859_1);
|
|
|
|
Properties var4;
|
|
try {
|
|
Properties properties = new Properties();
|
|
properties.load(reader);
|
|
var4 = properties;
|
|
} catch (Throwable var7) {
|
|
if (reader != null) {
|
|
try {
|
|
reader.close();
|
|
} catch (Throwable var5) {
|
|
var7.addSuppressed(var5);
|
|
}
|
|
}
|
|
|
|
throw var7;
|
|
}
|
|
|
|
if (reader != null) {
|
|
reader.close();
|
|
}
|
|
|
|
return var4;
|
|
}
|
|
} catch (IOException var10) {
|
|
LOGGER.error("Failed to load properties from file: {}", path, var10);
|
|
return new Properties();
|
|
}
|
|
}
|
|
|
|
public void store(Path path) {
|
|
try {
|
|
Writer writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8);
|
|
|
|
try {
|
|
this.properties.store(writer, "Minecraft server properties");
|
|
} catch (Throwable var6) {
|
|
if (writer != null) {
|
|
try {
|
|
writer.close();
|
|
} catch (Throwable var5) {
|
|
var6.addSuppressed(var5);
|
|
}
|
|
}
|
|
|
|
throw var6;
|
|
}
|
|
|
|
if (writer != null) {
|
|
writer.close();
|
|
}
|
|
} catch (IOException var7) {
|
|
LOGGER.error("Failed to store properties to file: {}", path);
|
|
}
|
|
}
|
|
|
|
private static <V extends Number> Function<String, V> wrapNumberDeserializer(Function<String, V> parseFunc) {
|
|
return string -> {
|
|
try {
|
|
return (Number)parseFunc.apply(string);
|
|
} catch (NumberFormatException var3) {
|
|
return null;
|
|
}
|
|
};
|
|
}
|
|
|
|
protected static <V> Function<String, V> dispatchNumberOrString(IntFunction<V> byId, Function<String, V> byName) {
|
|
return string -> {
|
|
try {
|
|
return byId.apply(Integer.parseInt(string));
|
|
} catch (NumberFormatException var4) {
|
|
return byName.apply(string);
|
|
}
|
|
};
|
|
}
|
|
|
|
@Nullable
|
|
private String getStringRaw(String key) {
|
|
return (String)this.properties.get(key);
|
|
}
|
|
|
|
@Nullable
|
|
protected <V> V getLegacy(String key, Function<String, V> serializer) {
|
|
String string = this.getStringRaw(key);
|
|
if (string == null) {
|
|
return null;
|
|
} else {
|
|
this.properties.remove(key);
|
|
return (V)serializer.apply(string);
|
|
}
|
|
}
|
|
|
|
protected <V> V get(String key, Function<String, V> serializer, Function<V, String> deserializer, V defaultValue) {
|
|
String string = this.getStringRaw(key);
|
|
V object = MoreObjects.firstNonNull((V)(string != null ? serializer.apply(string) : null), defaultValue);
|
|
this.properties.put(key, deserializer.apply(object));
|
|
return object;
|
|
}
|
|
|
|
protected <V> Settings<T>.MutableValue<V> getMutable(String key, Function<String, V> serializer, Function<V, String> deserializer, V defaultValue) {
|
|
String string = this.getStringRaw(key);
|
|
V object = MoreObjects.firstNonNull((V)(string != null ? serializer.apply(string) : null), defaultValue);
|
|
this.properties.put(key, deserializer.apply(object));
|
|
return new Settings.MutableValue<>(key, object, deserializer);
|
|
}
|
|
|
|
protected <V> V get(String key, Function<String, V> serializer, UnaryOperator<V> modifier, Function<V, String> deserializer, V defaultValue) {
|
|
return this.get(key, string -> {
|
|
V object = (V)serializer.apply(string);
|
|
return object != null ? modifier.apply(object) : null;
|
|
}, deserializer, defaultValue);
|
|
}
|
|
|
|
protected <V> V get(String key, Function<String, V> mapper, V value) {
|
|
return this.get(key, mapper, Objects::toString, value);
|
|
}
|
|
|
|
protected <V> Settings<T>.MutableValue<V> getMutable(String key, Function<String, V> serializer, V defaultValue) {
|
|
return this.getMutable(key, serializer, Objects::toString, defaultValue);
|
|
}
|
|
|
|
protected String get(String key, String defaultValue) {
|
|
return this.get(key, Function.identity(), Function.identity(), defaultValue);
|
|
}
|
|
|
|
@Nullable
|
|
protected String getLegacyString(String key) {
|
|
return this.getLegacy(key, Function.identity());
|
|
}
|
|
|
|
protected int get(String key, int defaultValue) {
|
|
return this.get(key, wrapNumberDeserializer(Integer::parseInt), Integer.valueOf(defaultValue));
|
|
}
|
|
|
|
protected Settings<T>.MutableValue<Integer> getMutable(String key, int defaultValue) {
|
|
return this.getMutable(key, wrapNumberDeserializer(Integer::parseInt), defaultValue);
|
|
}
|
|
|
|
protected int get(String key, UnaryOperator<Integer> modifier, int defaultValue) {
|
|
return this.get(key, wrapNumberDeserializer(Integer::parseInt), modifier, Objects::toString, defaultValue);
|
|
}
|
|
|
|
protected long get(String key, long defaultValue) {
|
|
return this.get(key, wrapNumberDeserializer(Long::parseLong), defaultValue);
|
|
}
|
|
|
|
protected boolean get(String key, boolean defaultValue) {
|
|
return this.get(key, Boolean::valueOf, defaultValue);
|
|
}
|
|
|
|
protected Settings<T>.MutableValue<Boolean> getMutable(String key, boolean defaultValue) {
|
|
return this.getMutable(key, Boolean::valueOf, defaultValue);
|
|
}
|
|
|
|
@Nullable
|
|
protected Boolean getLegacyBoolean(String key) {
|
|
return this.getLegacy(key, Boolean::valueOf);
|
|
}
|
|
|
|
protected Properties cloneProperties() {
|
|
Properties properties = new Properties();
|
|
properties.putAll(this.properties);
|
|
return properties;
|
|
}
|
|
|
|
protected abstract T reload(RegistryAccess registryAccess, Properties properties);
|
|
|
|
public class MutableValue<V> implements Supplier<V> {
|
|
private final String key;
|
|
private final V value;
|
|
private final Function<V, String> serializer;
|
|
|
|
MutableValue(final String key, final V value, final Function<V, String> serializer) {
|
|
this.key = key;
|
|
this.value = value;
|
|
this.serializer = serializer;
|
|
}
|
|
|
|
public V get() {
|
|
return this.value;
|
|
}
|
|
|
|
public T update(RegistryAccess registryAccess, V newValue) {
|
|
Properties properties = Settings.this.cloneProperties();
|
|
properties.put(this.key, this.serializer.apply(newValue));
|
|
return Settings.this.reload(registryAccess, properties);
|
|
}
|
|
}
|
|
}
|