diff --git a/src/me/ryanhamshire/GriefPrevention/BlockEventHandler.java b/src/me/ryanhamshire/GriefPrevention/BlockEventHandler.java index b220c49..39bb3bb 100644 --- a/src/me/ryanhamshire/GriefPrevention/BlockEventHandler.java +++ b/src/me/ryanhamshire/GriefPrevention/BlockEventHandler.java @@ -255,7 +255,7 @@ public class BlockEventHandler implements Listener 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(playerData.claims.size() == 0) + if(playerData.getClaims().size() == 0) { //radius == 0 means protect ONLY the chest 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())) { 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)))) { GriefPrevention.sendMessage(player, TextMode.Warn, Messages.BuildingOutsideClaims); playerData.warnedAboutBuildingOutsideClaims = true; - if(playerData.claims.size() < 2) + if(playerData.getClaims().size() < 2) { GriefPrevention.sendMessage(player, TextMode.Instr, Messages.SurvivalBasicsVideo, DataStore.SURVIVAL_VIDEO_URL); } diff --git a/src/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimsTask.java b/src/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimsTask.java index 157782a..d5a9fe8 100644 --- a/src/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimsTask.java +++ b/src/me/ryanhamshire/GriefPrevention/CleanupUnusedClaimsTask.java @@ -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 Calendar sevenDaysAgo = Calendar.getInstance(); 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(newPlayerClaimsExpired && playerData.claims.size() == 1) + if(newPlayerClaimsExpired && playerData.getClaims().size() == 1) { //if that's a chest claim and those are set to expire if(claim.getArea() <= areaOfDefaultClaim && GriefPrevention.instance.config_claims_chestClaimExpirationDays > 0) @@ -108,13 +108,13 @@ class CleanupUnusedClaimsTask implements Runnable Calendar earliestPermissibleLastLogin = Calendar.getInstance(); 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 Vector claims = new Vector(); - 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 @@ -138,7 +138,7 @@ class CleanupUnusedClaimsTask implements Runnable //if the player has been gone two weeks, scan claim content to assess player investment Calendar earliestAllowedLoginDate = Calendar.getInstance(); 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 if(claim.isAdminClaim() || claim.getWidth() > 25 || claim.getHeight() > 25) return; diff --git a/src/me/ryanhamshire/GriefPrevention/DataStore.java b/src/me/ryanhamshire/GriefPrevention/DataStore.java index 47cc2ce..a6fc8d6 100644 --- a/src/me/ryanhamshire/GriefPrevention/DataStore.java +++ b/src/me/ryanhamshire/GriefPrevention/DataStore.java @@ -193,13 +193,13 @@ public abstract class DataStore //adjust blocks and other records if(ownerData != null) { - ownerData.claims.remove(claim); - ownerData.bonusClaimBlocks -= claim.getArea(); + ownerData.getClaims().remove(claim); + ownerData.setBonusClaimBlocks(ownerData.getBonusClaimBlocks() - claim.getArea()); this.savePlayerData(claim.ownerID, ownerData); } - newOwnerData.claims.add(claim); - newOwnerData.bonusClaimBlocks += claim.getArea(); + newOwnerData.getClaims().add(claim); + newOwnerData.setBonusClaimBlocks(newOwnerData.getBonusClaimBlocks() + claim.getArea()); this.savePlayerData(newOwnerID, newOwnerData); } @@ -239,7 +239,7 @@ public abstract class DataStore if(!newClaim.isAdminClaim() && writeToStorage) { PlayerData ownerData = this.getPlayerData(newClaim.ownerID); - ownerData.claims.add(newClaim); + ownerData.getClaims().add(newClaim); this.savePlayerData(newClaim.ownerID, ownerData); } @@ -330,22 +330,12 @@ public abstract class DataStore //first, look in memory 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) { - playerData = this.getPlayerDataFromStorage(playerID); + playerData = new PlayerData(); 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 this.playerNameToPlayerDataMap.put(playerID, playerData); } @@ -404,11 +394,11 @@ public abstract class DataStore if(!claim.isAdminClaim()) { 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; } } diff --git a/src/me/ryanhamshire/GriefPrevention/DatabaseDataStore.java b/src/me/ryanhamshire/GriefPrevention/DatabaseDataStore.java index 1bbd6c0..7474621 100644 --- a/src/me/ryanhamshire/GriefPrevention/DatabaseDataStore.java +++ b/src/me/ryanhamshire/GriefPrevention/DatabaseDataStore.java @@ -484,9 +484,9 @@ public class DatabaseDataStore extends DataStore //if data for this player exists, use it if(results.next()) { - playerData.lastLogin = results.getTimestamp("lastlogin"); - playerData.accruedClaimBlocks = results.getInt("accruedblocks"); - playerData.bonusClaimBlocks = results.getInt("bonusblocks"); + playerData.setLastLogin(results.getTimestamp("lastlogin")); + playerData.setAccruedClaimBlocks(results.getInt("accruedblocks")); + playerData.setBonusClaimBlocks(results.getInt("bonusblocks")); } } catch(SQLException e) @@ -515,12 +515,12 @@ public class DatabaseDataStore extends DataStore this.refreshDataConnection(); 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.execute("DELETE FROM griefprevention_playerdata WHERE name='" + playerID.toString() + "';"); 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) { @@ -562,7 +562,7 @@ public class DatabaseDataStore extends DataStore //group bonus blocks are stored in the player data table, with player name = $groupName String playerName = "$" + groupName; PlayerData playerData = new PlayerData(); - playerData.bonusClaimBlocks = currentValue; + playerData.setBonusClaimBlocks(currentValue); this.savePlayerData(playerName, playerData); } diff --git a/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java b/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java index b26acdf..e2f9f83 100644 --- a/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java +++ b/src/me/ryanhamshire/GriefPrevention/DeliverClaimBlocksTask.java @@ -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 //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 - playerData.accruedClaimBlocks += accruedBlocks; + playerData.setAccruedClaimBlocks(playerData.getAccruedClaimBlocks() + accruedBlocks); //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 diff --git a/src/me/ryanhamshire/GriefPrevention/FlatFileDataStore.java b/src/me/ryanhamshire/GriefPrevention/FlatFileDataStore.java index 243dfad..465fefc 100644 --- a/src/me/ryanhamshire/GriefPrevention/FlatFileDataStore.java +++ b/src/me/ryanhamshire/GriefPrevention/FlatFileDataStore.java @@ -477,25 +477,25 @@ public class FlatFileDataStore extends DataStore DateFormat dateFormat = new SimpleDateFormat("yyyy.MM.dd.HH.mm.ss"); try { - playerData.lastLogin = dateFormat.parse(lastLoginTimestampString); + playerData.setLastLogin(dateFormat.parse(lastLoginTimestampString)); } catch(ParseException parseException) { GriefPrevention.AddLogEntry("Unable to load last login for \"" + playerFile.getName() + "\"."); - playerData.lastLogin = null; + playerData.setLastLogin(null); } //second line is accrued claim blocks String accruedBlocksString = inStream.readLine(); //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 String bonusBlocksString = inStream.readLine(); //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 //String claimsString = inStream.readLine(); @@ -536,26 +536,26 @@ public class FlatFileDataStore extends DataStore outStream = new BufferedWriter(new FileWriter(playerDataFile)); //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"); - outStream.write(dateFormat.format(playerData.lastLogin)); + outStream.write(dateFormat.format(playerData.getLastLogin())); outStream.newLine(); //second line is accrued claim blocks - outStream.write(String.valueOf(playerData.accruedClaimBlocks)); + outStream.write(String.valueOf(playerData.getAccruedClaimBlocks())); outStream.newLine(); //third line is bonus claim blocks - outStream.write(String.valueOf(playerData.bonusClaimBlocks)); + outStream.write(String.valueOf(playerData.getBonusClaimBlocks())); outStream.newLine(); //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())); - for(int i = 1; i < playerData.claims.size(); i++) + outStream.write(this.locationToString(playerData.getClaims().get(0).getLesserBoundaryCorner())); + 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(); diff --git a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java index 743d1b4..48eccaf 100644 --- a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java +++ b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java @@ -871,7 +871,7 @@ public class GriefPrevention extends JavaPlugin //count claims PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); - int originalClaimCount = playerData.claims.size(); + int originalClaimCount = playerData.getClaims().size(); //check count if(originalClaimCount == 0) @@ -1124,9 +1124,9 @@ public class GriefPrevention extends JavaPlugin if(claim == null) { 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(clearPermissions) @@ -1282,7 +1282,7 @@ public class GriefPrevention extends JavaPlugin { //determine max purchasable blocks 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(maxPurchasable <= 0) @@ -1328,7 +1328,7 @@ public class GriefPrevention extends JavaPlugin economy.withdrawPlayer(player, totalCost); //add blocks - playerData.accruedClaimBlocks += blockCount; + playerData.setAccruedClaimBlocks(playerData.getAccruedClaimBlocks() + blockCount); this.dataStore.savePlayerData(player.getUniqueId(), playerData); //inform player @@ -1403,7 +1403,7 @@ public class GriefPrevention extends JavaPlugin economy.depositPlayer(player, totalValue); //subtract blocks - playerData.accruedClaimBlocks -= blockCount; + playerData.setAccruedClaimBlocks(playerData.getAccruedClaimBlocks() - blockCount); this.dataStore.savePlayerData(player.getUniqueId(), playerData); //inform player @@ -1598,14 +1598,14 @@ public class GriefPrevention extends JavaPlugin //load the target player's data 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()))); - for(int i = 0; i < playerData.claims.size(); i++) + 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.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())); } - if(playerData.claims.size() > 0) + if(playerData.getClaims().size() > 0) GriefPrevention.sendMessage(player, TextMode.Instr, " =" + playerData.getRemainingClaimBlocks()); //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 PlayerData playerData = this.dataStore.getPlayerData(targetPlayer.getUniqueId()); - playerData.bonusClaimBlocks += adjustment; + playerData.setBonusClaimBlocks(playerData.getBonusClaimBlocks() + adjustment); 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 + "."); return true; @@ -2040,9 +2040,9 @@ public class GriefPrevention extends JavaPlugin if(claim == null) { 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 diff --git a/src/me/ryanhamshire/GriefPrevention/PlayerData.java b/src/me/ryanhamshire/GriefPrevention/PlayerData.java index 35f0c42..69b9fd6 100644 --- a/src/me/ryanhamshire/GriefPrevention/PlayerData.java +++ b/src/me/ryanhamshire/GriefPrevention/PlayerData.java @@ -38,16 +38,16 @@ public class PlayerData public UUID playerID; //the player's claims - public Vector claims = new Vector(); + private Vector claims = null; //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 public Location lastAfkCheckLocation = null; //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 public ShovelMode shovelMode = ShovelMode.Basic; @@ -74,9 +74,12 @@ public class PlayerData //timestamp of last death, for use in preventing death message spam long lastDeathTimeStamp = 0; + //whether the player was kicked (set and used during logout) + boolean wasKicked = false; + //spam - public Date lastLogin; //when the player last logged into the server - public String lastMessage = ""; //the player's last chat message, or slash command complete with parameters + 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 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 boolean spamWarned = false; //whether the player recently received a warning @@ -106,16 +109,6 @@ public class PlayerData 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 public boolean inPvpCombat() { @@ -137,10 +130,10 @@ public class PlayerData //the number of claim blocks a player has available for claiming land public int getRemainingClaimBlocks() { - int remainingBlocks = this.accruedClaimBlocks + this.bonusClaimBlocks; - for(int i = 0; i < this.claims.size(); i++) + int remainingBlocks = this.getAccruedClaimBlocks() + this.getBonusClaimBlocks(); + for(int i = 0; i < this.getClaims().size(); i++) { - Claim claim = this.claims.get(i); + Claim claim = this.getClaims().get(i); remainingBlocks -= claim.getArea(); } @@ -149,4 +142,109 @@ public class PlayerData 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 getClaims() + { + if(this.claims == null) + { + this.claims = new Vector(); + + //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; + } + + } \ No newline at end of file diff --git a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java index 1b2c77f..bb7501e 100644 --- a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java +++ b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java @@ -24,6 +24,7 @@ import java.util.Date; import java.util.HashSet; import java.util.List; import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -416,6 +417,8 @@ class PlayerEventHandler implements Listener } } + private ConcurrentHashMap lastLoginThisServerSessionMap = new ConcurrentHashMap(); + //when a player attempts to join the server... @EventHandler(priority = EventPriority.HIGHEST) void onPlayerLogin (PlayerLoginEvent event) @@ -426,29 +429,32 @@ class PlayerEventHandler implements Listener if(GriefPrevention.instance.config_spam_enabled) { //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(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 - PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); - long millisecondsSinceLastLogin = (new Date()).getTime() - playerData.lastLogin.getTime(); - long secondsSinceLastLogin = millisecondsSinceLastLogin / 1000; - long cooldownRemaining = GriefPrevention.instance.config_spam_loginCooldownSeconds - secondsSinceLastLogin; - - //if cooldown remaining and player doesn't have permission to spam - if(cooldownRemaining > 0 && !player.hasPermission("griefprevention.spam")) + Date lastLoginThisSession = lastLoginThisServerSessionMap.get(player.getUniqueId()); + if(lastLoginThisSession != null) { - //DAS BOOT! - event.setResult(Result.KICK_OTHER); - event.setKickMessage("You must wait " + cooldownRemaining + " seconds before logging-in again."); - event.disallow(event.getResult(), event.getKickMessage()); - return; + long millisecondsSinceLastLogin = now - lastLoginThisSession.getTime(); + long secondsSinceLastLogin = millisecondsSinceLastLogin / 1000; + long cooldownRemaining = GriefPrevention.instance.config_spam_loginCooldownSeconds - secondsSinceLastLogin; + + //if cooldown remaining + if(cooldownRemaining > 0) + { + //DAS BOOT! + event.setResult(Result.KICK_OTHER); + event.setKickMessage("You must wait " + cooldownRemaining + " seconds before logging-in again."); + event.disallow(event.getResult(), event.getKickMessage()); + return; + } } } //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) { 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(); //note login time - long now = Calendar.getInstance().getTimeInMillis(); + Date nowDate = new Date(); + long now = nowDate.getTime(); PlayerData playerData = this.dataStore.getPlayerData(playerID); 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.hasPlayedBefore()) @@ -577,15 +585,33 @@ class PlayerEventHandler implements Listener 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... @EventHandler(priority = EventPriority.HIGHEST) void onPlayerQuit(PlayerQuitEvent event) { - Player player = event.getPlayer(); + Player player = event.getPlayer(); 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(player.isBanned() && playerData.ipAddress != null) + if(isBanned && playerData.ipAddress != null) { long now = Calendar.getInstance().getTimeInMillis(); 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 - if(player.isBanned()) + if(isBanned) { event.setQuitMessage(null); } //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); } @@ -619,7 +645,7 @@ class PlayerEventHandler implements Listener 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 - for(Claim claim : playerData.claims) + for(Claim claim : playerData.getClaims()) { claim.areExplosivesAllowed = false; } @@ -1311,7 +1337,7 @@ class PlayerEventHandler implements Listener claim = claim.parent; } PlayerData otherPlayerData = this.dataStore.getPlayerData(claim.ownerID); - Date lastLogin = otherPlayerData.lastLogin; + Date lastLogin = otherPlayerData.getLastLogin(); Date now = new Date(); long daysElapsed = (now.getTime() - lastLogin.getTime()) / (1000 * 60 * 60 * 24);