# IStalk - Project Rules

## Relay Server

The relay server repo lives at `/Users/mahmoudaglan/istalk-relay-server/` (NOT inside this Unity project).

- Always edit relay server code from that path
- It auto-deploys to CapRover on push to master
- GitLab remote: `https://gitlab.caprover.al-arcade.com/root/istalk-relay-server.git`
- The copy at `/Users/mahmoudaglan/istalk/relay-server/` is stale — do not use it

## Tech Stack

- **Engine:** Unity 6 (URP 17.3)
- **Networking:** FishNet v4 + Synapse UDP transport
- **Relay:** Node.js WebSocket server (lobby + binary relay)
- **Platform:** PC (Steam) — mouse + keyboard FPS controls
- **Plugins:** DOTween, Cinemachine 3, AI Navigation, Input System

## Development Priority Order

1. **Multiplayer First** — every line of code is networked code
2. **Tools First** — build designer-facing tools, never hardcode content
3. **Gameplay Features**
4. **Visuals**
5. **Optimization**

### Tools First Rule

Never solve a problem by hardcoding map layouts, item placements, room connections, ability values, spawn positions, loot tables, movement thresholds, or balancing values into code. Instead use ScriptableObjects, custom inspectors, visual gizmos, and data assets so designers can configure systems entirely in the Unity Editor without modifying source.

- If a feature requires code changes to add new content, the architecture is wrong
- Every system must assume hundreds of variations created without touching code
- Choose a reusable tool over a quick hardcoded solution — unless it blocks multiplayer functionality
- GlobalRules_SO is the single source for all tuning constants
- New items/rooms/traps are added as .asset files in Resources/, discovered at runtime via `Resources.LoadAll<T>()`

## FishNet Rules

Every script is multiplayer code. No exceptions.

- Always determine: who runs this? Server, Client, Both, Owner-only?
- Guard camera/input with `if (!IsOwner) return;`
- Use FishNet lifecycle callbacks (`OnStartServer`, `OnStartClient`, `OnStartNetwork`), not `Start()`/`Awake()`
- Use `ServerManager.Despawn()` instead of `Destroy()` on networked objects
- Never use `IsOwner` inside `OnStartServer` — use `Owner.IsLocalClient`
