Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
import it.unimi.dsi.fastutil.objects.Object2LongArrayMap;
import it.unimi.dsi.fastutil.objects.Object2LongMap;

import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.IdentityHashMap;
Expand Down Expand Up @@ -65,7 +63,7 @@ public static void bootstrap() {
KeyBindingHelper.registerKeyBinding(OPEN_GUI_KEY);

modConfig = ModConfig.load();
modConfig.saveNow(); // creates the default file if it doesn't exist yet
modConfig.save(); // creates the default file if it doesn't exist yet

ClientTickEvents.START_CLIENT_TICK.register((minecraft) -> {
final GameContext gameContext = GameContext.get().orElse(null);
Expand Down Expand Up @@ -240,11 +238,4 @@ public static void debugLog(String msg) {
logger.info(msg);
}
}

public static File getConfigDirectory() {
final String mcRoot = Minecraft.getInstance().gameDirectory.getAbsolutePath();
var dir = Paths.get(mcRoot, "config", "MapSync").toFile();
dir.mkdirs();
return dir;
}
}
Original file line number Diff line number Diff line change
@@ -1,81 +1,75 @@
package gjum.minecraft.mapsync.mod.config;

import static gjum.minecraft.mapsync.mod.MapSyncMod.logger;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.Timer;
import java.util.TimerTask;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Objects;
import net.fabricmc.loader.api.FabricLoader;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* subclasses must have constructor without args, to create default config
*/
public class JsonConfig {
abstract class JsonConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(JsonConfig.class);
static final Gson GSON = new GsonBuilder()
.excludeFieldsWithoutExposeAnnotation()
.setPrettyPrinting()
.create();

private static final Timer timer = new Timer();
private static long saveLaterTimeout = 300;
private long lastSaveTime = 0;
.excludeFieldsWithoutExposeAnnotation()
.setPrettyPrinting()
.create();

protected File configFile;

/**
* Doesn't save any newly created config; for that, call `saveNow()`.
*/
public static <T extends JsonConfig> @NotNull T load(@NotNull File file, Class<T> clazz) {
try (FileReader reader = new FileReader(file)) {
T config = GSON.fromJson(reader, clazz);
config.configFile = file;
logger.info("Loaded existing {}", file);
protected abstract void resetToDefaults();

/// Doesn't save any newly created config; for that, call `saveNow()`.
protected static <T extends JsonConfig> @NotNull T load(
final @NotNull File configFile,
final @NotNull Class<T> configClass
) {
Objects.requireNonNull(configFile);
Objects.requireNonNull(configClass);
T config;
try (final var reader = new FileReader(configFile)) {
config = GSON.fromJson(reader, configClass);
config.configFile = configFile;
LOGGER.info("Loaded existing {}", configFile);
return config;
} catch (FileNotFoundException ignored) {
} catch (IOException e) {
logger.error("Failed to load config file {}", file, e);
}
catch (final FileNotFoundException ignored) {}
catch (final Exception e) {
LOGGER.error("Failed to load config file {}", configFile, e);
}
try {
final T config = clazz.getConstructor().newInstance();
config.configFile = file;
logger.info("Created default {}", file);
config = configClass.getConstructor().newInstance();
config.configFile = configFile;
config.resetToDefaults();
LOGGER.info("Created default {}", configFile);
return config;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
InvocationTargetException ex) {
throw new IllegalArgumentException(ex);
}
}

public void saveLater() {
final long originalSaveRequestTime = System.currentTimeMillis();
timer.schedule(new TimerTask() {
@Override
public void run() {
if (lastSaveTime > originalSaveRequestTime) return; // already saved while waiting
saveNow();
}
}, saveLaterTimeout);
catch (final ReflectiveOperationException e) {
throw new IllegalStateException(e);
}
}

synchronized
public void saveNow() {
public void save() {
LOGGER.info("Saving {} to {}", getClass().getSimpleName(), this.configFile);
try {
lastSaveTime = System.currentTimeMillis();
logger.info("Saving {} to {}", getClass().getSimpleName(), configFile);
configFile.getParentFile().mkdirs();
String json = GSON.toJson(this);
FileOutputStream fos = new FileOutputStream(configFile);
fos.write(json.getBytes());
fos.close();
} catch (IOException e) {
logger.error("Failed to save config file {}", configFile, e);
Files.createDirectories(this.configFile.getParentFile().toPath());
Files.write(
this.configFile.toPath(),
GSON.toJson(this).getBytes()
);
}
catch (final Exception e) {
LOGGER.error("Failed to save config file {}", this.configFile, e);
}
}

protected static @NotNull Path getConfigDir() {
return FabricLoader.getInstance().getConfigDir().resolve("MapSync");
}
}
Original file line number Diff line number Diff line change
@@ -1,38 +1,45 @@
package gjum.minecraft.mapsync.mod.config;

import com.google.gson.annotations.Expose;
import java.io.File;
import java.nio.file.Path;
import org.jetbrains.annotations.NotNull;

import gjum.minecraft.mapsync.mod.MapSyncMod;
import net.minecraft.client.Minecraft;

public class ModConfig extends JsonConfig {
public final class ModConfig extends JsonConfig {
@Expose
private boolean showDebugLog = false;

public boolean isShowDebugLog() {
return showDebugLog;
return this.showDebugLog;
}

public void setShowDebugLog(boolean value) {
showDebugLog = value;
saveLater();
public void setShowDebugLog(
final boolean value
) {
this.showDebugLog = value;
}

@Expose
private int catchupWatermark = 100;

public int getCatchupWatermark() {
return catchupWatermark;
return Math.max(1, this.catchupWatermark);
}

public void setCatchupWatermark(
final int value
) {
this.catchupWatermark = value;
}

public void setCatchupWatermark(int value) {
catchupWatermark = value;
saveLater();
@Override
protected void resetToDefaults() {
this.showDebugLog = false;
this.catchupWatermark = 100;
}

public static ModConfig load() {
return ModConfig.load(new File(MapSyncMod.getConfigDirectory(), "mod-config.json"), ModConfig.class);
public static @NotNull ModConfig load() {
return ModConfig.load(
getConfigDir().resolve("mod-config.json").toFile(),
ModConfig.class
);
}
}
Original file line number Diff line number Diff line change
@@ -1,77 +1,45 @@
package gjum.minecraft.mapsync.mod.config;

import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.annotations.Expose;
import gjum.minecraft.mapsync.mod.data.GameAddress;
import java.io.File;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

import gjum.minecraft.mapsync.mod.MapSyncMod;
import net.minecraft.client.Minecraft;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;

public class ServerConfig extends JsonConfig {
public GameAddress gameAddress;

public final class ServerConfig extends JsonConfig {
@Expose
private @NotNull List<String> syncServerAddresses = new ArrayList<>();

public @NotNull List<String> getSyncServerAddresses() {
return syncServerAddresses;
private ArrayList<String> syncServerAddresses = new ArrayList<>();

public @NotNull List<@NotNull String> getSyncServerAddresses() {
return this.syncServerAddresses.stream()
.map(String::trim)
.filter(StringUtils::isNotEmpty)
.map((address) -> address.contains(":") ? address : (address + ":12312"))
.distinct()
.collect(Collectors.toCollection(ArrayList::new));
}

public void setSyncServerAddresses(@NotNull List<String> addresses) {
syncServerAddresses = addresses.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(address -> !address.isEmpty())
.map(address -> address.contains(":") ? address : (address + ":12312"))
.collect(Collectors.toCollection(ArrayList::new));

saveLater();
public void setSyncServerAddresses(
final @NotNull List<String> syncAddresses
) {
this.syncServerAddresses = new ArrayList<>(syncAddresses);
}

public static ServerConfig load(GameAddress gameAddress) {
var dir = Path.of(MapSyncMod.getConfigDirectory().getAbsolutePath(), gameAddress.asFsName()).toFile();
dir.mkdirs();
var conf = load(new File(dir, "server-config.json"), ServerConfig.class);
conf.gameAddress = gameAddress;

loadDefaults(conf);

conf.syncServerAddresses = conf.syncServerAddresses.stream()
.filter(Objects::nonNull)
.map(String::trim)
.filter(address -> !address.isEmpty())
.collect(Collectors.toCollection(ArrayList::new));

return conf;
@Override
public void resetToDefaults() {
this.setSyncServerAddresses(List.of(
"ws://localhost:12312"
));
}

private static void loadDefaults(ServerConfig conf) {
ServerConfig defaults;
try (var input = ServerConfig.class.getResourceAsStream("/default-config.json")) {
if (input == null) return;
String json = new String(input.readAllBytes(), StandardCharsets.UTF_8);
JsonObject root = new Gson().fromJson(json, JsonObject.class);
JsonObject servers = root.get("servers").getAsJsonObject();
// TODO: Don't get, instead iterate through keys
JsonObject server = servers.get(conf.gameAddress.address()).getAsJsonObject();
defaults = GSON.fromJson(server, ServerConfig.class);
} catch (IllegalStateException | NullPointerException ignored) {
return;
} catch (Throwable e) {
e.printStackTrace();
return;
}
if (conf.syncServerAddresses.isEmpty() && defaults.syncServerAddresses != null) {
conf.setSyncServerAddresses(defaults.syncServerAddresses);
}
public static @NotNull ServerConfig load(
final @NotNull GameAddress gameAddress
) {
return load(
getConfigDir().resolve("%s.json".formatted(gameAddress.asFsName())).toFile(),
ServerConfig.class
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@
import gjum.minecraft.mapsync.mod.sync.DimensionState;
import gjum.minecraft.mapsync.mod.net.SyncClient;
import gjum.minecraft.mapsync.mod.sync.GameContext;
import java.util.List;
import java.util.Arrays;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Stream;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox;
Expand Down Expand Up @@ -64,12 +63,13 @@ protected void init() {
.builder(
Component.literal("Connect"),
(button) -> {
final List<String> syncAddresses = Stream.of(StringUtils.split(this.addressFieldValue, ','))
.filter(StringUtils::isNotBlank)
.distinct()
.toList();
this.gameContext.getGameConfig().setSyncServerAddresses(syncAddresses);
this.gameContext.getSyncConnections().setAll(Set.copyOf(syncAddresses));
this.gameContext.getGameConfig().setSyncServerAddresses(Arrays.asList(
StringUtils.split(this.addressFieldValue, ',')
));
this.gameContext.getGameConfig().save();
this.gameContext.getSyncConnections().setAll(Set.copyOf(
this.gameContext.getGameConfig().getSyncServerAddresses()
));
}
)
.pos(offsetRight - 100, this.offsetTop + 40)
Expand Down Expand Up @@ -174,6 +174,7 @@ public boolean isPauseScreen() {

@Override
public void onClose() {
this.gameContext.getGameConfig().save();
this.minecraft.setScreen(this.parentScreen);
}
}
Loading