Claim expiration: improvements+config option. Closes #24

- Claim expiration collects all players (uuids) that own claims, and
iterates this set instead of iterating through every single claim.
- Individual claims had a "last modified" timestamp, so this method was
valid before, but makes no sense now since expiration is based on player
inactivity instead of claim inactivity.

New config option under the advanced node allows controlling the
frequency each player in the aforementioned set is checked for
inactivity.
This commit is contained in:
RoboMWM 2018-09-22 05:21:00 -07:00
parent 93a36dd9e1
commit f6b35d71bf
3 changed files with 54 additions and 31 deletions

View File

@ -21,31 +21,33 @@
import org.bukkit.Bukkit;
import org.bukkit.OfflinePlayer;
import java.util.UUID;
//asynchronously loads player data without caching it in the datastore, then
//passes those data to a claim cleanup task which might decide to delete a claim for inactivity
class CleanupUnusedClaimPreTask implements Runnable
{
private Claim claim = null;
private UUID ownerID = null;
CleanupUnusedClaimPreTask(Claim claim)
CleanupUnusedClaimPreTask(UUID uuid)
{
this.claim = claim;
this.ownerID = uuid;
}
@Override
public void run()
{
//get the data
PlayerData ownerData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(claim.ownerID);
OfflinePlayer ownerInfo = Bukkit.getServer().getOfflinePlayer(claim.ownerID);
PlayerData ownerData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(ownerID);
OfflinePlayer ownerInfo = Bukkit.getServer().getOfflinePlayer(ownerID);
//expiration code uses last logout timestamp to decide whether to expire claims
//don't expire claims for online players
if(ownerInfo.isOnline()) return;
if(ownerInfo.getLastPlayed() <= 0) return;
GriefPrevention.AddLogEntry("Looking for expired claims. Checking data for " + claim.ownerID.toString(), CustomLogEntryTypes.Debug, true);
GriefPrevention.AddLogEntry("Looking for expired claims. Checking data for " + ownerID.toString(), CustomLogEntryTypes.Debug, true);
//skip claims belonging to exempted players based on block totals in config
int bonusBlocks = ownerData.getBonusClaimBlocks();
@ -54,8 +56,25 @@ class CleanupUnusedClaimPreTask implements Runnable
GriefPrevention.AddLogEntry("Player exempt from claim expiration based on claim block counts vs. config file settings.", CustomLogEntryTypes.Debug, true);
return;
}
Claim claimToExpire = null;
for (Claim claim : GriefPrevention.instance.dataStore.getClaims())
{
if (claim.ownerID.equals(ownerID))
{
claimToExpire = claim;
break;
}
}
if (claimToExpire == null)
{
GriefPrevention.AddLogEntry("Unable to find a claim to expire for " + ownerID.toString(), CustomLogEntryTypes.Debug, false);
return;
}
//pass it back to the main server thread, where it's safe to delete a claim if needed
Bukkit.getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new CleanupUnusedClaimTask(claim, ownerData, ownerInfo), 1L);
Bukkit.getScheduler().scheduleSyncDelayedTask(GriefPrevention.instance, new CleanupUnusedClaimTask(claimToExpire, ownerData, ownerInfo), 1L);
}
}

View File

@ -18,7 +18,10 @@
package me.ryanhamshire.GriefPrevention;
import java.util.Random;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.UUID;
import org.bukkit.Bukkit;
@ -29,38 +32,36 @@ import org.bukkit.Bukkit;
//runs every 1 minute in the main thread
class FindUnusedClaimsTask implements Runnable
{
int nextClaimIndex;
{
private Set<UUID> claimOwnerUUIDs = new HashSet<>();
private Iterator<UUID> claimOwnerIterator;
FindUnusedClaimsTask()
{
//start scanning in a random spot
if(GriefPrevention.instance.dataStore.claims.size() == 0)
{
this.nextClaimIndex = 0;
}
else
{
Random randomNumberGenerator = new Random();
this.nextClaimIndex = randomNumberGenerator.nextInt(GriefPrevention.instance.dataStore.claims.size());
}
refreshUUIDs();
}
@Override
public void run()
{
//don't do anything when there are no claims
if(GriefPrevention.instance.dataStore.claims.size() == 0) return;
if(claimOwnerUUIDs.isEmpty()) return;
//wrap search around to beginning
if(this.nextClaimIndex >= GriefPrevention.instance.dataStore.claims.size()) this.nextClaimIndex = 0;
if(!claimOwnerIterator.hasNext())
{
refreshUUIDs();
return;
}
//decide which claim to check next
Claim claim = GriefPrevention.instance.dataStore.claims.get(this.nextClaimIndex++);
//skip administrative claims
if(claim.isAdminClaim()) return;
Bukkit.getScheduler().runTaskAsynchronously(GriefPrevention.instance, new CleanupUnusedClaimPreTask(claim));
Bukkit.getScheduler().runTaskAsynchronously(GriefPrevention.instance, new CleanupUnusedClaimPreTask(claimOwnerIterator.next()));
}
public void refreshUUIDs()
{
claimOwnerUUIDs.clear();
for (Claim claim : GriefPrevention.instance.dataStore.claims)
claimOwnerUUIDs.add(claim.ownerID);
claimOwnerIterator = claimOwnerUUIDs.iterator();
}
}

View File

@ -198,6 +198,7 @@ public class GriefPrevention extends JavaPlugin
public boolean config_pistonsInClaimsOnly; //whether pistons are limited to only move blocks located within the piston's land claim
public boolean config_advanced_fixNegativeClaimblockAmounts; //whether to attempt to fix negative claim block amounts (some addons cause/assume players can go into negative amounts)
public int config_advanced_claim_expiration_check_rate; //How often GP should check for expired claims, amount in seconds
//custom log settings
public int config_logs_daysToKeep;
@ -327,7 +328,7 @@ public class GriefPrevention extends JavaPlugin
//start recurring cleanup scan for unused claims belonging to inactive players
FindUnusedClaimsTask task2 = new FindUnusedClaimsTask();
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, task2, 20L * 60, 20L * 60);
this.getServer().getScheduler().scheduleSyncRepeatingTask(this, task2, 20L * 60, 20L * config_advanced_claim_expiration_check_rate);
//register for events
PluginManager pluginManager = this.getServer().getPluginManager();
@ -767,6 +768,7 @@ public class GriefPrevention extends JavaPlugin
this.databasePassword = config.getString("GriefPrevention.Database.Password", "");
this.config_advanced_fixNegativeClaimblockAmounts = config.getBoolean("GriefPrevention.Advanced.fixNegativeClaimblockAmounts", true);
this.config_advanced_claim_expiration_check_rate = config.getInt("GriefPrevention.Advanced.ClaimExpirationCheckRate", 60);
//custom logger settings
this.config_logs_daysToKeep = config.getInt("GriefPrevention.Abridged Logs.Days To Keep", 7);
@ -893,6 +895,7 @@ public class GriefPrevention extends JavaPlugin
outConfig.set("GriefPrevention.BanCommandPattern", this.config_ban_commandFormat);
outConfig.set("GriefPrevention.Advanced.fixNegativeClaimblockAmounts", this.config_advanced_fixNegativeClaimblockAmounts);
outConfig.set("GriefPrevention.Advanced.ClaimExpirationCheckRate", this.config_advanced_claim_expiration_check_rate);
//custom logger settings
outConfig.set("GriefPrevention.Abridged Logs.Days To Keep", this.config_logs_daysToKeep);