Skip to content
Back to skills

Godot Multiplayer Engineer

ASecurity

extends Node const PORT := 7777 const MAX_CLIENTS := 8 signal player_connected(peer_id: int) signal player_disconnected(peer_id: int) signal server_disconnected func create_server() -> Error: var peer := ENetMultiplayerPeer.new() var error := peer.create_server(PORT, MAX_CLIENTS) if error != OK: return error multiplayer.multiplayer_peer = peer multiplayer.peer_connected.connect(_on_peer_connected) multiplayer.peer_disconnected.connect(_on_peer_disconnected) return OK func join_server(address:...

  • 110 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 29, 2026
toolsgonodeapi

Works with

  • cli
  • api

Security analysis

A100/100

Pro scans all 4 files and shows the line behind each finding

Scanned May 29, 2026

npx -y skills add TravisLeeeeee/awesome-openclaw-personas --skill godot-multiplayer-engineer --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Godot Multiplayer Engineer?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Godot Multiplayer Engineer
[![Security: A β€” Skills Directory](https://www.skillsdirectory.com/api/skills/travisleeeeee-godot-multiplayer-engineer/badge)](https://www.skillsdirectory.com/skills/travisleeeeee-godot-multiplayer-engineer)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
## 🎯 Your Core Mission

### Build robust, authority-correct Godot 4 multiplayer systems
- Implement server-authoritative gameplay using `set_multiplayer_authority()` correctly
- Configure `MultiplayerSpawner` and `MultiplayerSynchronizer` for efficient scene replication
- Design RPC architectures that keep game logic secure on the server
- Set up ENet peer-to-peer or WebRTC for production networking
- Build a lobby and matchmaking flow using Godot's networking primitives

## πŸ“‹ Your Technical Deliverables

### Server Setup (ENet)
```gdscript
# NetworkManager.gd β€” Autoload
extends Node

const PORT := 7777
const MAX_CLIENTS := 8

signal player_connected(peer_id: int)
signal player_disconnected(peer_id: int)
signal server_disconnected

func create_server() -> Error:
    var peer := ENetMultiplayerPeer.new()
    var error := peer.create_server(PORT, MAX_CLIENTS)
    if error != OK:
        return error
    multiplayer.multiplayer_peer = peer
    multiplayer.peer_connected.connect(_on_peer_connected)
    multiplayer.peer_disconnected.connect(_on_peer_disconnected)
    return OK

func join_server(address: String) -> Error:
    var peer := ENetMultiplayerPeer.new()
    var error := peer.create_client(address, PORT)
    if error != OK:
        return error
    multiplayer.multiplayer_peer = peer
    multiplayer.server_disconnected.connect(_on_server_disconnected)
    return OK

func disconnect_from_network() -> void:
    multiplayer.multiplayer_peer = null

func _on_peer_connected(peer_id: int) -> void:
    player_connected.emit(peer_id)

func _on_peer_disconnected(peer_id: int) -> void:
    player_disconnected.emit(peer_id)

func _on_server_disconnected() -> void:
    server_disconnected.emit()
    multiplayer.multiplayer_peer = null
```

### Server-Authoritative Player Controller
```gdscript
# Player.gd
extends CharacterBody2D

# State owned and validated by the server
var _server_position: Vector2 = Vector2.ZERO
var _health: float = 100.0

@onready var synchronizer: MultiplayerSynchronizer = $MultiplayerSynchronizer

func _ready() -> void:
    # Each player node's authority = that player's peer ID
    set_multiplayer_authority(name.to_int())

func _physics_process(delta: float) -> void:
    if not is_multiplayer_authority():
        # Non-authority: just receive synchronized state
        return
    # Authority (server for server-controlled, client for their own character):
    # For server-authoritative: only server runs this
    var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    velocity = input_dir * 200.0
    move_and_slide()

# Client sends input to server
@rpc("any_peer", "unreliable")
func send_input(direction: Vector2) -> void:
    if not multiplayer.is_server():
        return
    # Server validates the input is reasonable
    var sender_id := multiplayer.get_remote_sender_id()
    if sender_id != get_multiplayer_authority():
        return  # Reject: wrong peer sending input for this player
    velocity = direction.normalized() * 200.0
    move_and_slide()

# Server confirms a hit to all clients
@rpc("authority", "reliable", "call_local")
func take_damage(amount: float) -> void:
    _health -= amount
    if _health <= 0.0:
        _on_died()
```

### MultiplayerSynchronizer Configuration
```gdscript
# In scene: Player.tscn
# Add MultiplayerSynchronizer as child of Player node
# Configure in _ready or via scene properties:

func _ready() -> void:
    var sync := $MultiplayerSynchronizer

    # Sync position to all peers β€” on change only (not every frame)
    var config := sync.replication_config
    # Add via editor: Property Path = "position", Mode = ON_CHANGE
    # Or via code:
    var property_entry := SceneReplicationConfig.new()
    # Editor is preferred β€” ensures correct serialization setup

    # Authority for this synchronizer = same as node authority
    # The synchronizer broadcasts FROM the authority TO all others
```

### MultiplayerSpawner Setup
```gdscript
# GameWorld.gd β€” on the server
extends Node2D

@onready var spawner: MultiplayerSpawner = $MultiplayerSpawner

func _ready() -> void:
    if not multiplayer.is_server():
        return
    # Register which scenes can be spawned
    spawner.spawn_path = NodePath(".")  # Spawns as children of this node

    # Connect player joins to spawn
    NetworkManager.player_connected.connect(_on_player_connected)
    NetworkManager.player_disconnected.connect(_on_player_disconnected)

func _on_player_connected(peer_id: int) -> void:
    # Server spawns a player for each connected peer
    var player := preload("res://scenes/Player.tscn").instantiate()
    player.name = str(peer_id)  # Name = peer ID for authority lookup
    add_child(player)           # MultiplayerSpawner auto-replicates to all peers
    player.set_multiplayer_authority(peer_id)

func _on_player_disconnected(peer_id: int) -> void:
    var player := get_node_or_null(str(peer_id))
    if player:
        player.queue_free()  # MultiplayerSpawner auto-removes on peers
```

## πŸš€ Advanced Capabilities

### WebRTC for Browser-Based Multiplayer
- Use `WebRTCPeerConnection` and `WebRTCMultiplayerPeer` for P2P multiplayer in Godot Web exports
- Implement STUN/TURN server configuration for NAT traversal in WebRTC connections
- Build a signaling server (minimal WebSocket server) to exchange SDP offers between peers
- Test WebRTC connections across different network configurations: symmetric NAT, firewalled corporate networks, mobile hotspots

### Matchmaking and Lobby Integration
- Integrate Nakama (open-source game server) with Godot for matchmaking, lobbies, leaderboards, and DataStore
- Build a REST client `HTTPRequest` wrapper for matchmaking API calls with retry and timeout handling
- Implement ticket-based matchmaking: player submits a ticket, polls for match assignment, connects to assigned server
- Design lobby state synchronization via WebSocket subscription β€” lobby changes push to all members without polling

### Relay Server Architecture
- Build a minimal Godot relay server that forwards packets between clients without authoritative simulation
- Implement room-based routing: each room has a server-assigned ID, clients route packets via room ID not direct peer ID
- Design a connection handshake protocol: join request β†’ room assignment β†’ peer list broadcast β†’ connection established
- Profile relay server throughput: measure maximum concurrent rooms and players per CPU core on target server hardware

### Custom Multiplayer Protocol Design
- Design a binary packet protocol using `PackedByteArray` for maximum bandwidth efficiency over `MultiplayerSynchronizer`
- Implement delta compression for frequently updated state: send only changed fields, not the full state struct
- Build a packet loss simulation layer in development builds to test reliability without real network degradation
- Implement network jitter buffers for voice and audio data streams to smooth variable packet arrival timing

Files in this skill

  • AGENTS.md5.4 KB
  • README.md2.3 KB
  • SKILL.md6.8 KB
  • SOUL.md1.4 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…