Skip to main content

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.

Input (Read On Server)

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.