> 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.
npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill godot-multiplayer
Connect peers, call functions remotely with @rpc, assign authority, and replicate state
with MultiplayerSpawner/MultiplayerSynchronizer. Targets Godot 4.3+ (ENet). Treat
all client input as untrusted; keep the server authoritative.
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.
ENetMultiplayerPeer), call create_server(port, max) orcreate_client(ip, port), and assign it to multiplayer.multiplayer_peer. The
server's unique ID is always 1; clients get random positive IDs.
multiplayer: peer_connected(id),peer_disconnected(id), connected_to_server, connection_failed,
server_disconnected.
@rpc(...). Call them on a Callable via rpc() (all peers) orrpc_id(peer_id) (one peer). Inside, multiplayer.get_remote_sender_id() tells you who
sent it.
all @rpc methods in a script; mismatches break silently.
set_multiplayer_authority(id); gate input/RPCs byis_multiplayer_authority().
MultiplayerSpawner (auto-instances scenes on clients) andMultiplayerSynchronizer (auto-syncs selected properties).
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()
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:
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
@rpc("authority", "call_local", "reliable")
func spawn_projectile(owner_id: int) -> void:
_do_spawn(owner_id)
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()
# 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).
sync.set_visibility_for(target_peer_id, true)
@rpc method in a script must exist with the samedeclaration 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.
@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.
with identical names on all peers (use MultiplayerSpawner or add_child(node, true) for
readable, deterministic names).
hits) directly. Send *intent*, validate on the server, then broadcast results.
@rpc methods must be on Node-derived classes, notplain Resource/RefCounted.
dictionaries, PackedArrays).
multiplayer.multiplayer_peer = OfflineMultiplayerPeer.new().
MultiplayerSpawner setup, transfer modes/channels, SceneMultiplayerauthentication (auth_callback/complete_auth), a lobby skeleton, and dedicated-server
export notes, read references/replication-and-rpc.md.
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.Guide users through a structured workflow for co-authoring documentation. Use when user wants to write documentation, proposals, technical specs, decision docs, or similar structured content. This workflow helps users efficiently transfer context, refine content through iteration, and verify the doc works for readers. Trigger when user mentions writing docs, creating proposals, drafting specs, or similar documentation tasks.
Automatically creates user-facing changelogs from git commits by analyzing commit history, categorizing changes, and transforming technical commits into clear, customer-friendly release notes. Turns hours of manual changelog writing into minutes of automated generation.
Use when implementing any feature or bugfix, before writing implementation code
Use when you have a spec or requirements for a multi-step task, before touching code
Use when creating new skills, editing existing skills, or verifying skills work before deployment
Use when writing or improving README files. Not all READMEs are the same — provides templates and guidance matched to your audience and project type.
| Remove signs of AI-generated writing from text. Use when editing or reviewing text to make it sound more natural and human-written. Based on Wikipedia's inflated symbolism, promotional language, superficial -ing analyses, vague attributions, em dash overuse, rule of three, AI vocabulary words, negative parallelisms, and excessive conjunctive phrases.
Official Opentrons Protocol API for OT-2 and Flex robots. Use when writing protocols specifically for Opentrons hardware with full access to Protocol API v2 features. Best for production Opentrons protocols, official API compatibility. For multi-vendor automation or broader equipment control use pylabrobot.
Take gamedev-skills/godot-multiplayer from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.