Overview
The network layer handles all client connections, packet processing, and network I/O for the game server. It uses asynchronous NIO for high-performance connection management.
ConnectionManager
Manages network connections for game clients using asynchronous socket channels.
Package: org.l2jmobius.commons.network
Location: ConnectionManager.java:48
Class Signature
public class ConnectionManager<T extends Client<Connection<T>>>
The client type associated with this connection manager
Constructor
public ConnectionManager(
InetSocketAddress address,
Function<Connection<T>, T> clientFactory,
PacketHandler<T> packetHandler
) throws IOException
Initializes the connection manager with the specified configuration.
address
InetSocketAddress
required
The network address and port to bind the server socket
clientFactory
Function<Connection<T>, T>
required
Factory function to create client instances (typically GameClient::new)
The handler for processing incoming packets
Throws: IOException - if an I/O error occurs when opening the socket channel
Implementation Details
The ConnectionManager uses:
- AsynchronousChannelGroup - Custom thread pool for async I/O operations
- AsynchronousServerSocketChannel - Non-blocking server socket
- IP Protection - Connection rate limiting per IP address
- TCP Configuration - Configurable Nagle’s algorithm support
Thread Pool Configuration
_group = AsynchronousChannelGroup.withCachedThreadPool(
new ThreadPoolExecutor(
_config.threadPoolSize,
Integer.MAX_VALUE,
1, TimeUnit.MINUTES,
new SynchronousQueue<>(),
new MMOThreadFactory("Server", _config.threadPriority)
),
0
);
Socket Configuration
_socketChannel = _group.provider().openAsynchronousServerSocketChannel(_group);
_socketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
_socketChannel.bind(_config.address);
Methods
shutdown()
Shuts down the connection manager gracefully, closing all connections and releasing resources.
Shutdown sequence:
- Closes the server socket channel
- Initiates thread pool shutdown
- Waits for shutdown completion (configured timeout)
- Forces immediate shutdown if timeout exceeded
getIpProtector()
public IPProtector getIpProtector()
The IP protection instance managing connection rate limits
Connection Acceptance Flow
When a client connects:
Accept Connection
Server socket accepts the incoming connection asynchronously
Configure Socket
Sets TCP_NODELAY option based on Nagle’s algorithm configurationchannel.setOption(StandardSocketOptions.TCP_NODELAY, !_config.useNagle);
IP Protection Check
Validates that the connecting IP hasn’t exceeded connection limitsfinal String ip = remoteAddress.getAddress().getHostAddress();
if (!_ipProtector.canConnect(ip))
{
channel.close();
return;
}
Create Connection
Creates a Connection object wrapping the socket channel
Create Client
Uses the factory to create a GameClient instancefinal T client = _clientFactory.apply(connection);
Start Reading
Notifies client of connection and begins reading packetsclient.onConnected();
client.read();
Usage Example
// In GameServer.java:426
new ConnectionManager<>(
new InetSocketAddress(ServerConfig.PORT_GAME),
GameClient::new,
new GamePacketHandler()
);
GameClient
Represents a client connected to the game server, managing the connection state, encryption, and associated player.
Package: org.l2jmobius.gameserver.network
Location: GameClient.java:52
Class Signature
public class GameClient extends Client<org.l2jmobius.commons.network.Connection<GameClient>>
Constructor
public GameClient(org.l2jmobius.commons.network.Connection<GameClient> connection)
connection
Connection<GameClient>
required
The underlying network connection
Key Fields
private ConnectionState _connectionState = ConnectionState.CONNECTED;
private Encryption _encryption = null;
private String _ip = "N/A";
private String _accountName;
private SessionKey _sessionKey;
private Player _player;
private ClientHardwareInfoHolder _hardwareInfo;
private final FloodProtectors _floodProtectors = new FloodProtectors(this);
private final ReentrantLock _playerLock = new ReentrantLock();
Connection States
Clients progress through these states:
- CONNECTED - Socket connected, awaiting protocol version
- AUTHENTICATED - Session validated with login server
- ENTERING - Character selected, loading into world
- IN_GAME - Fully loaded and playing
- DISCONNECTED - Connection closed
Core Methods
Lifecycle Methods
onConnected()
@Override
public void onConnected()
Called when the network connection is established. Logs the connection.
onDisconnection()
@Override
public void onDisconnection()
Called when the connection is closed. Handles cleanup:
- Notifies login server of logout
- Triggers disconnection handlers
- Updates connection state
Encryption Methods
enableCrypt()
public byte[] enableCrypt()
Enables packet encryption and returns the encryption key.
The 8-byte encryption key used for packet encryption
Encryption Key:
private static final byte[] CRYPT_KEY =
{
(byte) 0x94, (byte) 0x35, (byte) 0x00, (byte) 0x00,
(byte) 0xa1, (byte) 0x6c, (byte) 0x54, (byte) 0x87
};
encrypt() / decrypt()
@Override
public boolean encrypt(Buffer data, int offset, int size)
@Override
public boolean decrypt(Buffer data, int offset, int size)
Encrypt/decrypt packet data using the Blowfish-based encryption.
The buffer containing packet data
Starting offset in the buffer
Number of bytes to encrypt/decrypt
Packet Methods
sendPacket()
public void sendPacket(ServerPacket packet)
public void sendPacket(SystemMessageId systemMessageId)
Sends a packet to the client.
The server packet to send
Implementation:
public void sendPacket(ServerPacket packet)
{
if (packet == null)
{
LOGGER.warning(TraceUtil.getStackTrace(new Exception()));
return;
}
writePacket(packet);
packet.runImpl(_player);
}
close()
public void close(ServerPacket packet)
public void closeNow()
Closes the client connection, optionally sending a final packet.
Optional packet to send before closing (e.g., disconnect message)
Player Management
getPlayer() / setPlayer()
public Player getPlayer()
public void setPlayer(Player player)
Gets or sets the active player character associated with this client.
load()
public Player load(int characterSlot)
Loads a character from the database for the specified character slot.
The character slot index (0-based)
The loaded player instance, or null if loading failed
Location: GameClient.java:495
Loading sequence:
- Validates character slot and retrieves object ID
- Checks for duplicate login attempts
- Loads character data from database
- Sets default states (running, standing)
- Refreshes overload and expertise penalties
Character Management
markToDeleteChar()
public byte markToDeleteChar(int characterSlot)
Marks a character for deletion or deletes it immediately based on configuration.
The character slot to delete
-1: Error occurred
0: Character deleted or marked for deletion
1: Character is clan member (cannot delete)
2: Character is clan leader (cannot delete)
Location: GameClient.java:254
restore()
public void restore(int characterSlot)
Restores a character that was marked for deletion.
The character slot to restore
Session Management
setAccountName() / getAccountName()
public void setAccountName(String accountName)
public String getAccountName()
Manages the account name for this connection.
setSessionId() / getSessionId()
public void setSessionId(SessionKey sessionKey)
public SessionKey getSessionId()
Manages the session key used for authentication with the login server.
Protection & Security
getFloodProtectors()
public FloodProtectors getFloodProtectors()
The flood protection manager for this client
Provides access to various flood protection mechanisms (chat, actions, packets).
getPlayerLock()
public ReentrantLock getPlayerLock()
A reentrant lock for thread-safe player operations
GamePacketHandler
Handles incoming packets from game clients by interpreting packet IDs and creating appropriate packet instances.
Package: org.l2jmobius.gameserver.network
Location: GamePacketHandler.java:33
Class Signature
public class GamePacketHandler implements PacketHandler<GameClient>
Methods
handlePacket()
@Override
public ReadablePacket<GameClient> handlePacket(ReadableBuffer buffer, GameClient client)
Converts raw buffer data into a typed packet instance.
The buffer containing the packet data
The client that sent the packet
returns
ReadablePacket<GameClient>
The created packet instance, or null if invalid
Packet Processing Flow
Read Packet ID
Extracts the first byte as the packet IDfinal int packetId = Byte.toUnsignedInt(buffer.readByte());
Check for Extended Packet
If packet ID is 0xD0, reads additional 2 bytes for extended packet IDcase 0xD0: // Ex client packet
final int exPacketId = Short.toUnsignedInt(buffer.readShort());
Validate Packet ID
Ensures the packet ID is within valid rangeif ((packetId < 0) || (packetId >= ClientPackets.PACKET_ARRAY.length))
return null;
Find Packet Enum
Looks up the packet enum from the packet arrayfinal ClientPackets packetEnum = ClientPackets.PACKET_ARRAY[packetId];
Validate Connection State
Checks if the packet is allowed in the client’s current stateif (!packetEnum.getConnectionStates().contains(client.getConnectionState()))
return null;
Create Packet Instance
Instantiates the packet using the enum’s factory methodreturn packetEnum.newPacket();
Packet Types
Normal Packets: Single-byte packet ID (0x00 - 0xFF, excluding 0xD0)
Extended Packets: Three-byte header (0xD0 + 2-byte extended ID)
PacketHandler Interface
Functional interface for packet handling implementations.
Package: org.l2jmobius.commons.network
Location: PacketHandler.java:28
Interface Signature
@FunctionalInterface
public interface PacketHandler<T extends Client<Connection<T>>>
Method
ReadablePacket<T> handlePacket(ReadableBuffer buffer, T client);
Converts raw buffer data into a readable packet.
The buffer containing the data to be converted
The client who sent the data
A packet instance corresponding to the received data
Usage Examples
Creating a Network Connection Manager
// Start the game server network listener
ConnectionManager<GameClient> connectionManager = new ConnectionManager<>(
new InetSocketAddress("0.0.0.0", 7777), // Bind to all interfaces on port 7777
GameClient::new, // Client factory
new GamePacketHandler() // Packet handler
);
Sending Packets to a Client
GameClient client = ...; // Obtain client reference
// Send a system message
client.sendPacket(SystemMessageId.WELCOME_TO_LINEAGE);
// Send a custom server packet
ServerPacket packet = new CreatureSay(...);
client.sendPacket(packet);
Handling Client Disconnection
// Graceful disconnect with final packet
client.close(new LeaveWorld());
// Immediate disconnect
client.closeNow();
Loading a Character
GameClient client = ...;
int characterSlot = 0; // First character slot
Player player = client.load(characterSlot);
if (player != null)
{
client.setPlayer(player);
client.setConnectionState(ConnectionState.IN_GAME);
}
Network Configuration
Key configuration options affecting the network layer:
ServerConfig.PORT_GAME - Game server listening port (default: 7777)
ConnectionConfig.threadPoolSize - I/O thread pool size
ConnectionConfig.useNagle - Enable/disable Nagle’s algorithm
ConnectionConfig.shutdownWaitTime - Graceful shutdown timeout
- GameServer - Main server initialization
- DatabaseFactory - Database connections used by GameClient
FloodProtectors - Client action rate limiting
Encryption - Packet encryption/decryption
ConnectionState - Client connection state enum