Reduced CPU time for player login and logout.

By about 85%.
This commit is contained in:
ryanhamshire 2014-10-30 19:24:07 -07:00
parent 73ad9c99df
commit cb808ecacd
9 changed files with 220 additions and 106 deletions

View File

@ -255,7 +255,7 @@ public class BlockEventHandler implements Listener
int radius = GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius; int radius = GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius;
//if the player doesn't have any claims yet, automatically create a claim centered at the chest //if the player doesn't have any claims yet, automatically create a claim centered at the chest
if(playerData.claims.size() == 0) if(playerData.getClaims().size() == 0)
{ {
//radius == 0 means protect ONLY the chest //radius == 0 means protect ONLY the chest
if(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius == 0) if(GriefPrevention.instance.config_claims_automaticClaimsForNewPlayersRadius == 0)
@ -316,13 +316,13 @@ public class BlockEventHandler implements Listener
else if(!this.trashBlocks.contains(block.getType()) && GriefPrevention.instance.claimsEnabledForWorld(block.getWorld())) else if(!this.trashBlocks.contains(block.getType()) && GriefPrevention.instance.claimsEnabledForWorld(block.getWorld()))
{ {
if(!playerData.warnedAboutBuildingOutsideClaims if(!playerData.warnedAboutBuildingOutsideClaims
&& ((playerData.lastClaim == null && playerData.claims.size() == 0) && ((playerData.lastClaim == null && playerData.getClaims().size() == 0)
|| (playerData.lastClaim != null && playerData.lastClaim.isNear(player.getLocation(), 15)))) || (playerData.lastClaim != null && playerData.lastClaim.isNear(player.getLocation(), 15))))
{ {
GriefPrevention.sendMessage(player, TextMode.Warn, Messages.BuildingOutsideClaims); GriefPrevention.sendMessage(player, TextMode.Warn, Messages.BuildingOutsideClaims);
playerData.warnedAboutBuildingOutsideClaims = true; playerData.warnedAboutBuildingOutsideClaims = true;
if(playerData.claims.size() < 2) if(playerData.getClaims().size() < 2)
{ {
GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo, DataStore.SURVIVAL_VIDEO_URL); GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo, DataStore.SURVIVAL_VIDEO_URL);
} }

View File

@ -80,10 +80,10 @@ class CleanupUnusedClaimsTask implements Runnable
//if he's been gone at least a week, if he has ONLY the new player claim, it will be removed //if he's been gone at least a week, if he has ONLY the new player claim, it will be removed
Calendar sevenDaysAgo = Calendar.getInstance(); Calendar sevenDaysAgo = Calendar.getInstance();
sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_chestClaimExpirationDays); sevenDaysAgo.add(Calendar.DATE, -GriefPrevention.instance.config_claims_chestClaimExpirationDays);
boolean newPlayerClaimsExpired = sevenDaysAgo.getTime().after(playerData.lastLogin); boolean newPlayerClaimsExpired = sevenDaysAgo.getTime().after(playerData.getLastLogin());
//if only one claim, and the player hasn't played in a week //if only one claim, and the player hasn't played in a week
if(newPlayerClaimsExpired && playerData.claims.size() == 1) if(newPlayerClaimsExpired && playerData.getClaims().size() == 1)
{ {
//if that's a chest claim and those are set to expire //if that's a chest claim and those are set to expire
if(claim.getArea() <= areaOfDefaultClaim && GriefPrevention.instance.config_claims_chestClaimExpirationDays > 0) if(claim.getArea() <= areaOfDefaultClaim && GriefPrevention.instance.config_claims_chestClaimExpirationDays > 0)
@ -108,13 +108,13 @@ class CleanupUnusedClaimsTask implements Runnable
Calendar earliestPermissibleLastLogin = Calendar.getInstance(); Calendar earliestPermissibleLastLogin = Calendar.getInstance();
earliestPermissibleLastLogin.add(Calendar.DATE, -GriefPrevention.instance.config_claims_expirationDays); earliestPermissibleLastLogin.add(Calendar.DATE, -GriefPrevention.instance.config_claims_expirationDays);
if(earliestPermissibleLastLogin.getTime().after(playerData.lastLogin)) if(earliestPermissibleLastLogin.getTime().after(playerData.getLastLogin()))
{ {
//make a copy of this player's claim list //make a copy of this player's claim list
Vector<Claim> claims = new Vector<Claim>(); Vector<Claim> claims = new Vector<Claim>();
for(int i = 0; i < playerData.claims.size(); i++) for(int i = 0; i < playerData.getClaims().size(); i++)
{ {
claims.add(playerData.claims.get(i)); claims.add(playerData.getClaims().get(i));
} }
//delete them //delete them
@ -138,7 +138,7 @@ class CleanupUnusedClaimsTask implements Runnable
//if the player has been gone two weeks, scan claim content to assess player investment //if the player has been gone two weeks, scan claim content to assess player investment
Calendar earliestAllowedLoginDate = Calendar.getInstance(); Calendar earliestAllowedLoginDate = Calendar.getInstance();
earliestAllowedLoginDate.add(Calendar.DATE, -GriefPrevention.instance.config_claims_unusedClaimExpirationDays); earliestAllowedLoginDate.add(Calendar.DATE, -GriefPrevention.instance.config_claims_unusedClaimExpirationDays);
boolean needsInvestmentScan = earliestAllowedLoginDate.getTime().after(playerData.lastLogin); boolean needsInvestmentScan = earliestAllowedLoginDate.getTime().after(playerData.getLastLogin());
//avoid scanning large claims and administrative claims //avoid scanning large claims and administrative claims
if(claim.isAdminClaim() || claim.getWidth() > 25 || claim.getHeight() > 25) return; if(claim.isAdminClaim() || claim.getWidth() > 25 || claim.getHeight() > 25) return;

View File

@ -193,13 +193,13 @@ public abstract class DataStore
//adjust blocks and other records //adjust blocks and other records
if(ownerData != null) if(ownerData != null)
{ {
ownerData.claims.remove(claim); ownerData.getClaims().remove(claim);
ownerData.bonusClaimBlocks -= claim.getArea(); ownerData.setBonusClaimBlocks(ownerData.getBonusClaimBlocks() - claim.getArea());
this.savePlayerData(claim.ownerID, ownerData); this.savePlayerData(claim.ownerID, ownerData);
} }
newOwnerData.claims.add(claim); newOwnerData.getClaims().add(claim);
newOwnerData.bonusClaimBlocks += claim.getArea(); newOwnerData.setBonusClaimBlocks(newOwnerData.getBonusClaimBlocks() + claim.getArea());
this.savePlayerData(newOwnerID, newOwnerData); this.savePlayerData(newOwnerID, newOwnerData);
} }
@ -239,7 +239,7 @@ public abstract class DataStore
if(!newClaim.isAdminClaim() && writeToStorage) if(!newClaim.isAdminClaim() && writeToStorage)
{ {
PlayerData ownerData = this.getPlayerData(newClaim.ownerID); PlayerData ownerData = this.getPlayerData(newClaim.ownerID);
ownerData.claims.add(newClaim); ownerData.getClaims().add(newClaim);
this.savePlayerData(newClaim.ownerID, ownerData); this.savePlayerData(newClaim.ownerID, ownerData);
} }
@ -330,22 +330,12 @@ public abstract class DataStore
//first, look in memory //first, look in memory
PlayerData playerData = this.playerNameToPlayerDataMap.get(playerID); PlayerData playerData = this.playerNameToPlayerDataMap.get(playerID);
//if not there, look in secondary storage //if not there, build a fresh instance with some blanks for what may be in secondary storage
if(playerData == null) if(playerData == null)
{ {
playerData = this.getPlayerDataFromStorage(playerID); playerData = new PlayerData();
playerData.playerID = playerID; playerData.playerID = playerID;
//find all the claims belonging to this player and note them for future reference
for(int i = 0; i < this.claims.size(); i++)
{
Claim claim = this.claims.get(i);
if(playerID.equals(claim.ownerID))
{
playerData.claims.add(claim);
}
}
//shove that new player data into the hash map cache //shove that new player data into the hash map cache
this.playerNameToPlayerDataMap.put(playerID, playerData); this.playerNameToPlayerDataMap.put(playerID, playerData);
} }
@ -404,11 +394,11 @@ public abstract class DataStore
if(!claim.isAdminClaim()) if(!claim.isAdminClaim())
{ {
PlayerData ownerData = this.getPlayerData(claim.ownerID); PlayerData ownerData = this.getPlayerData(claim.ownerID);
for(int i = 0; i < ownerData.claims.size(); i++) for(int i = 0; i < ownerData.getClaims().size(); i++)
{ {
if(ownerData.claims.get(i).id.equals(claim.id)) if(ownerData.getClaims().get(i).id.equals(claim.id))
{ {
ownerData.claims.remove(i); ownerData.getClaims().remove(i);
break; break;
} }
} }

View File

@ -484,9 +484,9 @@ public class DatabaseDataStore extends DataStore
//if data for this player exists, use it //if data for this player exists, use it
if(results.next()) if(results.next())
{ {
playerData.lastLogin = results.getTimestamp("lastlogin"); playerData.setLastLogin(results.getTimestamp("lastlogin"));
playerData.accruedClaimBlocks = results.getInt("accruedblocks"); playerData.setAccruedClaimBlocks(results.getInt("accruedblocks"));
playerData.bonusClaimBlocks = results.getInt("bonusblocks"); playerData.setBonusClaimBlocks(results.getInt("bonusblocks"));
} }
} }
catch(SQLException e) catch(SQLException e)
@ -515,12 +515,12 @@ public class DatabaseDataStore extends DataStore
this.refreshDataConnection(); this.refreshDataConnection();
SimpleDateFormat sqlFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); SimpleDateFormat sqlFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String dateString = sqlFormat.format(playerData.lastLogin); String dateString = sqlFormat.format(playerData.getLastLogin());
Statement statement = databaseConnection.createStatement(); Statement statement = databaseConnection.createStatement();
statement.execute("DELETE FROM griefprevention_playerdata WHERE name='" + playerID.toString() + "';"); statement.execute("DELETE FROM griefprevention_playerdata WHERE name='" + playerID.toString() + "';");
statement = databaseConnection.createStatement(); statement = databaseConnection.createStatement();
statement.execute("INSERT INTO griefprevention_playerdata (name, lastlogin, accruedblocks, bonusblocks) VALUES ('" + playerID.toString() + "', '" + dateString + "', " + playerData.accruedClaimBlocks + ", " + playerData.bonusClaimBlocks + ");"); statement.execute("INSERT INTO griefprevention_playerdata (name, lastlogin, accruedblocks, bonusblocks) VALUES ('" + playerID.toString() + "', '" + dateString + "', " + playerData.getAccruedClaimBlocks() + ", " + playerData.getBonusClaimBlocks() + ");");
} }
catch(SQLException e) catch(SQLException e)
{ {
@ -562,7 +562,7 @@ public class DatabaseDataStore extends DataStore
//group bonus blocks are stored in the player data table, with player name = $groupName //group bonus blocks are stored in the player data table, with player name = $groupName
String playerName = "$" + groupName; String playerName = "$" + groupName;
PlayerData playerData = new PlayerData(); PlayerData playerData = new PlayerData();
playerData.bonusClaimBlocks = currentValue; playerData.setBonusClaimBlocks(currentValue);
this.savePlayerData(playerName, playerData); this.savePlayerData(playerName, playerData);
} }

View File

@ -53,15 +53,15 @@ class DeliverClaimBlocksTask implements Runnable
{ {
//if player is over accrued limit, accrued limit was probably reduced in config file AFTER he accrued //if player is over accrued limit, accrued limit was probably reduced in config file AFTER he accrued
//in that case, leave his blocks where they are //in that case, leave his blocks where they are
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks) continue; if(playerData.getAccruedClaimBlocks() > GriefPrevention.instance.config_claims_maxAccruedBlocks) continue;
//add blocks //add blocks
playerData.accruedClaimBlocks += accruedBlocks; playerData.setAccruedClaimBlocks(playerData.getAccruedClaimBlocks() + accruedBlocks);
//respect limits //respect limits
if(playerData.accruedClaimBlocks > GriefPrevention.instance.config_claims_maxAccruedBlocks) if(playerData.getAccruedClaimBlocks() > GriefPrevention.instance.config_claims_maxAccruedBlocks)
{ {
playerData.accruedClaimBlocks = GriefPrevention.instance.config_claims_maxAccruedBlocks; playerData.setAccruedClaimBlocks(GriefPrevention.instance.config_claims_maxAccruedBlocks);
} }
//intentionally NOT saving data here to reduce overall secondary storage access frequency //intentionally NOT saving data here to reduce overall secondary storage access frequency

View File

@ -477,25 +477,25 @@ public class FlatFileDataStore extends DataStore
DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss"); DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
try try
{ {
playerData.lastLogin = dateFormat.parse(lastLoginTimestampString); playerData.setLastLogin(dateFormat.parse(lastLoginTimestampString));
} }
catch(ParseException parseException) catch(ParseException parseException)
{ {
GriefPrevention.AddLogEntry("Unable to load last login for \"" + playerFile.getName() + "\"."); GriefPrevention.AddLogEntry("Unable to load last login for \"" + playerFile.getName() + "\".");
playerData.lastLogin = null; playerData.setLastLogin(null);
} }
//second line is accrued claim blocks //second line is accrued claim blocks
String accruedBlocksString = inStream.readLine(); String accruedBlocksString = inStream.readLine();
//convert that to a number and store it //convert that to a number and store it
playerData.accruedClaimBlocks = Integer.parseInt(accruedBlocksString); playerData.setAccruedClaimBlocks(Integer.parseInt(accruedBlocksString));
//third line is any bonus claim blocks granted by administrators //third line is any bonus claim blocks granted by administrators
String bonusBlocksString = inStream.readLine(); String bonusBlocksString = inStream.readLine();
//convert that to a number and store it //convert that to a number and store it
playerData.bonusClaimBlocks = Integer.parseInt(bonusBlocksString); playerData.setBonusClaimBlocks(Integer.parseInt(bonusBlocksString));
//fourth line is a double-semicolon-delimited list of claims, which is currently ignored //fourth line is a double-semicolon-delimited list of claims, which is currently ignored
//String claimsString = inStream.readLine(); //String claimsString = inStream.readLine();
@ -536,26 +536,26 @@ public class FlatFileDataStore extends DataStore
outStream = new BufferedWriter(new FileWriter(playerDataFile)); outStream = new BufferedWriter(new FileWriter(playerDataFile));
//first line is last login timestamp //first line is last login timestamp
if(playerData.lastLogin == null)playerData.lastLogin = new Date(); if(playerData.getLastLogin() == null) playerData.setLastLogin(new Date());
DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss"); DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss");
outStream.write(dateFormat.format(playerData.lastLogin)); outStream.write(dateFormat.format(playerData.getLastLogin()));
outStream.newLine(); outStream.newLine();
//second line is accrued claim blocks //second line is accrued claim blocks
outStream.write(String.valueOf(playerData.accruedClaimBlocks)); outStream.write(String.valueOf(playerData.getAccruedClaimBlocks()));
outStream.newLine(); outStream.newLine();
//third line is bonus claim blocks //third line is bonus claim blocks
outStream.write(String.valueOf(playerData.bonusClaimBlocks)); outStream.write(String.valueOf(playerData.getBonusClaimBlocks()));
outStream.newLine(); outStream.newLine();
//fourth line is a double-semicolon-delimited list of claims //fourth line is a double-semicolon-delimited list of claims
if(playerData.claims.size() > 0) if(playerData.getClaims().size() > 0)
{ {
outStream.write(this.locationToString(playerData.claims.get(0).getLesserBoundaryCorner())); outStream.write(this.locationToString(playerData.getClaims().get(0).getLesserBoundaryCorner()));
for(int i = 1; i < playerData.claims.size(); i++) for(int i = 1; i < playerData.getClaims().size(); i++)
{ {
outStream.write(";;" + this.locationToString(playerData.claims.get(i).getLesserBoundaryCorner())); outStream.write(";;" + this.locationToString(playerData.getClaims().get(i).getLesserBoundaryCorner()));
} }
} }
outStream.newLine(); outStream.newLine();

View File

@ -871,7 +871,7 @@ public class GriefPrevention extends JavaPlugin
//count claims //count claims
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
int originalClaimCount = playerData.claims.size(); int originalClaimCount = playerData.getClaims().size();
//check count //check count
if(originalClaimCount == 0) if(originalClaimCount == 0)
@ -1124,9 +1124,9 @@ public class GriefPrevention extends JavaPlugin
if(claim == null) if(claim == null)
{ {
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
for(int i = 0; i < playerData.claims.size(); i++) for(int i = 0; i < playerData.getClaims().size(); i++)
{ {
claim = playerData.claims.get(i); claim = playerData.getClaims().get(i);
//if untrusting "all" drop all permissions //if untrusting "all" drop all permissions
if(clearPermissions) if(clearPermissions)
@ -1282,7 +1282,7 @@ public class GriefPrevention extends JavaPlugin
{ {
//determine max purchasable blocks //determine max purchasable blocks
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
int maxPurchasable = GriefPrevention.instance.config_claims_maxAccruedBlocks - playerData.accruedClaimBlocks; int maxPurchasable = GriefPrevention.instance.config_claims_maxAccruedBlocks - playerData.getAccruedClaimBlocks();
//if the player is at his max, tell him so //if the player is at his max, tell him so
if(maxPurchasable <= 0) if(maxPurchasable <= 0)
@ -1328,7 +1328,7 @@ public class GriefPrevention extends JavaPlugin
economy.withdrawPlayer(player, totalCost); economy.withdrawPlayer(player, totalCost);
//add blocks //add blocks
playerData.accruedClaimBlocks += blockCount; playerData.setAccruedClaimBlocks(playerData.getAccruedClaimBlocks() + blockCount);
this.dataStore.savePlayerData(player.getUniqueId(), playerData); this.dataStore.savePlayerData(player.getUniqueId(), playerData);
//inform player //inform player
@ -1403,7 +1403,7 @@ public class GriefPrevention extends JavaPlugin
economy.depositPlayer(player, totalValue); economy.depositPlayer(player, totalValue);
//subtract blocks //subtract blocks
playerData.accruedClaimBlocks -= blockCount; playerData.setAccruedClaimBlocks(playerData.getAccruedClaimBlocks() - blockCount);
this.dataStore.savePlayerData(player.getUniqueId(), playerData); this.dataStore.savePlayerData(player.getUniqueId(), playerData);
//inform player //inform player
@ -1598,14 +1598,14 @@ public class GriefPrevention extends JavaPlugin
//load the target player's data //load the target player's data
PlayerData playerData = this.dataStore.getPlayerData(otherPlayer.getUniqueId()); PlayerData playerData = this.dataStore.getPlayerData(otherPlayer.getUniqueId());
GriefPrevention.sendMessage(player, TextMode.Instr, " " + playerData.accruedClaimBlocks + "(+" + (playerData.bonusClaimBlocks + this.dataStore.getGroupBonusBlocks(otherPlayer.getUniqueId())) + ")=" + (playerData.accruedClaimBlocks + playerData.bonusClaimBlocks + this.dataStore.getGroupBonusBlocks(otherPlayer.getUniqueId()))); GriefPrevention.sendMessage(player, TextMode.Instr, " " + playerData.getAccruedClaimBlocks() + "(+" + (playerData.getBonusClaimBlocks() + this.dataStore.getGroupBonusBlocks(otherPlayer.getUniqueId())) + ")=" + (playerData.getAccruedClaimBlocks() + playerData.getBonusClaimBlocks() + this.dataStore.getGroupBonusBlocks(otherPlayer.getUniqueId())));
for(int i = 0; i < playerData.claims.size(); i++) for(int i = 0; i < playerData.getClaims().size(); i++)
{ {
Claim claim = playerData.claims.get(i); Claim claim = playerData.getClaims().get(i);
GriefPrevention.sendMessage(player, TextMode.Instr, " (-" + claim.getArea() + ") " + getfriendlyLocationString(claim.getLesserBoundaryCorner())); GriefPrevention.sendMessage(player, TextMode.Instr, " (-" + claim.getArea() + ") " + getfriendlyLocationString(claim.getLesserBoundaryCorner()));
} }
if(playerData.claims.size() > 0) if(playerData.getClaims().size() > 0)
GriefPrevention.sendMessage(player, TextMode.Instr, " =" + playerData.getRemainingClaimBlocks()); GriefPrevention.sendMessage(player, TextMode.Instr, " =" + playerData.getRemainingClaimBlocks());
//drop the data we just loaded, if the player isn't online //drop the data we just loaded, if the player isn't online
@ -1738,10 +1738,10 @@ public class GriefPrevention extends JavaPlugin
//give blocks to player //give blocks to player
PlayerData playerData = this.dataStore.getPlayerData(targetPlayer.getUniqueId()); PlayerData playerData = this.dataStore.getPlayerData(targetPlayer.getUniqueId());
playerData.bonusClaimBlocks += adjustment; playerData.setBonusClaimBlocks(playerData.getBonusClaimBlocks() + adjustment);
this.dataStore.savePlayerData(targetPlayer.getUniqueId(), playerData); this.dataStore.savePlayerData(targetPlayer.getUniqueId(), playerData);
GriefPrevention.sendMessage(player, TextMode.Success, Messages.AdjustBlocksSuccess, targetPlayer.getName(), String.valueOf(adjustment), String.valueOf(playerData.bonusClaimBlocks)); GriefPrevention.sendMessage(player, TextMode.Success, Messages.AdjustBlocksSuccess, targetPlayer.getName(), String.valueOf(adjustment), String.valueOf(playerData.getBonusClaimBlocks()));
if(player != null) GriefPrevention.AddLogEntry(player.getName() + " adjusted " + targetPlayer.getName() + "'s bonus claim blocks by " + adjustment + "."); if(player != null) GriefPrevention.AddLogEntry(player.getName() + " adjusted " + targetPlayer.getName() + "'s bonus claim blocks by " + adjustment + ".");
return true; return true;
@ -2040,9 +2040,9 @@ public class GriefPrevention extends JavaPlugin
if(claim == null) if(claim == null)
{ {
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
for(int i = 0; i < playerData.claims.size(); i++) for(int i = 0; i < playerData.getClaims().size(); i++)
{ {
targetClaims.add(playerData.claims.get(i)); targetClaims.add(playerData.getClaims().get(i));
} }
} }
else else

View File

@ -38,16 +38,16 @@ public class PlayerData
public UUID playerID; public UUID playerID;
//the player's claims //the player's claims
public Vector<Claim> claims = new Vector<Claim>(); private Vector<Claim> claims = null;
//how many claim blocks the player has earned via play time //how many claim blocks the player has earned via play time
public int accruedClaimBlocks = GriefPrevention.instance.config_claims_initialBlocks; private Integer accruedClaimBlocks = null;
//where this player was the last time we checked on him for earning claim blocks //where this player was the last time we checked on him for earning claim blocks
public Location lastAfkCheckLocation = null; public Location lastAfkCheckLocation = null;
//how many claim blocks the player has been gifted by admins, or purchased via economy integration //how many claim blocks the player has been gifted by admins, or purchased via economy integration
public int bonusClaimBlocks = 0; private Integer bonusClaimBlocks = null;
//what "mode" the shovel is in determines what it will do when it's used //what "mode" the shovel is in determines what it will do when it's used
public ShovelMode shovelMode = ShovelMode.Basic; public ShovelMode shovelMode = ShovelMode.Basic;
@ -74,8 +74,11 @@ public class PlayerData
//timestamp of last death, for use in preventing death message spam //timestamp of last death, for use in preventing death message spam
long lastDeathTimeStamp = 0; long lastDeathTimeStamp = 0;
//whether the player was kicked (set and used during logout)
boolean wasKicked = false;
//spam //spam
public Date lastLogin; //when the player last logged into the server private Date lastLogin = null; //when the player last logged into the server
public String lastMessage = ""; //the player's last chat message, or slash command complete with parameters public String lastMessage = ""; //the player's last chat message, or slash command complete with parameters
public Date lastMessageTimestamp = new Date(); //last time the player sent a chat message or used a monitored slash command public Date lastMessageTimestamp = new Date(); //last time the player sent a chat message or used a monitored slash command
public int spamCount = 0; //number of consecutive "spams" public int spamCount = 0; //number of consecutive "spams"
@ -106,16 +109,6 @@ public class PlayerData
public InetAddress ipAddress; public InetAddress ipAddress;
PlayerData()
{
//default last login date value to 5 minutes ago to ensure a brand new player can log in
//see login cooldown feature, PlayerEventHandler.onPlayerLogin()
//if the player successfully logs in, this value will be overwritten with the current date and time
Calendar fiveMinutesBack = Calendar.getInstance();
fiveMinutesBack.add(Calendar.MINUTE, -5);
this.lastLogin = fiveMinutesBack.getTime();
}
//whether or not this player is "in" pvp combat //whether or not this player is "in" pvp combat
public boolean inPvpCombat() public boolean inPvpCombat()
{ {
@ -137,10 +130,10 @@ public class PlayerData
//the number of claim blocks a player has available for claiming land //the number of claim blocks a player has available for claiming land
public int getRemainingClaimBlocks() public int getRemainingClaimBlocks()
{ {
int remainingBlocks = this.accruedClaimBlocks + this.bonusClaimBlocks; int remainingBlocks = this.getAccruedClaimBlocks() + this.getBonusClaimBlocks();
for(int i = 0; i < this.claims.size(); i++) for(int i = 0; i < this.getClaims().size(); i++)
{ {
Claim claim = this.claims.get(i); Claim claim = this.getClaims().get(i);
remainingBlocks -= claim.getArea(); remainingBlocks -= claim.getArea();
} }
@ -149,4 +142,109 @@ public class PlayerData
return remainingBlocks; return remainingBlocks;
} }
//don't load data from secondary storage until it's needed
public int getAccruedClaimBlocks()
{
if(this.accruedClaimBlocks == null) this.loadDataFromSecondaryStorage();
return accruedClaimBlocks;
}
public void setAccruedClaimBlocks(Integer accruedClaimBlocks)
{
this.accruedClaimBlocks = accruedClaimBlocks;
}
public int getBonusClaimBlocks()
{
if(this.bonusClaimBlocks == null) this.loadDataFromSecondaryStorage();
return bonusClaimBlocks;
}
public void setBonusClaimBlocks(Integer bonusClaimBlocks)
{
this.bonusClaimBlocks = bonusClaimBlocks;
}
public Date getLastLogin()
{
if(this.lastLogin == null) this.loadDataFromSecondaryStorage();
return this.lastLogin;
}
public void setLastLogin(Date lastLogin)
{
this.lastLogin = lastLogin;
}
private void loadDataFromSecondaryStorage()
{
//reach out to secondary storage to get any data there
PlayerData storageData = GriefPrevention.instance.dataStore.getPlayerDataFromStorage(this.playerID);
//fill in any missing pieces
if(this.lastLogin == null)
{
if(storageData.lastLogin != null)
{
this.lastLogin = storageData.lastLogin;
}
else
{
//default last login date value to 5 minutes ago to ensure a brand new player can log in
//see login cooldown feature, PlayerEventHandler.onPlayerLogin()
//if the player successfully logs in, this value will be overwritten with the current date and time
Calendar fiveMinutesBack = Calendar.getInstance();
fiveMinutesBack.add(Calendar.MINUTE, -5);
this.lastLogin = fiveMinutesBack.getTime();
}
}
if(this.accruedClaimBlocks == null)
{
if(storageData.accruedClaimBlocks != null)
{
this.accruedClaimBlocks = storageData.accruedClaimBlocks;
}
else
{
this.accruedClaimBlocks = GriefPrevention.instance.config_claims_initialBlocks;
}
}
if(this.bonusClaimBlocks == null)
{
if(storageData.bonusClaimBlocks != null)
{
this.bonusClaimBlocks = storageData.bonusClaimBlocks;
}
else
{
this.bonusClaimBlocks = 0;
}
}
}
public Vector<Claim> getClaims()
{
if(this.claims == null)
{
this.claims = new Vector<Claim>();
//find all the claims belonging to this player and note them for future reference
DataStore dataStore = GriefPrevention.instance.dataStore;
for(int i = 0; i < dataStore.claims.size(); i++)
{
Claim claim = dataStore.claims.get(i);
if(playerID.equals(claim.ownerID))
{
this.claims.add(claim);
}
}
}
return claims;
}
} }

View File

@ -24,6 +24,7 @@ import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -416,6 +417,8 @@ class PlayerEventHandler implements Listener
} }
} }
private ConcurrentHashMap<UUID, Date> lastLoginThisServerSessionMap = new ConcurrentHashMap<UUID, Date>();
//when a player attempts to join the server... //when a player attempts to join the server...
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
void onPlayerLogin (PlayerLoginEvent event) void onPlayerLogin (PlayerLoginEvent event)
@ -426,18 +429,21 @@ class PlayerEventHandler implements Listener
if(GriefPrevention.instance.config_spam_enabled) if(GriefPrevention.instance.config_spam_enabled)
{ {
//FEATURE: login cooldown to prevent login/logout spam with custom clients //FEATURE: login cooldown to prevent login/logout spam with custom clients
long now = Calendar.getInstance().getTimeInMillis();
//if allowed to join and login cooldown enabled //if allowed to join and login cooldown enabled
if(GriefPrevention.instance.config_spam_loginCooldownSeconds > 0 && event.getResult() == Result.ALLOWED) if(GriefPrevention.instance.config_spam_loginCooldownSeconds > 0 && event.getResult() == Result.ALLOWED && !player.hasPermission("griefprevention.spam"))
{ {
//determine how long since last login and cooldown remaining //determine how long since last login and cooldown remaining
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); Date lastLoginThisSession = lastLoginThisServerSessionMap.get(player.getUniqueId());
long millisecondsSinceLastLogin = (new Date()).getTime() - playerData.lastLogin.getTime(); if(lastLoginThisSession != null)
{
long millisecondsSinceLastLogin = now - lastLoginThisSession.getTime();
long secondsSinceLastLogin = millisecondsSinceLastLogin / 1000; long secondsSinceLastLogin = millisecondsSinceLastLogin / 1000;
long cooldownRemaining = GriefPrevention.instance.config_spam_loginCooldownSeconds - secondsSinceLastLogin; long cooldownRemaining = GriefPrevention.instance.config_spam_loginCooldownSeconds - secondsSinceLastLogin;
//if cooldown remaining and player doesn't have permission to spam //if cooldown remaining
if(cooldownRemaining > 0 && !player.hasPermission("griefprevention.spam")) if(cooldownRemaining > 0)
{ {
//DAS BOOT! //DAS BOOT!
event.setResult(Result.KICK_OTHER); event.setResult(Result.KICK_OTHER);
@ -446,9 +452,9 @@ class PlayerEventHandler implements Listener
return; return;
} }
} }
}
//if logging-in account is banned, remember IP address for later //if logging-in account is banned, remember IP address for later
long now = Calendar.getInstance().getTimeInMillis();
if(GriefPrevention.instance.config_smartBan && event.getResult() == Result.KICK_BANNED) if(GriefPrevention.instance.config_smartBan && event.getResult() == Result.KICK_BANNED)
{ {
this.tempBannedIps.add(new IpBanInfo(event.getAddress(), now + this.MILLISECONDS_IN_DAY, player.getName())); this.tempBannedIps.add(new IpBanInfo(event.getAddress(), now + this.MILLISECONDS_IN_DAY, player.getName()));
@ -468,10 +474,12 @@ class PlayerEventHandler implements Listener
UUID playerID = player.getUniqueId(); UUID playerID = player.getUniqueId();
//note login time //note login time
long now = Calendar.getInstance().getTimeInMillis(); Date nowDate = new Date();
long now = nowDate.getTime();
PlayerData playerData = this.dataStore.getPlayerData(playerID); PlayerData playerData = this.dataStore.getPlayerData(playerID);
playerData.lastSpawn = now; playerData.lastSpawn = now;
playerData.lastLogin = new Date(); playerData.setLastLogin(nowDate);
this.lastLoginThisServerSessionMap.put(playerID, nowDate);
//if player has never played on the server before, may need pvp protection //if player has never played on the server before, may need pvp protection
if(!player.hasPlayedBefore()) if(!player.hasPlayedBefore())
@ -577,15 +585,33 @@ class PlayerEventHandler implements Listener
playerData.lastDeathTimeStamp = now; playerData.lastDeathTimeStamp = now;
} }
//when a player gets kicked...
@EventHandler(priority = EventPriority.HIGHEST)
void onPlayerKicked(PlayerKickEvent event)
{
Player player = event.getPlayer();
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
playerData.wasKicked = true;
}
//when a player quits... //when a player quits...
@EventHandler(priority = EventPriority.HIGHEST) @EventHandler(priority = EventPriority.HIGHEST)
void onPlayerQuit(PlayerQuitEvent event) void onPlayerQuit(PlayerQuitEvent event)
{ {
Player player = event.getPlayer(); Player player = event.getPlayer();
PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId());
boolean isBanned;
if(playerData.wasKicked)
{
isBanned = player.isBanned();
}
else
{
isBanned = false;
}
//if banned, add IP to the temporary IP ban list //if banned, add IP to the temporary IP ban list
if(player.isBanned() && playerData.ipAddress != null) if(isBanned && playerData.ipAddress != null)
{ {
long now = Calendar.getInstance().getTimeInMillis(); long now = Calendar.getInstance().getTimeInMillis();
this.tempBannedIps.add(new IpBanInfo(playerData.ipAddress, now + this.MILLISECONDS_IN_DAY, player.getName())); this.tempBannedIps.add(new IpBanInfo(playerData.ipAddress, now + this.MILLISECONDS_IN_DAY, player.getName()));
@ -598,13 +624,13 @@ class PlayerEventHandler implements Listener
} }
//silence notifications when the player is banned //silence notifications when the player is banned
if(player.isBanned()) if(isBanned)
{ {
event.setQuitMessage(null); event.setQuitMessage(null);
} }
//make sure his data is all saved - he might have accrued some claim blocks while playing that were not saved immediately //make sure his data is all saved - he might have accrued some claim blocks while playing that were not saved immediately
if(!player.isBanned()) else
{ {
this.dataStore.savePlayerData(player.getUniqueId(), playerData); this.dataStore.savePlayerData(player.getUniqueId(), playerData);
} }
@ -619,7 +645,7 @@ class PlayerEventHandler implements Listener
PlayerData playerData = this.dataStore.getPlayerData(playerID); PlayerData playerData = this.dataStore.getPlayerData(playerID);
//FEATURE: claims where players have allowed explosions will revert back to not allowing them when the owner logs out //FEATURE: claims where players have allowed explosions will revert back to not allowing them when the owner logs out
for(Claim claim : playerData.claims) for(Claim claim : playerData.getClaims())
{ {
claim.areExplosivesAllowed = false; claim.areExplosivesAllowed = false;
} }
@ -1311,7 +1337,7 @@ class PlayerEventHandler implements Listener
claim = claim.parent; claim = claim.parent;
} }
PlayerData otherPlayerData = this.dataStore.getPlayerData(claim.ownerID); PlayerData otherPlayerData = this.dataStore.getPlayerData(claim.ownerID);
Date lastLogin = otherPlayerData.lastLogin; Date lastLogin = otherPlayerData.getLastLogin();
Date now = new Date(); Date now = new Date();
long daysElapsed = (now.getTime() - lastLogin.getTime()) / (1000 * 60 * 60 * 24); long daysElapsed = (now.getTime() - lastLogin.getTime()) / (1000 * 60 * 60 * 24);