diff --git a/Commands.md b/Commands.md new file mode 100644 index 0000000..464bc15 --- /dev/null +++ b/Commands.md @@ -0,0 +1,72 @@ +# In-Game Commands + +Commands are typed in the in-game chat. The prefix is configurable in `config.json` (default: `!`). Each command can be enabled/disabled individually in the config. + +Operators (users with the appropriate `rights` bitmask) can use disabled commands. + +## General Commands + +| Command | Description | Default | +|---------|-------------|---------| +| `!help` | Show enabled commands | Enabled | +| `!playtime` | Show account playtime | Enabled | +| `!timer` | Toggle quest timer display | Enabled | +| `!reload` | Reload all players in current Land (forces client refresh) | Enabled | +| `!psn ` | Link a PSN ID to your account | Enabled | +| `!discord` | Generate a token for Discord account linking (use with `/link` in Discord) | Enabled | +| `!course ` | Toggle a subscription course on/off | Enabled | + +## Admin Commands + +| Command | Description | Default | +|---------|-------------|---------| +| `!rights ` | Set the rights bitmask on your account | Disabled | +| `!tele ` | Teleport to coordinates | Disabled | +| `!kqf get` | Show current Key Quest Flag hex value (G10+ only) | Disabled | +| `!kqf set ` | Set Key Quest Flags (16-char hex, requires Land switch to apply) | Disabled | +| `!ban [duration]` | Ban a user, optionally with duration | Disabled | + +### Ban Duration Format + +Duration uses ``: + +| Unit | Meaning | +|------|---------| +| `s` | Seconds | +| `m` | Minutes | +| `h` | Hours | +| `d` | Days | +| `mo` | Months | +| `y` | Years | + +Example: `!ban 12345 30d` bans character 12345 for 30 days. Omitting the duration bans permanently. + +## Raviente Commands + +These control the Raviente large-scale raid. Some subcommands require the ZZ client. + +| Command | Description | +|---------|-------------| +| `!ravi start` | Start Great Slaying event | +| `!ravi cm` | Check current damage multiplier | +| `!ravi ss` | Send sedation support (ZZ only) | +| `!ravi sr` | Send resurrection support (ZZ only) | +| `!ravi rs` | Request sedation support (ZZ only) | + +## Special Chat + +| Input | Effect | +|-------|--------| +| `@dice` | Roll a random number 1–100 | + +## Configuration + +Commands are defined in the `Commands` array in `config.json`: + +```json +"Commands": [ + { "Name": "help", "Enabled": true, "Prefix": "help" }, + { "Name": "rights", "Enabled": false, "Prefix": "rights" }, + ... +] +``` diff --git a/Database-Setup.md b/Database-Setup.md new file mode 100644 index 0000000..125d44a --- /dev/null +++ b/Database-Setup.md @@ -0,0 +1,141 @@ +# Database Setup + +Erupe uses PostgreSQL. The schema is managed through three layers: a base dump, incremental patches, and optional demo data. + +## Initial Setup + +Create the database and restore the base schema (pg_dump custom format, not plain SQL): + +```bash +createdb -U postgres erupe +pg_restore -U postgres -d erupe schemas/init.sql +``` + +This bootstraps the schema to v9.1.0. + +## Patch Schemas + +Apply all files in `schemas/patch-schema/` **in numerical order**. Each patch is idempotent but must follow the previous ones: + +```bash +for f in schemas/patch-schema/*.sql; do + psql -U postgres -d erupe -f "$f" +done +``` + +Notable patches: +| Patch | Effect | +|-------|--------| +| `00-psn-id.sql` | Adds PSN ID column to users | +| `02-tower.sql` | Adds Tower mode tables | +| `08-kill-counts.sql` | Adds kill_logs table | +| `10-rework-distributions.sql` | Migrates distribution system (**deletes old distribution data**) | +| `12-event_quest_cycling.sql` | Adds event quest rotation timestamps | +| `14-fix-fpoint-trades.sql` | Reworks FPoint shop (**deletes old FPoint items**) | +| `16-discord-password-resets.sql` | Adds Discord account linking columns | + +## Bundled Demo Data + +Optional SQL files in `schemas/bundled-schema/` populate game content. Load any you want: + +```bash +psql -U postgres -d erupe -f schemas/bundled-schema/EventQuests.sql +``` + +| File | Content | +|------|---------| +| `DistributionDemo.sql` | Gift box items (equipment, item box pages) | +| `DivaShops.sql` | Diva Defense shop items | +| `EventQuests.sql` | ~200+ event quest definitions | +| `FestaDefaults.sql` | Festa prize tiers (personal/guild, soul thresholds) | +| `FPointItems.sql` | ~100+ Frontier Point shop items | +| `GachaDemo.sql` | 3 gacha examples (normal, step-up, box) | +| `NetcafeDefaults.sql` | Net Cafe bonus items | +| `OtherShops.sql` | Miscellaneous shop data | +| `RoadShopItems.sql` | Road shop unlockables | +| `ScenarioDefaults.sql` | Scenario counter initialization | + +## Key Tables + +### Users & Characters + +| Table | Purpose | +|-------|---------| +| `users` | Accounts (bcrypt password, rights bitmask, PSN ID, Discord token) | +| `characters` | Character data with ~17 bytea savedata fields | +| `sign_sessions` | Active authentication tokens | +| `bans` | Ban records with optional expiry | + +### Game Content + +| Table | Purpose | +|-------|---------| +| `distribution` + `distribution_items` | Gift box system (login bonuses, GM gifts) | +| `event_quests` | Event quest rotation (quest_type, quest_id, cycling timestamps) | +| `gacha_shop` + `gacha_entries` + `gacha_items` | Gacha lottery (normal, step-up, box) | +| `shop_items` | Shop inventory (cost, HR/SR/GR requirements) | +| `fpoint_items` | Frontier Point shop | +| `cafebonus` | Net Cafe time-based bonuses | +| `scenario_counter` | Scenario/cutscene unlock tracking | + +### Guilds (14 tables) + +| Table | Purpose | +|-------|---------| +| `guilds` | Guild info (name, leader, RP, icon, recruiting) | +| `guild_characters` | Membership and roles | +| `guild_applications` | Pending invites/applications | +| `guild_posts` | Bulletin board | +| `guild_adventures` | Guild adventure tracking | +| `guild_hunts` | Guild hunt records | +| `guild_meals` | Guild meal cooking | +| `guild_alliances` | Inter-guild alliances | + +### Events + +| Table | Purpose | +|-------|---------| +| `events` | Active events (type: festa/diva/vs/mezfes) | +| `festa_registrations` | Festa sign-ups | +| `festa_trials` + `festa_prizes` | Festa scores and rewards | +| `feature_weapon` | Daily featured weapon rotation | +| `tower` | Tower mode progress (TR, TRP, TSP) | +| `rengoku_score` | Rengoku survival scores | +| `kill_logs` | Monster kill tracking | + +## Common Admin Operations + +### Add an event quest +```sql +INSERT INTO event_quests (max_players, quest_type, quest_id, mark) +VALUES (4, 28, 23045, 2); +``` +See [Enumerations](Enumerations#event-quests) for quest type and mark values. + +### Create a gift distribution +```sql +INSERT INTO distribution (type, deadline, event_name, description, times_acceptable) +VALUES (1, '2099-12-31', 'Welcome Gift', 'A gift for new hunters', 1) +RETURNING id; + +INSERT INTO distribution_items (distribution_id, item_type, item_id, quantity) +VALUES (, 7, 482, 10); +``` +See [Enumerations](Enumerations#distribution-types) for type/item_type values. + +### Ban a user +```sql +INSERT INTO bans (user_id, expires_at) +VALUES (, NOW() + INTERVAL '7 days'); +``` + +### Reset Raviente +```sql +SELECT ravireset(0); +``` + +### Check active sessions +```sql +SELECT u.username, s.token FROM sign_sessions s +JOIN users u ON u.id = s.user_id; +``` diff --git a/Home.md b/Home.md index 518aebb..906c463 100644 --- a/Home.md +++ b/Home.md @@ -1,3 +1,80 @@ ## What is Erupe? -Erupe is a server emulator for Monster Hunter Frontier written in Golang. +Erupe is a community-maintained server emulator for Monster Hunter Frontier, written in Go. It implements the sign, entrance, and channel servers needed to play the game after Capcom shut down the official servers in December 2019. All code is clean-room reverse-engineered from protocol analysis. + +Most core systems are functional: quests, guilds, multiplayer, shops/gacha, mail, character saves, and housing. Some endgame event systems (tournaments, tower) have minimal implementations. See [Client Versions](Client-Versions) for supported game versions (Season 6.0 through ZZ). + +## Getting Started + +### Prerequisites + +- **Go 1.25+** +- **PostgreSQL** (14+ recommended) +- **Game client files** — legally obtained MHF client (quest/scenario binaries go in `bin/`) + +### 1. Set Up the Database + +Create a PostgreSQL database named `erupe`, then restore the base schema: + +```bash +createdb -U postgres erupe +pg_restore -U postgres -d erupe schemas/init.sql +``` + +The `init.sql` is a pg_dump archive (not plain SQL) that bootstraps the schema to v9.1.0. + +Then apply patch schemas **in numerical order**: + +```bash +psql -U postgres -d erupe -f schemas/patch-schema/00-psn-id.sql +psql -U postgres -d erupe -f schemas/patch-schema/01-wiiu-key.sql +# ... continue through all patches +``` + +Optionally load demo data from `schemas/bundled-schema/` for shops, events, gacha, etc.: + +```bash +psql -U postgres -d erupe -f schemas/bundled-schema/EventQuests.sql +psql -U postgres -d erupe -f schemas/bundled-schema/OtherShops.sql +# ... any others you want +``` + +### 2. Configure + +Copy `config.example.json` to `config.json` and edit it. At minimum, set: +- `Host` — your server IP (or `127.0.0.1` for local play) +- `Database` — PostgreSQL connection details +- `ClientMode` — must match your game client version (default: `ZZ`) + +See [Erupe Configuration](Erupe-Configuration) for full reference. + +### 3. Build and Run + +```bash +go build -o erupe-ce +./erupe-ce +``` + +### Docker Alternative + +From the `docker/` directory: + +```bash +docker compose up db pgadmin # Start PostgreSQL + pgAdmin (http://localhost:5050) +# Use pgAdmin to restore init.sql and apply patch schemas +docker compose up server # Start Erupe +``` + +## Wiki Pages + +### Setup & Operations +- **[Database Setup](Database-Setup)** — schema management, table reference, bundled demo data, common admin SQL +- **[Server Operations](Server-Operations)** — quest/scenario files, save system, REST API, Discord bot, Docker +- **[Erupe Configuration](Erupe-Configuration)** — full config.json reference (general, debug, gameplay, worlds, courses) +- **[Commands](Commands)** — in-game chat commands (general, admin, Raviente) + +### Reference +- **[Enumerations](Enumerations)** — distribution types, item types, course types, quest types and flags +- **[Client Versions](Client-Versions)** — all MHF versions from Season 1.0 to Z3.1 with dates, platforms, and ClientMode IDs +- **[Scenarios](Scenarios)** — scenario quest database with IDs and dates (Forward through end-of-service) +- **[Hard Core Monsters Schedule Map](Hard-Core-Monsters-Schedule-Map)** — HC/GHC monster schedule data from mhfsch.bin diff --git a/Server-Operations.md b/Server-Operations.md new file mode 100644 index 0000000..2c0ffc8 --- /dev/null +++ b/Server-Operations.md @@ -0,0 +1,172 @@ +# Server Operations + +## Quest & Scenario Files + +The `bin/` directory (configured via `BinPath` in config.json) holds game data files the server sends to clients. + +``` +bin/ +├── quests/ # Quest binary files +├── scenarios/ # Cutscene/scenario files +├── events/ # Organized quest archives (not read by server) +├── rengoku_data.bin # Rengoku survival mode config +└── save_override.bin # Optional: forces savedata values on character creation +``` + +### Quest File Naming + +Files in `quests/` follow this pattern: + +``` +[questID][time][season].bin +``` + +- **questID**: 5-digit hex ID (e.g., `23045`) +- **time**: `d` = day, `n` = night +- **season**: `0` = warm, `1` = cold, `2` = breeding + +Example: `23045d1.bin` is quest 23045, daytime, cold season. + +If `SeasonOverride` is enabled in the config, the server converts quest filenames to match the current in-game season automatically. + +### Scenario File Naming + +Files in `scenarios/` follow this pattern: + +``` +[CategoryID]_0_0_0_S[MainID]_T[Flags]_C[ChapterID].bin +``` + +Missing scenario files will crash the client — make sure all referenced scenarios have corresponding files. + +### Quest Caching + +Decrypted quest data is cached in memory. The cache expires after `QuestCacheExpiry` seconds (default: 300). Encrypted quest files are auto-decrypted on load. + +### Quest Backporting + +If `ClientMode` is set to Z1 or earlier, quest data is automatically backported for compatibility with older clients. + +## Save Data + +### Character Saves + +Character data is stored in the `characters` table across ~17 bytea columns: `savedata`, `decomyset`, `hunternavi`, `otomoairou`, `partner`, `platebox`, `platedata`, `platemyset`, `rengokudata`, `savemercenary`, `minidata`, `gacha_items`, `house_info`, `login_boost`, `skin_hist`, `scenariodata`, `savefavoritequest`. + +Save data offsets vary by game version (the server reads different offsets depending on `ClientMode`). + +### Save Backups + +Configured in `config.json`: + +```json +"SaveDumps": { + "Enabled": true, + "RawEnabled": false, + "OutputDir": "save-backups" +} +``` + +When enabled, every save operation writes a backup to `save-backups//`. Set `RawEnabled` to also dump the uncompressed save data. + +### Save Corruption + +If `DeleteOnSaveCorruption` is enabled, characters with corrupt save data are flagged as deleted. When disabled (default), the character remains in the database but may be unplayable. + +## API Server + +The optional REST API (default port 8080) provides launcher integration and account management. + +### Launcher Endpoints + +| Method | Path | Purpose | +|--------|------|---------| +| GET | `/launcher` | Launcher splash page (banners, messages, links) | +| POST | `/login` | Authenticate (username/password → token + character list) | +| POST | `/register` | Create account | +| POST | `/character/create` | Create character (requires token) | +| POST | `/character/delete` | Delete character (requires token + charId) | +| POST | `/character/export` | Export character save data | + +### Screenshot Endpoints + +| Method | Path | Purpose | +|--------|------|---------| +| POST | `/api/ss/bbs/upload.php` | Upload screenshot (JPEG, requires token) | +| GET | `/api/ss/bbs/{id}` | Retrieve screenshot | + +Screenshot config: +```json +"Screenshots": { + "Enabled": true, + "OutputDir": "screenshots", + "UploadQuality": 100 +} +``` + +## Discord Integration + +### Setup + +1. Create a bot on the [Discord Developer Portal](https://discord.com/developers/applications) with the `applications.commands` scope +2. Configure in `config.json`: + +```json +"Discord": { + "Enabled": true, + "BotToken": "YOUR_BOT_TOKEN", + "RelayChannel": { + "Enabled": true, + "MaxMessageLength": 183, + "RelayChannelID": "CHANNEL_ID" + } +} +``` + +### Slash Commands + +Registered automatically when the bot starts: + +| Command | Description | +|---------|-------------| +| `/link ` | Link Discord account to Erupe account (token from `!discord` in-game) | +| `/password ` | Change password (requires linked account) | + +### Chat Relay + +When `RelayChannel` is enabled: +- **Game → Discord**: World chat and stage chat are relayed to the configured Discord channel +- **Discord → Game**: Messages from the Discord channel appear in-game with a `[D]` prefix + +Messages are normalized: Discord mentions become `@username`, emoji become `:emoji_name:`, and non-ASCII characters are stripped. Long messages are split into 61-character chunks to fit the in-game chat. + +## Docker + +### Services + +| Service | Port | Purpose | +|---------|------|---------| +| `db` | 5432 | PostgreSQL (auto-inits schema on first run via `setup.sh`) | +| `pgadmin` | 5050 | Database admin UI (`user@pgadmin.com` / `password`) | +| `server` | 53312, 8080, 53310, 54001-54008 | Erupe | +| `web` | 80 | Apache for patch file hosting | + +### Workflow + +```bash +cd docker/ +docker compose up db pgadmin # 1. Start DB (auto-applies schemas on first run) +# Configure config.json (use "db" as database host) +# Place quest/scenario files in bin/ +docker compose up server # 2. Start Erupe +``` + +### Data Persistence + +- Database: `docker/db-data/` +- Save data: `docker/savedata/` +- Full wipe: `docker compose down` then delete these directories + +### Troubleshooting + +If PostgreSQL doesn't initialize properly, check that `docker/init/setup.sh` has LF line endings (not CRLF).