# Selda Multiplayer Architecture

This is the target architecture for turning the current local browser prototype into a wallet-authenticated multiplayer game.

## Goals

- Players authenticate with a Solana wallet.
- Each wallet owns one or more saved characters.
- Character profile stores name, colors, selected hero base, equipped weapon, equipped scroll, equipped relic, cosmetic skin, companion, XP, level, inventory, quest flags, and land ownership.
- Players can see other players in shared maps and social spaces.
- Normal maps shard into rooms capped at five players; the sixth player is placed into a new room for that map.
- The marketplace hub is uncapped so all online players can gather in one shared market room.
- Up to five players can enter a quest/dungeon/world boss room together.
- A shared marketplace lets players meet, trade, list NFT-like items, and buy/sell cosmetics or gear with `$SELDA`.

## Server Model

Use an authoritative Node/WebSocket backend. The current canvas client remains the renderer and input layer, but movement, party membership, marketplace listings, and multiplayer combat state should be synchronized through the server.

Current prototype implementation:

- `server.js` serves the static game and exposes a `/ws` WebSocket endpoint.
- The client sends player state, chat messages, earned resources, and marketplace claim requests.
- The server assigns normal map rooms with a cap of five players.
- The server assigns all players near the marketplace into `hub:marketplace`, which has no cap.
- The server broadcasts remote player snapshots/updates to players in the same room.
- The client renders remote players as sprites with name and level labels.
- Global chat broadcasts to every connected player.
- Local chat broadcasts only to the current room.
- Marketplace SELDA claims are validated server-side against a server-tracked earned-resource ledger before payout.

Recommended stack:

- API: Node.js with Fastify or Express.
- Realtime: WebSocket server using `ws` or Socket.IO.
- Database: Postgres.
- Cache/presence: Redis.
- Wallet auth: Sign-in with Solana message challenge.
- Chain integration: Solana RPC for wallet verification, token balances, NFT ownership, and transaction signatures.

## Core Tables

```sql
players (
  id uuid primary key,
  wallet_address text unique not null,
  created_at timestamptz not null,
  last_seen_at timestamptz not null
);

characters (
  id uuid primary key,
  player_id uuid references players(id),
  name text not null,
  hero_key text not null,
  primary_color text not null,
  accent_color text not null,
  equipped_weapon text not null,
  equipped_scroll text,
  equipped_relic text,
  companion text,
  level int not null,
  xp int not null,
  hp int not null,
  max_hp int not null,
  renown int not null,
  land_plots int not null,
  current_area text not null,
  position_x int not null,
  position_y int not null,
  updated_at timestamptz not null
);

inventories (
  character_id uuid references characters(id),
  item_key text not null,
  quantity int not null default 1,
  bound boolean not null default false,
  primary key (character_id, item_key)
);

quest_flags (
  character_id uuid references characters(id),
  flag_key text not null,
  value boolean not null,
  updated_at timestamptz not null,
  primary key (character_id, flag_key)
);

parties (
  id uuid primary key,
  leader_character_id uuid references characters(id),
  status text not null,
  created_at timestamptz not null
);

party_members (
  party_id uuid references parties(id),
  character_id uuid references characters(id),
  joined_at timestamptz not null,
  primary key (party_id, character_id)
);

market_listings (
  id uuid primary key,
  seller_character_id uuid references characters(id),
  item_key text not null,
  price_selda numeric not null,
  status text not null,
  created_at timestamptz not null,
  sold_at timestamptz
);

homes (
  id uuid primary key,
  owner_character_id uuid references characters(id),
  area_key text not null,
  position_x int not null,
  position_y int not null,
  name text not null,
  color text not null,
  accent_color text not null,
  built_at timestamptz not null
);

treasury_events (
  id uuid primary key,
  character_id uuid references characters(id),
  event_type text not null,
  amount_selda numeric not null,
  metadata jsonb not null default '{}',
  created_at timestamptz not null
);
```

## Realtime Areas

Use two area types:

- Shared hubs: marketplace towns and overworld social plazas. These show many players, but combat is disabled or limited.
- Sharded map rooms: overworld, interiors, dungeons, boss worlds, and quest maps. These are capped at five players; extra players are placed in a new room for the same map.
- Shared hub: the marketplace uses one uncapped `hub:marketplace` room so all players can meet there.

The current four new worlds can become public entrance zones with instanced boss arenas:

- Greenwood Expanse
- Azure Reef
- Stormpeak Kingdom
- Glassdune Empire

## WebSocket Events

Client to server:

- `auth:challenge`
- `auth:verify`
- `character:update`
- `state`
- `earn`
- `chat`
- `claim`
- `move`
- `equip`
- `party:create`
- `party:invite`
- `party:join`
- `instance:enter`
- `combat:attack`
- `combat:scroll`
- `market:list`
- `market:buy`

Server to client:

- `presence:snapshot`
- `presence:join`
- `presence:update`
- `presence:leave`
- `room:assigned`
- `room:status`
- `chat:message`
- `claim:result`
- `character:saved`
- `party:update`
- `instance:state`
- `combat:result`
- `loot:drop`
- `market:update`

## Client Changes Needed

- Replace local-only save/load with API-backed wallet saves.
- Keep local save as guest mode.
- Add character creation/edit screen:
  - Name
  - Body color
  - Accent color
  - Hero base
  - Starting weapon preference
- Add marketplace hub UI and player nameplates.
- Add party panel with invite/join/leave and ready state.
- Add server reconciliation for player position and enemy health.
- Promote the current in-memory room/reward state to durable Postgres rows before production.

## Security Rules

- Never trust client-submitted rewards.
- Server decides boss kills, loot drops, marketplace transfers, XP, and token rewards.
- The prototype server keeps its own earned-resource counters and only pays claims against those counters; production should move monster kills, fishing, woodcutting, chests, quests, and drops fully server-side.
- Wallet auth requires a fresh nonce and signed message.
- Marketplace purchases require either an on-chain transaction or server-verified internal `$SELDA` ledger transaction.

## Payout Settlement

SELDA payouts do not strictly require Helius. A production payout service can use standard Solana RPC to sign and submit SPL token transfers from a server treasury wallet, using the SELDA mint and associated token accounts.

Helius is useful but optional:

- Standard Solana RPC is enough for creating token accounts, signing transfers, checking balances, and confirming transactions.
- Helius helps with reliable RPC, parsed transaction history, webhooks, enhanced token/NFT indexing, and priority/observability tooling.
- The required production pieces are a server treasury keypair, a persistent payout ledger, idempotency keys, wallet signature auth, per-wallet rate limits, fraud checks, and confirmed transaction recording.

## Migration Path

1. Add wallet profile API and persist the current local save format.
2. Add character customization and server-backed equipment slots.
3. Add WebSocket presence in capped map rooms and the shared marketplace hub.
4. Add parties capped at five players.
5. Convert dungeons/world bosses into authoritative party instances.
6. Add marketplace listings and item ownership verification.
7. Move home building and treasury events from local prototype state into database records.
