# Terminal Realms — portable PHP edition

A no-build, account-based text RPG engine using PHP, vanilla HTML/CSS/JavaScript, JSON adventure packages, and SQLite.

## Requirements

- PHP 8.1 or newer
- PDO SQLite extension (`pdo_sqlite`)
- PHP sessions enabled
- Apache, Nginx, Caddy, or PHP's built-in development server
- Write permission on `storage/`
- HTTPS for production use

## Install

1. Upload this entire folder into a web-accessible directory.
2. Ensure the web-server user can write to `storage/`.
3. Visit `index.php`. SQLite creates and migrates the database automatically.

There is no Composer install, npm install, build process, or external service.

For a quick local test:

```sh
php -S 127.0.0.1:8080
```

Then open `http://127.0.0.1:8080/`.

## Account commands

```text
REGISTER <username>   Create an account and log in
LOGIN <username>      Log in to an existing account
WHOAMI                Display the current account
PASSWD                Change the current password
LOGOUT                Close the current session
DELETE ACCOUNT        Permanently delete the account and all saves
```

Passwords are collected through hidden terminal prompts. They are never displayed, placed in command history, or stored as plain text. Usernames are 3–24 characters and may contain letters, numbers, hyphens, and underscores. Passwords are 10–128 characters; passphrases are supported.

Account deletion requires the current password plus the exact confirmation `DELETE <username>`. Deletion cannot be undone.

## Authentication and security

- Passwords use PHP's current `PASSWORD_DEFAULT` algorithm through `password_hash()` and `password_verify()`.
- Session identifiers rotate after registration, login, password changes, and logout.
- State-changing requests require a per-session CSRF token.
- Login attempts are throttled after five failures within fifteen minutes.
- Security headers block framing, cross-origin resources, camera, microphone, and location access.
- Saved adventures are keyed to the authenticated user, so progress follows the account across browsers and devices.

The included Apache rule blocks direct web access to `storage/`. On Nginx, Caddy, or another server, add an equivalent rule denying requests to that directory. Always use HTTPS in production so passwords and session cookies are encrypted in transit.

## Add an adventure

1. Copy `data/adventures/ashes-of-thornwatch.json` to a new kebab-case filename such as `the-sunken-road.json`.
2. Change `adventure.id` to match the filename without `.json`.
3. Edit the rooms, exits, items, characters, player template, equipment, and text.
4. Validate it against `data/adventure.schema.json`.
5. Either change `default_adventure` in `config.php` or open `index.php?adventure=the-sunken-road`.

Each exit's `to` value is another room ID. Use `null` for a demonstration boundary. Door states are `open`, `closed`, `locked`, or `blocked`; a locked exit can name an item ID in `key`.

## Saves and backups

Every accepted gameplay command auto-saves to `storage/terminal-realms.sqlite`; `SAVE` and `LOAD` also work explicitly. Adventure source JSON is never modified.

Back up the SQLite database together with its `-wal` and `-shm` files while the site is live, or stop PHP briefly and copy the main database file. Deleting an account removes its user record and every associated save in a single transaction.
