diff --git a/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java b/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java index ed4a659..c732ff6 100644 --- a/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java +++ b/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java @@ -15,106 +15,114 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ - + package me.ryanhamshire.GriefPrevention; import java.util.Collection; import me.ryanhamshire.GriefPrevention.events.AccrueClaimBlocksEvent; -import org.bukkit.Location; import org.bukkit.entity.Player; //FEATURE: give players claim blocks for playing, as long as they're not away from their computer //runs every 5 minutes in the main thread, grants blocks per hour / 12 to each online player who appears to be actively playing -class DeliverClaimBlocksTask implements Runnable -{ +class DeliverClaimBlocksTask implements Runnable +{ private Player player; private GriefPrevention instance; private int idleThresholdSquared; - + public DeliverClaimBlocksTask(Player player, GriefPrevention instance) { this.player = player; this.instance = instance; this.idleThresholdSquared = instance.config_claims_accruedIdleThreshold * instance.config_claims_accruedIdleThreshold; } - - @Override - public void run() - { - //if no player specified, this task will create a player-specific task for each online player, scheduled one tick apart - if(this.player == null) - { - @SuppressWarnings("unchecked") + + @Override + public void run() + { + //if no player specified, this task will create a player-specific task for each online player, scheduled one tick apart + if(this.player == null) + { + @SuppressWarnings("unchecked") Collection players = (Collection)GriefPrevention.instance.getServer().getOnlinePlayers(); - - long i = 0; - for(Player onlinePlayer : players) - { - DeliverClaimBlocksTask newTask = new DeliverClaimBlocksTask(onlinePlayer, instance); - instance.getServer().getScheduler().scheduleSyncDelayedTask(instance, newTask, i++); - } - } - - //otherwise, deliver claim blocks to the specified player - else - { - if(!this.player.isOnline()) + + long i = 0; + for(Player onlinePlayer : players) { - return; + DeliverClaimBlocksTask newTask = new DeliverClaimBlocksTask(onlinePlayer, instance); + instance.getServer().getScheduler().scheduleSyncDelayedTask(instance, newTask, i++); } - - DataStore dataStore = instance.dataStore; - PlayerData playerData = dataStore.getPlayerData(player.getUniqueId()); - - Location lastLocation = playerData.lastAfkCheckLocation; - try + + return; //tasks started for each player + } + + //deliver claim blocks to the specified player + if(!this.player.isOnline()) + { + return; //player is not online to receive claim blocks + } + + DataStore dataStore = instance.dataStore; + PlayerData playerData = dataStore.getPlayerData(player.getUniqueId()); + + // check if player is idle. considered idle if + // in vehicle or is in water (pushed by water) + // or has not moved at least defined blocks since last check + boolean isIdle = false; + try + { + isIdle = player.isInsideVehicle() || player.getLocation().getBlock().isLiquid() || + !(playerData.lastAfkCheckLocation == null || playerData.lastAfkCheckLocation.distanceSquared(player.getLocation()) > idleThresholdSquared); + } + catch(IllegalArgumentException ignore) //can't measure distance when to/from are different worlds + { + } + + //remember current location for next time + playerData.lastAfkCheckLocation = player.getLocation(); + + try + { + //determine how fast blocks accrue for this player //RoboMWM: addons determine this instead + int accrualRate = instance.config_claims_blocksAccruedPerHour_default; + + //determine idle accrual rate when idle + if (isIdle) { - //if he's not in a vehicle and has moved at least three blocks since the last check - //and he's not being pushed around by fluids - if(!player.isInsideVehicle() && - (lastLocation == null || lastLocation.distanceSquared(player.getLocation()) > idleThresholdSquared) && - !player.getLocation().getBlock().isLiquid()) - { - //determine how fast blocks accrue for this player //RoboMWM: addons determine this instead - int accrualRate = instance.config_claims_blocksAccruedPerHour_default; - - AccrueClaimBlocksEvent event = new AccrueClaimBlocksEvent(player, accrualRate); - instance.getServer().getPluginManager().callEvent(event); - if (event.isCancelled()) - { - GriefPrevention.AddLogEntry(player.getName() + " claim block delivery was canceled by another plugin.", CustomLogEntryTypes.Debug, true); - } - else - { - accrualRate = event.getBlocksToAccrue(); - if (accrualRate < 0) accrualRate = 0; - playerData.accrueBlocks(accrualRate); - GriefPrevention.AddLogEntry("Delivering " + event.getBlocksToAccrue() + " blocks to " + player.getName(), CustomLogEntryTypes.Debug, true); - - //intentionally NOT saving data here to reduce overall secondary storage access frequency - //many other operations will cause this player's data to save, including his eventual logout - //dataStore.savePlayerData(player.getUniqueIdentifier(), playerData); - } - } - else + if (instance.config_claims_accruedIdlePercent <= 0) { GriefPrevention.AddLogEntry(player.getName() + " wasn't active enough to accrue claim blocks this round.", CustomLogEntryTypes.Debug, true); + return; //idle accrual percentage is disabled } + + accrualRate = (int) (accrualRate * (instance.config_claims_accruedIdlePercent / 100.0D)); } - catch(IllegalArgumentException e) //can't measure distance when to/from are different worlds + + //fire event for addons + AccrueClaimBlocksEvent event = new AccrueClaimBlocksEvent(player, accrualRate, isIdle); + instance.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { - + GriefPrevention.AddLogEntry(player.getName() + " claim block delivery was canceled by another plugin.", CustomLogEntryTypes.Debug, true); + return; //event was cancelled } - catch(Exception e) - { - GriefPrevention.AddLogEntry("Problem delivering claim blocks to player " + player.getName() + ":"); - e.printStackTrace(); - } - - //remember current location for next time - playerData.lastAfkCheckLocation = player.getLocation(); - } - } + + //set actual accrual + accrualRate = event.getBlocksToAccrue(); + if (accrualRate < 0) accrualRate = 0; + playerData.accrueBlocks(accrualRate); + GriefPrevention.AddLogEntry("Delivering " + event.getBlocksToAccrue() + " blocks to " + player.getName(), CustomLogEntryTypes.Debug, true); + + //intentionally NOT saving data here to reduce overall secondary storage access frequency + //many other operations will cause this player's data to save, including his eventual logout + //dataStore.savePlayerData(player.getUniqueIdentifier(), playerData); + } + catch(Exception e) + { + GriefPrevention.AddLogEntry("Problem delivering claim blocks to player " + player.getName() + ":"); + e.printStackTrace(); + } + } } diff --git a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java index 439cc80..f51e8fc 100644 --- a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java +++ b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java @@ -108,6 +108,7 @@ public class GriefPrevention extends JavaPlugin public int config_claims_blocksAccruedPerHour_default; //how many additional blocks players get each hour of play (can be zero) without any special permissions public int config_claims_maxAccruedBlocks_default; //the limit on accrued blocks (over time) for players without any special permissions. doesn't limit purchased or admin-gifted blocks public int config_claims_accruedIdleThreshold; //how far (in blocks) a player must move in order to not be considered afk/idle when determining accrued claim blocks + public int config_claims_accruedIdlePercent; //how much percentage of claim block accruals should idle players get public int config_claims_maxDepth; //limit on how deep claims can go public int config_claims_expirationDays; //how many days of inactivity before a player loses his claims public int config_claims_expirationExemptionTotalBlocks; //total claim blocks amount which will exempt a player from claim expiration @@ -541,6 +542,7 @@ public class GriefPrevention extends JavaPlugin this.config_claims_maxAccruedBlocks_default = config.getInt("GriefPrevention.Claims.Max Accrued Claim Blocks.Default", this.config_claims_maxAccruedBlocks_default); this.config_claims_accruedIdleThreshold = config.getInt("GriefPrevention.Claims.AccruedIdleThreshold", 0); this.config_claims_accruedIdleThreshold = config.getInt("GriefPrevention.Claims.Accrued Idle Threshold", this.config_claims_accruedIdleThreshold); + this.config_claims_accruedIdlePercent = config.getInt("GriefPrevention.Claims.AccruedIdlePercent", 0); this.config_claims_abandonReturnRatio = config.getDouble("GriefPrevention.Claims.AbandonReturnRatio", 1); this.config_claims_automaticClaimsForNewPlayersRadius = config.getInt("GriefPrevention.Claims.AutomaticNewPlayerClaimsRadius", 4); this.config_claims_claimsExtendIntoGroundDistance = Math.abs(config.getInt("GriefPrevention.Claims.ExtendIntoGroundDistance", 5)); @@ -794,6 +796,7 @@ public class GriefPrevention extends JavaPlugin outConfig.set("GriefPrevention.Claims.Claim Blocks Accrued Per Hour.Default", this.config_claims_blocksAccruedPerHour_default); outConfig.set("GriefPrevention.Claims.Max Accrued Claim Blocks.Default", this.config_claims_maxAccruedBlocks_default); outConfig.set("GriefPrevention.Claims.Accrued Idle Threshold", this.config_claims_accruedIdleThreshold); + outConfig.set("GriefPrevention.Claims.AccruedIdlePercent", this.config_claims_accruedIdlePercent); outConfig.set("GriefPrevention.Claims.AbandonReturnRatio", this.config_claims_abandonReturnRatio); outConfig.set("GriefPrevention.Claims.AutomaticNewPlayerClaimsRadius", this.config_claims_automaticClaimsForNewPlayersRadius); outConfig.set("GriefPrevention.Claims.ExtendIntoGroundDistance", this.config_claims_claimsExtendIntoGroundDistance); diff --git a/src/me/ryanhamshire/GriefPrevention/events/AccrueClaimBlocksEvent.java b/src/me/ryanhamshire/GriefPrevention/events/AccrueClaimBlocksEvent.java index c3691b2..c905aeb 100644 --- a/src/me/ryanhamshire/GriefPrevention/events/AccrueClaimBlocksEvent.java +++ b/src/me/ryanhamshire/GriefPrevention/events/AccrueClaimBlocksEvent.java @@ -24,14 +24,33 @@ public class AccrueClaimBlocksEvent extends Event private Player player; private int blocksToAccrue; + private boolean isIdle = false; private boolean cancelled = false; + /** + * @param player Player receiving accruals + * @param blocksToAccrue Blocks to accrue + * + * @deprecated Use {@link #AccrueClaimBlocksEvent(Player, int, boolean)} instead + */ public AccrueClaimBlocksEvent(Player player, int blocksToAccrue) { this.player = player; this.blocksToAccrue = blocksToAccrue / 6; } + /** + * @param player Player receiving accruals + * @param blocksToAccrue Blocks to accrue + * @param isIdle Whether player is detected as idle + */ + public AccrueClaimBlocksEvent(Player player, int blocksToAccrue, boolean isIdle) + { + this.player = player; + this.blocksToAccrue = blocksToAccrue / 6; + this.isIdle = isIdle; + } + public Player getPlayer() { return this.player; @@ -45,6 +64,13 @@ public class AccrueClaimBlocksEvent extends Event return this.blocksToAccrue; } + /** + * @return whether the player was detected as idle (used for idle accrual percentage) + */ + public boolean isIdle() { + return this.isIdle; + } + public boolean isCancelled() { return this.cancelled;