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> { 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 Function wrapNumberDeserializer(Function parseFunc) { return string -> { try { return (Number)parseFunc.apply(string); } catch (NumberFormatException var3) { return null; } }; } protected static Function dispatchNumberOrString(IntFunction byId, Function 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 getLegacy(String key, Function serializer) { String string = this.getStringRaw(key); if (string == null) { return null; } else { this.properties.remove(key); return (V)serializer.apply(string); } } protected V get(String key, Function serializer, Function 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 Settings.MutableValue getMutable(String key, Function serializer, Function 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 get(String key, Function serializer, UnaryOperator modifier, Function 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 get(String key, Function mapper, V value) { return this.get(key, mapper, Objects::toString, value); } protected Settings.MutableValue getMutable(String key, Function 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.MutableValue getMutable(String key, int defaultValue) { return this.getMutable(key, wrapNumberDeserializer(Integer::parseInt), defaultValue); } protected int get(String key, UnaryOperator 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.MutableValue 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 implements Supplier { private final String key; private final V value; private final Function serializer; MutableValue(final String key, final V value, final Function 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); } } }