diff --git a/trunk/dist/game/config/AdminCommands.xml b/trunk/dist/game/config/AdminCommands.xml
index 7328fbcc4d..2f6757243b 100644
--- a/trunk/dist/game/config/AdminCommands.xml
+++ b/trunk/dist/game/config/AdminCommands.xml
@@ -322,6 +322,10 @@
+
+
+
+
diff --git a/trunk/dist/game/config/Server.ini b/trunk/dist/game/config/Server.ini
index a81a51646e..2603491df8 100644
--- a/trunk/dist/game/config/Server.ini
+++ b/trunk/dist/game/config/Server.ini
@@ -78,7 +78,7 @@ AcceptAlternateID = True
# Datapack root directory.
# Defaults to current directory from which the server is started unless the below line is uncommented.
# WARNING: If the specified path is invalid, it will lead to multiple errors!
-#Default: .
+# Default: .
DatapackRoot = .
# Define how many players are allowed to play simultaneously on your server.
@@ -109,6 +109,21 @@ ServerListAge = 0
ServerListBrackets = False
+# ---------------------------------------------------------------------------
+# Player HWID settings (DO NOT USE)
+# ---------------------------------------------------------------------------
+
+# Check if hardware information is sent upon login.
+# Players without hardware information are kicked from the game.
+# To receive hardware information from client, l2.ini NetSendHardWare must be set to true.
+# Default: False
+EnableHardwareInfo = False
+
+# Maximum number of players per HWID allowed to enter game.
+# Default: 0 (unlimited)
+MaxPlayersPerHWID = 0
+
+
# ---------------------------------------------------------------------------
# Misc Player Settings
# ---------------------------------------------------------------------------
diff --git a/trunk/dist/game/data/html/admin/charhwinfo.htm b/trunk/dist/game/data/html/admin/charhwinfo.htm
new file mode 100644
index 0000000000..d65175b253
--- /dev/null
+++ b/trunk/dist/game/data/html/admin/charhwinfo.htm
@@ -0,0 +1,25 @@
+
Hardware Information: %name%
+
+
+
+
+
Hardware (%name%)
+
+
+
+
+
+
MAC Address:
%macAddress%
+
CPU:
%cpuName%
+
CPU Speed:
%cpuSpeed%
+
CPU Core Count:
%cpuCoreCount%
+
VGA:
%vgaName%
+
VGA Version:
%vgaVersion%
+
VGA Driver Version:
%vgaDriverVersion%
+
Windows Platform Id:
%windowsPlatformId%
+
Windows Major Version:
%windowsMajorVersion%
+
Windows Minor Version:
%windowsMinorVersion%
+
Windows Build:
%windowsBuildNumber%
+
+
+
\ No newline at end of file
diff --git a/trunk/dist/game/data/html/admin/charinfo.htm b/trunk/dist/game/data/html/admin/charinfo.htm
index 411587c858..7a0fc8829e 100644
--- a/trunk/dist/game/data/html/admin/charinfo.htm
+++ b/trunk/dist/game/data/html/admin/charinfo.htm
@@ -35,6 +35,9 @@
" : "");
adminReply.replace("%noblesse%", player.isNoble() ? "Yes" : "No");
diff --git a/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminHwid.java b/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminHwid.java
new file mode 100644
index 0000000000..a2f7af5523
--- /dev/null
+++ b/trunk/dist/game/data/scripts/handlers/admincommandhandlers/AdminHwid.java
@@ -0,0 +1,66 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package handlers.admincommandhandlers;
+
+import com.l2jmobius.gameserver.cache.HtmCache;
+import com.l2jmobius.gameserver.handler.IAdminCommandHandler;
+import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
+import com.l2jmobius.gameserver.network.serverpackets.NpcHtmlMessage;
+
+/**
+ * @author Mobius
+ */
+public class AdminHwid implements IAdminCommandHandler
+{
+ private static final String[] ADMIN_COMMANDS =
+ {
+ "admin_hwid",
+ "admin_hwinfo"
+ };
+
+ @Override
+ public boolean useAdminCommand(String command, L2PcInstance activeChar)
+ {
+ if ((activeChar.getTarget() == null) || !activeChar.getTarget().isPlayer() || (activeChar.getTarget().getActingPlayer().getClient() == null) || (activeChar.getTarget().getActingPlayer().getClient().getHardwareInfo() == null))
+ {
+ return true;
+ }
+ final L2PcInstance target = activeChar.getTarget().getActingPlayer();
+ final NpcHtmlMessage html = new NpcHtmlMessage(0, 1);
+ html.setHtml(HtmCache.getInstance().getHtm(activeChar.getHtmlPrefix(), "data/html/admin/charhwinfo.htm"));
+ html.replace("%name%", target.getName());
+ html.replace("%macAddress%", target.getClient().getHardwareInfo().getMacAddress());
+ html.replace("%windowsPlatformId%", target.getClient().getHardwareInfo().getWindowsPlatformId());
+ html.replace("%windowsMajorVersion%", target.getClient().getHardwareInfo().getWindowsMajorVersion());
+ html.replace("%windowsMinorVersion%", target.getClient().getHardwareInfo().getWindowsMinorVersion());
+ html.replace("%windowsBuildNumber%", target.getClient().getHardwareInfo().getWindowsBuildNumber());
+ html.replace("%cpuName%", target.getClient().getHardwareInfo().getCpuName());
+ html.replace("%cpuSpeed%", target.getClient().getHardwareInfo().getCpuSpeed());
+ html.replace("%cpuCoreCount%", target.getClient().getHardwareInfo().getCpuCoreCount());
+ html.replace("%vgaVersion%", target.getClient().getHardwareInfo().getVgaVersion());
+ html.replace("%vgaName%", target.getClient().getHardwareInfo().getVgaName());
+ html.replace("%vgaDriverVersion%", target.getClient().getHardwareInfo().getVgaDriverVersion());
+ activeChar.sendPacket(html);
+ return true;
+ }
+
+ @Override
+ public String[] getAdminCommandList()
+ {
+ return ADMIN_COMMANDS;
+ }
+}
\ No newline at end of file
diff --git a/trunk/java/com/l2jmobius/Config.java b/trunk/java/com/l2jmobius/Config.java
index b6663c5ffd..0e0325b263 100644
--- a/trunk/java/com/l2jmobius/Config.java
+++ b/trunk/java/com/l2jmobius/Config.java
@@ -850,6 +850,8 @@ public final class Config
public static int DATABASE_MAX_CONNECTIONS;
public static int DATABASE_MAX_IDLE_TIME;
public static int MAXIMUM_ONLINE_USERS;
+ public static boolean HARDWARE_INFO_ENABLED;
+ public static int MAX_PLAYERS_PER_HWID;
public static Pattern CHARNAME_TEMPLATE_PATTERN;
public static String PET_NAME_TEMPLATE;
public static String CLAN_NAME_TEMPLATE;
@@ -1110,6 +1112,9 @@ public final class Config
MAX_CHARACTERS_NUMBER_PER_ACCOUNT = serverSettings.getInt("CharMaxNumber", 7);
MAXIMUM_ONLINE_USERS = serverSettings.getInt("MaximumOnlineUsers", 100);
+ HARDWARE_INFO_ENABLED = serverSettings.getBoolean("EnableHardwareInfo", false);
+ MAX_PLAYERS_PER_HWID = serverSettings.getInt("MaxPlayersPerHWID", 0);
+
final String[] protocols = serverSettings.getString("AllowedProtocolRevisions", "603;606;607").split(";");
PROTOCOL_LIST = new ArrayList<>(protocols.length);
for (String protocol : protocols)
diff --git a/trunk/java/com/l2jmobius/gameserver/model/holders/ClientHardwareInfoHolder.java b/trunk/java/com/l2jmobius/gameserver/model/holders/ClientHardwareInfoHolder.java
new file mode 100644
index 0000000000..16288d7d4f
--- /dev/null
+++ b/trunk/java/com/l2jmobius/gameserver/model/holders/ClientHardwareInfoHolder.java
@@ -0,0 +1,218 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.model.holders;
+
+/**
+ * @author Mobius
+ */
+public class ClientHardwareInfoHolder
+{
+ private final String _macAddress;
+ private final int _windowsPlatformId;
+ private final int _windowsMajorVersion;
+ private final int _windowsMinorVersion;
+ private final int _windowsBuildNumber;
+ private final int _directxVersion;
+ private final int _directxRevision;
+ private final String _cpuName;
+ private final int _cpuSpeed;
+ private final int _cpuCoreCount;
+ private final int _vgaCount;
+ private final int _vgaPcxSpeed;
+ private final int _physMemorySlot1;
+ private final int _physMemorySlot2;
+ private final int _physMemorySlot3;
+ private final int _videoMemory;
+ private final int _vgaVersion;
+ private final String _vgaName;
+ private final String _vgaDriverVersion;
+
+ public ClientHardwareInfoHolder(String macAddress, int windowsPlatformId, int windowsMajorVersion, int windowsMinorVersion, int windowsBuildNumber, int directxVersion, int directxRevision, String cpuName, int cpuSpeed, int cpuCoreCount, int vgaCount, int vgaPcxSpeed, int physMemorySlot1, int physMemorySlot2, int physMemorySlot3, int videoMemory, int vgaVersion, String vgaName, String vgaDriverVersion)
+ {
+ _macAddress = macAddress;
+ _windowsPlatformId = windowsPlatformId;
+ _windowsMajorVersion = windowsMajorVersion;
+ _windowsMinorVersion = windowsMinorVersion;
+ _windowsBuildNumber = windowsBuildNumber;
+ _directxVersion = directxVersion;
+ _directxRevision = directxRevision;
+ _cpuName = cpuName;
+ _cpuSpeed = cpuSpeed;
+ _cpuCoreCount = cpuCoreCount;
+ _vgaCount = vgaCount;
+ _vgaPcxSpeed = vgaPcxSpeed;
+ _physMemorySlot1 = physMemorySlot1;
+ _physMemorySlot2 = physMemorySlot2;
+ _physMemorySlot3 = physMemorySlot3;
+ _videoMemory = videoMemory;
+ _vgaVersion = vgaVersion;
+ _vgaName = vgaName;
+ _vgaDriverVersion = vgaDriverVersion;
+ }
+
+ /**
+ * @return the macAddress
+ */
+ public String getMacAddress()
+ {
+ return _macAddress;
+ }
+
+ /**
+ * @return the windowsPlatformId
+ */
+ public int getWindowsPlatformId()
+ {
+ return _windowsPlatformId;
+ }
+
+ /**
+ * @return the windowsMajorVersion
+ */
+ public int getWindowsMajorVersion()
+ {
+ return _windowsMajorVersion;
+ }
+
+ /**
+ * @return the windowsMinorVersion
+ */
+ public int getWindowsMinorVersion()
+ {
+ return _windowsMinorVersion;
+ }
+
+ /**
+ * @return the windowsBuildNumber
+ */
+ public int getWindowsBuildNumber()
+ {
+ return _windowsBuildNumber;
+ }
+
+ /**
+ * @return the directxVersion
+ */
+ public int getDirectxVersion()
+ {
+ return _directxVersion;
+ }
+
+ /**
+ * @return the directxRevision
+ */
+ public int getDirectxRevision()
+ {
+ return _directxRevision;
+ }
+
+ /**
+ * @return the cpuName
+ */
+ public String getCpuName()
+ {
+ return _cpuName;
+ }
+
+ /**
+ * @return the cpuSpeed
+ */
+ public int getCpuSpeed()
+ {
+ return _cpuSpeed;
+ }
+
+ /**
+ * @return the cpuCoreCount
+ */
+ public int getCpuCoreCount()
+ {
+ return _cpuCoreCount;
+ }
+
+ /**
+ * @return the vgaCount
+ */
+ public int getVgaCount()
+ {
+ return _vgaCount;
+ }
+
+ /**
+ * @return the vgaPcxSpeed
+ */
+ public int getVgaPcxSpeed()
+ {
+ return _vgaPcxSpeed;
+ }
+
+ /**
+ * @return the physMemorySlot1
+ */
+ public int getPhysMemorySlot1()
+ {
+ return _physMemorySlot1;
+ }
+
+ /**
+ * @return the physMemorySlot2
+ */
+ public int getPhysMemorySlot2()
+ {
+ return _physMemorySlot2;
+ }
+
+ /**
+ * @return the physMemorySlot3
+ */
+ public int getPhysMemorySlot3()
+ {
+ return _physMemorySlot3;
+ }
+
+ /**
+ * @return the videoMemory
+ */
+ public int getVideoMemory()
+ {
+ return _videoMemory;
+ }
+
+ /**
+ * @return the vgaVersion
+ */
+ public int getVgaVersion()
+ {
+ return _vgaVersion;
+ }
+
+ /**
+ * @return the vgaName
+ */
+ public String getVgaName()
+ {
+ return _vgaName;
+ }
+
+ /**
+ * @return the vgaDriverVersion
+ */
+ public String getVgaDriverVersion()
+ {
+ return _vgaDriverVersion;
+ }
+}
\ No newline at end of file
diff --git a/trunk/java/com/l2jmobius/gameserver/network/client/ExIncomingPackets.java b/trunk/java/com/l2jmobius/gameserver/network/client/ExIncomingPackets.java
index 47dd70bffb..67bec079ca 100644
--- a/trunk/java/com/l2jmobius/gameserver/network/client/ExIncomingPackets.java
+++ b/trunk/java/com/l2jmobius/gameserver/network/client/ExIncomingPackets.java
@@ -261,7 +261,7 @@ public enum ExIncomingPackets implements IIncomingPackets
REQUEST_GOODS_INVENTORY_ITEM(0xAB, null, ConnectionState.IN_GAME),
REQUEST_FIRST_PLAY_START(0xAC, null, ConnectionState.IN_GAME),
REQUEST_FLY_MOVE_START(0xAD, RequestFlyMoveStart::new, ConnectionState.IN_GAME),
- REQUEST_HARDWARE_INFO(0xAE, null, ConnectionState.IN_GAME),
+ REQUEST_HARDWARE_INFO(0xAE, RequestHardWareInfo::new, ConnectionState.IN_GAME),
SEND_CHANGE_ATTRIBUTE_TARGET_ITEM(0xB0, null, ConnectionState.IN_GAME),
REQUEST_CHANGE_ATTRIBUTE_ITEM(0xB1, null, ConnectionState.IN_GAME),
REQUEST_CHANGE_ATTRIBUTE_CANCEL(0xB2, null, ConnectionState.IN_GAME),
diff --git a/trunk/java/com/l2jmobius/gameserver/network/client/L2GameClient.java b/trunk/java/com/l2jmobius/gameserver/network/client/L2GameClient.java
index 72afe093f9..192a9d63cc 100644
--- a/trunk/java/com/l2jmobius/gameserver/network/client/L2GameClient.java
+++ b/trunk/java/com/l2jmobius/gameserver/network/client/L2GameClient.java
@@ -53,6 +53,7 @@ import com.l2jmobius.gameserver.model.L2World;
import com.l2jmobius.gameserver.model.actor.L2Summon;
import com.l2jmobius.gameserver.model.actor.instance.L2PcInstance;
import com.l2jmobius.gameserver.model.entity.L2Event;
+import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder;
import com.l2jmobius.gameserver.model.olympiad.OlympiadManager;
import com.l2jmobius.gameserver.model.zone.ZoneId;
import com.l2jmobius.gameserver.network.SystemMessageId;
@@ -86,7 +87,7 @@ public final class L2GameClient extends ChannelInboundHandler
private L2PcInstance _activeChar;
private final ReentrantLock _activeCharLock = new ReentrantLock();
private SecondaryPasswordAuth _secondaryAuth;
-
+ private ClientHardwareInfoHolder _hardwareInfo;
private boolean _isAuthedGG;
private final long _connectionStartTime = System.currentTimeMillis();
private CharSelectInfoPackage[] _charSlotMapping = null;
@@ -941,4 +942,20 @@ public final class L2GameClient extends ChannelInboundHandler
{
return _crypt;
}
+
+ /**
+ * @return the hardwareInfo
+ */
+ public ClientHardwareInfoHolder getHardwareInfo()
+ {
+ return _hardwareInfo;
+ }
+
+ /**
+ * @param hardwareInfo
+ */
+ public void setHardwareInfo(ClientHardwareInfoHolder hardwareInfo)
+ {
+ _hardwareInfo = hardwareInfo;
+ }
}
diff --git a/trunk/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java b/trunk/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
index 6d07f6d269..49ad61fbbb 100644
--- a/trunk/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
+++ b/trunk/java/com/l2jmobius/gameserver/network/clientpackets/EnterWorld.java
@@ -94,6 +94,7 @@ import com.l2jmobius.gameserver.network.serverpackets.PledgeShowMemberListAll;
import com.l2jmobius.gameserver.network.serverpackets.PledgeShowMemberListUpdate;
import com.l2jmobius.gameserver.network.serverpackets.PledgeSkillList;
import com.l2jmobius.gameserver.network.serverpackets.QuestList;
+import com.l2jmobius.gameserver.network.serverpackets.ServerClose;
import com.l2jmobius.gameserver.network.serverpackets.ShortCutInit;
import com.l2jmobius.gameserver.network.serverpackets.SkillCoolTime;
import com.l2jmobius.gameserver.network.serverpackets.SkillList;
@@ -138,6 +139,32 @@ public class EnterWorld implements IClientIncomingPacket
@Override
public void run(L2GameClient client)
{
+ // HWID
+ if (Config.HARDWARE_INFO_ENABLED)
+ {
+ if (client.getHardwareInfo() == null)
+ {
+ client.close(ServerClose.STATIC_PACKET);
+ return;
+ }
+ if (Config.MAX_PLAYERS_PER_HWID > 0)
+ {
+ int count = 0;
+ for (L2PcInstance player : L2World.getInstance().getPlayers())
+ {
+ if ((player.isOnlineInt() == 1) && (player.getClient().getHardwareInfo().equals(client.getHardwareInfo())))
+ {
+ count++;
+ }
+ }
+ if (count >= Config.MAX_PLAYERS_PER_HWID)
+ {
+ client.close(ServerClose.STATIC_PACKET);
+ return;
+ }
+ }
+ }
+
final L2PcInstance activeChar = client.getActiveChar();
if (activeChar == null)
{
diff --git a/trunk/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java b/trunk/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java
new file mode 100644
index 0000000000..17448bbe52
--- /dev/null
+++ b/trunk/java/com/l2jmobius/gameserver/network/clientpackets/RequestHardWareInfo.java
@@ -0,0 +1,85 @@
+/*
+ * This file is part of the L2J Mobius project.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+package com.l2jmobius.gameserver.network.clientpackets;
+
+import com.l2jmobius.commons.network.PacketReader;
+import com.l2jmobius.gameserver.model.holders.ClientHardwareInfoHolder;
+import com.l2jmobius.gameserver.network.client.L2GameClient;
+
+/**
+ * @author Mobius
+ */
+public final class RequestHardWareInfo implements IClientIncomingPacket
+{
+ private String _macAddress;
+ private int _windowsPlatformId;
+ private int _windowsMajorVersion;
+ private int _windowsMinorVersion;
+ private int _windowsBuildNumber;
+ private int _directxVersion;
+ private int _directxRevision;
+ private String _cpuName;
+ private int _cpuSpeed;
+ private int _cpuCoreCount;
+ private int _vgaCount;
+ private int _vgaPcxSpeed;
+ private int _physMemorySlot1;
+ private int _physMemorySlot2;
+ private int _physMemorySlot3;
+ private int _videoMemory;
+ private int _vgaVersion;
+ private String _vgaName;
+ private String _vgaDriverVersion;
+
+ @Override
+ public boolean read(L2GameClient client, PacketReader packet)
+ {
+ _macAddress = packet.readS();
+ _windowsPlatformId = packet.readD();
+ _windowsMajorVersion = packet.readD();
+ _windowsMinorVersion = packet.readD();
+ _windowsBuildNumber = packet.readD();
+ _directxVersion = packet.readD();
+ _directxRevision = packet.readD();
+ for (int i = 0; i < 16; i++)
+ {
+ packet.readC();
+ }
+ _cpuName = packet.readS();
+ _cpuSpeed = packet.readD();
+ _cpuCoreCount = packet.readC();
+ packet.readD();
+ _vgaCount = packet.readD();
+ _vgaPcxSpeed = packet.readD();
+ _physMemorySlot1 = packet.readD();
+ _physMemorySlot2 = packet.readD();
+ _physMemorySlot3 = packet.readD();
+ packet.readC();
+ _videoMemory = packet.readD();
+ packet.readD();
+ _vgaVersion = packet.readD();
+ _vgaName = packet.readS();
+ _vgaDriverVersion = packet.readS();
+ return true;
+ }
+
+ @Override
+ public void run(L2GameClient client)
+ {
+ client.setHardwareInfo(new ClientHardwareInfoHolder(_macAddress, _windowsPlatformId, _windowsMajorVersion, _windowsMinorVersion, _windowsBuildNumber, _directxVersion, _directxRevision, _cpuName, _cpuSpeed, _cpuCoreCount, _vgaCount, _vgaPcxSpeed, _physMemorySlot1, _physMemorySlot2, _physMemorySlot3, _videoMemory, _vgaVersion, _vgaName, _vgaDriverVersion));
+ }
+}