From 8e2291ecb2aa26e520b14a8ec5bf0e05805c468d Mon Sep 17 00:00:00 2001 From: Flemmli97 Date: Sun, 13 Jun 2021 17:23:04 +0200 Subject: [PATCH] delete inactive claims close #54 --- Changelog.txt | 3 + .../java/io/github/flemmli97/flan/Flan.java | 4 ++ .../flemmli97/flan/claim/ClaimStorage.java | 5 ++ .../github/flemmli97/flan/config/Config.java | 3 + .../flan/player/OfflinePlayerData.java | 69 ++++++++++++++++++- .../flan/player/PlayerClaimData.java | 5 ++ 6 files changed, 88 insertions(+), 1 deletion(-) diff --git a/Changelog.txt b/Changelog.txt index 694757a..d2acde2 100644 --- a/Changelog.txt +++ b/Changelog.txt @@ -15,6 +15,9 @@ Flan 1.5.0 - Add EDITPOTIONS permission for that. There are no limits to potion effects so this should be admin reserved only. Default global value is ALLFALSE so disabled for that reason +- Add claim deletion for inactive players. Added config for that are: + inactivityTime - How long in days a player has to be offline for it to check the player + inactivityBlocksMax - How much claimblocks the player can have at max for it to delete the claims Flan 1.4.2 ====================== 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 569a56d..1e49aad 100644 --- a/common/src/main/java/io/github/flemmli97/flan/Flan.java +++ b/common/src/main/java/io/github/flemmli97/flan/Flan.java @@ -6,12 +6,16 @@ import net.minecraft.server.MinecraftServer; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.time.format.DateTimeFormatter; + public class Flan { public static final Logger logger = LogManager.getLogger("flan"); public static boolean permissionAPI, gunpowder, playerAbilityLib; + public static final DateTimeFormatter onlineTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + public static void lockRegistry(MinecraftServer server) { PermissionRegistry.lock(); } 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 a2ff0eb..4d66125 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 @@ -62,6 +62,7 @@ public class ClaimStorage { public ClaimStorage(MinecraftServer server, ServerWorld world) { this.globalClaim = new GlobalClaim(world); this.read(server, world); + OfflinePlayerData.deleteUnusedClaims(server, this, world); } public UUID generateUUID() { @@ -304,6 +305,10 @@ public class ClaimStorage { file.createNewFile(); dirty = true; } else { + if (e.getValue().isEmpty()) { + file.delete(); + continue; + } if (this.dirty.remove(owner.equals(adminClaimString) ? null : e.getKey())) { dirty = true; } else { 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 a284fb7..470c6cc 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 @@ -58,6 +58,9 @@ public class Config { public boolean lockDrops = true; public int dropTicks = 6000; + public int inactivityTime = 30; + public int inactivityBlocksMax = 2000; + public boolean log; public Map> defaultGroups = createHashMap(map -> { 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 cf7d245..436e8a1 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,7 @@ package io.github.flemmli97.flan.player; import com.google.gson.JsonObject; +import io.github.flemmli97.flan.Flan; import io.github.flemmli97.flan.api.IPlayerData; import io.github.flemmli97.flan.claim.Claim; import io.github.flemmli97.flan.claim.ClaimStorage; @@ -11,13 +12,18 @@ import net.minecraft.util.WorldSavePath; import java.io.File; import java.io.FileReader; +import java.io.FileWriter; import java.io.IOException; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; public class OfflinePlayerData implements IPlayerData { public final int claimBlocks, additionalClaimBlocks; + public final LocalDateTime lastOnline; public final UUID owner; public final MinecraftServer server; @@ -26,15 +32,17 @@ public class OfflinePlayerData implements IPlayerData { int claim = ConfigHandler.config.startingBlocks; int add = 0; this.owner = uuid; + LocalDateTime last = LocalDateTime.now(); if (dir.exists()) { 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 = obj.get("ClaimBlocks").getAsInt(); add = obj.get("AdditionalBlocks").getAsInt(); - reader.close(); + last = LocalDateTime.parse(obj.get("LastSeen").getAsString(), Flan.onlineTimeFormatter); } } catch (IOException e) { e.printStackTrace(); @@ -42,6 +50,36 @@ public class OfflinePlayerData implements IPlayerData { } this.claimBlocks = claim; this.additionalClaimBlocks = add; + this.lastOnline = last; + this.server = server; + } + + private OfflinePlayerData(MinecraftServer server, File dataFile, UUID uuid) { + 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 = obj.get("ClaimBlocks").getAsInt(); + add = obj.get("AdditionalBlocks").getAsInt(); + if (obj.has("LastSeen")) { + last = LocalDateTime.parse(obj.get("LastSeen").getAsString(), Flan.onlineTimeFormatter); + } 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; } @@ -65,4 +103,33 @@ public class OfflinePlayerData implements IPlayerData { } return usedClaimsBlocks; } + + public static Map collectAllPlayerData(MinecraftServer server) { + File dir = new File(server.getSavePath(WorldSavePath.PLAYERDATA).toFile(), "/claimData/"); + 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)); + } + } + } + return playerDatas; + } + + public static void deleteUnusedClaims(MinecraftServer server, ClaimStorage storage, ServerWorld world) { + if (ConfigHandler.config.inactivityTime == -1) + return; + Map playerData = collectAllPlayerData(server); + LocalDateTime now = LocalDateTime.now(); + playerData.forEach((uuid, data) -> { + if (now.isAfter(data.lastOnline.plusDays(ConfigHandler.config.inactivityTime)) + && data.claimBlocks + data.additionalClaimBlocks < ConfigHandler.config.inactivityBlocksMax) { + Flan.log("{} Deleting all claims for inactive player {} last seen {}", world.getRegistryKey(), data.owner, data.lastOnline); + storage.allClaimsFromPlayer(data.owner) + .forEach(claim -> storage.deleteClaim(claim, true, EnumEditMode.DEFAULT, world)); + } + }); + } } 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 c0f6dd5..3846e84 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 @@ -28,7 +28,9 @@ import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.time.LocalDateTime; import java.util.Collection; +import java.util.Date; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -60,6 +62,8 @@ public class PlayerClaimData implements IPlayerData { private final Map> defaultGroups = new HashMap<>(); + private Date lastOnline; + public PlayerClaimData(ServerPlayerEntity player) { this.player = player; this.claimBlocks = ConfigHandler.config.startingBlocks; @@ -316,6 +320,7 @@ public class PlayerClaimData implements IPlayerData { JsonObject obj = new JsonObject(); obj.addProperty("ClaimBlocks", this.claimBlocks); obj.addProperty("AdditionalBlocks", this.additionalClaimBlocks); + obj.addProperty("LastSeen", LocalDateTime.now().format(Flan.onlineTimeFormatter)); JsonObject defPerm = new JsonObject(); this.defaultGroups.forEach((key, value) -> { JsonObject perm = new JsonObject();