Source Code IP-Based Multibox Limit System

Unencrypted Source Code Resource

BettyBoop

New member
Rep
1
0
0
Rep
1
Vouches
0
0
0
Vouches
0
Posts
4
Likes
11
Bits
2 MONTHS
2 MONTHS OF SERVICE
LEVEL 5 40 XP
Hey everyone,

This time, I’ve post a Multibox Limiter that works based on player IP and ensures a fair gameplay environment, especially for PvP and economy stability.

🔧 What It Does:

This system limits the number of characters (boxes) a player can have open from the same IP address. Here are the key features:

✅ Configurable Limit:
The allowed number of boxes is set in players.properties via AllowedBoxes (default is 99, but you can easily change it).

✅ Smart Detection:
The system scans all active players and counts how many characters are logged in with the same IP.
  • If the number exceeds the allowed box count, the new login will be kicked with a warning message.
  • GMs are excluded from this check and can multibox freely.
✅ Live Syncing Across Boxes:
It keeps track of all active box character names per IP and syncs that info across all boxes, so players can see which of their characters are currently active.

✅ Auto-Update:
When a player logs out, the box count is automatically decreased and updated for the other boxes using the same IP.

🧠 Why Use It?​

Multiboxing can cause balance issues on many servers. This system helps maintain fairness, prevents abuse, and still allows flexibility for players with a reasonable limit. It’s especially useful for managing farm zones, events, or competitive areas.

Java:
diff --git a/aCis_gameserver/config/players.properties b/aCis_gameserver/config/players.properties
index c645204fe81e6eecd45227f2c741c7876c80b5ff..4714211bb7a75a6885e286c98fcb47771ed496d1 100644
--- a/aCis_gameserver/config/players.properties
+++ b/aCis_gameserver/config/players.properties
@@ -257,4 +257,12 @@ SubClassWithoutQuests = False
 MaxBuffsAmount = 20
 
 # Store buffs/debuffs on user logout. Default: True
-StoreSkillCooltime = True
\ No newline at end of file
+StoreSkillCooltime = True
+
+#=============================================================
+#                        Allowed Boxes Config
+#=============================================================
+
+#Default AllowedBoxes = 99
+# Max number of boxes per IP
+AllowedBoxes = 99
\ No newline at end of file
diff --git a/aCis_gameserver/java/net/sf/l2j/Config.java b/aCis_gameserver/java/net/sf/l2j/Config.java
index 9f5c32305e43c78c0760e014c5954fe42d088200..1ffc1d4a3200b44e7ead248f79d4e3f6cb674a40 100644
--- a/aCis_gameserver/java/net/sf/l2j/Config.java
+++ b/aCis_gameserver/java/net/sf/l2j/Config.java
@@ -349,6 +349,9 @@ public final class Config
    // Players
    // --------------------------------------------------
    
+   /** Allowed Boxes */
+   public static int ALLOWED_BOXES;
+   
    /** Misc */
    public static boolean EFFECT_CANCELING;
    public static double HP_REGEN_MULTIPLIER;
@@ -1109,6 +1112,8 @@ public final class Config
        MAX_BUFFS_AMOUNT = players.getProperty("MaxBuffsAmount", 20);
        STORE_SKILL_COOLTIME = players.getProperty("StoreSkillCooltime", true);
        
