Skip to main content

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>>>
T
type parameter
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)
packetHandler
PacketHandler<T>
required
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()

public void shutdown()
Shuts down the connection manager gracefully, closing all connections and releasing resources. Shutdown sequence:
  1. Closes the server socket channel
  2. Initiates thread pool shutdown
  3. Waits for shutdown completion (configured timeout)
  4. Forces immediate shutdown if timeout exceeded

getIpProtector()

public IPProtector getIpProtector()
returns
IPProtector
The IP protection instance managing connection rate limits

Connection Acceptance Flow

When a client connects:
1

Accept Connection

Server socket accepts the incoming connection asynchronously
2

Configure Socket

Sets TCP_NODELAY option based on Nagle’s algorithm configuration
channel.setOption(StandardSocketOptions.TCP_NODELAY, !_config.useNagle);
3

IP Protection Check

Validates that the connecting IP hasn’t exceeded connection limits
final String ip = remoteAddress.getAddress().getHostAddress();
if (!_ipProtector.canConnect(ip))
{
    channel.close();
    return;
}
4

Create Connection

Creates a Connection object wrapping the socket channel
5

Create Client

Uses the factory to create a GameClient instance
final T client = _clientFactory.apply(connection);
6

Start Reading

Notifies client of connection and begins reading packets
client.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:
  1. CONNECTED - Socket connected, awaiting protocol version
  2. AUTHENTICATED - Session validated with login server
  3. ENTERING - Character selected, loading into world
  4. IN_GAME - Fully loaded and playing
  5. 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.
returns
byte[]
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.
data
Buffer
required
The buffer containing packet data
offset
int
required
Starting offset in the buffer
size
int
required
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.
packet
ServerPacket
required
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.
packet
ServerPacket
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.
characterSlot
int
required
The character slot index (0-based)
returns
Player
The loaded player instance, or null if loading failed
Location: GameClient.java:495 Loading sequence:
  1. Validates character slot and retrieves object ID
  2. Checks for duplicate login attempts
  3. Loads character data from database
  4. Sets default states (running, standing)
  5. 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.
characterSlot
int
required
The character slot to delete
returns
byte
  • -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.
characterSlot
int
required
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()
returns
FloodProtectors
The flood protection manager for this client
Provides access to various flood protection mechanisms (chat, actions, packets).
getPlayerLock()
public ReentrantLock getPlayerLock()
returns
ReentrantLock
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.
buffer
ReadableBuffer
required
The buffer containing the packet data
client
GameClient
required
The client that sent the packet
returns
ReadablePacket<GameClient>
The created packet instance, or null if invalid

Packet Processing Flow

1

Read Packet ID

Extracts the first byte as the packet ID
final int packetId = Byte.toUnsignedInt(buffer.readByte());
2

Check for Extended Packet

If packet ID is 0xD0, reads additional 2 bytes for extended packet ID
case 0xD0: // Ex client packet
    final int exPacketId = Short.toUnsignedInt(buffer.readShort());
3

Validate Packet ID

Ensures the packet ID is within valid range
if ((packetId < 0) || (packetId >= ClientPackets.PACKET_ARRAY.length))
    return null;
4

Find Packet Enum

Looks up the packet enum from the packet array
final ClientPackets packetEnum = ClientPackets.PACKET_ARRAY[packetId];
5

Validate Connection State

Checks if the packet is allowed in the client’s current state
if (!packetEnum.getConnectionStates().contains(client.getConnectionState()))
    return null;
6

Create Packet Instance

Instantiates the packet using the enum’s factory method
return 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.
buffer
ReadableBuffer
required
The buffer containing the data to be converted
client
T
required
The client who sent the data
returns
ReadablePacket<T>
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

Build docs developers (and LLMs) love