diff --git a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java index 38ead3b..e31a958 100644 --- a/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java +++ b/src/me/ryanhamshire/GriefPrevention/GriefPrevention.java @@ -157,6 +157,8 @@ public class GriefPrevention extends JavaPlugin public boolean config_creaturesTrampleCrops; //whether or not non-player entities may trample crops public boolean config_zombiesBreakDoors; //whether or not hard-mode zombies may break down wooden doors + public int config_ipLimit; //how many players can share an IP address + public MaterialCollection config_mods_accessTrustIds; //list of block IDs which should require /accesstrust for player interaction public MaterialCollection config_mods_containerTrustIds; //list of block IDs which should require /containertrust for player interaction public List config_mods_ignoreClaimsAccounts; //list of player names which ALWAYS ignore claims @@ -542,6 +544,7 @@ public class GriefPrevention extends JavaPlugin String whisperCommandsToMonitor = config.getString("GriefPrevention.WhisperCommands", "/tell;/pm;/r;/w;/whisper;/t;/msg"); this.config_smartBan = config.getBoolean("GriefPrevention.SmartBan", true); + this.config_ipLimit = config.getInt("GriefPrevention.MaxPlayersPerIpAddress", 5); this.config_endermenMoveBlocks = config.getBoolean("GriefPrevention.EndermenMoveBlocks", false); this.config_silverfishBreakBlocks = config.getBoolean("GriefPrevention.SilverfishBreakBlocks", false); @@ -770,6 +773,7 @@ public class GriefPrevention extends JavaPlugin outConfig.set("GriefPrevention.WhisperCommands", whisperCommandsToMonitor); outConfig.set("GriefPrevention.SmartBan", this.config_smartBan); + outConfig.set("GriefPrevention.MaxPlayersPerIpAddress", this.config_ipLimit); outConfig.set("GriefPrevention.Siege.Worlds", siegeEnabledWorldNames); outConfig.set("GriefPrevention.Siege.BreakableBlocks", breakableBlocksList); diff --git a/src/me/ryanhamshire/GriefPrevention/PlayerData.java b/src/me/ryanhamshire/GriefPrevention/PlayerData.java index 04972ad..52de0d6 100644 --- a/src/me/ryanhamshire/GriefPrevention/PlayerData.java +++ b/src/me/ryanhamshire/GriefPrevention/PlayerData.java @@ -293,7 +293,7 @@ public class PlayerData if(totalBlocks < totalClaimsArea) { OfflinePlayer player = GriefPrevention.instance.getServer().getOfflinePlayer(this.playerID); - GriefPrevention.AddLogEntry(player.getName() + "has more claimed land than blocks available. Adding blocks to fix.", CustomLogEntryTypes.Debug, true); + GriefPrevention.AddLogEntry(player.getName() + " has more claimed land than blocks available. Adding blocks to fix.", CustomLogEntryTypes.Debug, true); GriefPrevention.AddLogEntry("Total blocks: " + totalBlocks + " Total claimed area: " + totalClaimsArea, CustomLogEntryTypes.Debug, true); for(Claim claim : this.claims) { diff --git a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java index 7b9d43d..064f1ee 100644 --- a/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java +++ b/src/me/ryanhamshire/GriefPrevention/PlayerEventHandler.java @@ -17,6 +17,7 @@ */ package me.ryanhamshire.GriefPrevention; +import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; @@ -527,6 +528,9 @@ class PlayerEventHandler implements Listener } private ConcurrentHashMap lastLoginThisServerSessionMap = new ConcurrentHashMap(); + + //counts how many players are using each IP address connected to the server right now + private ConcurrentHashMap ipCountHash = new ConcurrentHashMap(); //when a player attempts to join the server... @EventHandler(priority = EventPriority.HIGHEST) @@ -570,9 +574,30 @@ class PlayerEventHandler implements Listener } } + //ensure we're not over the limit for this IP address + InetAddress ipAddress = event.getAddress(); + String ipAddressString = ipAddress.toString(); + int ipLimit = GriefPrevention.instance.config_ipLimit; + if(ipLimit > 0) + { + Integer ipCount = this.ipCountHash.get(ipAddressString); + if(ipCount == null) ipCount = 0; + if(ipCount >= ipLimit) + { + event.setResult(Result.KICK_OTHER); + event.setKickMessage("Sorry, there are too many players logged in with your IP address."); + event.disallow(event.getResult(), event.getKickMessage()); + return; + } + else + { + this.ipCountHash.put(ipAddressString, ipCount + 1); + } + } + //remember the player's ip address PlayerData playerData = this.dataStore.getPlayerData(player.getUniqueId()); - playerData.ipAddress = event.getAddress(); + playerData.ipAddress = ipAddress; } //when a player successfully joins the server... @@ -788,6 +813,19 @@ class PlayerEventHandler implements Listener //drop data about this player this.dataStore.clearCachedPlayerData(playerID); + + //reduce count of players with that player's IP address + if(GriefPrevention.instance.config_ipLimit > 0) + { + InetAddress ipAddress = playerData.ipAddress; + if(ipAddress != null) + { + String ipAddressString = ipAddress.toString(); + Integer count = this.ipCountHash.get(ipAddressString); + if(count == null) count = 1; + this.ipCountHash.put(ipAddressString, count - 1); + } + } } //determines whether or not a login or logout notification should be silenced, depending on how many there have been in the last minute