183 lines
6.5 KiB
Markdown
183 lines
6.5 KiB
Markdown
|
|
# Xyvera
|
|||
|
|
|
|||
|
|
Cozy management gacha with meaningful guild strategy.
|
|||
|
|
|
|||
|
|
This repository is the proof-of-concept scaffold. It covers Steps 1–2 of the
|
|||
|
|
[implementation sequence](docs/ — see DOCS vault) and gives a runnable local
|
|||
|
|
stack to build the rest of the PoC against.
|
|||
|
|
|
|||
|
|
## Architecture
|
|||
|
|
|
|||
|
|
| Layer | Technology | Purpose |
|
|||
|
|
|---|---|---|
|
|||
|
|
| Client | Godot 4.3 | UI, scenes, local state cache |
|
|||
|
|
| Game backend | Nakama 3.22 | Auth, gacha, inventory, village RPCs |
|
|||
|
|
| Nakama DB | CockroachDB 23.2 | Nakama internal state |
|
|||
|
|
| Game DB | PostgreSQL 16 | Economy ledger, roster, content cache |
|
|||
|
|
|
|||
|
|
## Prerequisites
|
|||
|
|
|
|||
|
|
- Docker and Docker Compose v2
|
|||
|
|
- Godot 4.3+ with the [GDNakama plugin](https://github.com/heroiclabs/nakama-godot)
|
|||
|
|
- Python 3.10+ (for content validation tooling)
|
|||
|
|
- Node.js 20+ (for Nakama TypeScript module compilation)
|
|||
|
|
|
|||
|
|
## Start the dev stack
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd /path/to/xyvera
|
|||
|
|
|
|||
|
|
# 1. Copy the example env file and adjust if needed
|
|||
|
|
cp infra/.env.example .env
|
|||
|
|
|
|||
|
|
# 2. Start all services
|
|||
|
|
docker compose up -d
|
|||
|
|
|
|||
|
|
# 3. Verify they are running
|
|||
|
|
docker compose ps
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
Services after startup:
|
|||
|
|
|
|||
|
|
| Service | URL |
|
|||
|
|
|---|---|
|
|||
|
|
| Nakama console | http://localhost:7351 |
|
|||
|
|
| Nakama API | http://localhost:7350 |
|
|||
|
|
| CockroachDB admin | http://localhost:8080 |
|
|||
|
|
| PostgreSQL | localhost:5432 |
|
|||
|
|
|
|||
|
|
## Run migrations
|
|||
|
|
|
|||
|
|
PostgreSQL migrations in `migrations/` are applied automatically by the
|
|||
|
|
`postgres` container on first boot via `docker-entrypoint-initdb.d`.
|
|||
|
|
|
|||
|
|
To apply them manually (e.g. after resetting the volume):
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker compose exec postgres psql -U xyvera -d xyvera -f /migrations/001_initial_schema.sql
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
To reset the database entirely (destroys all data):
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker compose down -v
|
|||
|
|
docker compose up -d
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Build and deploy Nakama modules
|
|||
|
|
|
|||
|
|
Nakama TypeScript modules must be compiled to JavaScript before Nakama loads them.
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cd nakama
|
|||
|
|
npm install
|
|||
|
|
npm run build
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
The compiled `.js` files land in `nakama/modules/` alongside the source.
|
|||
|
|
The `nakama` service mounts this directory, so changes take effect after a
|
|||
|
|
container restart:
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker compose restart nakama
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Validate content files
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
pip install pyyaml jsonschema
|
|||
|
|
python3 tools/validate_content.py
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
This checks every file under `content/data/` against the matching schema
|
|||
|
|
in `content/schema/`. Run this before committing content changes.
|
|||
|
|
|
|||
|
|
## Open in Godot
|
|||
|
|
|
|||
|
|
1. Open Godot 4.3+.
|
|||
|
|
2. Import the project at `godot/`.
|
|||
|
|
3. Install the GDNakama plugin (Asset Library or manually from the repo above).
|
|||
|
|
4. Enable the plugin in Project → Project Settings → Plugins.
|
|||
|
|
5. Run the project (`F5`). The Main Menu will attempt to connect to `localhost:7349`.
|
|||
|
|
|
|||
|
|
The default connection target is `localhost:7349`, matching the Docker Compose stack.
|
|||
|
|
To connect to a different host, edit `SERVER_HOST` in `godot/src/nakama/NakamaClient.gd`.
|
|||
|
|
|
|||
|
|
## Project structure
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
xyvera/
|
|||
|
|
├── docker-compose.yml Local dev stack (Nakama + CockroachDB + Postgres)
|
|||
|
|
├── nakama/
|
|||
|
|
│ ├── modules/ TypeScript server-side modules (compiled to JS)
|
|||
|
|
│ │ ├── main.ts Entry point — registers all RPCs
|
|||
|
|
│ │ ├── auth.ts Account seeding
|
|||
|
|
│ │ ├── gacha.ts Pull execution (stub — implement PR 5)
|
|||
|
|
│ │ ├── inventory.ts Inventory and resources
|
|||
|
|
│ │ ├── progression.ts Level / ascension / skill (stub — PR 6)
|
|||
|
|
│ │ └── village.ts Assignment + manual work (stub — PR 5/8)
|
|||
|
|
│ ├── package.json
|
|||
|
|
│ └── tsconfig.json
|
|||
|
|
├── content/
|
|||
|
|
│ ├── schema/ YAML schemas for all content types
|
|||
|
|
│ │ ├── character.yaml
|
|||
|
|
│ │ ├── job.yaml
|
|||
|
|
│ │ ├── resource.yaml
|
|||
|
|
│ │ ├── banner.yaml
|
|||
|
|
│ │ └── event.yaml
|
|||
|
|
│ └── data/
|
|||
|
|
│ ├── characters/ 3 example characters (Lyra, Ember, Sable)
|
|||
|
|
│ ├── jobs/ 2 example jobs (Lumber Camp, Research Post)
|
|||
|
|
│ └── resources/ 7 core resource definitions
|
|||
|
|
├── migrations/
|
|||
|
|
│ └── 001_initial_schema.sql Players, ledger, roster, pulls, pity, content cache
|
|||
|
|
├── godot/
|
|||
|
|
│ ├── project.godot
|
|||
|
|
│ ├── assets/placeholders/
|
|||
|
|
│ └── src/
|
|||
|
|
│ ├── nakama/
|
|||
|
|
│ │ └── NakamaClient.gd Singleton wrapper for all server calls
|
|||
|
|
│ ├── systems/
|
|||
|
|
│ │ └── GameState.gd Global state cache (AutoLoad)
|
|||
|
|
│ └── screens/
|
|||
|
|
│ ├── MainMenu.gd/.tscn
|
|||
|
|
│ ├── Village.gd/.tscn Home hub + manual work button
|
|||
|
|
│ ├── GachaPull.gd/.tscn
|
|||
|
|
│ └── Inventory.gd/.tscn
|
|||
|
|
├── tools/
|
|||
|
|
│ └── validate_content.py Content schema validator
|
|||
|
|
└── infra/
|
|||
|
|
└── .env.example
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## Implementation sequence
|
|||
|
|
|
|||
|
|
This scaffold covers **Step 1 (Project Foundation)** and part of **Step 2 (Content Schemas)** from the spec.
|
|||
|
|
|
|||
|
|
Next PRs to implement:
|
|||
|
|
|
|||
|
|
| PR | Scope |
|
|||
|
|
|---|---|
|
|||
|
|
| PR 3 | Player profile model, secure auth |
|
|||
|
|
| PR 4 | Currency ledger and inventory API |
|
|||
|
|
| **PR 5** | **Manual work loop** — highest PoC priority |
|
|||
|
|
| PR 6 | Character progression (level, ascend, skills) |
|
|||
|
|
| PR 8 | Village passive production and assignment |
|
|||
|
|
| PR 9 | Event calendar framework |
|
|||
|
|
|
|||
|
|
The manual work loop (PR 5 / `village/manual_work` RPC) is the most important
|
|||
|
|
system to validate. The spec is explicit: if that mechanic fails to feel
|
|||
|
|
rewarding, the entire concept should be reconsidered before more content is built.
|
|||
|
|
|
|||
|
|
## Design decisions made in this scaffold
|
|||
|
|
|
|||
|
|
The following details were not fully specified in the design notes and were
|
|||
|
|
decided here. Record any changes in the relevant schema or module:
|
|||
|
|
|
|||
|
|
- **Pity defaults**: soft pity at 70 pulls, hard pity at 90 (similar to Genshin/HSR; tune via banner content YAML).
|
|||
|
|
- **Manual work cost**: 5 mana per action; 3 full-yield actions per day, 50% diminishing returns thereafter. All constants in `village.ts`.
|
|||
|
|
- **Passive cap**: 8 hours accumulation cap before collection is required. Prevents AFK advantage without real engagement.
|
|||
|
|
- **Separate Postgres from CockroachDB**: Nakama requires CockroachDB and manages its own schema there. The game economy, roster, and content live in a separate Postgres instance for clean migration ownership.
|
|||
|
|
- **Rarity tier**: R / SR / SSR / UR four-tier model for PoC per the spec recommendation (full branded naming ladder deferred to production).
|
|||
|
|
- **Wood as the bottleneck**: the first manual work target is wood, gating early construction upgrades. Stone is the secondary scarcity axis once construction buildings exist.
|