diff --git a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java index 8b0cde8da0..067181fe0d 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java +++ b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java @@ -29,6 +29,7 @@ import com.denizenscript.denizen.utilities.debugging.Debug; import com.denizenscript.denizen.utilities.depends.Depends; import com.denizenscript.denizen.utilities.entity.DenizenEntityType; +import com.denizenscript.denizen.utilities.flags.DataPersistenceFlagTracker; import com.denizenscript.denizen.utilities.flags.PlayerFlagHandler; import com.denizenscript.denizen.utilities.implementation.DenizenCoreImplementation; import com.denizenscript.denizen.utilities.maps.DenizenMapManager; @@ -41,6 +42,7 @@ import com.denizenscript.denizen.npc.DenizenNPCHelper; import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.events.OldEventManager; +import com.denizenscript.denizencore.flags.MapTagBasedFlagTracker; import com.denizenscript.denizencore.flags.SavableMapFlagTracker; import com.denizenscript.denizencore.objects.ObjectFetcher; import com.denizenscript.denizencore.scripts.ScriptHelper; @@ -51,9 +53,7 @@ import com.denizenscript.denizencore.utilities.debugging.SlowWarning; import com.denizenscript.denizencore.utilities.debugging.StrongWarning; import com.denizenscript.denizencore.utilities.text.ConfigUpdater; -import org.bukkit.Bukkit; -import org.bukkit.ChatColor; -import org.bukkit.OfflinePlayer; +import org.bukkit.*; import org.bukkit.command.Command; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; @@ -415,6 +415,13 @@ public void run() { } }, 1, 1); InventoryTag.setupInventoryTracker(); + if (!MapTagBasedFlagTracker.skipAllCleanings) { + for (World world : Bukkit.getWorlds()) { + for (Chunk chunk : world.getLoadedChunks()) { + new DataPersistenceFlagTracker(chunk).doTotalClean(); + } + } + } } catch (Exception e) { Debug.echoError(e); diff --git a/plugin/src/main/java/com/denizenscript/denizen/npc/traits/DenizenFlagsTrait.java b/plugin/src/main/java/com/denizenscript/denizen/npc/traits/DenizenFlagsTrait.java index b17422a8c2..c0ee1d0f92 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/npc/traits/DenizenFlagsTrait.java +++ b/plugin/src/main/java/com/denizenscript/denizen/npc/traits/DenizenFlagsTrait.java @@ -25,6 +25,7 @@ public SavableMapFlagTracker create(DataKey dataKey) { for (DataKey key : dataKey.getSubKeys()) { toRet.setRootMap(key.name(), MapTag.valueOf(key.getString(""), CoreUtilities.errorButNoDebugContext)); } + toRet.doTotalClean(); return toRet; } diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java index 25e98099c2..ec85d8d03e 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/EntityTag.java @@ -13,6 +13,7 @@ import com.denizenscript.denizen.utilities.entity.FakeEntity; import com.denizenscript.denizen.utilities.flags.DataPersistenceFlagTracker; import com.denizenscript.denizen.utilities.nbt.CustomNBT; +import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.flags.AbstractFlagTracker; import com.denizenscript.denizencore.flags.FlaggableObject; import com.denizenscript.denizencore.objects.*; @@ -427,10 +428,14 @@ public AbstractFlagTracker getFlagTracker() { @Override public void reapplyTracker(AbstractFlagTracker tracker) { - // Nothing to do. + if (cleanRateProtect + 60000 > DenizenCore.serverTimeMillis) { + ((DataPersistenceFlagTracker) tracker).doTotalClean(); + cleanRateProtect = DenizenCore.serverTimeMillis; + } } public Entity entity = null; + public long cleanRateProtect = -60000; public DenizenEntityType entity_type = null; private String data1 = null; private DespawnedEntity despawned_entity = null; diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java index 55a5473296..a3444d2c61 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/BukkitWorldScriptHelper.java @@ -7,6 +7,8 @@ import com.denizenscript.denizen.utilities.ScoreboardHelper; import com.denizenscript.denizen.utilities.debugging.Debug; import com.denizenscript.denizen.utilities.Settings; +import com.denizenscript.denizen.utilities.flags.DataPersistenceFlagTracker; +import com.denizenscript.denizencore.flags.MapTagBasedFlagTracker; import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.World; @@ -17,6 +19,7 @@ import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.ChunkLoadEvent; import org.bukkit.scoreboard.Scoreboard; import java.util.HashMap; @@ -109,4 +112,12 @@ public void playerLogin(PlayerLoginEvent event) { public void playerQuit(PlayerQuitEvent event) { NMSHandler.getPacketHelper().removeNoCollideTeam(event.getPlayer(), null); } + + @EventHandler + public void chunkLoadEvent(ChunkLoadEvent event) { + if (MapTagBasedFlagTracker.skipAllCleanings) { + return; + } + new DataPersistenceFlagTracker(event.getChunk()).doTotalClean(); + } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/Settings.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/Settings.java index 6946e82020..8986e4954c 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/Settings.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/Settings.java @@ -2,6 +2,7 @@ import com.denizenscript.denizen.Denizen; import com.denizenscript.denizen.utilities.flags.PlayerFlagHandler; +import com.denizenscript.denizencore.flags.MapTagBasedFlagTracker; import com.denizenscript.denizencore.utilities.debugging.Debug; import com.denizenscript.denizencore.objects.core.DurationTag; import com.denizenscript.denizencore.scripts.ScriptHelper; @@ -87,6 +88,7 @@ public static void refillCache() { cache_packetInterception = config.getBoolean("Packets.Interception", true); PlayerFlagHandler.cacheTimeoutSeconds = config.getLong("Saves.Offline player cache timeout", 300); PlayerFlagHandler.asyncPreload = config.getBoolean("Saves.Load async on login", true); + MapTagBasedFlagTracker.skipAllCleanings = config.getBoolean("Saves.Skip flag cleaning", false); } private static boolean cache_showDebug = true, cache_overrideHelp, cache_useDefaultScriptPath, diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/flags/DataPersistenceFlagTracker.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/flags/DataPersistenceFlagTracker.java index 5e5625fa1c..391fae3b40 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/flags/DataPersistenceFlagTracker.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/flags/DataPersistenceFlagTracker.java @@ -2,8 +2,10 @@ import com.denizenscript.denizen.utilities.DataPersistenceHelper; import com.denizenscript.denizencore.flags.MapTagBasedFlagTracker; +import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.utilities.CoreUtilities; +import org.bukkit.NamespacedKey; import org.bukkit.persistence.PersistentDataHolder; import java.util.Collection; @@ -44,4 +46,29 @@ public Collection listAllFlags() { .filter(k -> k.getNamespace().equals("denizen") && k.getKey().startsWith(keyPrefix)) .map(k -> k.getKey().substring(keyPrefix.length())).collect(Collectors.toList()); } + + public void doTotalClean() { + if (MapTagBasedFlagTracker.skipAllCleanings) { + return; + } + for (NamespacedKey key : holder.getPersistentDataContainer().getKeys()) { + if (!key.getNamespace().equals("denizen") || !key.getKey().startsWith("flag_")) { + continue; + } + ObjectTag map = holder.getPersistentDataContainer().get(key, DataPersistenceHelper.PERSISTER_TYPE); + if (!(map instanceof MapTag)) { + continue; + } + if (isExpired(((MapTag) map).map.get(expirationString))) { + holder.getPersistentDataContainer().remove(key); + continue; + } + ObjectTag subValue = ((MapTag) map).map.get(valueString); + if (subValue instanceof MapTag) { + if (doClean((MapTag) subValue)) { + holder.getPersistentDataContainer().set(key, DataPersistenceHelper.PERSISTER_TYPE, map); + } + } + } + } } diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml index 65206b0809..1b7f3ec48f 100644 --- a/plugin/src/main/resources/config.yml +++ b/plugin/src/main/resources/config.yml @@ -184,6 +184,9 @@ Saves: Offline player cache timeout: 300 # When set to 'true', player data will be loaded offthread during the login sequence, to avoid adding load to the server while players join. Load async on login: true + # When set to 'true', all automatic flag cleanups will be skipped. + # This might save some processing time on servers that rarely use flag expirations, but otherwise should be left as 'false'. + Skip flag cleaning: false Packets: # Whether to allow Denizen to intercept packets from and to player clients.