godot-multiplayer — Claude Code skill: what it does, how to install
Configures Godot 4.7 high-level multiplayer via ENet, @rpc calls, node authority, and state replication with MultiplayerSpawner and MultiplayerSynchronizer.
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer -a claude-codeWhat godot-multiplayer does
This skill guides the agent in writing high-level networking code for Godot 4.7 projects. It sets up server and client workflows with ENetMultiplayerPeer, handles multiplayer signals such as peer_connected, and scaffolds @rpc methods using options like any_peer, call_local, and reliable.
It covers player avatar authority assignment through set_multiplayer_authority() and property replication using MultiplayerSpawner alongside MultiplayerSynchronizer. RPC arguments cannot serialize engine Objects or Callables, so networking logic must stay limited to primitives, arrays, and dictionaries.
A strict constraint in Godot is RPC signature matching: every @rpc method declaration must be identical across both server and client scripts, or Godot raises runtime checksum errors pointing at unrelated methods.
What it helps with
- create host and join flows with ENetMultiplayerPeer in Godot 4.7
- assign avatar ownership with set_multiplayer_authority and isolate inputs
- replicate node positions and custom variables using MultiplayerSynchronizer
- validate client actions on the server before broadcasting RPC events
Example prompts for the agent
- Write an ENet host and join script for Godot 4.7 with connection signal handlers
- Implement a player controller using set_multiplayer_authority and client-to-server RPCs
- Configure MultiplayerSpawner to replicate projectile nodes across all connected peers
How to install godot-multiplayer
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer -a claude-code2Manually: put the files in place
~/.claude/skills/godot-multiplayer/SKILL.mdCopy the whole skill folder; for one project use .claude/skills/godot-multiplayer/
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer -a codex2Manually: put the files in place
.agents/skills/godot-multiplayer/SKILL.mdFor all projects use ~/.agents/skills/
1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer -a cursor2Manually: put the files in place
.cursor/skills/godot-multiplayer/SKILL.mdCursor also reads .agents/skills/ and .claude/skills/
1GitHub CLI
gh skill install gamedev-skills/awesome-gamedev-agent-skills godot-multiplayer2Manually: put the files in place
.github/skills/godot-multiplayer/SKILL.md1Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer -a gemini-cli2Platform CLI
gemini skills install https://github.com/gamedev-skills/awesome-gamedev-agent-skills --path skills/godot/godot-multiplayerManually: put the files in place
.devin/skills/godot-multiplayer/SKILL.mdThe legacy .windsurf/skills/ path still works
Skills CLI (Vercel)
npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer -a opencodeClaude.ai
Zip the folder and upload it in Settings → Capabilities → Skills
From the same set40
The whole set →Similar
Questions about godot-multiplayer
How to install godot-multiplayer in Claude Code?
Run npx skills add gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer -a claude-code in your terminal.
What does godot-multiplayer do?
It provides patterns and rules for building Godot 4.7 multiplayer systems using ENet, RPC annotations, and scene replication nodes.
Why does an RPC fail with Mode is authority errors?
The default mode for @rpc is authority. If a client owns the node, server-driven RPCs must specify any_peer and verify the sender ID manually.
Source text
SKILL.md · Apache-2.0
---
name: godot-multiplayer
description: >
Build networked games with Godot 4.7 high-level multiplayer: set up an
ENetMultiplayerPeer server/client, define RPCs with the @rpc annotation
(call via rpc()/rpc_id()), set per-node multiplayer authority, and replicate
state with MultiplayerSpawner and MultiplayerSynchronizer. Use when adding
multiplayer/networking to a Godot project, writing @rpc functions, or syncing
player/world state across peers.
---
# Godot Multiplayer (4.x high-level)
Connect peers, call functions remotely with `@rpc`, assign authority, and replicate state
with `MultiplayerSpawner`/`MultiplayerSynchronizer`. Targets **Godot 4.7** (ENet). Treat
all client input as untrusted; keep the server authoritative.
## When to use
- Use when adding networked multiplayer: hosting/joining over ENet, calling RPCs,
assigning per-node authority, or auto-spawning/syncing nodes across peers.
**When *not* to use:** local split-screen (no networking); raw TCP/UDP/WebSocket protocol
work (low-level `PacketPeer`); HTTP requests. For save/persistence → `save-systems`.
## Core workflow
1. **Create a peer** (`ENetMultiplayerPeer`), call `create_server(port, max)` or
`create_client(ip, port)`, and assign it to `multiplayer.multiplayer_peer`. The
server's unique ID is always `1`; clients get random positive IDs.
2. **Handle connection signals** on `multiplayer`: `peer_connected(id)`,
`peer_disconnected(id)`, `connected_to_server`, `connection_failed`,
`server_disconnected`.
3. **Define RPCs** with `@rpc(...)`. Call them on a `Callable` via `rpc()` (all peers) or
`rpc_id(peer_id)` (one peer). Inside, `multiplayer.get_remote_sender_id()` tells you who
sent it.
4. **Keep RPC signatures identical** on every peer that runs the script — Godot checksums
all `@rpc` methods in a script; a mismatch prints errors that can name an unrelated RPC.
5. **Assign authority** per node with `set_multiplayer_authority(id)`; gate input/RPCs by
`is_multiplayer_authority()`.
6. **Replicate state** with `MultiplayerSpawner` (auto-instances scenes on clients) and
`MultiplayerSynchronizer` (auto-syncs selected properties).
7. **Validate on the server.** Don't trust client-reported positions/results.
## Patterns
### 1. Host or join (ENet)
```gdscript
const PORT := 7000
const MAX_PLAYERS := 8
func host() -> void:
var peer := ENetMultiplayerPeer.new()
var err := peer.create_server(PORT, MAX_PLAYERS)
if err != OK:
push_error("Cannot host: %s" % err); return
multiplayer.multiplayer_peer = peer
multiplayer.peer_connected.connect(_on_peer_connected)
func join(ip := "127.0.0.1") -> void:
var peer := ENetMultiplayerPeer.new()
peer.create_client(ip, PORT)
multiplayer.multiplayer_peer = peer
multiplayer.connected_to_server.connect(func(): print("connected"))
func leave() -> void:
multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()
```
### 2. RPCs: client sends input to the server (any_peer, call_local)
This script sits on a player avatar whose authority is the owning client (Pattern 3), so
the server is *not* the node's authority. A server→clients RPC on such a node must be
`"any_peer"` and check that the sender is the server.
```gdscript
func _unhandled_input(event: InputEvent) -> void:
if event.is_action_pressed("fire") and is_multiplayer_authority():
request_fire.rpc_id(1) # send only to the server (id 1)
# Clients may call this; it runs on the server (and locally if server is a player).
@rpc("any_peer", "call_local", "reliable")
func request_fire() -> void:
if not multiplayer.is_server(): # ignore copies relayed to other clients
return
var sender := multiplayer.get_remote_sender_id()
if not _can_fire(sender): # server-side validation
return
spawn_projectile.rpc(sender) # tell everyone to spawn it
# "authority" here would make clients reject the server's call (the client is the
# authority), so accept any peer and keep only calls that come from the server.
@rpc("any_peer", "call_local", "reliable")
func spawn_projectile(owner_id: int) -> void:
if multiplayer.get_remote_sender_id() != 1:
return
_do_spawn(owner_id)
```
### 3. Per-node authority (each player controls their own avatar)
```gdscript
extends CharacterBody2D
func _ready() -> void:
# The node name is the owning peer's id; that peer is the authority.
set_multiplayer_authority(name.to_int())
func _physics_process(delta: float) -> void:
if not is_multiplayer_authority():
return # only the owner reads input & moves
velocity = Input.get_vector("left", "right", "up", "down") * 200.0
move_and_slide()
```
### 4. MultiplayerSynchronizer config (editor + replication)
```gdscript
# Add a MultiplayerSynchronizer child; in its Replication editor add the properties to
# sync (e.g. position, velocity). Set "Sync"/"Spawn" flags per property. From code you
# can scope visibility:
@onready var sync: MultiplayerSynchronizer = $MultiplayerSynchronizer
func _ready() -> void:
# Only replicate this node to a specific peer (e.g. private info). Per-peer visibility
# matters only once public_visibility is off; by default every peer receives it.
sync.public_visibility = false
sync.set_visibility_for(target_peer_id, true)
```
## Pitfalls
- **RPC signature checksum.** Every `@rpc` method in a script must exist with the same
declaration on both client and server builds — *even unused ones*. A mismatch causes
errors that may point at the wrong function. Argument names/count are not checked, but
the set of RPCs and their annotations are.
- **Default `@rpc` is `"authority"`.** Clients calling it are ignored unless you set
`"any_peer"`. Use `"call_local"` so the host (also a player) runs it too.
- **`RPC 'x' is not allowed on node ... from: 1. Mode is "authority"`** → the server called
an `"authority"` RPC on a node a client owns. "Authority" means the node's authority, not
the server. Use `"any_peer"` plus a `get_remote_sender_id() == 1` check, or move
server-driven RPCs to a server-owned node (e.g. a game manager).
- **NodePaths must match across peers.** RPC routing uses the node's path/name; spawn nodes
with identical names on all peers (use `MultiplayerSpawner` or `add_child(node, true)` for
readable, deterministic names).
- **Trusting the client.** Never let clients set authoritative state (health, position,
hits) directly. Send *intent*, validate on the server, then broadcast results.
- **RPC on non-Node classes fails.** `@rpc` methods must be on `Node`-derived classes, not
plain `Resource`/`RefCounted`.
- **RPCs don't serialize Objects/Callables.** Pass plain data (ints, strings, arrays,
dictionaries, PackedArrays).
- **Forgetting to reset the peer.** To disconnect cleanly, set
`multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new()`.
- **Android needs INTERNET permission** in the export preset or all networking is blocked.
## References
- For `MultiplayerSpawner` setup, transfer modes/channels, `SceneMultiplayer`
authentication (`auth_callback`/`complete_auth`), a lobby skeleton, and dedicated-server
export notes, read `references/replication-and-rpc.md`.
## Related skills
- `godot-nodes-scenes` — instancing the scenes that get spawned/synced.
- `godot-signals-groups` — connection signals and event flow.
- `godot-export` — exporting a headless dedicated server build.
© gamedev-skills · Apache-2.0 · gamedev-skills/awesome-gamedev-agent-skills