move read/write out of player nbt. aka read/write only when absolute necessary. improves performance

This commit is contained in:
Flemmli97 2021-07-30 17:05:49 +02:00
parent c6521bd217
commit bf9fd48a5f
17 changed files with 206 additions and 137 deletions

View File

@ -1,3 +1,7 @@
Flan 1.6.1
======================
- Better performance
Flan 1.6.0 Flan 1.6.0
====================== ======================
- Separate some stuff to make it more api like and to make it into an api jar. - Separate some stuff to make it more api like and to make it into an api jar.

View File

@ -29,4 +29,8 @@ public class Flan {
if (ConfigHandler.config.log) if (ConfigHandler.config.log)
Flan.logger.debug(msg, o); Flan.logger.debug(msg, o);
} }
public static void error(String msg, Object... o) {
Flan.logger.error(msg, o);
}
} }

View File

@ -5,6 +5,8 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; 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.Flan;
import io.github.flemmli97.flan.api.data.IPermissionContainer; import io.github.flemmli97.flan.api.data.IPermissionContainer;
import io.github.flemmli97.flan.api.data.IPermissionStorage; 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.math.ChunkPos;
import net.minecraft.util.registry.RegistryKey; import net.minecraft.util.registry.RegistryKey;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.dimension.DimensionType;
import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.Yaml;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException; 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.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -47,6 +50,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.stream.Collectors;
public class ClaimStorage implements IPermissionStorage { public class ClaimStorage implements IPermissionStorage {
@ -271,15 +275,16 @@ public class ClaimStorage implements IPermissionStorage {
public void read(MinecraftServer server, ServerWorld world) { public void read(MinecraftServer server, ServerWorld world) {
Flan.log("Loading claim data for world {}", world.getRegistryKey()); Flan.log("Loading claim data for world {}", world.getRegistryKey());
File dir = new File(DimensionType.getSaveDirectory(world.getRegistryKey(), server.getSavePath(WorldSavePath.ROOT).toFile()), "/data/claims/"); Path dir = ConfigHandler.getClaimSavePath(server, world.getRegistryKey());
if (dir.exists()) { if (Files.exists(dir)) {
try { try {
for (File file : dir.listFiles()) { for (Path file : Files.walk(dir).filter(Files::isRegularFile).collect(Collectors.toSet())) {
if (!file.getName().endsWith(".json")) String name = file.toFile().getName();
if (!name.endsWith(".json"))
continue; continue;
String realName = file.getName().replace(".json", ""); String realName = name.replace(".json", "");
UUID uuid = realName.equals(adminClaimString) ? null : UUID.fromString(file.getName().replace(".json", "")); UUID uuid = realName.equals(adminClaimString) ? null : UUID.fromString(realName);
FileReader reader = new FileReader(file); JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(file, StandardCharsets.UTF_8));
JsonArray arr = ConfigHandler.GSON.fromJson(reader, JsonArray.class); JsonArray arr = ConfigHandler.GSON.fromJson(reader, JsonArray.class);
reader.close(); reader.close();
if (arr == null) if (arr == null)
@ -299,23 +304,22 @@ public class ClaimStorage implements IPermissionStorage {
public void save(MinecraftServer server, RegistryKey<World> reg) { public void save(MinecraftServer server, RegistryKey<World> reg) {
Flan.log("Saving claims for world {}", reg); Flan.log("Saving claims for world {}", reg);
File dir = new File(DimensionType.getSaveDirectory(reg, server.getSavePath(WorldSavePath.ROOT).toFile()), "/data/claims/"); Path dir = ConfigHandler.getClaimSavePath(server, reg);
if (!dir.exists())
dir.mkdir();
try { try {
Files.createDirectories(dir);
for (Map.Entry<UUID, Set<Claim>> e : this.playerClaimMap.entrySet()) { for (Map.Entry<UUID, Set<Claim>> e : this.playerClaimMap.entrySet()) {
String owner = e.getKey() == null ? adminClaimString : e.getKey().toString(); 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); Flan.debug("Attempting saving claim data for player uuid {}", owner);
boolean dirty = false; boolean dirty = false;
if (!file.exists()) { if (!Files.exists(file)) {
if (e.getValue().isEmpty()) if (e.getValue().isEmpty())
continue; continue;
file.createNewFile(); Files.createFile(file);
dirty = true; dirty = true;
} else { } else {
if (e.getValue().isEmpty()) { if (e.getValue().isEmpty()) {
file.delete(); Files.delete(file);
continue; continue;
} }
if (this.dirty.remove(owner.equals(adminClaimString) ? null : e.getKey())) { if (this.dirty.remove(owner.equals(adminClaimString) ? null : e.getKey())) {
@ -332,9 +336,9 @@ public class ClaimStorage implements IPermissionStorage {
JsonArray arr = new JsonArray(); JsonArray arr = new JsonArray();
e.getValue().forEach(claim -> arr.add(claim.toJson(new JsonObject()))); e.getValue().forEach(claim -> arr.add(claim.toJson(new JsonObject())));
Flan.debug("Attempting saving changed claim data {} for player uuid {}", arr, owner); Flan.debug("Attempting saving changed claim data {} for player uuid {}", arr, owner);
FileWriter writer = new FileWriter(file); JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(file, StandardCharsets.UTF_8));
ConfigHandler.GSON.toJson(arr, writer); ConfigHandler.GSON.toJson(arr, jsonWriter);
writer.close(); jsonWriter.close();
} }
} }
} catch (IOException e) { } catch (IOException e) {

View File

@ -149,7 +149,7 @@ public class Config {
try { try {
perms.put(PermissionRegistry.get(jperm.getKey()), jperm.getValue().getAsBoolean()); perms.put(PermissionRegistry.get(jperm.getKey()), jperm.getValue().getAsBoolean());
} catch (NullPointerException ex) { } 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 else
perms.put(PermissionRegistry.get(jperm.getKey()), GlobalType.valueOf(jperm.getValue().getAsString())); perms.put(PermissionRegistry.get(jperm.getKey()), GlobalType.valueOf(jperm.getValue().getAsString()));
} catch (NullPointerException ex) { } catch (NullPointerException ex) {
Flan.log("No permission with name {}", jperm.getKey()); Flan.error("No permission with name {}", jperm.getKey());
} }
}); });
} }

View File

@ -5,6 +5,14 @@ import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray; import com.google.gson.JsonArray;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import net.minecraft.server.MinecraftServer; 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 { public class ConfigHandler {
@ -12,6 +20,8 @@ public class ConfigHandler {
public static Config config; public static Config config;
public static LangConfig lang; public static LangConfig lang;
private static Map<RegistryKey<World>, Path> claimSavePath = new HashMap<>();
private static Path playerSavePath;
public static void serverLoad(MinecraftServer server) { public static void serverLoad(MinecraftServer server) {
config = new Config(server); config = new Config(server);
@ -24,6 +34,16 @@ public class ConfigHandler {
lang.load(); lang.load();
} }
public static Path getClaimSavePath(MinecraftServer server, RegistryKey<World> 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) { public static int fromJson(JsonObject obj, String key, int fallback) {
try { try {
return obj.get(key).getAsInt(); return obj.get(key).getAsInt();

View File

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

View File

@ -22,14 +22,14 @@ public abstract class ItemEntityMixin implements IOwnedItem {
@Inject(method = "readCustomDataFromTag", at = @At("RETURN")) @Inject(method = "readCustomDataFromTag", at = @At("RETURN"))
private void readData(CompoundTag tag, CallbackInfo info) { private void readData(CompoundTag tag, CallbackInfo info) {
if (tag.contains("io.github.flemmli97.flan.Flan:PlayerOrigin")) if (tag.contains("Flan:PlayerOrigin"))
this.playerOrigin = tag.getUuid("io.github.flemmli97.flan.Flan:PlayerOrigin"); this.playerOrigin = tag.getUuid("Flan:PlayerOrigin");
} }
@Inject(method = "writeCustomDataToTag", at = @At("RETURN")) @Inject(method = "writeCustomDataToTag", at = @At("RETURN"))
private void writeData(CompoundTag tag, CallbackInfo info) { private void writeData(CompoundTag tag, CallbackInfo info) {
if (this.playerOrigin != null) if (this.playerOrigin != null)
tag.putUuid("io.github.flemmli97.flan.Flan:PlayerOrigin", this.playerOrigin); tag.putUuid("Flan:PlayerOrigin", this.playerOrigin);
} }
@Override @Override

View File

@ -8,7 +8,7 @@ import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(LightningEntity.class) @Mixin(LightningEntity.class)
public class LightningFireEntityMixin { public abstract class LightningFireEntityMixin {
@Inject(method = "spawnFire", at = @At(value = "HEAD"), cancellable = true) @Inject(method = "spawnFire", at = @At(value = "HEAD"), cancellable = true)
private void stopFire(int attempts, CallbackInfo info) { private void stopFire(int attempts, CallbackInfo info) {

View File

@ -3,7 +3,6 @@ package io.github.flemmli97.flan.mixin;
import io.github.flemmli97.flan.claim.Claim; import io.github.flemmli97.flan.claim.Claim;
import io.github.flemmli97.flan.player.IPlayerClaimImpl; import io.github.flemmli97.flan.player.IPlayerClaimImpl;
import io.github.flemmli97.flan.player.PlayerClaimData; import io.github.flemmli97.flan.player.PlayerClaimData;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
@ -30,7 +29,7 @@ public abstract class PlayerClaimMixin implements IPlayerClaimImpl {
this.claimData = new PlayerClaimData((ServerPlayerEntity) (Object) this); 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) { private void readData(CompoundTag tag, CallbackInfo info) {
this.claimData.read(this.server); this.claimData.read(this.server);
} }
@ -38,7 +37,7 @@ public abstract class PlayerClaimMixin implements IPlayerClaimImpl {
@Inject(method = "writeCustomDataToTag", at = @At("RETURN")) @Inject(method = "writeCustomDataToTag", at = @At("RETURN"))
private void writeData(CompoundTag tag, CallbackInfo info) { private void writeData(CompoundTag tag, CallbackInfo info) {
this.claimData.save(this.server); this.claimData.save(this.server);
} }*/
@Inject(method = "tick", at = @At("HEAD")) @Inject(method = "tick", at = @At("HEAD"))
private void tickData(CallbackInfo info) { private void tickData(CallbackInfo info) {

View File

@ -1,6 +1,8 @@
package io.github.flemmli97.flan.player; package io.github.flemmli97.flan.player;
import com.google.gson.JsonObject; 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.Flan;
import io.github.flemmli97.flan.api.data.IPlayerData; import io.github.flemmli97.flan.api.data.IPlayerData;
import io.github.flemmli97.flan.claim.Claim; 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 io.github.flemmli97.flan.config.ConfigHandler;
import net.minecraft.server.MinecraftServer; import net.minecraft.server.MinecraftServer;
import net.minecraft.server.world.ServerWorld; 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.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -27,34 +28,31 @@ public class OfflinePlayerData implements IPlayerData {
public final LocalDateTime lastOnline; public final LocalDateTime lastOnline;
public final UUID owner; public final UUID owner;
public final MinecraftServer server; public final MinecraftServer server;
public final File saveFile; public final Path save;
public OfflinePlayerData(MinecraftServer server, UUID uuid) { public OfflinePlayerData(MinecraftServer server, UUID uuid) {
File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); this.save = ConfigHandler.getPlayerSavePath(server).resolve(uuid + ".json");
this.saveFile = new File(dir, uuid + ".json");
int claim = ConfigHandler.config.startingBlocks; int claim = ConfigHandler.config.startingBlocks;
int add = 0; int add = 0;
this.owner = uuid; this.owner = uuid;
LocalDateTime last = LocalDateTime.now(); LocalDateTime last = LocalDateTime.now();
if (dir.exists()) { if (Files.exists(this.save)) {
try { try {
File file = new File(dir, uuid + ".json"); JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(this.save, StandardCharsets.UTF_8));
if (file.exists()) { JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class);
FileReader reader = new FileReader(file); reader.close();
JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); if (obj == null) {
reader.close(); obj = new JsonObject();
claim = ConfigHandler.fromJson(obj, "ClaimBlocks", claim); Flan.error("Malformed json {}, using default values", uuid);
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);
}
}
} }
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) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} catch (RuntimeException e) {
Flan.error("Error parsing time for {}, ignoring", uuid);
} }
} }
this.claimBlocks = claim; this.claimBlocks = claim;
@ -63,40 +61,6 @@ public class OfflinePlayerData implements IPlayerData {
this.server = server; 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 @Override
public int getClaimBlocks() { public int getClaimBlocks() {
return this.claimBlocks; return this.claimBlocks;
@ -122,12 +86,10 @@ public class OfflinePlayerData implements IPlayerData {
public void setAdditionalClaims(int amount) { public void setAdditionalClaims(int amount) {
this.additionalClaimBlocks = amount; this.additionalClaimBlocks = amount;
try { try {
if (!this.saveFile.getParentFile().exists()) { Files.createDirectories(this.save.getParent());
this.saveFile.getParentFile().mkdirs(); if (!Files.exists(this.save))
this.saveFile.createNewFile(); Files.createFile(this.save);
} else if (!this.saveFile.exists()) JsonReader reader = ConfigHandler.GSON.newJsonReader(Files.newBufferedReader(this.save, StandardCharsets.UTF_8));
this.saveFile.createNewFile();
FileReader reader = new FileReader(this.saveFile);
JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class); JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class);
reader.close(); reader.close();
if (obj == null) { if (obj == null) {
@ -139,24 +101,22 @@ public class OfflinePlayerData implements IPlayerData {
obj.add("DefaultGroups", defPerm); obj.add("DefaultGroups", defPerm);
} else } else
obj.addProperty("AdditionalBlocks", this.additionalClaimBlocks); obj.addProperty("AdditionalBlocks", this.additionalClaimBlocks);
Flan.debug("Attempting to write following json data {} to file {}", obj, this.saveFile.getName()); Flan.debug("Attempting to write following json data {} to file {}", obj, this.save.getFileName());
FileWriter writer = new FileWriter(this.saveFile); JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(this.save, StandardCharsets.UTF_8));
ConfigHandler.GSON.toJson(obj, writer); ConfigHandler.GSON.toJson(obj, jsonWriter);
writer.close(); jsonWriter.close();
} catch (IOException e) { } 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<UUID, OfflinePlayerData> collectAllPlayerData(MinecraftServer server) { public static Map<UUID, OfflinePlayerData> collectAllPlayerData(MinecraftServer server) {
File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); Path dir = ConfigHandler.getPlayerSavePath(server);
Map<UUID, OfflinePlayerData> playerDatas = new HashMap<>(); Map<UUID, OfflinePlayerData> playerDatas = new HashMap<>();
if (dir.exists()) { if (Files.exists(dir)) {
for (File data : dir.listFiles()) { for (String name : dir.toFile().list((d, name) -> name.endsWith(".json"))) {
if (data.getName().endsWith(".json")) { UUID uuid = UUID.fromString(name.replace(".json", ""));
UUID uuid = UUID.fromString(data.getName().replace(".json", "")); playerDatas.put(uuid, new OfflinePlayerData(server, uuid));
playerDatas.put(uuid, new OfflinePlayerData(server, data, uuid));
}
} }
} }
return playerDatas; return playerDatas;

View File

@ -1,6 +1,8 @@
package io.github.flemmli97.flan.player; package io.github.flemmli97.flan.player;
import com.google.gson.JsonObject; 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.Flan;
import io.github.flemmli97.flan.api.data.IPermissionContainer; import io.github.flemmli97.flan.api.data.IPermissionContainer;
import io.github.flemmli97.flan.api.data.IPlayerData; import io.github.flemmli97.flan.api.data.IPlayerData;
@ -35,6 +37,10 @@ import java.io.File;
import java.io.FileReader; import java.io.FileReader;
import java.io.FileWriter; import java.io.FileWriter;
import java.io.IOException; 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.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
@ -66,7 +72,6 @@ public class PlayerClaimData implements IPlayerData {
private final ServerPlayerEntity player; private final ServerPlayerEntity player;
private boolean confirmDeleteAll, adminIgnoreClaim, claimBlockMessage; private boolean confirmDeleteAll, adminIgnoreClaim, claimBlockMessage;
private boolean dirty;
private final Map<String, Map<ClaimPermission, Boolean>> defaultGroups = new HashMap<>(); private final Map<String, Map<ClaimPermission, Boolean>> defaultGroups = new HashMap<>();
@ -88,7 +93,6 @@ public class PlayerClaimData implements IPlayerData {
this.claimBlocks = amount; this.claimBlocks = amount;
updateScoreFor(this.player, ClaimCriterias.AMOUNT, this.claimBlocks + this.additionalClaimBlocks); updateScoreFor(this.player, ClaimCriterias.AMOUNT, this.claimBlocks + this.additionalClaimBlocks);
updateScoreFor(this.player, ClaimCriterias.FREE, this.claimBlocks + this.additionalClaimBlocks - this.usedBlocks); updateScoreFor(this.player, ClaimCriterias.FREE, this.claimBlocks + this.additionalClaimBlocks - this.usedBlocks);
this.dirty = true;
} }
public boolean addClaimBlocks(int amount) { public boolean addClaimBlocks(int amount) {
@ -113,7 +117,6 @@ public class PlayerClaimData implements IPlayerData {
this.additionalClaimBlocks = Math.max(0, amount); this.additionalClaimBlocks = Math.max(0, amount);
updateScoreFor(this.player, ClaimCriterias.AMOUNT, this.claimBlocks + this.additionalClaimBlocks); updateScoreFor(this.player, ClaimCriterias.AMOUNT, this.claimBlocks + this.additionalClaimBlocks);
updateScoreFor(this.player, ClaimCriterias.FREE, this.claimBlocks + this.additionalClaimBlocks - this.usedBlocks); updateScoreFor(this.player, ClaimCriterias.FREE, this.claimBlocks + this.additionalClaimBlocks - this.usedBlocks);
this.dirty = true;
} }
@Override @Override
@ -225,7 +228,6 @@ public class PlayerClaimData implements IPlayerData {
perms.put(perm, mode == 1); perms.put(perm, mode == 1);
if (!has) if (!has)
this.defaultGroups.put(group, perms); this.defaultGroups.put(group, perms);
this.dirty = true;
return true; return true;
} }
@ -331,6 +333,8 @@ public class PlayerClaimData implements IPlayerData {
public void clone(PlayerClaimData data) { public void clone(PlayerClaimData data) {
this.claimBlocks = data.claimBlocks; this.claimBlocks = data.claimBlocks;
this.additionalClaimBlocks = data.additionalClaimBlocks; this.additionalClaimBlocks = data.additionalClaimBlocks;
this.defaultGroups.clear();
this.defaultGroups.putAll(data.defaultGroups);
if (ConfigHandler.config.lockDrops) if (ConfigHandler.config.lockDrops)
this.player.sendMessage(PermHelper.simpleColoredText(String.format(ConfigHandler.lang.unlockDropsCmd, "/flan unlockDrops"), Formatting.GOLD), false); 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) { public void save(MinecraftServer server) {
Flan.log("Saving player data for player {} with uuid {}", this.player.getName(), this.player.getUuid()); 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/"); Path dir = ConfigHandler.getPlayerSavePath(server);
if (!dir.exists())
dir.mkdirs();
try { try {
if (!this.dirty) Files.createDirectories(dir);
return; Path file = dir.resolve(this.player.getUuid() + ".json");
File file = new File(dir, this.player.getUuid() + ".json"); try {
if (!file.exists()) Files.createFile(file);
file.createNewFile(); } catch (FileAlreadyExistsException e) {
}
JsonObject obj = new JsonObject(); JsonObject obj = new JsonObject();
obj.addProperty("ClaimBlocks", this.claimBlocks); obj.addProperty("ClaimBlocks", this.claimBlocks);
obj.addProperty("AdditionalBlocks", this.additionalClaimBlocks); obj.addProperty("AdditionalBlocks", this.additionalClaimBlocks);
@ -389,9 +392,10 @@ public class PlayerClaimData implements IPlayerData {
defPerm.add(key, perm); defPerm.add(key, perm);
}); });
obj.add("DefaultGroups", defPerm); obj.add("DefaultGroups", defPerm);
FileWriter writer = new FileWriter(file);
ConfigHandler.GSON.toJson(obj, writer); JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(file, StandardCharsets.UTF_8));
writer.close(); ConfigHandler.GSON.toJson(obj, jsonWriter);
jsonWriter.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }
@ -399,19 +403,16 @@ public class PlayerClaimData implements IPlayerData {
public void read(MinecraftServer server) { public void read(MinecraftServer server) {
Flan.log("Reading player data for player {} with uuid {}", this.player.getName(), this.player.getUuid()); 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 { try {
File file = new File(dir, this.player.getUuid() + ".json"); Path file = ConfigHandler.getPlayerSavePath(server).resolve(this.player.getUuid() + ".json");
if (!file.exists()) { if (!Files.exists(file)) {
Flan.log("No player data found for player {} with uuid {}", this.player.getName(), this.player.getUuid()); Flan.log("No player data found for player {} with uuid {}", this.player.getName(), this.player.getUuid());
return; 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); JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class);
reader.close(); 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.claimBlocks = obj.get("ClaimBlocks").getAsInt();
this.additionalClaimBlocks = obj.get("AdditionalBlocks").getAsInt(); this.additionalClaimBlocks = obj.get("AdditionalBlocks").getAsInt();
JsonObject defP = ConfigHandler.fromJson(obj, "DefaultGroups"); 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) { public static void editForOfflinePlayer(MinecraftServer server, UUID uuid, int additionalClaimBlocks) {
Flan.log("Adding {} addional claimblocks for offline player with uuid {}", additionalClaimBlocks, uuid); Flan.log("Adding {} addional claimblocks for offline player with uuid {}", additionalClaimBlocks, uuid);
File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); Path dir = ConfigHandler.getPlayerSavePath(server);
if (!dir.exists())
dir.mkdirs();
try { try {
File file = new File(dir, uuid.toString() + ".json"); Files.createDirectories(dir);
if (!file.exists()) Path file = dir.resolve(uuid.toString() + ".json");
file.createNewFile(); try {
FileReader reader = new FileReader(file); 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); JsonObject obj = ConfigHandler.GSON.fromJson(reader, JsonObject.class);
reader.close(); reader.close();
if (obj == null) if (obj == null)
obj = new JsonObject(); obj = new JsonObject();
int additionalBlocks = ConfigHandler.fromJson(obj, "AdditionalBlocks", 0); int additionalBlocks = ConfigHandler.fromJson(obj, "AdditionalBlocks", 0);
obj.addProperty("AdditionalBlocks", additionalBlocks + additionalClaimBlocks); obj.addProperty("AdditionalBlocks", additionalBlocks + additionalClaimBlocks);
Flan.debug("Attempting to write following json data {} to file {}", obj, file.getName()); Flan.debug("Attempting to write following json data {} to file {}", obj, file.getFileName());
FileWriter writer = new FileWriter(file); JsonWriter jsonWriter = ConfigHandler.GSON.newJsonWriter(Files.newBufferedWriter(file, StandardCharsets.UTF_8));
ConfigHandler.GSON.toJson(obj, writer); ConfigHandler.GSON.toJson(obj, jsonWriter);
writer.close(); jsonWriter.close();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@ -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<CompoundTag> info) {
PlayerEvents.readClaimData(player);
}
}

View File

@ -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<CompoundTag> info) {
PlayerEvents.readClaimData(player);
}
}

View File

@ -15,7 +15,9 @@
"WitherMixin", "WitherMixin",
"SnowGolemMixin", "SnowGolemMixin",
"FabricFireMixin", "FabricFireMixin",
"LightningHitMixin" "LightningHitMixin",
"WorldSaveHandlerMixin",
"PlayerManagerMixin"
], ],
"server": [ "server": [
], ],

View File

@ -38,6 +38,8 @@ public class FlanForge {
forge.addListener(ServerEvents::serverStart); forge.addListener(ServerEvents::serverStart);
forge.addListener(ServerEvents::commands); forge.addListener(ServerEvents::commands);
forge.addListener(ServerEvents::savePlayer);
forge.addListener(ServerEvents::readPlayer);
ClaimCriterias.init(); ClaimCriterias.init();
} }

View File

@ -4,7 +4,9 @@ import io.github.flemmli97.flan.Flan;
import io.github.flemmli97.flan.api.permission.ObjectToPermissionMap; import io.github.flemmli97.flan.api.permission.ObjectToPermissionMap;
import io.github.flemmli97.flan.commands.CommandClaim; import io.github.flemmli97.flan.commands.CommandClaim;
import io.github.flemmli97.flan.config.ConfigHandler; import io.github.flemmli97.flan.config.ConfigHandler;
import io.github.flemmli97.flan.event.PlayerEvents;
import net.minecraftforge.event.RegisterCommandsEvent; import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.event.entity.player.PlayerEvent;
import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent; import net.minecraftforge.fml.event.server.FMLServerAboutToStartEvent;
public class ServerEvents { public class ServerEvents {
@ -18,4 +20,12 @@ public class ServerEvents {
public static void commands(RegisterCommandsEvent event) { public static void commands(RegisterCommandsEvent event) {
CommandClaim.register(event.getDispatcher(), false); 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());
}
} }

View File

@ -8,7 +8,7 @@ minecraft_version=1.16.5
yarn_mappings=1.16.5+build.9 yarn_mappings=1.16.5+build.9
loader_version=0.11.3 loader_version=0.11.3
# Mod Properties # Mod Properties
mod_version=1.6.0 mod_version=1.6.1
maven_group=io.github.flemmli97 maven_group=io.github.flemmli97
archives_base_name=flan archives_base_name=flan
# Dependencies # Dependencies