godot-adapt-single-to-multiplayer
Expert patterns for adding multiplayer to single-player games including client-server architecture, authoritative server design, MultiplayerSynchronizer, lag compensation (client prediction, server reconciliation), input buffering, and anti-cheat measures. Use when retrofitting multiplayer, porting to online play, or designing networked gameplay. Trigger keywords: MultiplayerPeer, ENetMultiplayerPeer, SceneMultiplayer, MultiplayerSynchronizer, rpc, rpc_id, multiplayer_authority, client_prediction, server_reconciliation, lag_compensation, rollback.
What this skill does
# Adapt: Single to Multiplayer
Expert guidance for retrofitting multiplayer into single-player games.
## NEVER Do (Expert Multiplayer Rules)
### Security & Authority
- **NEVER trust client-reported state** — Clients own their 'Input', NOT their 'Position' or 'Health'. Server must validate every coordinate and health change.
- **NEVER use `get_tree()` groups for authority checks** — Use `is_multiplayer_authority()`. Group registration is non-deterministic in high-latency joins.
- **NEVER allow unrestricted RPC rates** — A malicious client can call a 'FireWeapon' RPC 10,000 times per second. Always implement rate-limiting (`net_rpc_rate_limiter.gd`).
### Movement & Lag
- **NEVER skip Client-Side Prediction** — Movement without prediction feels 'heavy' and unresponsive. Predict movement locally, then correct only on server disagreement.
- **NEVER sync peers at 60Hz** — Sending entire state every frame will saturate client bandwidth. Use a lower tick-rate (20-30Hz) and interpolate between packets.
- **NEVER snap peer positions** — Abrupt position updates cause 'jitter'. Store a buffer of past states and lerp between them with a 100ms delay.
### Bandwidth & Sync
- **NEVER sync 'Full Floats' if possible** — Quantize Vector3 data (truncating decimals) to save 50%+ bandwidth. Use `MultiplayerSynchronizer` with delta-sync enabled.
- **NEVER ignore 'Late Joiners'** — Players who join mid-game won't see existing environmental changes. Broadcast a full world-state 'Snapshot' on peer connection.
- **NEVER test on 0ms ping** — Everything works on localhost. Use a simulator (`net_latency_simulator.gd`) with 150ms ping to identify sync bugs.
---
## Available Scripts
> **MANDATORY**: Read the appropriate script before implementing the corresponding pattern.
### [net_prediction_reconciliation.gd](scripts/net_prediction_reconciliation.gd)
Expert CharacterBody3D prediction with input-buffer replaying for server reconciliation.
### [net_snapshot_interpolation.gd](scripts/net_snapshot_interpolation.gd)
Professional snapshot interpolation logic for smoothing peer movement via jitter buffers.
### [net_auth_server_validator.gd](scripts/net_auth_server_validator.gd)
Authoritative server validator for anti-cheat (Position, Speed, and Action checks).
### [net_rpc_rate_limiter.gd](scripts/net_rpc_rate_limiter.gd)
Expert rate-limiter to prevent RPC flooding and macro-abuse by clients.
### [net_interest_management.gd](scripts/net_interest_management.gd)
Distance-based visibility management to optimize binary bandwidth per-peer.
### [net_delta_compression_sync.gd](scripts/net_delta_compression_sync.gd)
Expert quantization and significance-checking logic for delta-compression.
### [net_upnp_discovery_logic.gd](scripts/net_upnp_discovery_logic.gd)
Robust script for P2P network discovery and automatic port forwarding via UPNP.
### [net_debug_overlay_monitor.gd](scripts/net_debug_overlay_monitor.gd)
In-game diagnostic overlay reporting RTT (Ping), Packet Loss, and Jitter.
### [net_lag_compensation.gd](scripts/net_lag_compensation.gd)
Expert server-side state rewinding (Lag Compensation) for accurate hit-registration.
### [net_lobby_late_join_sync.gd](scripts/net_lobby_late_join_sync.gd)
Professional state-initialization logic to bridge 'Late Joiners' into a synced session.
### [net_latency_simulator.gd](scripts/net_latency_simulator.gd)
Editor-only tool for simulating high-ping and loss conditions for stress-testing.
---
## Architecture Patterns
### Pattern 1: Authoritative Server (Recommended)
```gdscript
# Server validates ALL gameplay logic
# Clients send inputs → Server processes → Server broadcasts state
# Pros: Secure, prevents cheating
# Cons: Requires server hosting, lag affects gameplay
# Use for: Competitive games, PvP, games with economies
```
### Pattern 2: Peer-to-Peer (Lockstep)
```gdscript
# All clients run identical simulation
# Inputs synced, deterministic physics
# Pros: No dedicated server needed
# Cons: Vulnerable to cheating, desyncs common
# Use for: Co-op, casual games, small player counts (2-4)
```
### Pattern 3: Hybrid (Authority Transfer)
```gdscript
# Host acts as server
# Authority can transfer between peers
# Use for: 4-8 player co-op, party games
```
---
## Step-by-Step Migration
### Step 1: Separate Input from Logic
```gdscript
# ❌ BAD: Input directly modifies state (single-player)
extends CharacterBody2D
func _physics_process(delta: float) -> void:
var input := Input.get_vector("left", "right", "up", "down")
velocity = input.normalized() * SPEED
move_and_slide()
# ✅ GOOD: Input → Logic separation
extends CharacterBody2D
var current_input := Vector2.ZERO
func _physics_process(delta: float) -> void:
# Only read input if this is OUR player
if is_multiplayer_authority():
current_input = Input.get_vector("left", "right", "up", "down")
# Send input to server (if we're client)
if multiplayer.get_unique_id() != 1: # Not server
rpc_id(1, "receive_input", current_input)
# EVERYONE processes movement (server + all clients)
_process_movement(delta, current_input)
func _process_movement(delta: float, input: Vector2) -> void:
velocity = input.normalized() * SPEED
move_and_slide()
@rpc("any_peer", "call_remote", "unreliable")
func receive_input(input: Vector2) -> void:
# Server receives client input
current_input = input
```
### Step 2: Set Up Multiplayer Authority
```gdscript
# server_setup.gd
extends Node
const PORT = 7777
const MAX_PLAYERS = 4
func host_game() -> void:
var peer := ENetMultiplayerPeer.new()
peer.create_server(PORT, MAX_PLAYERS)
multiplayer.multiplayer_peer = peer
multiplayer.peer_connected.connect(_on_player_connected)
multiplayer.peer_disconnected.connect(_on_player_disconnected)
print("Server started on port %d" % PORT)
func join_game(ip: String) -> void:
var peer := ENetMultiplayerPeer.new()
peer.create_client(ip, PORT)
multiplayer.multiplayer_peer = peer
print("Connecting to %s:%d" % [ip, PORT])
func _on_player_connected(id: int) -> void:
print("Player %d connected" % id)
spawn_player(id)
func _on_player_disconnected(id: int) -> void:
print("Player %d disconnected" % id)
despawn_player(id)
func spawn_player(id: int) -> void:
var player := preload("res://player.tscn").instantiate()
player.name = str(id) # CRITICAL: Name must be unique and match peer ID
player.set_multiplayer_authority(id) # Client owns their own player
get_node("/root/World").add_child(player, true) # true = replicate to all peers
```
### Step 3: Add MultiplayerSynchronizer
```gdscript
# Scene structure:
# Player (CharacterBody2D)
# ├─ Sprite2D
# ├─ CollisionShape2D
# └─ MultiplayerSynchronizer
# MultiplayerSynchronizer setup (in editor):
# - Root Path: "../" (points to Player node)
# - Replication Interval: 0.05 (20Hz updates)
# - Public Visibility: true
# - Synchronized Properties:
# - position
# - rotation
# - velocity (optional, for interpolation)
# No code needed! MultiplayerSynchronizer auto-syncs properties
```
---
## Client Prediction & Server Reconciliation
### Problem: Lag Makes Game Feel Unresponsive
```gdscript
# Without prediction:
# 1. Client presses W
# 2. Input sent to server
# 3. Server processes (50ms later)
# 4. Server sends back position
# 5. Client sees movement (100ms RTT)
# Result: 100ms delay between input and visual feedback
```
### Solution: Client-Side Prediction
```gdscript
# player_controller.gd
extends CharacterBody2D
var input_buffer: Array = []
var server_state := {"position": Vector2.ZERO, "tick": 0}
func _physics_process(delta: float) -> void:
if is_multiplayer_authority():
var input := Input.get_vector("left", "right", "up", "down")
# Client predicts movement IMMEDIATELY
var tick := Engine.get_physics_frames()
input_buffer.append({"input": inputRelated in Design
contribute
IncludedLocal-only OSS contribution command center. Auto-refreshes the user's in-flight PR and issue state on invoke so conversations start with full context — no need to brief Claude on what's in flight. Helps the user find issues to contribute to on GitHub, builds per-repo dossiers of what each upstream expects (CLA, DCO, branch convention, AI policy, draft-first, review bots, issue templates), runs deterministic gates before any external action so AI-assisted contributions don't reach maintainers as slop. State is markdown-only: candidate files at ~/.contribute-system/candidates/, repo dossiers at ~/.contribute-system/research/, append-only event log at ~/.contribute-system/log.jsonl. No database, no cloud calls. Use when the user asks about their PRs / issues / contributions, wants to find new work to take on, claim an issue, build/refresh a repo's dossier, or draft a Design Issue or PR. Trigger with "/contribute", "what's my PR status", "find a contribution", "claim issue X", "draft a Design Issue for Y", "refresh dossier for Z".
architectural-analysis
IncludedUser-triggered deep architectural analysis of a codebase or scoped subtree across eight modes — information architecture, data flow, integration points, UI surfaces, interaction patterns, data model, control flow, and failure modes. This skill should be used when the user asks to "diagram this codebase," "map the architecture," "show the data flow," "give me an ERD," "trace control flow," "find the integration points," "verify the layout pattern," "audit the UX architecture," or any similar request whose primary deliverable is mermaid diagrams plus cited reports under docs/architecture/. Dispatches haiku/sonnet sub-agents in parallel for per-mode exploration, then verifies every citation mechanically before any node lands in a diagram. Not for one-off prose explanations of code (use code-explanation) or for high-level system design from scratch (use system-design).
mcp
IncludedModel Context Protocol (MCP) server development and tool management. Languages: Python, TypeScript. Capabilities: build MCP servers, integrate external APIs, discover/execute MCP tools, manage multi-server configs, design agent-centric tools. Actions: create, build, integrate, discover, execute, configure MCP servers/tools. Keywords: MCP, Model Context Protocol, MCP server, MCP tool, stdio transport, SSE transport, tool discovery, resource provider, prompt template, external API integration, Gemini CLI MCP, Claude MCP, agent tools, tool execution, server config. Use when: building MCP servers, integrating external APIs as MCP tools, discovering available MCP tools, executing MCP capabilities, configuring multi-server setups, designing tools for AI agents.
react-native-skia
IncludedDesign, build, debug, and optimise high-polish animated graphics in React Native or Expo using @shopify/react-native-skia, Reanimated, and Gesture Handler. Use when the user wants canvas-driven UI, shaders, paths, rich text, image filters, sprite fields, Skottie, video frames, snapshots, web CanvasKit setup, or performance tuning for custom motion-heavy elements such as loaders, hero art, cards, charts, progress indicators, particle systems, or gesture-driven surfaces. Also use when the user asks for fluid, glow, glass, blob, parallax, 60fps/120fps, or GPU-friendly animated effects in React Native, even if they do not explicitly say "Skia". Do not use for ordinary form/layout work with standard views.
plaid
IncludedProduct Led AI Development — guides founders from idea to launched product. Six capabilities: Idea (discover a product idea), Validate (pressure-test the idea against fatal flaws, problem reality, competition, and 2-week MVP feasibility), Plan (vision intake + document generation), Design (translate image references into a design.md spec), Launch (go-to-market strategy), and Build (roadmap execution). Use when someone says "PLAID", "plaid idea", "help me find an idea", "product idea", "idea from my business", "idea from my expertise", "plaid validate", "validate my idea", "pressure-test", "is this idea good", "find fatal flaws", "validate the problem", "plan a product", "define my vision", "generate a PRD", "product strategy", "plaid design", "design from image", "translate image to design", "create design.md", "extract design tokens", "plaid launch", "go-to-market", "launch plan", "GTM strategy", "launch playbook", "plaid build", "build the app", "start building", or "execute the roadmap".
nextjs-framer-motion-animations
IncludedAdds production-safe Motion for React or Framer Motion animations to Next.js apps, including reveal, hover and tap micro-interactions, whileInView, stagger, AnimatePresence, layout and layoutId transitions, reorder, scroll-linked UI, and lightweight route-content transitions. Use when the user asks to add, refactor, or debug Motion or Framer Motion in App Router or Pages Router codebases, especially around server/client boundaries, reduced motion, LazyMotion, bundle size, hydration, or route transitions. Avoid for GSAP-style timelines, WebGL or 3D scenes, heavy scroll storytelling, or CSS-only effects unless Motion is explicitly requested.