From 783293472d8a792a6df11bab7b0f0de53e8ad909 Mon Sep 17 00:00:00 2001 From: "Alex \"mcmonkey\" Goodwin" Date: Tue, 17 Jan 2023 05:01:27 -0800 Subject: [PATCH] optimize ImprovedOfflinePlayer --- .../com/denizenscript/denizen/Denizen.java | 3 +- .../nms/abstracts/ImprovedOfflinePlayer.java | 190 +++++++++--------- .../denizen/nms/interfaces/PlayerHelper.java | 2 - .../denizen/objects/InventoryTag.java | 27 +-- .../denizen/objects/PlayerTag.java | 22 +- .../core/InventoryScriptHelper.java | 38 ++-- .../denizen/utilities/Settings.java | 6 + plugin/src/main/resources/config.yml | 7 + .../nms/v1_17/helpers/PlayerHelperImpl.java | 5 - .../v1_17/impl/ImprovedOfflinePlayerImpl.java | 53 ++--- .../nms/v1_18/helpers/PlayerHelperImpl.java | 5 - .../v1_18/impl/ImprovedOfflinePlayerImpl.java | 51 ++--- .../nms/v1_19/helpers/PlayerHelperImpl.java | 5 - .../v1_19/impl/ImprovedOfflinePlayerImpl.java | 51 ++--- 14 files changed, 223 insertions(+), 242 deletions(-) diff --git a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java index 345e6e5307..41cb15fc3b 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java +++ b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java @@ -479,7 +479,7 @@ public void onDisable() { hasDisabled = true; DenizenCore.shutdown(); ScoreboardHelper._saveScoreboards(); - InventoryScriptHelper._savePlayerInventories(); + InventoryScriptHelper.savePlayerInventories(); triggerRegistry.disableCoreMembers(); getLogger().log(Level.INFO, " v" + getDescription().getVersion() + " disabled."); Bukkit.getServer().getScheduler().cancelTasks(this); @@ -541,6 +541,7 @@ public void saveSaves(boolean lockUntilDone) { ScoreboardHelper._saveScoreboards(); // Save maps to maps.yml DenizenMapManager.saveMaps(); + InventoryScriptHelper.savePlayerInventories(); // Save server flags try { scoreboardsConfig.save(scoreboardsConfigFile); diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java b/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java index 75b195a287..9e3b312fed 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java +++ b/plugin/src/main/java/com/denizenscript/denizen/nms/abstracts/ImprovedOfflinePlayer.java @@ -26,9 +26,19 @@ * @name ImprovedOfflinePlayer * @version 1.6.0 * @author one4me + * + * + * + * Modified by mcmonkey and the DenizenScript team, to update to more recent Minecraft versions and improve performance + * */ import com.denizenscript.denizen.nms.util.jnbt.*; +import com.denizenscript.denizen.utilities.Settings; +import com.denizenscript.denizencore.DenizenCore; +import com.denizenscript.denizencore.utilities.CoreConfiguration; +import com.denizenscript.denizencore.utilities.debugging.Debug; +import com.denizenscript.denizencore.utilities.scheduling.OneTimeSchedulable; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; @@ -46,15 +56,59 @@ public abstract class ImprovedOfflinePlayer { - protected UUID player; - protected File file; - protected CompoundTag compound; - protected boolean exists; - protected boolean autosave = true; - public static Map offlineInventories = new HashMap<>(); - public static Map offlineEnderChests = new HashMap<>(); + public static void invalidateNow(UUID id) { + ImprovedOfflinePlayer player = offlinePlayers.remove(id); + if (player != null) { + if (player.inventory != null) { + player.setInventory(player.inventory); + } + if (player.enderchest != null) { + player.setEnderChest(player.enderchest); + } + if (player.modified) { + player.saveToFile(); + } + } + } + + public static Map offlinePlayers = new HashMap<>(); + + public UUID player; + public File file; + public CompoundTag compound; + public boolean exists; + public PlayerInventory inventory; + public Inventory enderchest; + public boolean modified = false; + public long timeLastLoaded; + + public void markModified() { + if (CoreConfiguration.debugVerbose) { + Debug.verboseLog("[Verbose] player data modified for " + player + ", wasModified=" + modified + ", delay=" + Settings.worldPlayerDataSaveDelay); + } + if (Settings.worldPlayerDataSaveDelay <= 0) { + saveToFile(); + return; + } + if (!modified && Settings.worldPlayerDataSaveDelay < 60 * 60 * 24) { + DenizenCore.schedule(new OneTimeSchedulable(() -> { + if (modified && offlinePlayers.get(player) == this) { + modified = false; + CompoundTag tag = compound; + if (CoreConfiguration.debugVerbose) { + Debug.verboseLog("[Verbose] async-saving player data for " + player); + } + DenizenCore.runAsync(() -> { + saveInternal(tag); + }); + } + }, Settings.worldPlayerDataSaveDelay)); + } + modified = true; + } public ImprovedOfflinePlayer(UUID playeruuid) { + timeLastLoaded = DenizenCore.currentTimeMonotonicMillis; this.exists = loadPlayerData(playeruuid); } @@ -96,9 +150,7 @@ public void setLocation(Location location) { .putInt("Dimension", w.getEnvironment().ordinal()) .put("Pos", new JNBTListTag(DoubleTag.class, position)) .put("Rotation", new JNBTListTag(FloatTag.class, rotation)).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getHealthFloat() { @@ -107,9 +159,7 @@ public float getHealthFloat() { public void setHealthFloat(float input) { this.compound = compound.createBuilder().putFloat("Health", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public abstract double getMaxHealth(); @@ -118,18 +168,17 @@ public void setHealthFloat(float input) { protected abstract boolean loadPlayerData(UUID uuid); - public abstract void savePlayerData(); - - public boolean exists() { - return this.exists; + public void saveToFile() { + if (exists && modified) { + modified = false; + saveInternal(compound); + } } - public boolean getAutoSave() { - return this.autosave; - } + public abstract void saveInternal(CompoundTag compound); - public void setAutoSave(boolean autosave) { - this.autosave = autosave; + public boolean exists() { + return this.exists; } public float getAbsorptionAmount() { @@ -138,9 +187,7 @@ public float getAbsorptionAmount() { public void setAbsorptionAmount(float input) { this.compound = compound.createBuilder().putFloat("AbsorptionAmount", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public Location getBedSpawnLocation() { @@ -163,9 +210,7 @@ public void setBedSpawnLocation(Location location, boolean override) { .putInt("SpawnZ", (int) location.getZ()) .putString("SpawnWorld", location.getWorld().getName()) .putBoolean("SpawnForced", override).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getExhaustion() { @@ -174,9 +219,7 @@ public float getExhaustion() { public void setExhaustion(float input) { this.compound = compound.createBuilder().putFloat("foodExhaustionLevel", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getExp() { @@ -185,9 +228,7 @@ public float getExp() { public void setExp(float input) { this.compound = compound.createBuilder().putFloat("XpP", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getFallDistance() { @@ -196,9 +237,7 @@ public float getFallDistance() { public void setFallDistance(float input) { this.compound = compound.createBuilder().putFloat("FallDistance", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public int getFireTicks() { @@ -207,9 +246,7 @@ public int getFireTicks() { public void setFireTicks(int input) { this.compound = compound.createBuilder().putShort("Fire", (short) input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getFlySpeed() { @@ -220,9 +257,7 @@ public void setFlySpeed(float speed) { CompoundTag compoundTag = (CompoundTag) this.compound.getValue().get("abilities"); compoundTag = compoundTag.createBuilder().putFloat("flySpeed", speed).build(); this.compound = compound.createBuilder().put("abilities", compoundTag).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public int getFoodLevel() { @@ -231,21 +266,16 @@ public int getFoodLevel() { public void setFoodLevel(int input) { this.compound = compound.createBuilder().putInt("foodLevel", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public GameMode getGameMode() { return GameMode.getByValue(this.compound.getInt("playerGameType")); } - @SuppressWarnings("deprecation")//Will most likely break in 1.7 public void setGameMode(GameMode input) { this.compound = compound.createBuilder().putInt("playerGameType", input.getValue()).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public boolean getIsOnGround() { @@ -254,9 +284,7 @@ public boolean getIsOnGround() { public void setIsOnGround(boolean input) { this.compound = compound.createBuilder().putBoolean("OnGround", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public int getItemInHand() { @@ -265,9 +293,7 @@ public int getItemInHand() { public void setItemInHand(int input) { this.compound = compound.createBuilder().putInt("SelectedItemSlot", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public int getLevel() { @@ -276,9 +302,7 @@ public int getLevel() { public void setLevel(int input) { this.compound = compound.createBuilder().putInt("XpLevel", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public UUID getUniqueId() { @@ -291,9 +315,7 @@ public int getRemainingAir() { public void setRemainingAir(int input) { this.compound = compound.createBuilder().putShort("Air", (short) input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getSaturation() { @@ -302,9 +324,7 @@ public float getSaturation() { public void setSaturation(float input) { this.compound = compound.createBuilder().putFloat("foodSaturationLevel", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getScore() { @@ -313,9 +333,7 @@ public float getScore() { public void setScore(int input) { this.compound = compound.createBuilder().putInt("Score", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public short getTimeAttack() { @@ -324,9 +342,7 @@ public short getTimeAttack() { public void setTimeAttack(short input) { this.compound = compound.createBuilder().putShort("AttackTime", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public short getTimeDeath() { @@ -335,9 +351,7 @@ public short getTimeDeath() { public void setTimeDeath(short input) { this.compound = compound.createBuilder().putShort("DeathTime", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public short getTimeHurt() { @@ -346,9 +360,7 @@ public short getTimeHurt() { public void setTimeHurt(short input) { this.compound = compound.createBuilder().putShort("HurtTime", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public short getTimeSleep() { @@ -357,9 +369,7 @@ public short getTimeSleep() { public void setTimeSleep(short input) { this.compound = compound.createBuilder().putShort("SleepTimer", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public int getTotalExperience() { @@ -368,9 +378,7 @@ public int getTotalExperience() { public void setTotalExperience(int input) { this.compound = compound.createBuilder().putInt("XpTotal", input).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public Vector getVelocity() { @@ -384,9 +392,7 @@ public void setVelocity(Vector vector) { motion.add(new DoubleTag(vector.getY())); motion.add(new DoubleTag(vector.getZ())); this.compound = compound.createBuilder().put("Motion", new JNBTListTag(DoubleTag.class, motion)).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public float getWalkSpeed() { @@ -397,9 +403,7 @@ public void setWalkSpeed(float speed) { CompoundTag compoundTag = (CompoundTag) this.compound.getValue().get("abilities"); compoundTag = compoundTag.createBuilder().putFloat("walkSpeed", speed).build(); this.compound = compound.createBuilder().put("abilities", compoundTag).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public boolean getAllowFlight() { @@ -410,9 +414,7 @@ public void setAllowFlight(boolean allow) { CompoundTag compoundTag = (CompoundTag) this.compound.getValue().get("abilities"); compoundTag = compoundTag.createBuilder().putBoolean("mayfly", allow).build(); this.compound = compound.createBuilder().put("abilities", compoundTag).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } public void setLastDeathLocation(Location deathLoc) { @@ -421,8 +423,6 @@ public void setLastDeathLocation(Location deathLoc) { .putIntArray("pos", new int[] {deathLoc.getBlockX(), deathLoc.getBlockY(), deathLoc.getBlockZ()}) .putString("dimension", deathLoc.getWorld().getKey().toString()).build(); this.compound = compound.createBuilder().put("LastDeathLocation", compoundTag).build(); - if (this.autosave) { - savePlayerData(); - } + markModified(); } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/PlayerHelper.java b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/PlayerHelper.java index e838af7923..86c2728b61 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/PlayerHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/nms/interfaces/PlayerHelper.java @@ -49,8 +49,6 @@ public void sendEntityDestroy(Player player, Entity entity) { public abstract ImprovedOfflinePlayer getOfflineData(UUID uuid); - public abstract ImprovedOfflinePlayer getOfflineData(OfflinePlayer offlinePlayer); - public abstract void resendDiscoveredRecipes(Player player); public abstract void quietlyAddRecipe(Player player, NamespacedKey key); diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/InventoryTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/InventoryTag.java index e4de0a78dc..44f8cdd5f0 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/InventoryTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/InventoryTag.java @@ -116,18 +116,14 @@ public static InventoryTag mirrorBukkitInventory(Inventory inventory) { return result; } // Iterate through offline player inventories - for (Map.Entry inv : ImprovedOfflinePlayer.offlineInventories.entrySet()) { - if (inv.getValue().equals(inventory)) { - return new InventoryTag(NMSHandler.playerHelper.getOfflineData(inv.getKey())); + for (ImprovedOfflinePlayer player : ImprovedOfflinePlayer.offlinePlayers.values()) { + if (player.inventory != null && player.inventory.equals(inventory)) { + return new InventoryTag(player); } - } - // Iterate through offline player enderchests - for (Map.Entry inv : ImprovedOfflinePlayer.offlineEnderChests.entrySet()) { - if (inv.getValue().equals(inventory)) { - return new InventoryTag(NMSHandler.playerHelper.getOfflineData(inv.getKey()), true); + if (player.enderchest != null && player.enderchest.equals(inventory)) { + return new InventoryTag(player, true); } } - return new InventoryTag(inventory); } @@ -691,10 +687,9 @@ else if (getIdType().equals("player")) { if (idHolder instanceof PlayerTag) { return; } - // Iterate through offline player inventories - for (Map.Entry inv : ImprovedOfflinePlayer.offlineInventories.entrySet()) { // TODO: Less weird lookup? - if (inv.getValue().equals(inventory)) { - idHolder = new PlayerTag(inv.getKey()); + for (ImprovedOfflinePlayer player : ImprovedOfflinePlayer.offlinePlayers.values()) { // TODO: Less weird lookup? + if (player.inventory != null && player.inventory.equals(inventory)) { + idHolder = new PlayerTag(player.player); return; } } @@ -704,9 +699,9 @@ else if (getIdType().equals("enderchest")) { return; } // Iterate through offline player enderchests - for (Map.Entry inv : ImprovedOfflinePlayer.offlineEnderChests.entrySet()) { // TODO: Less weird lookup? - if (inv.getValue().equals(inventory)) { - idHolder = new PlayerTag(inv.getKey()); + for (ImprovedOfflinePlayer player : ImprovedOfflinePlayer.offlinePlayers.values()) { // TODO: Less weird lookup? + if (player.enderchest != null && player.enderchest.equals(inventory)) { + idHolder = new PlayerTag(player.player); return; } } diff --git a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java index f99f14f1be..093eb2d6a5 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java +++ b/plugin/src/main/java/com/denizenscript/denizen/objects/PlayerTag.java @@ -22,6 +22,7 @@ import com.denizenscript.denizen.utilities.packets.HideParticles; import com.denizenscript.denizen.utilities.packets.ItemChangeMessage; import com.denizenscript.denizen.utilities.packets.NetworkInterceptHelper; +import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.flags.AbstractFlagTracker; import com.denizenscript.denizencore.flags.FlaggableObject; import com.denizenscript.denizencore.objects.*; @@ -254,7 +255,14 @@ public OfflinePlayer getOfflinePlayer() { } public ImprovedOfflinePlayer getNBTEditor() { - return NMSHandler.playerHelper.getOfflineData(getOfflinePlayer()); + ImprovedOfflinePlayer result = ImprovedOfflinePlayer.offlinePlayers.get(uuid); + if (result == null || (!result.modified && result.timeLastLoaded + Settings.worldPlayerDataMaxCacheTicks < DenizenCore.currentTimeMonotonicMillis)) { + result = NMSHandler.playerHelper.getOfflineData(uuid); + if (result != null) { + ImprovedOfflinePlayer.offlinePlayers.put(uuid, result); + } + } + return result; } @Override @@ -823,10 +831,17 @@ public static void register() { registerOfflineTag(LocationTag.class, "bed_spawn", (attribute, object) -> { try { NMSHandler.chunkHelper.changeChunkServerThread(object.getWorld()); - if (object.getOfflinePlayer().getBedSpawnLocation() == null) { + Location loc; + if (object.isOnline()) { + loc = object.getPlayerEntity().getBedSpawnLocation(); + } + else { + loc = object.getNBTEditor().getBedSpawnLocation(); + } + if (loc == null) { return null; } - return new LocationTag(object.getOfflinePlayer().getBedSpawnLocation()); + return new LocationTag(loc); } finally { NMSHandler.chunkHelper.restoreServerThread(object.getWorld()); @@ -3940,6 +3955,7 @@ else if (getPlayerEntity().getGameMode() == GameMode.SPECTATOR) { // // --> if (mechanism.matches("is_op") && mechanism.requireBoolean()) { + ImprovedOfflinePlayer.invalidateNow(getUUID()); getOfflinePlayer().setOp(mechanism.getValue().asBoolean()); } diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptHelper.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptHelper.java index c5a5ce7281..fd519ee0d4 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptHelper.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptHelper.java @@ -1,9 +1,10 @@ package com.denizenscript.denizen.scripts.containers.core; import com.denizenscript.denizen.Denizen; -import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.abstracts.ImprovedOfflinePlayer; import com.denizenscript.denizen.objects.InventoryTag; +import com.denizenscript.denizen.utilities.Settings; +import com.denizenscript.denizencore.DenizenCore; import com.denizenscript.denizencore.objects.core.ScriptTag; import org.bukkit.Bukkit; import org.bukkit.entity.Player; @@ -13,7 +14,6 @@ import org.bukkit.event.inventory.*; import org.bukkit.event.player.PlayerLoginEvent; import org.bukkit.inventory.Inventory; -import org.bukkit.inventory.PlayerInventory; import java.util.*; @@ -35,26 +35,32 @@ public InventoryScriptHelper() { Denizen.getInstance().getServer().getPluginManager().registerEvents(this, Denizen.getInstance()); } - public static void _savePlayerInventories() { - for (Map.Entry offlineInv : ImprovedOfflinePlayer.offlineInventories.entrySet()) { - NMSHandler.playerHelper.getOfflineData(offlineInv.getKey()).setInventory(offlineInv.getValue()); + private final static List toClearOfflinePlayers = new ArrayList<>(); + + public static void savePlayerInventories() { + for (ImprovedOfflinePlayer player : ImprovedOfflinePlayer.offlinePlayers.values()) { + if (player.inventory != null) { // TODO: optimize - remove inventories when no longer in use? + player.setInventory(player.inventory); + } + if (player.enderchest != null) { + player.setEnderChest(player.enderchest); + } + if (player.modified) { + player.saveToFile(); + } + if (player.timeLastLoaded + Settings.worldPlayerDataMaxCacheTicks < DenizenCore.currentTimeMonotonicMillis) { + toClearOfflinePlayers.add(player.player); + } } - for (Map.Entry offlineEnderChest : ImprovedOfflinePlayer.offlineEnderChests.entrySet()) { - NMSHandler.playerHelper.getOfflineData(offlineEnderChest.getKey()).setEnderChest(offlineEnderChest.getValue()); + for (UUID id : toClearOfflinePlayers) { + ImprovedOfflinePlayer.offlinePlayers.remove(id); } + toClearOfflinePlayers.clear(); } @EventHandler public void onPlayerLogin(PlayerLoginEvent event) { - UUID uuid = event.getPlayer().getUniqueId(); - if (ImprovedOfflinePlayer.offlineInventories.containsKey(uuid)) { - NMSHandler.playerHelper.getOfflineData(uuid).setInventory(ImprovedOfflinePlayer.offlineInventories.get(uuid)); - ImprovedOfflinePlayer.offlineInventories.remove(uuid); - } - if (ImprovedOfflinePlayer.offlineEnderChests.containsKey(uuid)) { - NMSHandler.playerHelper.getOfflineData(uuid).setEnderChest(ImprovedOfflinePlayer.offlineEnderChests.get(uuid)); - ImprovedOfflinePlayer.offlineEnderChests.remove(uuid); - } + ImprovedOfflinePlayer.invalidateNow(event.getPlayer().getUniqueId()); } public static HashSet allowedClicks = new HashSet<>(Arrays.asList(ClickType.CONTROL_DROP, ClickType.CREATIVE, ClickType.DROP, ClickType.LEFT, 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 63437dcbd1..2eb72e1ec7 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/Settings.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/Settings.java @@ -80,6 +80,8 @@ public static void refillCache() { allowAsyncPassThrough = config.getBoolean("Scripts.Economy.Pass async to main thread", false); skipChunkFlagCleaning = config.getBoolean("Saves.Skip chunk flag cleaning", false); nullifySkullSkinIds = config.getBoolean("Tags.Nullify skull skin ids", false); + worldPlayerDataSaveDelay = (float) DurationTag.valueOf(config.getString("Save world player file delay", "10s"), CoreUtilities.basicContext).getSeconds(); + worldPlayerDataMaxCacheTicks = DurationTag.valueOf(config.getString("World player data max cache", "1h"), CoreUtilities.basicContext).getTicks(); cache_overrideHelp = config.getBoolean("Debug.Override help", true); cache_useDefaultScriptPath = config.getBoolean("Scripts location.Use default script folder", true); cache_showExHelp = config.getBoolean("Debug.Ex command help", true); @@ -144,6 +146,10 @@ public static void refillCache() { public static boolean allowAsyncPassThrough = false; + public static float worldPlayerDataSaveDelay = 10; + + public static long worldPlayerDataMaxCacheTicks = 20 * 60 * 60; + public static boolean cache_overrideHelp, cache_showExHelp, cache_showExDebug, cache_canRecordStats, cache_defaultDebugMode, cache_healthTraitEnabledByDefault, cache_healthTraitAnimatedDeathEnabled, diff --git a/plugin/src/main/resources/config.yml b/plugin/src/main/resources/config.yml index f3909853ce..0fb69bf75a 100644 --- a/plugin/src/main/resources/config.yml +++ b/plugin/src/main/resources/config.yml @@ -309,6 +309,13 @@ Saves: # Player flags will still save as normal during shutdown, or when world saving is enabled. # This checks based on your default world (server.worlds.first). Only save if world save is on: false + # Delay (DurationTag) after modifying a PlayerTag's offline world-data (gamemode, inventory, etc) before it is saved to file. + # Larger delays are better for performance when this is used often. Shorter delays are better for interop. + # Set to '0' for instant save on modification. Set to '999h' to only save at shutdown. + Save world player file delay: 10s + # Duration to retain offline player data being purging. + # Higher values are better for perf but worse for RAM. Lower values are better for interop. Set to '0' to never cache. + World player data max cache: 1h Packets: # Whether to allow Denizen to intercept packets from and to player clients. diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java index 5c50eef4dd..788a9ae24e 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/helpers/PlayerHelperImpl.java @@ -303,11 +303,6 @@ public ImprovedOfflinePlayer getOfflineData(UUID uuid) { return new ImprovedOfflinePlayerImpl(uuid); } - @Override - public ImprovedOfflinePlayer getOfflineData(OfflinePlayer offlinePlayer) { - return new ImprovedOfflinePlayerImpl(offlinePlayer.getUniqueId()); - } - @Override public void resendRecipeDetails(Player player) { Collection> recipes = ((CraftServer) Bukkit.getServer()).getServer().getRecipeManager().getRecipes(); diff --git a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ImprovedOfflinePlayerImpl.java b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ImprovedOfflinePlayerImpl.java index 38b903e489..174d5767fa 100644 --- a/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ImprovedOfflinePlayerImpl.java +++ b/v1_17/src/main/java/com/denizenscript/denizen/nms/v1_17/impl/ImprovedOfflinePlayerImpl.java @@ -1,6 +1,7 @@ package com.denizenscript.denizen.nms.v1_17.impl; import com.denizenscript.denizen.nms.abstracts.ImprovedOfflinePlayer; +import com.denizenscript.denizen.nms.util.jnbt.CompoundTag; import com.denizenscript.denizen.nms.v1_17.impl.jnbt.CompoundTagImpl; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.nbt.ListTag; @@ -40,7 +41,7 @@ public InventoryHolder getOwner() { } } - public class OfflineCraftInventoryPlayer extends CraftInventoryPlayer { + public static class OfflineCraftInventoryPlayer extends CraftInventoryPlayer { public OfflineCraftInventoryPlayer(net.minecraft.world.entity.player.Inventory inventory) { super(inventory); @@ -54,14 +55,12 @@ public HumanEntity getHolder() { @Override public org.bukkit.inventory.PlayerInventory getInventory() { - if (offlineInventories.containsKey(getUniqueId())) { - return offlineInventories.get(getUniqueId()); + if (inventory == null) { + net.minecraft.world.entity.player.Inventory newInv = new OfflinePlayerInventory(null); + newInv.load(((CompoundTagImpl) this.compound).toNMSTag().getList("Inventory", 10)); + inventory = new OfflineCraftInventoryPlayer(newInv); } - net.minecraft.world.entity.player.Inventory inventory = new OfflinePlayerInventory(null); - inventory.load(((CompoundTagImpl) this.compound).toNMSTag().getList("Inventory", 10)); - org.bukkit.inventory.PlayerInventory inv = new OfflineCraftInventoryPlayer(inventory); - offlineInventories.put(getUniqueId(), inv); - return inv; + return inventory; } @Override @@ -70,21 +69,17 @@ public void setInventory(org.bukkit.inventory.PlayerInventory inventory) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("Inventory", inv.getInventory().save(new ListTag())); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override public Inventory getEnderChest() { - if (offlineEnderChests.containsKey(getUniqueId())) { - return offlineEnderChests.get(getUniqueId()); + if (enderchest == null) { + PlayerEnderChestContainer endchest = new PlayerEnderChestContainer(null); + endchest.fromTag(((CompoundTagImpl) this.compound).toNMSTag().getList("EnderItems", 10)); + enderchest = new CraftInventory(endchest); } - PlayerEnderChestContainer endchest = new PlayerEnderChestContainer(null); - endchest.fromTag(((CompoundTagImpl) this.compound).toNMSTag().getList("EnderItems", 10)); - org.bukkit.inventory.Inventory inv = new CraftInventory(endchest); - offlineEnderChests.put(getUniqueId(), inv); - return inv; + return enderchest; } @Override @@ -92,9 +87,7 @@ public void setEnderChest(Inventory inventory) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("EnderItems", ((PlayerEnderChestContainer) ((CraftInventory) inventory).getInventory()).createTag()); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override @@ -121,9 +114,7 @@ public void setAttributes(AttributeMap attributes) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("Attributes", attributes.save()); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override @@ -145,14 +136,12 @@ protected boolean loadPlayerData(UUID uuid) { } @Override - public void savePlayerData() { - if (this.exists) { - try { - NbtIo.writeCompressed(((CompoundTagImpl) this.compound).toNMSTag(), new FileOutputStream(this.file)); - } - catch (Exception e) { - Debug.echoError(e); - } + public void saveInternal(CompoundTag compound) { + try { + NbtIo.writeCompressed(((CompoundTagImpl) compound).toNMSTag(), new FileOutputStream(this.file)); + } + catch (Exception e) { + Debug.echoError(e); } } } diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java index 5a9d76b826..b485a962da 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/helpers/PlayerHelperImpl.java @@ -321,11 +321,6 @@ public ImprovedOfflinePlayer getOfflineData(UUID uuid) { return new ImprovedOfflinePlayerImpl(uuid); } - @Override - public ImprovedOfflinePlayer getOfflineData(OfflinePlayer offlinePlayer) { - return new ImprovedOfflinePlayerImpl(offlinePlayer.getUniqueId()); - } - @Override public void resendRecipeDetails(Player player) { Collection> recipes = ((CraftServer) Bukkit.getServer()).getServer().getRecipeManager().getRecipes(); diff --git a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ImprovedOfflinePlayerImpl.java b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ImprovedOfflinePlayerImpl.java index 82fc6674e4..6497c50a49 100644 --- a/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ImprovedOfflinePlayerImpl.java +++ b/v1_18/src/main/java/com/denizenscript/denizen/nms/v1_18/impl/ImprovedOfflinePlayerImpl.java @@ -1,6 +1,7 @@ package com.denizenscript.denizen.nms.v1_18.impl; import com.denizenscript.denizen.nms.abstracts.ImprovedOfflinePlayer; +import com.denizenscript.denizen.nms.util.jnbt.CompoundTag; import com.denizenscript.denizen.nms.v1_18.impl.jnbt.CompoundTagImpl; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.nbt.ListTag; @@ -54,14 +55,12 @@ public HumanEntity getHolder() { @Override public org.bukkit.inventory.PlayerInventory getInventory() { - if (offlineInventories.containsKey(getUniqueId())) { - return offlineInventories.get(getUniqueId()); + if (inventory == null) { + net.minecraft.world.entity.player.Inventory newInv = new OfflinePlayerInventory(null); + newInv.load(((CompoundTagImpl) this.compound).toNMSTag().getList("Inventory", 10)); + inventory = new OfflineCraftInventoryPlayer(newInv); } - net.minecraft.world.entity.player.Inventory inventory = new OfflinePlayerInventory(null); - inventory.load(((CompoundTagImpl) this.compound).toNMSTag().getList("Inventory", 10)); - org.bukkit.inventory.PlayerInventory inv = new OfflineCraftInventoryPlayer(inventory); - offlineInventories.put(getUniqueId(), inv); - return inv; + return inventory; } @Override @@ -70,21 +69,17 @@ public void setInventory(org.bukkit.inventory.PlayerInventory inventory) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("Inventory", inv.getInventory().save(new ListTag())); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override public Inventory getEnderChest() { - if (offlineEnderChests.containsKey(getUniqueId())) { - return offlineEnderChests.get(getUniqueId()); + if (enderchest == null) { + PlayerEnderChestContainer endchest = new PlayerEnderChestContainer(null); + endchest.fromTag(((CompoundTagImpl) this.compound).toNMSTag().getList("EnderItems", 10)); + enderchest = new CraftInventory(endchest); } - PlayerEnderChestContainer endchest = new PlayerEnderChestContainer(null); - endchest.fromTag(((CompoundTagImpl) this.compound).toNMSTag().getList("EnderItems", 10)); - org.bukkit.inventory.Inventory inv = new CraftInventory(endchest); - offlineEnderChests.put(getUniqueId(), inv); - return inv; + return enderchest; } @Override @@ -92,9 +87,7 @@ public void setEnderChest(Inventory inventory) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("EnderItems", ((PlayerEnderChestContainer) ((CraftInventory) inventory).getInventory()).createTag()); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override @@ -121,9 +114,7 @@ public void setAttributes(AttributeMap attributes) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("Attributes", attributes.save()); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override @@ -145,14 +136,12 @@ protected boolean loadPlayerData(UUID uuid) { } @Override - public void savePlayerData() { - if (this.exists) { - try { - NbtIo.writeCompressed(((CompoundTagImpl) this.compound).toNMSTag(), new FileOutputStream(this.file)); - } - catch (Exception e) { - Debug.echoError(e); - } + public void saveInternal(CompoundTag compound) { + try { + NbtIo.writeCompressed(((CompoundTagImpl) compound).toNMSTag(), new FileOutputStream(this.file)); + } + catch (Exception e) { + Debug.echoError(e); } } } diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java index 1322e72bb2..ff52a8b79e 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/helpers/PlayerHelperImpl.java @@ -321,11 +321,6 @@ public ImprovedOfflinePlayer getOfflineData(UUID uuid) { return new ImprovedOfflinePlayerImpl(uuid); } - @Override - public ImprovedOfflinePlayer getOfflineData(OfflinePlayer offlinePlayer) { - return new ImprovedOfflinePlayerImpl(offlinePlayer.getUniqueId()); - } - @Override public void resendRecipeDetails(Player player) { Collection> recipes = ((CraftServer) Bukkit.getServer()).getServer().getRecipeManager().getRecipes(); diff --git a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ImprovedOfflinePlayerImpl.java b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ImprovedOfflinePlayerImpl.java index 7292928aed..b3f3cd7886 100644 --- a/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ImprovedOfflinePlayerImpl.java +++ b/v1_19/src/main/java/com/denizenscript/denizen/nms/v1_19/impl/ImprovedOfflinePlayerImpl.java @@ -1,6 +1,7 @@ package com.denizenscript.denizen.nms.v1_19.impl; import com.denizenscript.denizen.nms.abstracts.ImprovedOfflinePlayer; +import com.denizenscript.denizen.nms.util.jnbt.CompoundTag; import com.denizenscript.denizen.nms.v1_19.impl.jnbt.CompoundTagImpl; import com.denizenscript.denizencore.utilities.debugging.Debug; import net.minecraft.nbt.ListTag; @@ -54,14 +55,12 @@ public HumanEntity getHolder() { @Override public org.bukkit.inventory.PlayerInventory getInventory() { - if (offlineInventories.containsKey(getUniqueId())) { - return offlineInventories.get(getUniqueId()); + if (inventory == null) { + net.minecraft.world.entity.player.Inventory newInv = new OfflinePlayerInventory(null); + newInv.load(((CompoundTagImpl) this.compound).toNMSTag().getList("Inventory", 10)); + inventory = new OfflineCraftInventoryPlayer(newInv); } - net.minecraft.world.entity.player.Inventory inventory = new OfflinePlayerInventory(null); - inventory.load(((CompoundTagImpl) this.compound).toNMSTag().getList("Inventory", 10)); - org.bukkit.inventory.PlayerInventory inv = new OfflineCraftInventoryPlayer(inventory); - offlineInventories.put(getUniqueId(), inv); - return inv; + return inventory; } @Override @@ -70,21 +69,17 @@ public void setInventory(org.bukkit.inventory.PlayerInventory inventory) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("Inventory", inv.getInventory().save(new ListTag())); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override public Inventory getEnderChest() { - if (offlineEnderChests.containsKey(getUniqueId())) { - return offlineEnderChests.get(getUniqueId()); + if (enderchest == null) { + PlayerEnderChestContainer endchest = new PlayerEnderChestContainer(null); + endchest.fromTag(((CompoundTagImpl) this.compound).toNMSTag().getList("EnderItems", 10)); + enderchest = new CraftInventory(endchest); } - PlayerEnderChestContainer endchest = new PlayerEnderChestContainer(null); - endchest.fromTag(((CompoundTagImpl) this.compound).toNMSTag().getList("EnderItems", 10)); - org.bukkit.inventory.Inventory inv = new CraftInventory(endchest); - offlineEnderChests.put(getUniqueId(), inv); - return inv; + return enderchest; } @Override @@ -92,9 +87,7 @@ public void setEnderChest(Inventory inventory) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("EnderItems", ((PlayerEnderChestContainer) ((CraftInventory) inventory).getInventory()).createTag()); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override @@ -121,9 +114,7 @@ public void setAttributes(AttributeMap attributes) { net.minecraft.nbt.CompoundTag nbtTagCompound = ((CompoundTagImpl) compound).toNMSTag(); nbtTagCompound.put("Attributes", attributes.save()); this.compound = CompoundTagImpl.fromNMSTag(nbtTagCompound); - if (this.autosave) { - savePlayerData(); - } + markModified(); } @Override @@ -145,14 +136,12 @@ protected boolean loadPlayerData(UUID uuid) { } @Override - public void savePlayerData() { - if (this.exists) { - try { - NbtIo.writeCompressed(((CompoundTagImpl) this.compound).toNMSTag(), new FileOutputStream(this.file)); - } - catch (Exception e) { - Debug.echoError(e); - } + public void saveInternal(CompoundTag compound) { + try { + NbtIo.writeCompressed(((CompoundTagImpl) compound).toNMSTag(), new FileOutputStream(this.file)); + } + catch (Exception e) { + Debug.echoError(e); } } }