From bf9fd48a5f994aa74d6a300378e0b074fa794489 Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Fri, 30 Jul 2021 17:05:49 +0200 Subject: [PATCH] move read/write out of player nbt. aka read/write only when absolute necessary. improves performance --- Changelog.txt | 4 + .../java/io/github/flemmli97/flan/Flan.java | 4 + .../flemmli97/flan/claim/ClaimStorage.java | 42 ++++--- .../github/flemmli97/flan/config/Config.java | 4 +- .../flemmli97/flan/config/ConfigHandler.java | 20 ++++ .../flemmli97/flan/event/PlayerEvents.java | 18 +++ .../flemmli97/flan/mixin/ItemEntityMixin.java | 6 +- .../flan/mixin/LightningFireEntityMixin.java | 2 +- .../flan/mixin/PlayerClaimMixin.java | 5 +- .../flan/player/OfflinePlayerData.java | 108 ++++++------------ .../flan/player/PlayerClaimData.java | 68 +++++------ .../flan/fabric/mixin/PlayerManagerMixin.java | 19 +++ .../fabric/mixin/WorldSaveHandlerMixin.java | 25 ++++ .../main/resources/flan.fabric.mixins.json | 4 +- .../io/github/flemmli97/flan/FlanForge.java | 2 + .../flan/forgeevent/ServerEvents.java | 10 ++ gradle.properties | 2 +- 17 files changed, 206 insertions(+), 137 deletions(-) create mode 100644 common/src/main/java/io/github/flemmli97/flan/event/PlayerEvents.java create mode 100644 fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/PlayerManagerMixin.java create mode 100644 fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/WorldSaveHandlerMixin.java diff --git a/Changelog.txt b/Changelog.txt index 69227d7..9dabd24 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -1,3 +1,7 @@ +Flan 1.6.1 +====================== +- Better performance + Flan 1.6.0 ====================== - Separate some stuff to make it more api like and to make it into an api jar. diff --git a/common/src/main/java/io/github/flemmli97/flan/Flan.java b/common/src/main/java/io/github/flemmli97/flan/Flan.java index 6d9ccbf..3fe0bbc 100644 --- a/common/src/main/java/io/github/flemmli97/flan/Flan.java +++ b/common/src/main/java/io/github/flemmli97/flan/Flan.java @@ -29,4 +29,8 @@ public class Flan { if (ConfigHandler.config.log) Flan.logger.debug(msg, o); } + + public static void error(String msg, Object... o) { + Flan.logger.error(msg, o); + } } diff --git a/common/src/main/java/io/github/flemmli97/flan/claim/ClaimStorage.java b/common/src/main/java/io/github/flemmli97/flan/claim/ClaimStorage.java index c3884ac..6c1e492 100644 --- a/common/src/main/java/io/github/flemmli97/flan/claim/ClaimStorage.java +++ b/common/src/main/java/io/github/flemmli97/flan/claim/ClaimStorage.java @@ -5,6 +5,8 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; import io.github.flemmli97.flan.Flan; import io.github.flemmli97.flan.api.data.IPermissionContainer; import io.github.flemmli97.flan.api.data.IPermissionStorage; @@ -32,13 +34,14 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.util.registry.RegistryKey; import net.minecraft.world.World; -import net.minecraft.world.dimension.DimensionType; import org.yaml.snakeyaml.Yaml; import java.io.File; import java.io.FileReader; -import java.io.FileWriter; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -47,6 +50,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; public class ClaimStorage implements IPermissionStorage { @@ -271,15 +275,16 @@ public class ClaimStorage implements IPermissionStorage { public void read(MinecraftServer server, ServerWorld world) { Flan.log("Loading claim data for world {}", world.getRegistryKey()); - File dir = new File(DimensionType.getSaveDirectory(world.getRegistryKey(), server.getSavePath(WorldSavePath.ROOT).toFile()), "/data/claims/"); - if (dir.exists()) { + Path dir = ConfigHandler.getClaimSavePath(server, world.getRegistryKey()); + if (Files.exists(dir)) { try { - for (File file : dir.listFiles()) { - if (!file.getName().endsWith(".json")) + for (Path file : Files.walk(dir).filter(Files::isRegularFile).collect(Collectors.toSet())) { + String name = file.toFile().getName(); + if (!name.endsWith(".json")) continue; - String realName = file.getName().replace(".json", ""); - UUID uuid = realName.equals(adminClaimString) ? null : UUID.fromString(file.getName().replace(".json", "")); - FileReader reader = new FileReader(file); + String realName = name.replace(".json", ""); + UUID uuid = realName.equals(adminClaimString) ? null : UUID.fromString(realName); + JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(file, StandardCharsets.UTF_8)); JsonArray arr = ConfigHandler.GSON.fromJson(reader, JsonArray.class); reader.close(); if (arr == null) @@ -299,23 +304,22 @@ public class ClaimStorage implements IPermissionStorage { public void save(MinecraftServer server, RegistryKey reg) { Flan.log("Saving claims for world {}", reg); - File dir = new File(DimensionType.getSaveDirectory(reg, server.getSavePath(WorldSavePath.ROOT).toFile()), "/data/claims/"); - if (!dir.exists()) - dir.mkdir(); + Path dir = ConfigHandler.getClaimSavePath(server, reg); try { + Files.createDirectories(dir); for (Map.Entry> e : this.playerClaimMap.entrySet()) { String owner = e.getKey() == null ? adminClaimString : e.getKey().toString(); - File file = new File(dir, owner + ".json"); + Path file = dir.resolve(owner + ".json"); Flan.debug("Attempting saving claim data for player uuid {}", owner); boolean dirty = false; - if (!file.exists()) { + if (!Files.exists(file)) { if (e.getValue().isEmpty()) continue; - file.createNewFile(); + Files.createFile(file); dirty = true; } else { if (e.getValue().isEmpty()) { - file.delete(); + Files.delete(file); continue; } if (this.dirty.remove(owner.equals(adminClaimString) ? null : e.getKey())) { @@ -332,9 +336,9 @@ public class ClaimStorage implements IPermissionStorage { JsonArray arr = new JsonArray(); e.getValue().forEach(claim -> arr.add(claim.toJson(new JsonObject()))); Flan.debug("Attempting saving changed claim data {} for player uuid {}", arr, owner); - FileWriter writer = new FileWriter(file); - ConfigHandler.GSON.toJson(arr, writer); - writer.close(); + JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(file, StandardCharsets.UTF_8)); + ConfigHandler.GSON.toJson(arr, jsonWriter); + jsonWriter.close(); } } } catch (IOException e) { diff --git a/common/src/main/java/io/github/flemmli97/flan/config/Config.java b/common/src/main/java/io/github/flemmli97/flan/config/Config.java index 98ba2c7..a88e7d6 100644 --- a/common/src/main/java/io/github/flemmli97/flan/config/Config.java +++ b/common/src/main/java/io/github/flemmli97/flan/config/Config.java @@ -149,7 +149,7 @@ public class Config { try { perms.put(PermissionRegistry.get(jperm.getKey()), jperm.getValue().getAsBoolean()); } catch (NullPointerException ex) { - Flan.log("No permission with name {}", jperm.getKey()); + Flan.error("No permission with name {}", jperm.getKey()); } }); } @@ -167,7 +167,7 @@ public class Config { else perms.put(PermissionRegistry.get(jperm.getKey()), GlobalType.valueOf(jperm.getValue().getAsString())); } catch (NullPointerException ex) { - Flan.log("No permission with name {}", jperm.getKey()); + Flan.error("No permission with name {}", jperm.getKey()); } }); } diff --git a/common/src/main/java/io/github/flemmli97/flan/config/ConfigHandler.java b/common/src/main/java/io/github/flemmli97/flan/config/ConfigHandler.java index 6214eca..a8f6e66 100644 --- a/common/src/main/java/io/github/flemmli97/flan/config/ConfigHandler.java +++ b/common/src/main/java/io/github/flemmli97/flan/config/ConfigHandler.java @@ -5,6 +5,14 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import net.minecraft.server.MinecraftServer; +import net.minecraft.util.WorldSavePath; +import net.minecraft.util.registry.RegistryKey; +import net.minecraft.world.World; +import net.minecraft.world.dimension.DimensionType; + +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; public class ConfigHandler { @@ -12,6 +20,8 @@ public class ConfigHandler { public static Config config; public static LangConfig lang; + private static Map, Path> claimSavePath = new HashMap<>(); + private static Path playerSavePath; public static void serverLoad(MinecraftServer server) { config = new Config(server); @@ -24,6 +34,16 @@ public class ConfigHandler { lang.load(); } + public static Path getClaimSavePath(MinecraftServer server, RegistryKey reg) { + return claimSavePath.computeIfAbsent(reg, r -> DimensionType.getSaveDirectory(r, server.getSavePath(WorldSavePath.ROOT).toFile()).toPath().resolve("data").resolve("claims")); + } + + public static Path getPlayerSavePath(MinecraftServer server) { + if (playerSavePath == null) + playerSavePath = server.getSavePath(WorldSavePath.PLAYERDATA).resolve("claimData"); + return playerSavePath; + } + public static int fromJson(JsonObject obj, String key, int fallback) { try { return obj.get(key).getAsInt(); diff --git a/common/src/main/java/io/github/flemmli97/flan/event/PlayerEvents.java b/common/src/main/java/io/github/flemmli97/flan/event/PlayerEvents.java new file mode 100644 index 0000000..a1e412b --- /dev/null +++ b/common/src/main/java/io/github/flemmli97/flan/event/PlayerEvents.java @@ -0,0 +1,18 @@ +package io.github.flemmli97.flan.event; + +import io.github.flemmli97.flan.player.PlayerClaimData; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.server.network.ServerPlayerEntity; + +public class PlayerEvents { + + public static void saveClaimData(PlayerEntity player) { + if (player instanceof ServerPlayerEntity) + PlayerClaimData.get((ServerPlayerEntity) player).save(player.getServer()); + } + + public static void readClaimData(PlayerEntity player) { + if (player instanceof ServerPlayerEntity) + PlayerClaimData.get((ServerPlayerEntity) player).read(player.getServer()); + } +} diff --git a/common/src/main/java/io/github/flemmli97/flan/mixin/ItemEntityMixin.java b/common/src/main/java/io/github/flemmli97/flan/mixin/ItemEntityMixin.java index e42bc78..93804d5 100644 --- a/common/src/main/java/io/github/flemmli97/flan/mixin/ItemEntityMixin.java +++ b/common/src/main/java/io/github/flemmli97/flan/mixin/ItemEntityMixin.java @@ -22,14 +22,14 @@ public abstract class ItemEntityMixin implements IOwnedItem { @Inject(method = "readCustomDataFromTag", at = @At("RETURN")) private void readData(CompoundTag tag, CallbackInfo info) { - if (tag.contains("io.github.flemmli97.flan.Flan:PlayerOrigin")) - this.playerOrigin = tag.getUuid("io.github.flemmli97.flan.Flan:PlayerOrigin"); + if (tag.contains("Flan:PlayerOrigin")) + this.playerOrigin = tag.getUuid("Flan:PlayerOrigin"); } @Inject(method = "writeCustomDataToTag", at = @At("RETURN")) private void writeData(CompoundTag tag, CallbackInfo info) { if (this.playerOrigin != null) - tag.putUuid("io.github.flemmli97.flan.Flan:PlayerOrigin", this.playerOrigin); + tag.putUuid("Flan:PlayerOrigin", this.playerOrigin); } @Override diff --git a/common/src/main/java/io/github/flemmli97/flan/mixin/LightningFireEntityMixin.java b/common/src/main/java/io/github/flemmli97/flan/mixin/LightningFireEntityMixin.java index 1c167ce..4ff1973 100644 --- a/common/src/main/java/io/github/flemmli97/flan/mixin/LightningFireEntityMixin.java +++ b/common/src/main/java/io/github/flemmli97/flan/mixin/LightningFireEntityMixin.java @@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LightningEntity.class) -public class LightningFireEntityMixin { +public abstract class LightningFireEntityMixin { @Inject(method = "spawnFire", at = @At(value = "HEAD"), cancellable = true) private void stopFire(int attempts, CallbackInfo info) { diff --git a/common/src/main/java/io/github/flemmli97/flan/mixin/PlayerClaimMixin.java b/common/src/main/java/io/github/flemmli97/flan/mixin/PlayerClaimMixin.java index f634729..889faf1 100644 --- a/common/src/main/java/io/github/flemmli97/flan/mixin/PlayerClaimMixin.java +++ b/common/src/main/java/io/github/flemmli97/flan/mixin/PlayerClaimMixin.java @@ -3,7 +3,6 @@ package io.github.flemmli97.flan.mixin; import io.github.flemmli97.flan.claim.Claim; import io.github.flemmli97.flan.player.IPlayerClaimImpl; import io.github.flemmli97.flan.player.PlayerClaimData; -import net.minecraft.nbt.CompoundTag; import net.minecraft.server.MinecraftServer; import net.minecraft.server.network.ServerPlayerEntity; import org.spongepowered.asm.mixin.Mixin; @@ -30,7 +29,7 @@ public abstract class PlayerClaimMixin implements IPlayerClaimImpl { this.claimData = new PlayerClaimData((ServerPlayerEntity) (Object) this); } - @Inject(method = "readCustomDataFromTag", at = @At("RETURN")) + /*@Inject(method = "readCustomDataFromTag", at = @At("RETURN")) private void readData(CompoundTag tag, CallbackInfo info) { this.claimData.read(this.server); } @@ -38,7 +37,7 @@ public abstract class PlayerClaimMixin implements IPlayerClaimImpl { @Inject(method = "writeCustomDataToTag", at = @At("RETURN")) private void writeData(CompoundTag tag, CallbackInfo info) { this.claimData.save(this.server); - } + }*/ @Inject(method = "tick", at = @At("HEAD")) private void tickData(CallbackInfo info) { diff --git a/common/src/main/java/io/github/flemmli97/flan/player/OfflinePlayerData.java b/common/src/main/java/io/github/flemmli97/flan/player/OfflinePlayerData.java index 9b5af6e..00e8ffe 100644 --- a/common/src/main/java/io/github/flemmli97/flan/player/OfflinePlayerData.java +++ b/common/src/main/java/io/github/flemmli97/flan/player/OfflinePlayerData.java @@ -1,6 +1,8 @@ package io.github.flemmli97.flan.player; import com.google.gson.JsonObject; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; import io.github.flemmli97.flan.Flan; import io.github.flemmli97.flan.api.data.IPlayerData; import io.github.flemmli97.flan.claim.Claim; @@ -8,12 +10,11 @@ import io.github.flemmli97.flan.claim.ClaimStorage; import io.github.flemmli97.flan.config.ConfigHandler; import net.minecraft.server.MinecraftServer; import net.minecraft.server.world.ServerWorld; -import net.minecraft.util.WorldSavePath; -import java.io.File; -import java.io.FileReader; -import java.io.FileWriter; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.LocalDateTime; import java.util.Collection; import java.util.HashMap; @@ -27,34 +28,31 @@ public class OfflinePlayerData implements IPlayerData { public final LocalDateTime lastOnline; public final UUID owner; public final MinecraftServer server; - public final File saveFile; + public final Path save; public OfflinePlayerData(MinecraftServer server, UUID uuid) { - File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); - this.saveFile = new File(dir, uuid + ".json"); + this.save = ConfigHandler.getPlayerSavePath(server).resolve(uuid + ".json"); int claim = ConfigHandler.config.startingBlocks; int add = 0; this.owner = uuid; LocalDateTime last = LocalDateTime.now(); - if (dir.exists()) { + if (Files.exists(this.save)) { try { - File file = new File(dir, uuid + ".json"); - if (file.exists()) { - FileReader reader = new FileReader(file); - JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); - reader.close(); - claim = ConfigHandler.fromJson(obj, "ClaimBlocks", claim); - add = ConfigHandler.fromJson(obj, "AdditionalBlocks", add); - if (obj.has("LastSeen")) { - try { - last = LocalDateTime.parse(obj.get("LastSeen").getAsString(), Flan.onlineTimeFormatter); - } catch (RuntimeException e) { - Flan.log("Error parsing time for {}, ignoring", uuid); - } - } + JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(this.save, StandardCharsets.UTF_8)); + JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); + reader.close(); + if (obj == null) { + obj = new JsonObject(); + Flan.error("Malformed json {}, using default values", uuid); } + claim = ConfigHandler.fromJson(obj, "ClaimBlocks", claim); + add = ConfigHandler.fromJson(obj, "AdditionalBlocks", add); + if (obj.has("LastSeen")) + last = LocalDateTime.parse(obj.get("LastSeen").getAsString(), Flan.onlineTimeFormatter); } catch (IOException e) { e.printStackTrace(); + } catch (RuntimeException e) { + Flan.error("Error parsing time for {}, ignoring", uuid); } } this.claimBlocks = claim; @@ -63,40 +61,6 @@ public class OfflinePlayerData implements IPlayerData { this.server = server; } - private OfflinePlayerData(MinecraftServer server, File dataFile, UUID uuid) { - this.saveFile = dataFile; - int claim = ConfigHandler.config.startingBlocks; - int add = 0; - LocalDateTime last = LocalDateTime.now(); - try { - FileReader reader = new FileReader(dataFile); - JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); - reader.close(); - - claim = ConfigHandler.fromJson(obj, "ClaimBlocks", claim); - add = ConfigHandler.fromJson(obj, "AdditionalBlocks", add); - if (obj.has("LastSeen")) { - try { - last = LocalDateTime.parse(obj.get("LastSeen").getAsString(), Flan.onlineTimeFormatter); - } catch (RuntimeException e) { - Flan.log("Error parsing time for {}, ignoring", uuid); - } - } else { - obj.addProperty("LastSeen", last.format(Flan.onlineTimeFormatter)); - FileWriter write = new FileWriter(dataFile); - ConfigHandler.GSON.toJson(obj, write); - write.close(); - } - } catch (IOException e) { - e.printStackTrace(); - } - this.claimBlocks = claim; - this.additionalClaimBlocks = add; - this.lastOnline = last; - this.owner = uuid; - this.server = server; - } - @Override public int getClaimBlocks() { return this.claimBlocks; @@ -122,12 +86,10 @@ public class OfflinePlayerData implements IPlayerData { public void setAdditionalClaims(int amount) { this.additionalClaimBlocks = amount; try { - if (!this.saveFile.getParentFile().exists()) { - this.saveFile.getParentFile().mkdirs(); - this.saveFile.createNewFile(); - } else if (!this.saveFile.exists()) - this.saveFile.createNewFile(); - FileReader reader = new FileReader(this.saveFile); + Files.createDirectories(this.save.getParent()); + if (!Files.exists(this.save)) + Files.createFile(this.save); + JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(this.save, StandardCharsets.UTF_8)); JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); reader.close(); if (obj == null) { @@ -139,24 +101,22 @@ public class OfflinePlayerData implements IPlayerData { obj.add("DefaultGroups", defPerm); } else obj.addProperty("AdditionalBlocks", this.additionalClaimBlocks); - Flan.debug("Attempting to write following json data {} to file {}", obj, this.saveFile.getName()); - FileWriter writer = new FileWriter(this.saveFile); - ConfigHandler.GSON.toJson(obj, writer); - writer.close(); + Flan.debug("Attempting to write following json data {} to file {}", obj, this.save.getFileName()); + JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(this.save, StandardCharsets.UTF_8)); + ConfigHandler.GSON.toJson(obj, jsonWriter); + jsonWriter.close(); } catch (IOException e) { - Flan.log("Error adding additional claimblocks to offline player {}", this.owner); + Flan.error("Error adding additional claimblocks to offline player {}", this.owner); } } public static Map collectAllPlayerData(MinecraftServer server) { - File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); + Path dir = ConfigHandler.getPlayerSavePath(server); Map playerDatas = new HashMap<>(); - if (dir.exists()) { - for (File data : dir.listFiles()) { - if (data.getName().endsWith(".json")) { - UUID uuid = UUID.fromString(data.getName().replace(".json", "")); - playerDatas.put(uuid, new OfflinePlayerData(server, data, uuid)); - } + if (Files.exists(dir)) { + for (String name : dir.toFile().list((d, name) -> name.endsWith(".json"))) { + UUID uuid = UUID.fromString(name.replace(".json", "")); + playerDatas.put(uuid, new OfflinePlayerData(server, uuid)); } } return playerDatas; diff --git a/common/src/main/java/io/github/flemmli97/flan/player/PlayerClaimData.java b/common/src/main/java/io/github/flemmli97/flan/player/PlayerClaimData.java index 5db7af4..59c6090 100644 --- a/common/src/main/java/io/github/flemmli97/flan/player/PlayerClaimData.java +++ b/common/src/main/java/io/github/flemmli97/flan/player/PlayerClaimData.java @@ -1,6 +1,8 @@ package io.github.flemmli97.flan.player; import com.google.gson.JsonObject; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; import io.github.flemmli97.flan.Flan; import io.github.flemmli97.flan.api.data.IPermissionContainer; import io.github.flemmli97.flan.api.data.IPlayerData; @@ -35,6 +37,10 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; import java.time.LocalDateTime; import java.util.Collection; import java.util.HashMap; @@ -66,7 +72,6 @@ public class PlayerClaimData implements IPlayerData { private final ServerPlayerEntity player; private boolean confirmDeleteAll, adminIgnoreClaim, claimBlockMessage; - private boolean dirty; private final Map> defaultGroups = new HashMap<>(); @@ -88,7 +93,6 @@ public class PlayerClaimData implements IPlayerData { this.claimBlocks = amount; updateScoreFor(this.player, ClaimCriterias.AMOUNT, this.claimBlocks + this.additionalClaimBlocks); updateScoreFor(this.player, ClaimCriterias.FREE, this.claimBlocks + this.additionalClaimBlocks - this.usedBlocks); - this.dirty = true; } public boolean addClaimBlocks(int amount) { @@ -113,7 +117,6 @@ public class PlayerClaimData implements IPlayerData { this.additionalClaimBlocks = Math.max(0, amount); updateScoreFor(this.player, ClaimCriterias.AMOUNT, this.claimBlocks + this.additionalClaimBlocks); updateScoreFor(this.player, ClaimCriterias.FREE, this.claimBlocks + this.additionalClaimBlocks - this.usedBlocks); - this.dirty = true; } @Override @@ -225,7 +228,6 @@ public class PlayerClaimData implements IPlayerData { perms.put(perm, mode == 1); if (!has) this.defaultGroups.put(group, perms); - this.dirty = true; return true; } @@ -331,6 +333,8 @@ public class PlayerClaimData implements IPlayerData { public void clone(PlayerClaimData data) { this.claimBlocks = data.claimBlocks; this.additionalClaimBlocks = data.additionalClaimBlocks; + this.defaultGroups.clear(); + this.defaultGroups.putAll(data.defaultGroups); if (ConfigHandler.config.lockDrops) this.player.sendMessage(PermHelper.simpleColoredText(String.format(ConfigHandler.lang.unlockDropsCmd, "/flan unlockDrops"), Formatting.GOLD), false); } @@ -369,15 +373,14 @@ public class PlayerClaimData implements IPlayerData { public void save(MinecraftServer server) { Flan.log("Saving player data for player {} with uuid {}", this.player.getName(), this.player.getUuid()); - File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); - if (!dir.exists()) - dir.mkdirs(); + Path dir = ConfigHandler.getPlayerSavePath(server); try { - if (!this.dirty) - return; - File file = new File(dir, this.player.getUuid() + ".json"); - if (!file.exists()) - file.createNewFile(); + Files.createDirectories(dir); + Path file = dir.resolve(this.player.getUuid() + ".json"); + try { + Files.createFile(file); + } catch (FileAlreadyExistsException e) { + } JsonObject obj = new JsonObject(); obj.addProperty("ClaimBlocks", this.claimBlocks); obj.addProperty("AdditionalBlocks", this.additionalClaimBlocks); @@ -389,9 +392,10 @@ public class PlayerClaimData implements IPlayerData { defPerm.add(key, perm); }); obj.add("DefaultGroups", defPerm); - FileWriter writer = new FileWriter(file); - ConfigHandler.GSON.toJson(obj, writer); - writer.close(); + + JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(file, StandardCharsets.UTF_8)); + ConfigHandler.GSON.toJson(obj, jsonWriter); + jsonWriter.close(); } catch (IOException e) { e.printStackTrace(); } @@ -399,19 +403,16 @@ public class PlayerClaimData implements IPlayerData { public void read(MinecraftServer server) { Flan.log("Reading player data for player {} with uuid {}", this.player.getName(), this.player.getUuid()); - File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); - if (!dir.exists()) - return; try { - File file = new File(dir, this.player.getUuid() + ".json"); - if (!file.exists()) { + Path file = ConfigHandler.getPlayerSavePath(server).resolve(this.player.getUuid() + ".json"); + if (!Files.exists(file)) { Flan.log("No player data found for player {} with uuid {}", this.player.getName(), this.player.getUuid()); return; } - FileReader reader = new FileReader(file); + JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(file, StandardCharsets.UTF_8)); JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); reader.close(); - Flan.debug("Read following json data {} from file {}", obj, file.getName()); + Flan.debug("Read following json data {} from file {}", obj, file.getFileName()); this.claimBlocks = obj.get("ClaimBlocks").getAsInt(); this.additionalClaimBlocks = obj.get("AdditionalBlocks").getAsInt(); JsonObject defP = ConfigHandler.fromJson(obj, "DefaultGroups"); @@ -441,24 +442,25 @@ public class PlayerClaimData implements IPlayerData { public static void editForOfflinePlayer(MinecraftServer server, UUID uuid, int additionalClaimBlocks) { Flan.log("Adding {} addional claimblocks for offline player with uuid {}", additionalClaimBlocks, uuid); - File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); - if (!dir.exists()) - dir.mkdirs(); + Path dir = ConfigHandler.getPlayerSavePath(server); try { - File file = new File(dir, uuid.toString() + ".json"); - if (!file.exists()) - file.createNewFile(); - FileReader reader = new FileReader(file); + Files.createDirectories(dir); + Path file = dir.resolve(uuid.toString() + ".json"); + try { + Files.createFile(file); + } catch (FileAlreadyExistsException e) { + } + JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(file, StandardCharsets.UTF_8)); JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); reader.close(); if (obj == null) obj = new JsonObject(); int additionalBlocks = ConfigHandler.fromJson(obj, "AdditionalBlocks", 0); obj.addProperty("AdditionalBlocks", additionalBlocks + additionalClaimBlocks); - Flan.debug("Attempting to write following json data {} to file {}", obj, file.getName()); - FileWriter writer = new FileWriter(file); - ConfigHandler.GSON.toJson(obj, writer); - writer.close(); + Flan.debug("Attempting to write following json data {} to file {}", obj, file.getFileName()); + JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(file, StandardCharsets.UTF_8)); + ConfigHandler.GSON.toJson(obj, jsonWriter); + jsonWriter.close(); } catch (IOException e) { e.printStackTrace(); } diff --git a/fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/PlayerManagerMixin.java b/fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/PlayerManagerMixin.java new file mode 100644 index 0000000..8182c9f --- /dev/null +++ b/fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/PlayerManagerMixin.java @@ -0,0 +1,19 @@ +package io.github.flemmli97.flan.fabric.mixin; + +import io.github.flemmli97.flan.event.PlayerEvents; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.server.PlayerManager; +import net.minecraft.server.network.ServerPlayerEntity; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(PlayerManager.class) +public abstract class PlayerManagerMixin { + + @Inject(method = "loadPlayerData", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/network/ServerPlayerEntity;fromTag(Lnet/minecraft/nbt/CompoundTag;)V")) + private void singlePlayerRead(ServerPlayerEntity player, CallbackInfoReturnable info) { + PlayerEvents.readClaimData(player); + } +} diff --git a/fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/WorldSaveHandlerMixin.java b/fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/WorldSaveHandlerMixin.java new file mode 100644 index 0000000..dc79590 --- /dev/null +++ b/fabric/src/main/java/io/github/flemmli97/flan/fabric/mixin/WorldSaveHandlerMixin.java @@ -0,0 +1,25 @@ +package io.github.flemmli97.flan.fabric.mixin; + +import io.github.flemmli97.flan.event.PlayerEvents; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.world.WorldSaveHandler; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(WorldSaveHandler.class) +public abstract class WorldSaveHandlerMixin { + + @Inject(method = "savePlayerData", at = @At(value = "RETURN")) + private void save(PlayerEntity player, CallbackInfo info) { + PlayerEvents.saveClaimData(player); + } + + @Inject(method = "loadPlayerData", at = @At(value = "RETURN")) + private void load(PlayerEntity player, CallbackInfoReturnable info) { + PlayerEvents.readClaimData(player); + } +} diff --git a/fabric/src/main/resources/flan.fabric.mixins.json b/fabric/src/main/resources/flan.fabric.mixins.json index 3ea1918..e33a6e2 100644 --- a/fabric/src/main/resources/flan.fabric.mixins.json +++ b/fabric/src/main/resources/flan.fabric.mixins.json @@ -15,7 +15,9 @@ "WitherMixin", "SnowGolemMixin", "FabricFireMixin", - "LightningHitMixin" + "LightningHitMixin", + "WorldSaveHandlerMixin", + "PlayerManagerMixin" ], "server": [ ], diff --git a/forge/src/main/java/io/github/flemmli97/flan/FlanForge.java b/forge/src/main/java/io/github/flemmli97/flan/FlanForge.java index c76fb24..4b8ffbd 100644 --- a/forge/src/main/java/io/github/flemmli97/flan/FlanForge.java +++ b/forge/src/main/java/io/github/flemmli97/flan/FlanForge.java @@ -38,6 +38,8 @@ public class FlanForge { forge.addListener(ServerEvents::serverStart); forge.addListener(ServerEvents::commands); + forge.addListener(ServerEvents::savePlayer); + forge.addListener(ServerEvents::readPlayer); ClaimCriterias.init(); } diff --git a/forge/src/main/java/io/github/flemmli97/flan/forgeevent/ServerEvents.java b/forge/src/main/java/io/github/flemmli97/flan/forgeevent/ServerEvents.java index 2685200..a85db87 100644 --- a/forge/src/main/java/io/github/flemmli97/flan/forgeevent/ServerEvents.java +++ b/forge/src/main/java/io/github/flemmli97/flan/forgeevent/ServerEvents.java @@ -4,7 +4,9 @@ import io.github.flemmli97.flan.Flan; import io.github.flemmli97.flan.api.permission.ObjectToPermissionMap; import io.github.flemmli97.flan.commands.CommandClaim; import io.github.flemmli97.flan.config.ConfigHandler; +import io.github.flemmli97.flan.event.PlayerEvents; import net.minecraftforge.event.RegisterCommandsEvent; +import net.minecraftforge.event.entity.player.PlayerEvent; import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; public class ServerEvents { @@ -18,4 +20,12 @@ public class ServerEvents { public static void commands(RegisterCommandsEvent event) { CommandClaim.register(event.getDispatcher(), false); } + + public static void savePlayer(PlayerEvent.SaveToFile event) { + PlayerEvents.saveClaimData(event.getPlayer()); + } + + public static void readPlayer(PlayerEvent.LoadFromFile event) { + PlayerEvents.readClaimData(event.getPlayer()); + } } diff --git a/gradle.properties b/gradle.properties index 9457356..fca4056 100644 --- a/gradle.properties +++ b/gradle.properties @@ -8,7 +8,7 @@ minecraft_version=1.16.5 yarn_mappings=1.16.5+build.9 loader_version=0.11.3 # Mod Properties -mod_version=1.6.0 +mod_version=1.6.1 maven_group=io.github.flemmli97 archives_base_name=flan # Dependencies