> ## Documentation Index
> Fetch the complete documentation index at: https://docs.summerengine.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CraftyPlayer

> Game-agnostic player contract: peer identity, synced state, and server-read input. Use CraftyCharacter3D for built-in 3D character behavior.

## 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)

```gdscript theme={null}
# 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:

```gdscript theme={null}
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.

```gdscript theme={null}
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`

<Warning>
  Keep authoritative game logic on server paths (`Crafty.is_server()`). Clients should render synced state, not decide outcomes.
</Warning>

## Input (Read On Server)

Each connected player has an input proxy you read on the server:

```gdscript theme={null}
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:

```gdscript theme={null}
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.