+       ALLOWED_BOXES = players.getProperty("AllowedBoxes", 99);
+       
    }
    
    /**
diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/Player.java b/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/Player.java
index f1491313b2102b39c9c121afc03cd5d676edd3dd..e6828650e46e96a534ed2722bef61e91cab19396 100644
--- a/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/Player.java
+++ b/aCis_gameserver/java/net/sf/l2j/gameserver/model/actor/Player.java
@@ -263,6 +263,8 @@ public final class Player extends Playable
    private static final Comparator<GeneralSkillNode> COMPARE_SKILLS_BY_LVL = Comparator.comparing(GeneralSkillNode::getValue);
    
    private GameClient _client;
+   public int _activeBoxes = -1;
+   public List<String> _activeBoxCharacters = new ArrayList<>();
    private final Map<Integer, String> _chars = new HashMap<>();
    
    private final String _accountName;
@@ -5628,6 +5630,84 @@ public final class Player extends Playable
    {
        _isInOlympiadMode = b;
    }
+   
+   /**
+    * Check if local player can make multibox and also refresh local boxes instances number.
+    * @return true, if successful
+    */
+   public boolean canMultiBox()
+   {
+       if (isGM())
+           return true;
+       
+       boolean canMultiBox = true;
+       int boxCount = 1;
+       final List<String> activeBoxes = new ArrayList<>();
+       if ((_client != null) && (getIPAddress() != null) && !_client.isDetached())
+       {
+           final String playerIP = getIPAddress();
+           for (Player player : World.getInstance().getPlayers())
+           {
+               if ((player != null) && (player != this) && player.isOnline() && (player.getClient() != null) && (player.getIPAddress() != null) && !player.getClient().isDetached() && playerIP.equals(player.getIPAddress()))
+               {
+                   // Ignore GMs when counting boxes
+                   if (player.isGM())
+                       continue;
+                   
+                   boxCount++;
+                   activeBoxes.add(player.getName());
+                   
+                   if (boxCount > Config.ALLOWED_BOXES)
+                   {
+                       canMultiBox = false;
+                       break;
+                   }
+               }
+           }
+       }
+       
+       if (canMultiBox)
+       {
+           _activeBoxes = boxCount;
+           if (!activeBoxes.contains(getName()))
+           {
+               activeBoxes.add(getName());
+               _activeBoxCharacters = activeBoxes;
+           }
+           refreshOtherBoxes();
+       }
+       
+       return canMultiBox;
+   }
+   
+   /**
+    * Increase active boxes number for local player and other boxer for same IP.
+    */
+   public void refreshOtherBoxes()
+   {
+       if ((_client != null) && (getIPAddress() != null) && !_client.isDetached())
+       {
+           final String playerIP = getIPAddress();
+           for (Player player : World.getInstance().getPlayers())
+           {
+               if ((player != null) && (player != this) && player.isOnline() && (player.getClient() != null) && (player.getIPAddress() != null) && !player.getClient().isDetached() && !player.getName().equals(getName()) && playerIP.equals(player.getIPAddress()))
+               {
+                   player._activeBoxes = _activeBoxes;
+                   player._activeBoxCharacters = _activeBoxCharacters;
+               }
+           }
+       }
+   }
+   
+   /**
+    * Decrease active boxes number for local player and other boxer for same IP.
+    */
+   public void decreaseBoxes()
+   {
+       _activeBoxes = _activeBoxes - 1;
+       _activeBoxCharacters.remove(getName());
+       refreshOtherBoxes();
+   }
        
    public boolean isInDuel()
    {
@@ -7414,6 +7494,17 @@ public final class Player extends Playable
        return gms;
    }
    
+   public String getIPAddress()
+   {
+       try
+       {
+           return getClient().getConnection().getInetAddress().getHostAddress().intern();
+       }
+       catch(final Exception e)
+       {
+           return null;
+       }
+   }
    
    public boolean isClanMemberWithClanHallorCastle()
    {
diff --git a/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java b/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java
index 6226e61ba95a91859cb2ad87e1c456b2e61b7ca3..bcf553d7b3a425e3012ce5c053584f7d74efd938 100644
--- a/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java
+++ b/aCis_gameserver/java/net/sf/l2j/gameserver/network/clientpackets/EnterWorld.java
@@ -104,6 +104,14 @@ public class EnterWorld extends L2GameClientPacket
        player.sendPacket(new HennaInfo(player));
        player.updateEffectIcons();
        player.sendPacket(new EtcStatusUpdate(player));
+       
+       // Means that it's not ok multiBox situation, so logout.
+       if (!player.canMultiBox())
+       {
+           player.sendMessage("I'm sorry, but you have reached the total number of boxes.");
+           player.logout(true);
+           return;
+       }
                    
        // Clan checks.
        final Clan clan = player.getClan();

P.S. For some, it may be useful. For others... it may be completely useless. I just leave it here in case someone finds it helpful. If not, no worries.
 
Last edited by a moderator:
Liked By 3 members :

splicho

Emudevs Founder
Administrator
splicho Rep
6
0
0
Rep
6
splicho Vouches
3
0
0
Vouches
3
Posts
1,003
Likes
1,435
Bits
2 YEARS
2 YEARS OF SERVICE
LEVEL 250 75 XP
Thanks for sharing! I went ahead and wrapped the code in a code block so it's preserved here even if the Pastebin link goes down :)
 

3,399

1,272

9,557

428

Top