RCONServer
Inherits: RefCounted < Object
RCON server for accepting remote management connections to game servers.
Description
RCONServer provides a complete server implementation for accepting RCON connections using either Source RCON (TCP) or BattlEye RCON (UDP) protocols. It handles multiple simultaneous clients, authentication, command registration with callbacks, and protocol-specific features.
Availability: This class is available in:
Editor builds (all platforms, for testing/development)
Exported games with
dedicated_servercustom feature tag (Windows and Linux only)
Check with ClassDB.class_exists("RCONServer") before use in templates.
The server runs network operations on a background thread and provides thread-safe access through the poll() method, which must be called regularly (typically in _process) to dispatch events and callbacks.
When you register a command using register_command(), a dynamic signal is automatically created with the name command_<command_name> that emits alongside the callback.
var server = RCONServer.new()
func _ready():
server.client_authenticated.connect(_on_client_auth)
server.register_command("status", _handle_status)
server.register_command("kick", _handle_kick)
# Dynamic signals are created automatically
server.command_status.connect(_on_status_cmd)
server.start_server(27015, "admin123", RCONServer.PROTOCOL_SOURCE)
func _process(_delta):
server.poll() # Dispatch events
func _handle_status(client_id: int, args: String, request_id: int):
server.send_response(client_id, request_id, "Server: Online")
func _on_status_cmd(client_id: int, args: String, request_id: int):
print("Status command from client %d" % client_id)
Tutorials
Methods
get_connected_clients() const |
|
get_protocol() const |
|
get_state() const |
|
is_running() const |
|
void |
poll() |
void |
register_command(command: String, callback: Callable) |
void |
send_raw_packet(client_id: int, packet: PackedByteArray) |
void |
send_response(client_id: int, request_id: int, response: String) |
start_server(port: int, password: String, protocol: Protocol) |
|
void |
|
void |
unregister_command(command: String) |
Signals
authentication_failed(client_id: int, address: String) 🔗
Emitted when a client fails authentication (incorrect password). The address parameter contains the client's IP address.
client_authenticated(client_id: int) 🔗
Emitted when a client successfully authenticates with the server.
client_connected(client_id: int, address: String) 🔗
Emitted when a new client connects to the server. Authentication may still be in progress.
client_disconnected(client_id: int) 🔗
Emitted when a client disconnects from the server.
client_timeout_warning(client_id: int, seconds_remaining: int) 🔗
Emitted when a BattlEye RCON client is approaching timeout (at 35 seconds, 10 seconds before the 45-second timeout). The seconds_remaining parameter indicates how many seconds until timeout.
command_received(client_id: int, command: String, request_id: int) 🔗
Emitted when a command is received from any client. This is a catch-all signal that fires for all commands, including those with registered handlers.
keep_alive_sent(client_id: int) 🔗
Emitted when a keep-alive packet is received from a BattlEye RCON client (empty command packet).
keep_alive_timeout(client_id: int) 🔗
Emitted when a BattlEye RCON client times out (no packets received for 45 seconds). The client is automatically disconnected.
packet_send_failed(client_id: int, error: String) 🔗
Emitted when sending a packet to a client fails. The error parameter contains a description of the failure.
packet_sent(client_id: int, packet: PackedByteArray) 🔗
Emitted when a packet is successfully sent to a client. Useful for low-level monitoring and debugging.
raw_packet_received(client_id: int, packet: PackedByteArray) 🔗
Emitted when a raw packet is received from a client. Useful for low-level protocol debugging or custom packet handling.
Emitted when a server error occurs. The error parameter contains a description of the error.
server_started() 🔗
Emitted when the server successfully starts and begins listening for connections.
server_stopped() 🔗
Emitted when the server stops.
Enumerations
enum Protocol: 🔗
Protocol PROTOCOL_SOURCE = 0
Use Source RCON protocol (TCP-based). Default port is 27015.
Protocol PROTOCOL_BATTLEYE = 1
Use BattlEye RCON protocol (UDP-based). Default ports are 2302-2305.
enum State: 🔗
State STATE_STOPPED = 0
Server is not running.
State STATE_STARTING = 1
Server is starting up.
State STATE_LISTENING = 2
Server is listening for client connections.
State STATE_ERROR = 3
An error occurred during server operation.
Method Descriptions
Array get_connected_clients() const 🔗
Returns an Array of client IDs for all currently connected clients.
var clients = server.get_connected_clients()
print("Connected clients: ", clients.size())
Protocol get_protocol() const 🔗
Returns the protocol being used by this server (PROTOCOL_SOURCE or PROTOCOL_BATTLEYE).
Returns the current server state. Possible values are:
STATE_STOPPED: Server is not running
STATE_STARTING: Server is starting up
STATE_LISTENING: Server is listening for connections
STATE_ERROR: An error occurred
Returns true if the server is currently running and listening for connections.
void poll() 🔗
Processes pending events from the network thread and dispatches signals and callbacks. This method must be called regularly (typically in _process) for the server to function properly.
func _process(_delta):
server.poll()
void register_command(command: String, callback: Callable) 🔗
Registers a command handler. When a client sends this command, the callback will be invoked with the signature func(client_id: int, args: String, request_id: int).
Additionally, a dynamic signal named command_<command_name> is automatically created and emitted alongside the callback.
# Register command
server.register_command("kick", _handle_kick)
# Connect to dynamic signal
server.command_kick.connect(_on_kick_command)
func _handle_kick(client_id: int, args: String, request_id: int):
var player_name = args.strip_edges()
# Kick logic...
server.send_response(client_id, request_id, "Kicked: " + player_name)
void send_raw_packet(client_id: int, packet: PackedByteArray) 🔗
Sends a raw packet to a specific client. Use RCONPacket methods to construct packets manually for low-level protocol control.
var packet = RCONPacket.create_source_command(1, "Custom response")
server.send_raw_packet(client_id, packet)
void send_response(client_id: int, request_id: int, response: String) 🔗
Sends a response to a command from a specific client. The request_id should match the request_id provided in the command callback.
func _handle_status(client_id: int, args: String, request_id: int):
var status = "Server: Online, Players: 5/10"
server.send_response(client_id, request_id, status)
Error start_server(port: int, password: String, protocol: Protocol) 🔗
Starts the RCON server on the specified port with the given password and protocol.
Returns @GlobalScope.OK if the server started successfully, or an error code otherwise.
Security Warning: RCON passwords are transmitted in plain text. Use strong passwords and consider VPN/SSH tunneling for remote access.
var err = server.start_server(27015, "secure_password", RCONServer.PROTOCOL_SOURCE)
if err != OK:
print("Failed to start server: ", err)
void stop_server() 🔗
Stops the RCON server and disconnects all clients. Emits the server_stopped signal.
server.stop_server()
void unregister_command(command: String) 🔗
Unregisters a previously registered command handler. The command will no longer trigger callbacks or signals.
server.unregister_command("status")