What Is CraftyPlayer?
CraftyPlayer is the minimal platform contract for a connected player.
It is intentionally game-agnostic:
- no required 3D movement model,
- no required health model,
- no required scene structure.
This is what allows card games, RTS, 2D games, and 3D action games to all use the same multiplayer platform.
Core Contract (Signatures)
Identity
Player identity fields are assigned by the platform during connection:
peer_id: int
player_id: String
display_name: String
avatar: Dictionary
Custom Synced Variables
set_synced and get_synced are the core data sync mechanism.
Use them for any gameplay data your clients need:
- card hand summaries,
- turn state,
- unit stats,
- score,
- custom RPG state.
set_synced(key: String, value: Variant) -> void
get_synced(key: String) -> Variant
Keep authoritative game logic on server paths (Crafty.is_server()). Clients should render synced state, not decide outcomes.
Each connected player has an input proxy you read on the server:
player.input.movement -> Vector2
player.input.look_direction -> Vector2
player.input.is_action_pressed(action: String) -> bool
player.input.is_action_just_pressed(action: String) -> bool
CraftyCharacter3D (Optional 3D Template)
For 3D action games, use CraftyCharacter3D in your player.tscn.
It includes:
CharacterBody3D movement-compatible node type,
- health fields (
health, max_health, is_alive),
- helpers (
respawn, damage, heal, kill, teleport),
- same synced API (
set_synced / get_synced).
Example:
Practical Rule
If your game needs built-in 3D character behavior, use CraftyCharacter3D.
If your game is not a 3D character game, extend CraftyPlayer directly and sync your own state model.