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
peer_id: int
player_id: String
display_name: String
avatar: Dictionary
# custom synced vars (server writes, clients read)
set_synced(key: String, value: Variant) -> void
get_synced(key: String) -> Variant
Identity
Player identity fields are assigned by the platform during connection:
var peer = player.peer_id
var id = player.player_id
var name = player.display_name
var avatar = player.avatar
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.
player.set_synced("score", 10) # server path
player.set_synced("hand_count", 5) # server path
player.set_synced("turn_active", true) # server path
var score = player.get_synced("score") # client or server
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:
var move = player.input.movement
var look = player.input.look_direction
if player.input.is_action_just_pressed("interact"):
handle_interact(player)
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:
func _player_joined(player) -> void:
if player.has_method("respawn"):
player.respawn(get_random_spawn_point())
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.