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);
 | |
| 		}
 | |
| 	}
 | |
| }
 |