docs: adds documentation files for the major configurable options.

This commit is contained in:
Houmgaor
2025-11-18 00:44:17 +01:00
parent 9a47a876eb
commit aa638b791d
12 changed files with 3439 additions and 0 deletions

356
CLAUDE.md Normal file
View File

@@ -0,0 +1,356 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Erupe is a community-maintained server emulator for Monster Hunter Frontier written in Go. It reverse-engineers the game server protocol to enable self-hosted Monster Hunter Frontier servers, supporting multiple game versions (Season 6.0 through ZZ) and platforms (PC, PS3, PS Vita, Wii U).
**Module name:** `erupe-ce`
**Go version:** 1.25+
**Current branch purpose:** Clean transition from 9.2.0 to future 9.3.0 release
## Build and Development Commands
### Building and Running
```bash
# Build the server
go build
# Build and produce binary
go build -o erupe-ce
# Run without building
go run .
# Run with hot reload during development
go run main.go
```
### Testing
```bash
# Run all tests
go test -v ./...
# Run tests for specific package
go test -v ./server/channelserver/...
# Run specific test
go test -v ./server/channelserver/... -run TestName
# Check for race conditions (important!)
go test -v -race ./...
# Generate test coverage
go test -v -cover ./...
go test ./... -coverprofile=/tmp/coverage.out
go tool cover -html=/tmp/coverage.out -o /tmp/coverage.html
```
### Code Quality
```bash
# Format code (ALWAYS run before committing)
gofmt -w .
# Lint code
golangci-lint run ./...
# Fix linting issues automatically
golangci-lint run ./... --fix
```
### Database Operations
```bash
# Connect to PostgreSQL
psql -U postgres -d erupe
# Apply schema patches (must be done in order)
psql -U postgres -d erupe -f patch-schema/01_patch.sql
psql -U postgres -d erupe -f patch-schema/02_patch.sql
# ... continue in order
# With password from environment
PGPASSWORD='password' psql -U postgres -d erupe -f schema.sql
```
### Docker Development
```bash
# Start database and pgadmin
docker compose up db pgadmin
# Start server (after configuring database)
docker compose up server
# Full stack
docker compose up
```
### Log Analysis
The project includes a comprehensive log analyzer tool in `tools/loganalyzer/`:
```bash
# Build log analyzer
cd tools/loganalyzer
go build -o loganalyzer
# Filter logs by level
./loganalyzer filter -f ../../logs/erupe.log -level error
# Analyze errors with stack traces
./loganalyzer errors -f ../../logs/erupe.log -stack -detailed
# Track player connections
./loganalyzer connections -f ../../logs/erupe.log -sessions
# Real-time log monitoring
./loganalyzer tail -f ../../logs/erupe.log -level error
# Generate statistics
./loganalyzer stats -f ../../logs/erupe.log -detailed
```
## Architecture
### Three-Server Architecture
Erupe uses a multi-server architecture that mirrors the original Monster Hunter Frontier server design:
1. **Sign Server** (Port 53312)
- Handles authentication and account management
- Located in `server/signserver/`
- Two versions: legacy (signserver) and modern HTTP-based (signv2server)
- Creates sign sessions with tokens for channel server authentication
2. **Entrance Server** (Port 53310)
- Manages world/server selection and character list
- Located in `server/entranceserver/`
- Routes players to available channel servers
- Maintains server availability information
3. **Channel Servers** (Ports 54001+)
- Handle actual gameplay sessions, quests, and player interactions
- Located in `server/channelserver/`
- Multiple instances can run simultaneously
- Organized by world types (Newbie, Normal, Cities, Tavern, Return, MezFes)
### Channel Server Internal Architecture
The channel server is the most complex component:
**Session Management** ([sys_session.go](server/channelserver/sys_session.go))
- Each player connection creates a `Session` struct
- Sessions handle packet queuing, encryption, and client state
- Uses goroutines for send/receive loops
- Thread-safe with mutex locks
**Handler System** ([handlers_table.go](server/channelserver/handlers_table.go))
- Packet handlers registered in `handlerTable` map
- Maps `network.PacketID` to `handlerFunc`
- Handlers organized by feature in separate files:
- `handlers_quest.go` - Quest system
- `handlers_guild.go` - Guild operations
- `handlers_stage.go` - Stage/room management
- `handlers_character.go` - Character data
- `handlers_*.go` - Feature-specific handlers
**Stage System** ([sys_stage.go](server/channelserver/sys_stage.go))
- Stages are game rooms/areas where players interact
- Thread-safe stage creation, entry, movement, and destruction
- Stage locking/unlocking for privacy
- Stage binary data for synchronizing state between players
**Semaphore System** ([sys_semaphore.go](server/channelserver/sys_semaphore.go))
- Resource locking mechanism for shared game resources
- Used for quests, events, and multiplayer coordination
- Global and local semaphores
**Special Event Systems**
- Raviente: Large-scale raid event (in `Server.raviente`)
- Diva Defense, Hunter's Festa, VS Tournament (handlers in `handlers_event.go`, `handlers_festa.go`, `handlers_tournament.go`)
### Network Layer
**Packet Structure** ([network/mhfpacket/](network/mhfpacket/))
- Packet definitions in `msg_*.go` files
- Each packet type implements `MHFPacket` interface
- Packets prefixed by type: `MSG_SYS_*`, `MSG_MHF_*`, `MSG_CA_*`
- Binary packet handling in `network/binpacket/`
**Encryption** ([network/crypt_packet.go](network/crypt_packet.go))
- Custom encryption layer wrapping connections
- Different crypto for different server types
**Compression** ([server/channelserver/compression/](server/channelserver/compression/))
- Delta compression (`deltacomp`) for bandwidth optimization
- Null compression (`nullcomp`) for debugging
### Common Utilities
**ByteFrame** ([common/byteframe/](common/byteframe/))
- Buffer for reading/writing binary data
- Provides methods for reading/writing various data types
- Critical for packet construction and parsing
**PascalString** ([common/pascalstring/](common/pascalstring/))
- Length-prefixed string format used by game protocol
- Different variants for different string types
**Client Context** ([network/clientctx/](network/clientctx/))
- Stores client version and capabilities
- Used for multi-version support
## Database Schema Management
**Schema Types:**
- **Initialization Schema:** Bootstraps database to version 9.1.0 (in `schemas/`)
- **Patch Schemas:** Development updates in `patch-schema/` (numbered, apply in order)
- **Update Schemas:** Production-ready consolidated updates (for releases)
- **Bundled Schemas:** Demo data templates in `schemas/bundled-schema/` (shops, events, gacha)
**Important:** Patch schemas are subject to change during development. They get consolidated into update schemas on release. Apply patches in numerical order.
## Configuration System
Configuration uses Viper and is defined in `config/config.go`. The `ErupeConfig` global variable holds runtime configuration loaded from `config.json`.
**Key configuration sections:**
- `DevMode` and `DevModeOptions` - Development flags and debugging
- `GameplayOptions` - Gameplay modifiers (NP/RP caps, boost times, quest allowances)
- `Database` - PostgreSQL connection settings
- `Sign`, `SignV2`, `Entrance`, `Channel` - Server enable/disable and ports
- `Discord` - Discord bot integration
- `Logging` - File logging with rotation (uses lumberjack)
## Concurrency Patterns
**Critical:** This codebase heavily uses goroutines and shared state. Always:
1. Use mutexes when accessing shared state:
- Server-level: `s.server.Lock()` / `s.server.Unlock()`
- Stage-level: `s.server.stagesLock.Lock()` / `s.server.stagesLock.Unlock()`
- Session-level: `s.Lock()` / `s.Unlock()`
2. Use RWMutex for read-heavy operations:
- `s.server.stagesLock.RLock()` for reads
- `s.server.stagesLock.Lock()` for writes
3. Test with race detector:
```bash
go test -race ./...
```
4. Common concurrency scenarios:
- Stage access: Always lock `s.server.stagesLock` when reading/writing stage map
- Session broadcasts: Iterate sessions under lock
- Database operations: Use transactions for multi-step operations
## Packet Handler Development
When adding new packet handlers:
1. Define packet structure in `network/mhfpacket/msg_*.go`
2. Implement `Build()` and `Parse()` methods
3. Add handler function in appropriate `handlers_*.go` file
4. Register in `handlerTable` map in `handlers_table.go`
5. Use helper functions:
- `doAckBufSucceed(s, ackHandle, data)` - Success response with data
- `doAckBufFail(s, ackHandle, data)` - Failure response
- `stubEnumerateNoResults(s, ackHandle)` - Empty enumerate response
- `stubGetNoResults(s, ackHandle)` - Empty get response
Example handler pattern:
```go
func handleMsgMhfYourPacket(s *Session, p mhfpacket.MHFPacket) {
pkt := p.(*mhfpacket.MsgMhfYourPacket)
// Process packet
resp := byteframe.NewByteFrame()
resp.WriteUint32(someValue)
doAckBufSucceed(s, pkt.AckHandle, resp.Data())
}
```
## Testing Practices
- Use table-driven tests for multiple scenarios
- Mock database operations where appropriate
- Test concurrent access patterns with goroutines
- Test both success and error paths
- Add tests in `*_test.go` files next to source files
## Common Pitfalls
1. **Thread Safety:** Always consider concurrent access. If unsure, add locks.
2. **Database Queries:** Use parameterized queries (`$1`, `$2`) to prevent SQL injection
3. **Error Handling:** Never ignore errors - log them or handle appropriately
4. **Session State:** Be careful with session state during disconnects
5. **Packet Ordering:** Some packets have ordering requirements - check client expectations
6. **Binary Data:** Always use `byteframe` for binary reads/writes to ensure correct endianness
## Commit and PR Guidelines
**Commit message format:**
- `feat: description` - New features
- `fix: description` - Bug fixes
- `refactor: description` - Code refactoring
- `docs: description` - Documentation
- `chore: description` - Maintenance tasks
**Before committing:**
1. Run `gofmt -w .`
2. Run tests: `go test -v ./...`
3. Check for race conditions: `go test -race ./...`
4. Update CHANGELOG.md under "Unreleased" section
**PR Requirements:**
- Clear description of changes
- Test coverage for new features
- No race conditions
- Passes all existing tests
- Updated documentation if needed
## Discord Integration
Optional Discord bot in `server/discordbot/` provides:
- Real-time server activity notifications
- Player connection/disconnection events
- Quest completions and event notifications
Configured via `Discord` section in config.json.
## Multi-Version Support
The codebase supports multiple game client versions through:
- `ClientMode` configuration setting
- Client context detection
- Version-specific packet handling
- Binary file compatibility (quests/scenarios in `bin/`)
Primary focus: G10-ZZ (ClientMode), with varying support for older versions.

249
docs/README.md Normal file
View File

@@ -0,0 +1,249 @@
# Erupe Configuration Documentation
Comprehensive configuration documentation for Erupe, the Monster Hunter Frontier server emulator.
## Quick Start
1. Copy [config.example.json](../config.example.json) to `config.json`
2. Read [Basic Settings](basic-settings.md) and [Server Configuration](server-configuration.md)
3. Set up [Database](database.md)
4. Adjust [Gameplay Options](gameplay-options.md) to your preference
5. Start the server!
## Documentation Index
### Essential Configuration
- **[Basic Settings](basic-settings.md)** - Host, language, and basic server options
- **[Server Configuration](server-configuration.md)** - Sign, Entrance, and Channel server setup
- **[Database](database.md)** - PostgreSQL configuration and schema management
### Development
- **[Development Mode](development-mode.md)** - Debug options, packet logging, and testing tools
- **[Logging](logging.md)** - File logging, rotation, and log analysis
### Gameplay & Features
- **[Gameplay Options](gameplay-options.md)** - NP/RP caps, boost times, quest allowances
- **[Courses](courses.md)** - Subscription course configuration
- **[In-Game Commands](commands.md)** - Chat commands for players and admins
### Optional Features
- **[Discord Integration](discord-integration.md)** - Real-time Discord bot for server activity
## Configuration File Structure
The main configuration file is `config.json` with this structure:
```json
{
"Host": "127.0.0.1",
"BinPath": "bin",
"Language": "en",
"DevMode": false,
"DevModeOptions": { ... },
"GameplayOptions": { ... },
"Logging": { ... },
"Discord": { ... },
"Commands": [ ... ],
"Courses": [ ... ],
"Database": { ... },
"Sign": { ... },
"SignV2": { ... },
"Channel": { ... },
"Entrance": { ... }
}
```
## Configuration Sections
| Section | Documentation | Purpose |
|---------|---------------|---------|
| Basic Settings | [basic-settings.md](basic-settings.md) | Host, paths, language, login notices |
| DevMode | [development-mode.md](development-mode.md) | Development and debugging options |
| GameplayOptions | [gameplay-options.md](gameplay-options.md) | Gameplay balance and modifiers |
| Logging | [logging.md](logging.md) | File logging and rotation |
| Discord | [discord-integration.md](discord-integration.md) | Discord bot integration |
| Commands | [commands.md](commands.md) | In-game chat commands |
| Courses | [courses.md](courses.md) | Subscription courses |
| Database | [database.md](database.md) | PostgreSQL connection |
| Sign/SignV2 | [server-configuration.md](server-configuration.md#sign-server) | Authentication servers |
| Channel | [server-configuration.md](server-configuration.md#channel-server) | Gameplay server |
| Entrance | [server-configuration.md](server-configuration.md#entrance-server) | World list server |
## Common Configuration Scenarios
### Local Development Server
Perfect for testing and development:
```json
{
"Host": "127.0.0.1",
"DevMode": true,
"DevModeOptions": {
"AutoCreateAccount": true,
"MaxLauncherHR": true
},
"Database": {
"Host": "localhost",
"User": "postgres",
"Password": "dev",
"Database": "erupe_dev"
}
}
```
See: [development-mode.md](development-mode.md)
### Production Server (Minimal)
Minimal production-ready configuration:
```json
{
"Host": "",
"DevMode": false,
"DisableSoftCrash": true,
"Logging": {
"LogToFile": true,
"LogMaxBackups": 7,
"LogMaxAge": 30
},
"Database": {
"Host": "localhost",
"User": "erupe",
"Password": "SECURE_PASSWORD_HERE",
"Database": "erupe"
}
}
```
See: [basic-settings.md](basic-settings.md), [logging.md](logging.md)
### Community Server
Feature-rich community server:
```json
{
"Host": "",
"DevMode": false,
"HideLoginNotice": false,
"LoginNotices": ["Welcome to our server!"],
"GameplayOptions": {
"MaximumNP": 999999,
"BoostTimeDuration": 240
},
"Discord": {
"Enabled": true,
"BotToken": "YOUR_TOKEN",
"RealtimeChannelID": "YOUR_CHANNEL_ID"
},
"Commands": [
{"Name": "Reload", "Enabled": true, "Prefix": "!reload"},
{"Name": "Course", "Enabled": true, "Prefix": "!course"}
]
}
```
See: [gameplay-options.md](gameplay-options.md), [discord-integration.md](discord-integration.md), [commands.md](commands.md)
## Security Checklist
Before running a public server, verify:
- [ ] `DevMode: false` - Disable development mode
- [ ] `AutoCreateAccount: false` - Require manual account creation
- [ ] `DisableTokenCheck: false` - Enable token validation
- [ ] `CleanDB: false` - Don't wipe database on startup
- [ ] Strong database password set
- [ ] `Rights` command disabled (or carefully controlled)
- [ ] `KeyQuest` command disabled (unless intentional)
- [ ] Firewall configured for only necessary ports
- [ ] Database not exposed publicly
- [ ] Logging enabled for monitoring
See: [development-mode.md#security-warnings](development-mode.md#security-warnings)
## Performance Tuning
For large servers:
1. **Increase player limits**: Adjust `MaxPlayers` in channel configuration
2. **Add more channels**: Distribute load across multiple channel servers
3. **Optimize database**: Use connection pooling, increase shared buffers
4. **Increase log rotation**: Larger `LogMaxSize` and `LogMaxBackups`
5. **Monitor resources**: Use log analyzer to track errors and performance
See: [server-configuration.md](server-configuration.md), [database.md#performance-tuning](database.md#performance-tuning)
## Configuration Validation
Erupe validates configuration on startup. Common errors:
| Error | Cause | Fix |
|-------|-------|-----|
| "Database password is blank" | Empty password field | Set a password in config |
| "Invalid host address" | Malformed Host value | Use valid IP or leave empty for auto-detect |
| "Discord failed" | Invalid Discord config | Check bot token and channel ID |
| Port already in use | Port conflict | Change port or stop conflicting service |
## Environment-Specific Configuration
### Docker
When running in Docker, use service names for hosts:
```json
{
"Database": {
"Host": "db",
"Port": 5432
}
}
```
See: [database.md#docker-setup](database.md#docker-setup)
### Cloud Hosting
For cloud deployments:
- Use environment variables for secrets (requires code modification)
- Enable `DisableSoftCrash: true` for auto-restart
- Use absolute paths for logs (`/var/log/erupe/erupe.log`)
- Consider external database (RDS, Cloud SQL)
## Additional Resources
- [CLAUDE.md](../CLAUDE.md) - Development guide and architecture
- [config.example.json](../config.example.json) - Full example configuration
- [Log Analyzer](../tools/loganalyzer/) - Log analysis tools
- [GitHub Issues](https://github.com/Andoryuuta/Erupe/issues) - Report bugs and request features
## Getting Help
If you need help with configuration:
1. Check the relevant documentation page above
2. Review [config.example.json](../config.example.json) for examples
3. Check server logs for specific errors
4. Search [GitHub Issues](https://github.com/Andoryuuta/Erupe/issues)
5. Ask in the Erupe Discord community
## Contributing
Found an error or want to improve these docs?
1. Fork the repository
2. Edit the documentation in `docs/`
3. Submit a pull request
See [CLAUDE.md](../CLAUDE.md#commit-and-pr-guidelines) for contribution guidelines.

89
docs/basic-settings.md Normal file
View File

@@ -0,0 +1,89 @@
# Basic Server Settings
Basic configuration options for Erupe server hosting.
## Configuration
```json
{
"Host": "127.0.0.1",
"BinPath": "bin",
"Language": "en",
"DisableSoftCrash": false,
"HideLoginNotice": true,
"LoginNotices": [
"<BODY><CENTER><SIZE_3><C_4>Welcome to Erupe!"
],
"PatchServerManifest": "",
"PatchServerFile": "",
"ScreenshotAPIURL": "",
"DeleteOnSaveCorruption": false
}
```
## Settings Reference
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `Host` | string | auto-detect | Server IP address. Leave empty to auto-detect. Use `"127.0.0.1"` for local hosting |
| `BinPath` | string | `"bin"` | Path to binary game data (quests, scenarios, etc.) |
| `Language` | string | `"en"` | Server language. `"en"` for English, `"jp"` for Japanese |
| `DisableSoftCrash` | boolean | `false` | When `true`, server exits immediately on crash (useful for auto-restart scripts) |
| `HideLoginNotice` | boolean | `true` | Hide the Erupe welcome notice on login |
| `LoginNotices` | array | `[]` | Custom MHFML-formatted login notices to display to players |
| `PatchServerManifest` | string | `""` | Override URL for patch manifest server (optional) |
| `PatchServerFile` | string | `""` | Override URL for patch file server (optional) |
| `ScreenshotAPIURL` | string | `""` | Destination URL for screenshots uploaded to BBS (optional) |
| `DeleteOnSaveCorruption` | boolean | `false` | If `true`, corrupted save data will be flagged for deletion |
## Login Notices
Login notices use MHFML (Monster Hunter Frontier Markup Language) formatting:
```text
<BODY><CENTER><SIZE_3><C_4>Large Centered Red Text<BR>
<BODY><LEFT><SIZE_2><C_5>Normal Left-Aligned Yellow Text<BR>
<BODY><C_7>White Text
```
**Common MHFML Tags:**
- `<BODY>` - Start new line
- `<BR>` - Line break
- `<CENTER>`, `<LEFT>`, `<RIGHT>` - Text alignment
- `<SIZE_2>`, `<SIZE_3>` - Text size
- `<C_4>` (Red), `<C_5>` (Yellow), `<C_7>` (White) - Text color
## Examples
### Local Development Server
```json
{
"Host": "127.0.0.1",
"BinPath": "bin",
"Language": "en",
"DisableSoftCrash": false,
"HideLoginNotice": false
}
```
### Production Server with Auto-Restart
```json
{
"Host": "",
"BinPath": "bin",
"Language": "en",
"DisableSoftCrash": true,
"HideLoginNotice": false,
"LoginNotices": [
"<BODY><CENTER><SIZE_3><C_4>Welcome to Our Server!<BR><BODY><LEFT><SIZE_2><C_5>Join our Discord: discord.gg/example"
]
}
```
## Related Documentation
- [Server Configuration](server-configuration.md) - Server types and ports
- [Configuration Overview](README.md) - All configuration options

335
docs/commands.md Normal file
View File

@@ -0,0 +1,335 @@
# In-Game Commands
In-game chat commands for players and administrators.
## Configuration
```json
{
"Commands": [
{
"Name": "Rights",
"Enabled": false,
"Prefix": "!rights"
},
{
"Name": "Raviente",
"Enabled": true,
"Prefix": "!ravi"
},
{
"Name": "Teleport",
"Enabled": false,
"Prefix": "!tele"
},
{
"Name": "Reload",
"Enabled": true,
"Prefix": "!reload"
},
{
"Name": "KeyQuest",
"Enabled": false,
"Prefix": "!kqf"
},
{
"Name": "Course",
"Enabled": true,
"Prefix": "!course"
}
]
}
```
## How Commands Work
1. **Player Types Command**: Player sends a chat message starting with the command prefix
2. **Command Parser**: Server checks if message matches any enabled command prefix
3. **Command Handler**: Executes the command logic
4. **Response**: Server sends feedback message to the player
Commands are parsed in [handlers_cast_binary.go:90](../server/channelserver/handlers_cast_binary.go#L90).
## Available Commands
### Reload
**Prefix:** `!reload`
**Recommended:** Enabled
**Usage:** `!reload`
Reloads all players and objects in the current stage:
1. Removes all other players/objects from view
2. Waits 500ms
3. Re-adds all players/objects with updated data
**Use Cases:**
- Visual glitches (players appearing in wrong positions)
- Objects not displaying correctly
- Stage synchronization issues
**Example:**
```text
Player types: !reload
Server: "Reloading all players and objects..."
[View refreshes]
```
### Raviente
**Prefix:** `!ravi`
**Recommended:** Enabled
**Usage:** `!ravi <subcommand>`
Control Raviente raid event.
**Subcommands:**
- `!ravi start` - Start the Raviente event
- `!ravi cm` or `!ravi checkmultiplier` - Check current damage multiplier
**Examples:**
```text
Player types: !ravi start
Server: "Raviente event started!"
Player types: !ravi cm
Server: "Current Raviente multiplier: 2.5x"
```
### Course
**Prefix:** `!course`
**Recommended:** Enabled
**Usage:** `!course <course_name>`
Enable or disable subscription courses for your character.
**Course Names:**
- `hunterlife` or `hl` - Hunter Life Course
- `extra` or `ex` - Extra Course
- `premium` - Premium Course
- `assist` - Assist Course
- `n` - N Course
- `hiden` - Hiden Course
- `huntersupport` or `hs` - Hunter Support Course
- `nboost` - N Boost Course
- `netcafe` or `nc` - NetCafe Course
- `hlrenewing` - Hunter Life Renewing Course
- `exrenewing` - Extra Renewing Course
**Note:** Only courses with `Enabled: true` in the [Courses](courses.md) configuration can be toggled.
**Examples:**
```text
Player types: !course premium
Server: "Premium Course enabled!"
[Player's account rights updated]
Player types: !course premium
Server: "Premium Course disabled!"
[Toggled off]
Player types: !course hiden
Server: "Hiden Course is locked on this server"
[Course not enabled in config]
```
### KeyQuest (KQF)
**Prefix:** `!kqf`
**Recommended:** Disabled (unless intentional)
**Usage:** `!kqf get` or `!kqf set <hex>`
Get or set Key Quest flags (unlocks).
**Subcommands:**
- `!kqf get` - Display current KQF value
- `!kqf set <16-char hex>` - Set KQF value
**Examples:**
```text
Player types: !kqf get
Server: "Your KQF is: 0123456789ABCDEF"
Player types: !kqf set 0000000000000000
Server: "KQF set successfully!"
[Quest unlocks updated]
Player types: !kqf set invalid
Server: "Usage: !kqf set <16 hex characters>"
```
**Warning:** This allows players to unlock content. Disable unless you want players to have this power.
### Rights
**Prefix:** `!rights`
**Recommended:** Disabled
**Usage:** `!rights <number>`
Modify account rights/permissions (bitfield of enabled courses and permissions).
**Example:**
```text
Player types: !rights 255
Server: "Account rights set to: 255"
[All courses/permissions enabled]
Player types: !rights abc
Server: "Usage: !rights <number>"
```
**⚠️ SECURITY WARNING:** This allows players to grant themselves admin privileges and all courses. **Only enable in development or for trusted administrators.**
### Teleport
**Prefix:** `!tele`
**Recommended:** Disabled (not yet implemented)
**Usage:** `!tele <location>`
Teleport to specific locations.
**Status:** Command structure exists but handler not fully implemented in the codebase.
## Command Configuration
Each command has three properties:
```json
{
"Name": "CommandName",
"Enabled": true,
"Prefix": "!prefix"
}
```
| Property | Type | Description |
|----------|------|-------------|
| `Name` | string | Command identifier (must match internal name) |
| `Enabled` | boolean | Whether the command is active |
| `Prefix` | string | Chat prefix that triggers the command |
### Customizing Prefixes
You can change command prefixes:
```json
{
"Name": "Reload",
"Enabled": true,
"Prefix": "/reload"
}
```
Now players would type `/reload` instead of `!reload`.
### Disabling Commands
Set `Enabled: false` to disable:
```json
{
"Name": "Rights",
"Enabled": false,
"Prefix": "!rights"
}
```
When disabled, typing the command returns:
```text
Server: "The Rights command is disabled on this server"
```
## Security Considerations
### High-Risk Commands (Disable in Production)
- **Rights**: Grants admin privileges and all courses
- **KeyQuest**: Unlocks restricted content
### Medium-Risk Commands (Use with Caution)
- **Course**: Allows players to toggle courses without payment
- Mitigate by limiting which courses are `Enabled` in [Courses](courses.md)
### Safe Commands
- **Reload**: Only affects visual state, no persistent changes
- **Raviente**: Only affects raid event, no account changes
## Implementation Details
Commands are initialized on server startup from the config:
```go
// handlers_cast_binary.go:40
func init() {
commands = make(map[string]config.Command)
for _, cmd := range config.ErupeConfig.Commands {
commands[cmd.Name] = cmd
if cmd.Enabled {
logger.Info(fmt.Sprintf("Command %s: Enabled, prefix: %s", cmd.Name, cmd.Prefix))
}
}
}
```
Each command handler checks if the command is enabled before executing.
## Examples
### Minimal Safe Configuration
```json
{
"Commands": [
{"Name": "Reload", "Enabled": true, "Prefix": "!reload"},
{"Name": "Raviente", "Enabled": true, "Prefix": "!ravi"}
]
}
```
### Full Development Configuration
```json
{
"Commands": [
{"Name": "Rights", "Enabled": true, "Prefix": "!rights"},
{"Name": "Raviente", "Enabled": true, "Prefix": "!ravi"},
{"Name": "Teleport", "Enabled": true, "Prefix": "!tele"},
{"Name": "Reload", "Enabled": true, "Prefix": "!reload"},
{"Name": "KeyQuest", "Enabled": true, "Prefix": "!kqf"},
{"Name": "Course", "Enabled": true, "Prefix": "!course"}
]
}
```
### Custom Prefixes
```json
{
"Commands": [
{"Name": "Reload", "Enabled": true, "Prefix": "/refresh"},
{"Name": "Raviente", "Enabled": true, "Prefix": "/ravi"},
{"Name": "Course", "Enabled": true, "Prefix": "/sub"}
]
}
```
## Related Documentation
- [Courses](courses.md) - Course configuration for the `!course` command
- [Discord Integration](discord-integration.md) - Commands may post to Discord
- [Gameplay Options](gameplay-options.md) - Gameplay balance settings

610
docs/configuration.md Normal file
View File

@@ -0,0 +1,610 @@
# Erupe Configuration Guide
This guide explains the important configuration sections in `config.json`. Use [config.example.json](../config.example.json) as a template.
## Table of Contents
- [Basic Settings](#basic-settings)
- [Development Mode](#development-mode)
- [Gameplay Options](#gameplay-options)
- [Logging](#logging)
- [Discord Integration](#discord-integration)
- [In-Game Commands](#in-game-commands)
- [Courses](#courses)
- [Database](#database)
- [Server Configuration](#server-configuration)
---
## Basic Settings
```json
{
"Host": "127.0.0.1",
"BinPath": "bin",
"Language": "en",
"DisableSoftCrash": false,
"HideLoginNotice": true
}
```
| Setting | Type | Description |
|---------|------|-------------|
| `Host` | string | Server IP address. Leave empty to auto-detect. Use `"127.0.0.1"` for local hosting |
| `BinPath` | string | Path to binary game data (quests, scenarios, etc.) |
| `Language` | string | Server language. `"en"` for English, `"jp"` for Japanese |
| `DisableSoftCrash` | boolean | When `true`, server exits immediately on crash (useful for auto-restart scripts) |
| `HideLoginNotice` | boolean | Hide the Erupe welcome notice on login |
| `LoginNotices` | array | Custom MHFML-formatted login notices to display |
### Additional Settings
- **`PatchServerManifest`**: Override URL for patch manifest server
- **`PatchServerFile`**: Override URL for patch file server
- **`ScreenshotAPIURL`**: Destination for screenshots uploaded to BBS
- **`DeleteOnSaveCorruption`**: If `true`, corrupted save data will be flagged for deletion
---
## Development Mode
```json
{
"DevMode": true,
"DevModeOptions": {
"AutoCreateAccount": true,
"CleanDB": false,
"MaxLauncherHR": false,
"LogInboundMessages": false,
"LogOutboundMessages": false,
"MaxHexdumpLength": 256,
"DivaEvent": 0,
"FestaEvent": -1,
"TournamentEvent": 0,
"MezFesEvent": true,
"MezFesAlt": false,
"DisableTokenCheck": false,
"QuestDebugTools": false,
"SaveDumps": {
"Enabled": true,
"OutputDir": "savedata"
}
}
}
```
| Setting | Type | Description |
|---------|------|-------------|
| `DevMode` | boolean | Enables development mode (more verbose logging, development logger format) |
| `AutoCreateAccount` | boolean | **⚠️ SECURITY RISK**: Auto-create accounts on login (disable in production) |
| `CleanDB` | boolean | **⚠️ DESTRUCTIVE**: Wipes database on server start |
| `MaxLauncherHR` | boolean | Sets launcher HR to HR7 to join non-beginner worlds |
| `LogInboundMessages` | boolean | Log all packets received from clients (very verbose) |
| `LogOutboundMessages` | boolean | Log all packets sent to clients (very verbose) |
| `MaxHexdumpLength` | number | Maximum bytes to display in packet hexdumps |
| `DivaEvent` | number | Diva Defense event status (0 = off, higher = active) |
| `FestaEvent` | number | Hunter's Festa event status (-1 = off, higher = active) |
| `TournamentEvent` | number | VS Tournament event status (0 = off, higher = active) |
| `MezFesEvent` | boolean | Enable/disable MezFes event |
| `MezFesAlt` | boolean | Swap Volpakkun for Tokotoko in MezFes |
| `DisableTokenCheck` | boolean | **⚠️ SECURITY RISK**: Skip login token validation |
| `QuestDebugTools` | boolean | Enable quest debugging logs |
| `SaveDumps.Enabled` | boolean | Enable saving character data dumps |
| `SaveDumps.OutputDir` | string | Directory for save data dumps |
---
## Gameplay Options
```json
{
"GameplayOptions": {
"FeaturedWeapons": 1,
"MaximumNP": 100000,
"MaximumRP": 50000,
"DisableLoginBoost": false,
"DisableBoostTime": false,
"BoostTimeDuration": 120,
"GuildMealDuration": 60,
"BonusQuestAllowance": 3,
"DailyQuestAllowance": 1
}
}
```
| Setting | Type | Description |
|---------|------|-------------|
| `FeaturedWeapons` | number | Number of Active Feature weapons generated daily |
| `MaximumNP` | number | Maximum Network Points (NP) a player can hold |
| `MaximumRP` | number | Maximum Road Points (RP) a player can hold |
| `DisableLoginBoost` | boolean | Disable login boost system |
| `DisableBoostTime` | boolean | Disable daily NetCafe boost time |
| `BoostTimeDuration` | number | NetCafe boost time duration in minutes (default: 120) |
| `GuildMealDuration` | number | Guild meal activation duration in minutes (default: 60) |
| `BonusQuestAllowance` | number | Daily Bonus Point Quest allowance |
| `DailyQuestAllowance` | number | Daily Quest allowance |
---
## Logging
```json
{
"Logging": {
"LogToFile": true,
"LogFilePath": "logs/erupe.log",
"LogMaxSize": 100,
"LogMaxBackups": 3,
"LogMaxAge": 28,
"LogCompress": true
}
}
```
Erupe uses [lumberjack](https://github.com/natefinch/lumberjack) for automatic log rotation and compression.
| Setting | Type | Description |
|---------|------|-------------|
| `LogToFile` | boolean | Enable file logging (logs to both console and file) |
| `LogFilePath` | string | Path to log file (directory will be created automatically) |
| `LogMaxSize` | number | Maximum log file size in MB before rotation (default: 100) |
| `LogMaxBackups` | number | Number of old log files to keep (default: 3) |
| `LogMaxAge` | number | Maximum days to retain old logs (default: 28) |
| `LogCompress` | boolean | Compress rotated log files with gzip |
**Log Format:**
- When `DevMode: true`: Console format (human-readable)
- When `DevMode: false`: JSON format (production)
**Log Analysis:**
Use the built-in log analyzer tool to analyze logs. See [Log Analysis Guide](../tools/loganalyzer/README.md) or [CLAUDE.md](../CLAUDE.md#log-analysis).
---
## Discord Integration
```json
{
"Discord": {
"Enabled": false,
"BotToken": "",
"RealtimeChannelID": ""
}
}
```
Erupe includes an optional Discord bot that posts real-time server activity to a Discord channel.
| Setting | Type | Description |
|---------|------|-------------|
| `Enabled` | boolean | Enable Discord integration |
| `BotToken` | string | Discord bot token from Discord Developer Portal |
| `RealtimeChannelID` | string | Discord channel ID where activity messages will be posted |
### How Discord Integration Works
When enabled, the Discord bot:
1. **Connects on Server Startup**: The bot authenticates using the provided bot token
2. **Monitors Game Activity**: Listens for in-game chat messages and events
3. **Posts to Discord**: Sends formatted messages to the specified channel
**What Gets Posted:**
- Player chat messages (when sent to world/server chat)
- Player connection/disconnection events
- Quest completions
- Special event notifications
### Setup Instructions
1. **Create a Discord Bot:**
- Go to [Discord Developer Portal](https://discord.com/developers/applications)
- Create a new application
- Go to the "Bot" section and create a bot
- Copy the bot token
2. **Get Channel ID:**
- Enable Developer Mode in Discord (User Settings → Advanced → Developer Mode)
- Right-click the channel you want to use
- Click "Copy ID"
3. **Add Bot to Server:**
- Go to OAuth2 → URL Generator in the Developer Portal
- Select scopes: `bot`
- Select permissions: `Send Messages`, `Read Message History`
- Use the generated URL to invite the bot to your server
4. **Configure Erupe:**
```json
{
"Discord": {
"Enabled": true,
"BotToken": "YOUR_BOT_TOKEN_HERE",
"RealtimeChannelID": "YOUR_CHANNEL_ID_HERE"
}
}
```
**Implementation Details:**
- Bot code: [server/discordbot/discord_bot.go](../server/discordbot/discord_bot.go)
- Uses [discordgo](https://github.com/bwmarrin/discordgo) library
- Message normalization for Discord mentions and emojis
- Non-blocking message sending (errors are logged but don't crash the server)
---
## In-Game Commands
```json
{
"Commands": [
{
"Name": "Rights",
"Enabled": false,
"Prefix": "!rights"
},
{
"Name": "Raviente",
"Enabled": true,
"Prefix": "!ravi"
},
{
"Name": "Teleport",
"Enabled": false,
"Prefix": "!tele"
},
{
"Name": "Reload",
"Enabled": true,
"Prefix": "!reload"
},
{
"Name": "KeyQuest",
"Enabled": false,
"Prefix": "!kqf"
},
{
"Name": "Course",
"Enabled": true,
"Prefix": "!course"
}
]
}
```
In-game chat commands allow players to perform various actions by typing commands in the chat.
### Available Commands
| Command | Prefix | Description | Usage |
|---------|--------|-------------|-------|
| **Rights** | `!rights` | Modify account rights/permissions | `!rights <number>` |
| **Raviente** | `!ravi` | Control Raviente event | `!ravi start`, `!ravi cm` (check multiplier) |
| **Teleport** | `!tele` | Teleport to locations | `!tele <location>` |
| **Reload** | `!reload` | Reload all players and objects in current stage | `!reload` |
| **KeyQuest** | `!kqf` | Get/set Key Quest flags | `!kqf get`, `!kqf set <hex>` |
| **Course** | `!course` | Enable/disable subscription courses | `!course <course_name>` |
### How Commands Work
1. **Player Types Command**: Player sends a chat message starting with the command prefix
2. **Command Parser**: Server checks if message matches any enabled command prefix
3. **Command Handler**: Executes the command logic
4. **Response**: Server sends feedback message to the player
**Implementation Details:**
- Commands are parsed in [handlers_cast_binary.go:90](../server/channelserver/handlers_cast_binary.go#L90)
- Command map is initialized from config on server startup
- Each command has its own handler function
- Disabled commands return a "command disabled" message
### Example Command Usage
**Reload Command:**
```text
Player types: !reload
Server: "Reloading all players and objects..."
Server: Removes all other players/objects from view
Server: Re-adds all players/objects with updated data
```
**Course Command:**
```text
Player types: !course premium
Server: "Premium Course enabled!"
Server: Updates player's account rights in database
Server: Updates player's rights in current session
```
**KeyQuest Command:**
```text
Player types: !kqf get
Server: "Your KQF is: 0123456789ABCDEF"
Player types: !kqf set 0000000000000000
Server: "KQF set successfully!"
```
### Security Considerations
- **Rights Command**: Can grant admin privileges - disable in production
- **KeyQuest Command**: Can unlock content - disable if not desired
- Commands are per-server configuration (can be different per channel server)
---
## Courses
```json
{
"Courses": [
{"Name": "HunterLife", "Enabled": true},
{"Name": "Extra", "Enabled": true},
{"Name": "Premium", "Enabled": true},
{"Name": "Assist", "Enabled": false},
{"Name": "N", "Enabled": false},
{"Name": "Hiden", "Enabled": false},
{"Name": "HunterSupport", "Enabled": false},
{"Name": "NBoost", "Enabled": false},
{"Name": "NetCafe", "Enabled": true},
{"Name": "HLRenewing", "Enabled": true},
{"Name": "EXRenewing", "Enabled": true}
]
}
```
Courses are subscription-based features in Monster Hunter Frontier (similar to premium subscriptions).
| Course | Description |
|--------|-------------|
| `HunterLife` | Hunter Life Course - Basic subscription benefits |
| `Extra` | Extra Course - Additional benefits |
| `Premium` | Premium Course - Premium features |
| `Assist` | Assist Course - Helper features |
| `N` | N Course |
| `Hiden` | Hiden Course - Secret/hidden features |
| `HunterSupport` | Hunter Support Course |
| `NBoost` | N Boost Course |
| `NetCafe` | NetCafe Course - Internet cafe benefits |
| `HLRenewing` | Hunter Life Renewing Course |
| `EXRenewing` | Extra Renewing Course |
**Note:** When `Enabled: true`, players can toggle the course on/off using the `!course` command (if enabled). When `Enabled: false`, the course is completely locked and cannot be activated.
---
## Database
```json
{
"Database": {
"Host": "localhost",
"Port": 5432,
"User": "postgres",
"Password": "",
"Database": "erupe"
}
}
```
PostgreSQL database configuration.
| Setting | Type | Description |
|---------|------|-------------|
| `Host` | string | Database host (default: `localhost`) |
| `Port` | number | Database port (default: `5432`) |
| `User` | string | Database user |
| `Password` | string | Database password (**required**, must not be empty) |
| `Database` | string | Database name |
**Setup:**
1. Install PostgreSQL
2. Create database: `createdb erupe`
3. Apply schema: `psql -U postgres -d erupe -f schema.sql`
4. Apply patches in order: `psql -U postgres -d erupe -f patch-schema/01_patch.sql`
See [CLAUDE.md](../CLAUDE.md#database-operations) for more details.
---
## Server Configuration
### Sign Server (Authentication)
```json
{
"Sign": {
"Enabled": true,
"Port": 53312
}
}
```
Legacy sign server for authentication and account management.
| Setting | Type | Description |
|---------|------|-------------|
| `Enabled` | boolean | Enable the sign server |
| `Port` | number | Port number (default: 53312) |
### SignV2 Server (Modern Authentication)
```json
{
"SignV2": {
"Enabled": false,
"Port": 8080
}
}
```
Modern HTTP-based sign server (alternative to legacy sign server).
| Setting | Type | Description |
|---------|------|-------------|
| `Enabled` | boolean | Enable the modern sign server |
| `Port` | number | Port number (default: 8080) |
**Note:** Only enable one sign server at a time (Sign OR SignV2, not both).
### Channel Server
```json
{
"Channel": {
"Enabled": true
}
}
```
Channel servers handle actual gameplay sessions, quests, and player interactions.
| Setting | Type | Description |
|---------|------|-------------|
| `Enabled` | boolean | Enable channel servers (required for gameplay) |
### Entrance Server
```json
{
"Entrance": {
"Enabled": true,
"Port": 53310,
"Entries": [
{
"Name": "Newbie",
"Description": "",
"IP": "",
"Type": 3,
"Recommended": 2,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54001, "MaxPlayers": 100 },
{ "Port": 54002, "MaxPlayers": 100 }
]
}
]
}
}
```
Entrance server manages world/server selection and character lists.
| Setting | Type | Description |
|---------|------|-------------|
| `Enabled` | boolean | Enable entrance server (required) |
| `Port` | number | Entrance server port (default: 53310) |
#### Entrance Entries
Each entry represents a "world" in the server list.
| Field | Type | Description |
|-------|------|-------------|
| `Name` | string | World name displayed to players |
| `Description` | string | World description (optional) |
| `IP` | string | Override IP (leave empty to use Host setting) |
| `Type` | number | World type: `1`=Normal, `2`=Cities, `3`=Newbie, `4`=Tavern, `5`=Return, `6`=MezFes |
| `Recommended` | number | Recommendation status: `0`=None, `2`=Recommended, `6`=Special |
| `AllowedClientFlags` | number | Client version flags (0 = all allowed) |
| `Channels` | array | List of channel servers in this world |
#### Channel Configuration
| Field | Type | Description |
|-------|------|-------------|
| `Port` | number | Channel server port (must be unique) |
| `MaxPlayers` | number | Maximum players per channel |
| `CurrentPlayers` | number | Current player count (auto-updated, can be set to 0) |
**World Types Explained:**
- **Newbie (Type 3)**: For new players, typically recommended
- **Normal (Type 1)**: Standard gameplay world
- **Cities (Type 2)**: Social/town areas
- **Tavern (Type 4)**: Bar/tavern areas
- **Return (Type 5)**: For returning players
- **MezFes (Type 6)**: MezFes event world
---
## Complete Example
Here's a minimal production-ready configuration:
```json
{
"Host": "",
"BinPath": "bin",
"Language": "en",
"DisableSoftCrash": true,
"HideLoginNotice": false,
"DevMode": false,
"DevModeOptions": {
"AutoCreateAccount": false
},
"GameplayOptions": {
"MaximumNP": 100000,
"MaximumRP": 50000
},
"Logging": {
"LogToFile": true,
"LogFilePath": "logs/erupe.log",
"LogMaxSize": 100,
"LogMaxBackups": 7,
"LogMaxAge": 30,
"LogCompress": true
},
"Discord": {
"Enabled": false
},
"Commands": [
{"Name": "Reload", "Enabled": true, "Prefix": "!reload"},
{"Name": "Course", "Enabled": true, "Prefix": "!course"}
],
"Database": {
"Host": "localhost",
"Port": 5432,
"User": "erupe",
"Password": "CHANGE_ME",
"Database": "erupe"
},
"Sign": {
"Enabled": true,
"Port": 53312
},
"Channel": {
"Enabled": true
},
"Entrance": {
"Enabled": true,
"Port": 53310,
"Entries": [
{
"Name": "Main",
"Type": 1,
"Channels": [
{ "Port": 54001, "MaxPlayers": 100 }
]
}
]
}
}
```
---
## Additional Resources
- [CLAUDE.md](../CLAUDE.md) - Development guide
- [config.example.json](../config.example.json) - Full example configuration
- [Log Analyzer Tool](../tools/loganalyzer/) - Log analysis utilities

219
docs/courses.md Normal file
View File

@@ -0,0 +1,219 @@
# Courses
Subscription course configuration for Monster Hunter Frontier.
## Configuration
```json
{
"Courses": [
{"Name": "HunterLife", "Enabled": true},
{"Name": "Extra", "Enabled": true},
{"Name": "Premium", "Enabled": true},
{"Name": "Assist", "Enabled": false},
{"Name": "N", "Enabled": false},
{"Name": "Hiden", "Enabled": false},
{"Name": "HunterSupport", "Enabled": false},
{"Name": "NBoost", "Enabled": false},
{"Name": "NetCafe", "Enabled": true},
{"Name": "HLRenewing", "Enabled": true},
{"Name": "EXRenewing", "Enabled": true}
]
}
```
## What Are Courses?
Courses are subscription-based premium features in Monster Hunter Frontier, similar to premium subscriptions or season passes. Each course grants different benefits, bonuses, and access to content.
## Course List
| Course | Name | Description |
|--------|------|-------------|
| `HunterLife` | Hunter Life Course | Basic subscription with fundamental benefits |
| `Extra` | Extra Course | Additional premium features and bonuses |
| `Premium` | Premium Course | Premium-tier benefits and exclusive content |
| `Assist` | Assist Course | Helper features for newer players |
| `N` | N Course | Special N-series benefits |
| `Hiden` | Hiden Course | Secret/hidden features and content |
| `HunterSupport` | Hunter Support Course | Support features for hunters |
| `NBoost` | N Boost Course | N-series boost benefits |
| `NetCafe` | NetCafe Course | Internet cafe benefits (bonus rewards, boost time) |
| `HLRenewing` | Hunter Life Renewing | Renewed Hunter Life benefits |
| `EXRenewing` | Extra Renewing | Renewed Extra Course benefits |
## How Courses Work
### Enabled vs Disabled
- **`Enabled: true`**: Players can toggle the course on/off using the `!course` command
- **`Enabled: false`**: Course is locked and cannot be activated by players
### Account Rights
Courses are stored as a bitfield in the database (`users.rights` column). Each course has a unique bit position:
```text
Rights Bitfield:
Bit 0: HunterLife
Bit 1: Extra
Bit 2: Premium
... (and so on)
```
### Using the !course Command
When the [!course command](commands.md#course) is enabled, players can toggle courses:
```text
Player types: !course premium
Server: "Premium Course enabled!"
Player types: !course premium
Server: "Premium Course disabled!"
```
**Important:** Players can only toggle courses that are `Enabled: true` in the configuration.
## Configuration Examples
### Open Server (All Courses Available)
```json
{
"Courses": [
{"Name": "HunterLife", "Enabled": true},
{"Name": "Extra", "Enabled": true},
{"Name": "Premium", "Enabled": true},
{"Name": "Assist", "Enabled": true},
{"Name": "N", "Enabled": true},
{"Name": "Hiden", "Enabled": true},
{"Name": "HunterSupport", "Enabled": true},
{"Name": "NBoost", "Enabled": true},
{"Name": "NetCafe", "Enabled": true},
{"Name": "HLRenewing", "Enabled": true},
{"Name": "EXRenewing", "Enabled": true}
]
}
```
### Restricted Server (Core Courses Only)
```json
{
"Courses": [
{"Name": "HunterLife", "Enabled": true},
{"Name": "Extra", "Enabled": true},
{"Name": "Premium", "Enabled": false},
{"Name": "Assist", "Enabled": false},
{"Name": "N", "Enabled": false},
{"Name": "Hiden", "Enabled": false},
{"Name": "HunterSupport", "Enabled": false},
{"Name": "NBoost", "Enabled": false},
{"Name": "NetCafe", "Enabled": true},
{"Name": "HLRenewing", "Enabled": false},
{"Name": "EXRenewing", "Enabled": false}
]
}
```
### Free-to-Play Server (NetCafe Only)
```json
{
"Courses": [
{"Name": "HunterLife", "Enabled": false},
{"Name": "Extra", "Enabled": false},
{"Name": "Premium", "Enabled": false},
{"Name": "Assist", "Enabled": false},
{"Name": "N", "Enabled": false},
{"Name": "Hiden", "Enabled": false},
{"Name": "HunterSupport", "Enabled": false},
{"Name": "NBoost", "Enabled": false},
{"Name": "NetCafe", "Enabled": true},
{"Name": "HLRenewing", "Enabled": false},
{"Name": "EXRenewing", "Enabled": false}
]
}
```
## Course Benefits
While Erupe emulates the course system, the exact benefits depend on game client implementation. Common benefits include:
### HunterLife
- Increased reward multipliers
- Extra item box space
- Access to HunterLife-exclusive quests
### Extra
- Additional bonus rewards
- Extra carve/gather attempts
- Special decorations and items
### Premium
- All HunterLife + Extra benefits
- Premium-exclusive content
- Enhanced reward rates
### NetCafe
- Boost time periods (see [Gameplay Options](gameplay-options.md))
- Increased reward rates
- NetCafe-exclusive bonuses
## Setting Courses Manually
### Via Database
Directly modify the `users.rights` column:
```sql
-- Enable all courses for a user
UPDATE users SET rights = 2047 WHERE username = 'player';
-- Enable only HunterLife (bit 0 = 2^0 = 1)
UPDATE users SET rights = 1 WHERE username = 'player';
-- Enable HunterLife + Extra + NetCafe (bits 0, 1, 8 = 1 + 2 + 256 = 259)
UPDATE users SET rights = 259 WHERE username = 'player';
```
### Via !rights Command
If the [!rights command](commands.md#rights) is enabled:
```text
!rights 2047
```
Enables all courses (2047 = all 11 bits set).
**Bitfield Calculator:**
- HunterLife: 2^0 = 1
- Extra: 2^1 = 2
- Premium: 2^2 = 4
- NetCafe: 2^8 = 256
- Total: Add the values together
## Implementation Details
Course checking is implemented throughout the codebase:
```go
// Check if player has a specific course
if mhfcourse.CourseExists(courseID, session.courses) {
// Grant course benefits
}
```
Course data is loaded from the database on character login and cached in the session.
## Related Documentation
- [In-Game Commands](commands.md) - Using `!course` command
- [Gameplay Options](gameplay-options.md) - NetCafe boost time configuration

409
docs/database.md Normal file
View File

@@ -0,0 +1,409 @@
# Database Configuration
PostgreSQL database configuration and setup for Erupe.
## Configuration
```json
{
"Database": {
"Host": "localhost",
"Port": 5432,
"User": "postgres",
"Password": "",
"Database": "erupe"
}
}
```
## Settings Reference
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `Host` | string | `"localhost"` | Database host address |
| `Port` | number | `5432` | PostgreSQL port |
| `User` | string | `"postgres"` | Database user |
| `Password` | string | *required* | Database password (must not be empty) |
| `Database` | string | `"erupe"` | Database name |
**Important:** The `Password` field must not be empty. The server will refuse to start if the password is blank.
## Initial Setup
### 1. Install PostgreSQL
**Ubuntu/Debian:**
```bash
sudo apt update
sudo apt install postgresql postgresql-contrib
```
**macOS (Homebrew):**
```bash
brew install postgresql
brew services start postgresql
```
**Windows:**
Download and install from [postgresql.org](https://www.postgresql.org/download/windows/)
### 2. Create Database User
```bash
# Switch to postgres user
sudo -u postgres psql
# Create user with password
CREATE USER erupe WITH PASSWORD 'your_secure_password';
# Grant privileges
ALTER USER erupe CREATEDB;
# Exit psql
\q
```
### 3. Create Database
```bash
# Create database
createdb -U erupe erupe
# Or via psql
psql -U postgres
CREATE DATABASE erupe OWNER erupe;
\q
```
### 4. Apply Schema
From the Erupe root directory:
```bash
# Apply initial schema (bootstraps to version 9.1.0)
psql -U erupe -d erupe -f schemas/schema.sql
```
### 5. Apply Patches (Development Branch)
If using the development branch, apply patch schemas in order:
```bash
# Apply patches sequentially
psql -U erupe -d erupe -f patch-schema/01_patch.sql
psql -U erupe -d erupe -f patch-schema/02_patch.sql
# ... continue in order
```
**Note:** Patch schemas are development updates and may change. They get consolidated into update schemas on release.
### 6. (Optional) Load Bundled Data
Load demo data for shops, events, and gacha:
```bash
psql -U erupe -d erupe -f schemas/bundled-schema/shops.sql
psql -U erupe -d erupe -f schemas/bundled-schema/events.sql
psql -U erupe -d erupe -f schemas/bundled-schema/gacha.sql
```
## Schema Management
Erupe uses a multi-tiered schema system:
### Schema Types
1. **Initialization Schema** (`schemas/schema.sql`)
- Bootstraps database to version 9.1.0
- Creates all tables, indexes, and base data
- Use for fresh installations
2. **Patch Schemas** (`patch-schema/*.sql`)
- Development-time updates
- Numbered sequentially (01, 02, 03...)
- Applied in order during active development
- **May change during development cycle**
3. **Update Schemas** (for releases)
- Production-ready consolidated updates
- Stable and tested
- Created when patches are finalized for release
4. **Bundled Schemas** (`schemas/bundled-schema/*.sql`)
- Optional demo/template data
- Shops, events, gacha pools
- Not required but helpful for testing
### Applying Schemas
**Fresh Installation:**
```bash
psql -U erupe -d erupe -f schemas/schema.sql
```
**Development (with patches):**
```bash
# First apply base schema
psql -U erupe -d erupe -f schemas/schema.sql
# Then apply patches in order
for patch in patch-schema/*.sql; do
psql -U erupe -d erupe -f "$patch"
done
```
**With Password:**
```bash
PGPASSWORD='your_password' psql -U erupe -d erupe -f schema.sql
```
## Configuration Examples
### Local Development
```json
{
"Database": {
"Host": "localhost",
"Port": 5432,
"User": "postgres",
"Password": "dev_password",
"Database": "erupe_dev"
}
}
```
### Production (Dedicated Database Server)
```json
{
"Database": {
"Host": "db.example.com",
"Port": 5432,
"User": "erupe",
"Password": "very_secure_password_here",
"Database": "erupe_production"
}
}
```
### Docker Container
```json
{
"Database": {
"Host": "db",
"Port": 5432,
"User": "postgres",
"Password": "docker_password",
"Database": "erupe"
}
}
```
The `Host: "db"` refers to the Docker Compose service name.
## Docker Setup
Using Docker Compose (see `docker-compose.yml`):
```yaml
services:
db:
image: postgres:13
environment:
POSTGRES_PASSWORD: test
POSTGRES_DB: erupe
ports:
- "5432:5432"
volumes:
- pgdata:/var/lib/postgresql/data
```
Start database:
```bash
docker compose up db
```
Apply schema to Docker database:
```bash
docker compose exec db psql -U postgres -d erupe -f /path/to/schema.sql
```
## Database Maintenance
### Backup Database
```bash
# Full backup
pg_dump -U erupe erupe > erupe_backup.sql
# Compressed backup
pg_dump -U erupe erupe | gzip > erupe_backup.sql.gz
# With password
PGPASSWORD='password' pg_dump -U erupe erupe > backup.sql
```
### Restore Database
```bash
# Drop and recreate database
dropdb -U erupe erupe
createdb -U erupe erupe
# Restore from backup
psql -U erupe -d erupe -f erupe_backup.sql
# From compressed backup
gunzip -c erupe_backup.sql.gz | psql -U erupe -d erupe
```
### Clean Database (Development)
```bash
# Connect to database
psql -U erupe -d erupe
-- Delete all user data
DELETE FROM guild_characters;
DELETE FROM guilds;
DELETE FROM characters;
DELETE FROM sign_sessions;
DELETE FROM users;
-- Exit
\q
```
Or use `CleanDB: true` in [Development Mode](development-mode.md) (⚠️ destructive!).
### Check Database Size
```bash
psql -U erupe -d erupe -c "SELECT pg_size_pretty(pg_database_size('erupe'));"
```
### Vacuum Database
Reclaim space and optimize:
```bash
psql -U erupe -d erupe -c "VACUUM ANALYZE;"
```
## Troubleshooting
### Connection Refused
**Error:** `could not connect to server: Connection refused`
**Solutions:**
- Verify PostgreSQL is running: `sudo systemctl status postgresql`
- Check port is correct: `5432` (default)
- Verify host is accessible
- Check firewall rules
### Authentication Failed
**Error:** `password authentication failed for user "erupe"`
**Solutions:**
- Verify password is correct in config
- Check `pg_hba.conf` authentication method
- Ensure user exists: `psql -U postgres -c "\du"`
### Database Does Not Exist
**Error:** `database "erupe" does not exist`
**Solutions:**
- Create database: `createdb -U erupe erupe`
- Verify database name matches config
### Permission Denied
**Error:** `permission denied for table users`
**Solutions:**
```sql
-- Grant all privileges on database
GRANT ALL PRIVILEGES ON DATABASE erupe TO erupe;
-- Grant all privileges on all tables
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO erupe;
```
### Schema Version Mismatch
**Error:** Server starts but data doesn't load properly
**Solutions:**
- Check if all patches were applied in order
- Verify schema version in database
- Re-apply missing patches
## Security Best Practices
1. **Use Strong Passwords**: Never use default or weak passwords
2. **Limit Network Access**: Use firewall rules to restrict database access
3. **Don't Expose PostgreSQL Publicly**: Only allow connections from Erupe server
4. **Use SSL/TLS**: Enable SSL for production databases
5. **Regular Backups**: Automate daily backups
6. **Separate Users**: Don't use `postgres` superuser for Erupe
## Performance Tuning
For larger servers, optimize PostgreSQL:
### Connection Pooling
Consider using PgBouncer for connection pooling:
```bash
sudo apt install pgbouncer
```
### PostgreSQL Configuration
Edit `/etc/postgresql/13/main/postgresql.conf`:
```conf
# Increase shared buffers (25% of RAM)
shared_buffers = 2GB
# Increase work memory
work_mem = 16MB
# Increase maintenance work memory
maintenance_work_mem = 512MB
# Enable query logging (development)
log_statement = 'all'
log_duration = on
```
Restart PostgreSQL:
```bash
sudo systemctl restart postgresql
```
## Related Documentation
- [Basic Settings](basic-settings.md) - Basic server configuration
- [Development Mode](development-mode.md) - CleanDB option
- [Server Configuration](server-configuration.md) - Server setup
- [CLAUDE.md](../CLAUDE.md#database-operations) - Database operations guide

166
docs/development-mode.md Normal file
View File

@@ -0,0 +1,166 @@
# Development Mode
Development mode configuration for testing and debugging Erupe.
## Configuration
```json
{
"DevMode": true,
"DevModeOptions": {
"AutoCreateAccount": true,
"CleanDB": false,
"MaxLauncherHR": false,
"LogInboundMessages": false,
"LogOutboundMessages": false,
"MaxHexdumpLength": 256,
"DivaEvent": 0,
"FestaEvent": -1,
"TournamentEvent": 0,
"MezFesEvent": true,
"MezFesAlt": false,
"DisableTokenCheck": false,
"QuestDebugTools": false,
"SaveDumps": {
"Enabled": true,
"OutputDir": "savedata"
}
}
}
```
## Settings Reference
### DevMode
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `DevMode` | boolean | `false` | Enables development mode (more verbose logging, development logger format) |
When `DevMode` is enabled:
- Logging uses console format (human-readable) instead of JSON
- More detailed stack traces on errors
- Development-friendly output
### DevModeOptions
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `AutoCreateAccount` | boolean | `false` | **⚠️ SECURITY RISK**: Auto-create accounts on login (disable in production) |
| `CleanDB` | boolean | `false` | **⚠️ DESTRUCTIVE**: Wipes database on server start (deletes all users, characters, guilds) |
| `MaxLauncherHR` | boolean | `false` | Sets launcher HR to HR7 to join non-beginner worlds |
| `LogInboundMessages` | boolean | `false` | Log all packets received from clients (very verbose) |
| `LogOutboundMessages` | boolean | `false` | Log all packets sent to clients (very verbose) |
| `MaxHexdumpLength` | number | `256` | Maximum bytes to display in packet hexdumps |
| `DivaEvent` | number | `0` | Diva Defense event status (0 = off, higher = active) |
| `FestaEvent` | number | `-1` | Hunter's Festa event status (-1 = off, higher = active) |
| `TournamentEvent` | number | `0` | VS Tournament event status (0 = off, higher = active) |
| `MezFesEvent` | boolean | `false` | Enable/disable MezFes event |
| `MezFesAlt` | boolean | `false` | Swap Volpakkun for Tokotoko in MezFes |
| `DisableTokenCheck` | boolean | `false` | **⚠️ SECURITY RISK**: Skip login token validation |
| `QuestDebugTools` | boolean | `false` | Enable quest debugging logs |
### Save Dumps
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `SaveDumps.Enabled` | boolean | `false` | Enable saving character data dumps for analysis |
| `SaveDumps.OutputDir` | string | `"savedata"` | Directory for save data dumps |
## Security Warnings
### AutoCreateAccount
**Never enable in production!** This setting allows anyone to create an account by simply trying to log in with any username. This is convenient for development but a major security risk for public servers.
### CleanDB
**Extremely destructive!** This setting wipes all user data from the database on every server restart. Only use for rapid testing cycles in isolated development environments.
### DisableTokenCheck
**Security vulnerability!** Bypasses login token validation, allowing unauthorized access. Only use in isolated development environments.
## Packet Logging
When debugging network issues, enable packet logging:
```json
{
"DevModeOptions": {
"LogInboundMessages": true,
"LogOutboundMessages": true,
"MaxHexdumpLength": 512
}
}
```
**Warning:** This generates **massive** log files very quickly. Only enable when actively debugging specific packet issues.
## Event Testing
Test special events by enabling them:
```json
{
"DevModeOptions": {
"DivaEvent": 1,
"FestaEvent": 0,
"TournamentEvent": 1,
"MezFesEvent": true,
"MezFesAlt": false
}
}
```
## Examples
### Safe Development Configuration
```json
{
"DevMode": true,
"DevModeOptions": {
"AutoCreateAccount": true,
"CleanDB": false,
"MaxLauncherHR": true,
"QuestDebugTools": true,
"SaveDumps": {
"Enabled": true,
"OutputDir": "savedata"
}
}
}
```
### Production Configuration
```json
{
"DevMode": false,
"DevModeOptions": {
"AutoCreateAccount": false,
"CleanDB": false,
"DisableTokenCheck": false
}
}
```
### Packet Debugging Configuration
```json
{
"DevMode": true,
"DevModeOptions": {
"LogInboundMessages": true,
"LogOutboundMessages": true,
"MaxHexdumpLength": 1024
}
}
```
## Related Documentation
- [Logging](logging.md) - Logging configuration
- [Basic Settings](basic-settings.md) - Basic server settings

199
docs/discord-integration.md Normal file
View File

@@ -0,0 +1,199 @@
# Discord Integration
Real-time Discord bot integration for posting server activity to Discord channels.
## Configuration
```json
{
"Discord": {
"Enabled": false,
"BotToken": "",
"RealtimeChannelID": ""
}
}
```
## Settings Reference
| Setting | Type | Description |
|---------|------|-------------|
| `Enabled` | boolean | Enable Discord integration |
| `BotToken` | string | Discord bot token from Discord Developer Portal |
| `RealtimeChannelID` | string | Discord channel ID where activity messages will be posted |
## How It Works
When enabled, the Discord bot:
1. **Connects on Server Startup**: The bot authenticates using the provided bot token
2. **Monitors Game Activity**: Listens for in-game chat messages and events
3. **Posts to Discord**: Sends formatted messages to the specified channel
### What Gets Posted
- Player chat messages (when sent to world/server chat)
- Player connection/disconnection events
- Quest completions
- Special event notifications
### Message Format
Messages are posted in this format:
```text
**PlayerName**: Hello everyone!
```
Discord mentions and emojis in messages are normalized for proper display.
## Setup Instructions
### 1. Create a Discord Bot
1. Go to [Discord Developer Portal](https://discord.com/developers/applications)
2. Click "New Application"
3. Give your application a name (e.g., "Erupe Server Bot")
4. Go to the "Bot" section in the left sidebar
5. Click "Add Bot"
6. Under the bot's username, click "Reset Token" to reveal your bot token
7. **Copy this token** - you'll need it for the config
**Important:** Keep your bot token secret! Anyone with this token can control your bot.
### 2. Get Channel ID
1. Enable Developer Mode in Discord:
- User Settings → Advanced → Developer Mode (toggle on)
2. Right-click the channel where you want bot messages
3. Click "Copy ID"
4. This is your `RealtimeChannelID`
### 3. Add Bot to Your Server
1. In Discord Developer Portal, go to OAuth2 → URL Generator
2. Select scopes:
- `bot`
3. Select bot permissions:
- `Send Messages`
- `Read Message History`
4. Copy the generated URL at the bottom
5. Paste the URL in your browser and select your Discord server
6. Click "Authorize"
### 4. Configure Erupe
Edit your `config.json`:
```json
{
"Discord": {
"Enabled": true,
"BotToken": "YOUR_BOT_TOKEN_HERE",
"RealtimeChannelID": "YOUR_CHANNEL_ID_HERE"
}
}
```
### 5. Start Erupe
The bot will connect automatically on server startup. You should see:
```text
INFO Discord bot connected successfully
```
## Example Configuration
```json
{
"Discord": {
"Enabled": true,
"BotToken": "MTIzNDU2Nzg5MDEyMzQ1Njc4OQ.AbCdEf.GhIjKlMnOpQrStUvWxYz123456789",
"RealtimeChannelID": "987654321098765432"
}
}
```
## Implementation Details
- **Bot Code**: [server/discordbot/discord_bot.go](../server/discordbot/discord_bot.go)
- **Library**: Uses [discordgo](https://github.com/bwmarrin/discordgo)
- **Message Normalization**: Discord mentions (`<@123456>`) and emojis (`:emoji:`) are normalized
- **Error Handling**: Non-blocking - errors are logged but don't crash the server
- **Threading**: Bot runs in a separate goroutine
## Troubleshooting
### Bot doesn't connect
**Error:** `Discord failed to create realtimeChannel`
**Solutions:**
- Verify the `RealtimeChannelID` is correct
- Ensure the bot has been added to your server
- Check that the bot has permission to read the channel
### Bot connects but doesn't post messages
**Solutions:**
- Verify the bot has `Send Messages` permission in the channel
- Check channel permissions - the bot's role must have access
- Look for error messages in server logs
### Invalid token error
**Error:** `Discord failed: authentication failed`
**Solutions:**
- Regenerate the bot token in Discord Developer Portal
- Copy the entire token, including any special characters
- Ensure no extra spaces in the config file
### Bot posts but messages are blank
**Issue:** Message normalization may be failing
**Solution:**
- Check server logs for Discord-related errors
- Verify game chat is being sent to world/server chat, not private chat
## Security Considerations
1. **Never commit your bot token** - Add `config.json` to `.gitignore`
2. **Regenerate compromised tokens** - If your token is exposed, regenerate immediately
3. **Limit bot permissions** - Only grant necessary permissions
4. **Monitor bot activity** - Check for unusual posting patterns
## Advanced Usage
### Multiple Channels
Currently, Erupe supports posting to a single channel. To post to multiple channels, you would need to modify the bot code.
### Custom Message Formatting
To customize message formatting, edit [sys_channel_server.go:354](../server/channelserver/sys_channel_server.go#L354):
```go
func (s *Server) DiscordChannelSend(charName string, content string) {
if s.erupeConfig.Discord.Enabled && s.discordBot != nil {
// Customize this format
message := fmt.Sprintf("**%s**: %s", charName, content)
s.discordBot.RealtimeChannelSend(message)
}
}
```
### Webhook Alternative
For simpler one-way messaging, consider using Discord webhooks instead of a full bot. This would require code modifications but wouldn't need bot creation/permissions.
## Related Documentation
- [In-Game Commands](commands.md) - Chat commands that may trigger Discord posts
- [Logging](logging.md) - Server logging configuration

161
docs/gameplay-options.md Normal file
View File

@@ -0,0 +1,161 @@
# Gameplay Options
Gameplay modifiers and balance settings for Erupe.
## Configuration
```json
{
"GameplayOptions": {
"FeaturedWeapons": 1,
"MaximumNP": 100000,
"MaximumRP": 50000,
"DisableLoginBoost": false,
"DisableBoostTime": false,
"BoostTimeDuration": 120,
"GuildMealDuration": 60,
"BonusQuestAllowance": 3,
"DailyQuestAllowance": 1
}
}
```
## Settings Reference
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `FeaturedWeapons` | number | `1` | Number of Active Feature weapons generated daily |
| `MaximumNP` | number | `100000` | Maximum Network Points (NP) a player can hold |
| `MaximumRP` | number | `50000` | Maximum Road Points (RP) a player can hold |
| `DisableLoginBoost` | boolean | `false` | Disable login boost system entirely |
| `DisableBoostTime` | boolean | `false` | Disable daily NetCafe boost time |
| `BoostTimeDuration` | number | `120` | NetCafe boost time duration in minutes |
| `GuildMealDuration` | number | `60` | Guild meal activation duration in minutes |
| `BonusQuestAllowance` | number | `3` | Daily Bonus Point Quest allowance |
| `DailyQuestAllowance` | number | `1` | Daily Quest allowance |
## Detailed Explanations
### Featured Weapons
Featured/Active Feature weapons are special weapon variants with unique properties. This setting controls how many are generated and available each day.
- Set to `0` to disable featured weapons
- Set to `1`-`3` for normal operation
- Higher values generate more variety
### Network Points (NP) and Road Points (RP)
NP and RP are in-game currencies/points used for various purchases and progression:
- **Network Points (NP)**: Used for purchasing items, materials, and services
- **Road Points (RP)**: Used for unlocking road/progression rewards
**Default Caps:**
- NP: `100,000`
- RP: `50,000`
You can increase these caps for more relaxed gameplay or decrease them to maintain balance.
### Boost Systems
Monster Hunter Frontier has several boost systems that increase rewards and experience:
#### Login Boost
Automatically granted when logging in. Disable with `DisableLoginBoost: true`.
#### NetCafe Boost Time
Daily time-limited boost that simulates NetCafe benefits:
```json
{
"DisableBoostTime": false,
"BoostTimeDuration": 120
}
```
- `DisableBoostTime: false` - Boost time is active
- `BoostTimeDuration: 120` - Lasts 120 minutes (2 hours)
### Guild Meals
Guild meals are buffs that guild members can activate:
```json
{
"GuildMealDuration": 60
}
```
Duration in minutes after cooking before the meal expires.
### Quest Allowances
Daily limits for special quest types:
- **BonusQuestAllowance**: Number of Bonus Point Quests per day
- **DailyQuestAllowance**: Number of Daily Quests per day
Set to `0` to disable limits entirely.
## Examples
### Casual/Relaxed Server
```json
{
"GameplayOptions": {
"FeaturedWeapons": 3,
"MaximumNP": 999999,
"MaximumRP": 999999,
"DisableLoginBoost": false,
"DisableBoostTime": false,
"BoostTimeDuration": 240,
"GuildMealDuration": 120,
"BonusQuestAllowance": 10,
"DailyQuestAllowance": 5
}
}
```
### Balanced Server (Default)
```json
{
"GameplayOptions": {
"FeaturedWeapons": 1,
"MaximumNP": 100000,
"MaximumRP": 50000,
"DisableLoginBoost": false,
"DisableBoostTime": false,
"BoostTimeDuration": 120,
"GuildMealDuration": 60,
"BonusQuestAllowance": 3,
"DailyQuestAllowance": 1
}
}
```
### Hardcore/Challenge Server
```json
{
"GameplayOptions": {
"FeaturedWeapons": 0,
"MaximumNP": 50000,
"MaximumRP": 25000,
"DisableLoginBoost": true,
"DisableBoostTime": true,
"BonusQuestAllowance": 1,
"DailyQuestAllowance": 1
}
}
```
## Related Documentation
- [Courses](courses.md) - Subscription course configuration
- [In-Game Commands](commands.md) - Player commands

201
docs/logging.md Normal file
View File

@@ -0,0 +1,201 @@
# Logging Configuration
File logging and log rotation configuration for Erupe.
## Configuration
```json
{
"Logging": {
"LogToFile": true,
"LogFilePath": "logs/erupe.log",
"LogMaxSize": 100,
"LogMaxBackups": 3,
"LogMaxAge": 28,
"LogCompress": true
}
}
```
## Settings Reference
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `LogToFile` | boolean | `true` | Enable file logging (logs to both console and file) |
| `LogFilePath` | string | `"logs/erupe.log"` | Path to log file (directory will be created automatically) |
| `LogMaxSize` | number | `100` | Maximum log file size in MB before rotation |
| `LogMaxBackups` | number | `3` | Number of old log files to keep |
| `LogMaxAge` | number | `28` | Maximum days to retain old logs |
| `LogCompress` | boolean | `true` | Compress rotated log files with gzip |
## How It Works
Erupe uses [lumberjack](https://github.com/natefinch/lumberjack) for automatic log rotation and compression.
### Log Rotation
When the current log file reaches `LogMaxSize` MB:
1. Current log is closed and renamed to `erupe.log.YYYY-MM-DD-HH-MM-SS`
2. If `LogCompress: true`, the old log is compressed to `.gz` format
3. A new `erupe.log` file is created
4. Old logs beyond `LogMaxBackups` count are deleted
5. Logs older than `LogMaxAge` days are deleted
### Example Log Files
```text
logs/
├── erupe.log (current, 45 MB)
├── erupe.log.2025-11-17-14-23-45.gz (100 MB compressed)
├── erupe.log.2025-11-16-08-15-32.gz (100 MB compressed)
└── erupe.log.2025-11-15-19-42-18.gz (100 MB compressed)
```
## Log Format
Log format depends on `DevMode` setting:
### Development Mode (DevMode: true)
Console format (human-readable):
```text
2025-11-18T10:30:45.123Z INFO channelserver Player connected {"charID": 12345, "ip": "127.0.0.1"}
2025-11-18T10:30:46.456Z ERROR channelserver Failed to load data {"error": "database timeout"}
```
### Production Mode (DevMode: false)
JSON format (machine-parsable):
```json
{"level":"info","ts":"2025-11-18T10:30:45.123Z","logger":"channelserver","msg":"Player connected","charID":12345,"ip":"127.0.0.1"}
{"level":"error","ts":"2025-11-18T10:30:46.456Z","logger":"channelserver","msg":"Failed to load data","error":"database timeout"}
```
## Log Analysis
Erupe includes a built-in log analyzer tool in `tools/loganalyzer/`:
```bash
# Filter by log level
./loganalyzer filter -f ../../logs/erupe.log -level error
# Analyze errors with stack traces
./loganalyzer errors -f ../../logs/erupe.log -stack -detailed
# Track player connections
./loganalyzer connections -f ../../logs/erupe.log -sessions
# Real-time monitoring
./loganalyzer tail -f ../../logs/erupe.log -level error
# Generate statistics
./loganalyzer stats -f ../../logs/erupe.log -detailed
```
See [CLAUDE.md](../CLAUDE.md#log-analysis) for more details.
## Examples
### Minimal Logging (Development)
```json
{
"Logging": {
"LogToFile": false
}
}
```
Only logs to console, no file logging.
### Standard Production Logging
```json
{
"Logging": {
"LogToFile": true,
"LogFilePath": "logs/erupe.log",
"LogMaxSize": 100,
"LogMaxBackups": 7,
"LogMaxAge": 30,
"LogCompress": true
}
}
```
Keeps up to 7 log files, 30 days maximum, compressed.
### High-Volume Server
```json
{
"Logging": {
"LogToFile": true,
"LogFilePath": "/var/log/erupe/erupe.log",
"LogMaxSize": 500,
"LogMaxBackups": 14,
"LogMaxAge": 60,
"LogCompress": true
}
}
```
Larger log files (500 MB), more backups (14), longer retention (60 days).
### Debug/Testing (No Rotation)
```json
{
"Logging": {
"LogToFile": true,
"LogFilePath": "logs/debug.log",
"LogMaxSize": 1000,
"LogMaxBackups": 0,
"LogMaxAge": 0,
"LogCompress": false
}
}
```
Single large log file, no rotation, no compression. Useful for debugging sessions.
## Disk Space Considerations
Calculate approximate disk usage:
```text
Total Disk Usage = (LogMaxSize × LogMaxBackups) × CompressionRatio
```
**Compression ratios:**
- Text logs: ~10:1 (100 MB → 10 MB compressed)
- JSON logs: ~8:1 (100 MB → 12.5 MB compressed)
**Example:**
```text
LogMaxSize: 100 MB
LogMaxBackups: 7
Compression: enabled (~10:1 ratio)
Total: (100 MB × 7) / 10 = 70 MB (approximately)
```
## Best Practices
1. **Enable compression** - Saves significant disk space
2. **Set reasonable MaxSize** - 100-200 MB works well for most servers
3. **Adjust retention** - Keep logs for at least 7 days, preferably 30
4. **Use absolute paths in production** - `/var/log/erupe/erupe.log` instead of `logs/erupe.log`
5. **Monitor disk space** - Set up alerts if disk usage exceeds 80%
6. **Use JSON format in production** - Easier to parse with log analysis tools
## Related Documentation
- [Development Mode](development-mode.md) - DevMode affects log format
- [Basic Settings](basic-settings.md) - Basic server configuration
- [CLAUDE.md](../CLAUDE.md#log-analysis) - Log analyzer tool usage

View File

@@ -0,0 +1,445 @@
# Server Configuration
Configuration for Erupe's three-server architecture: Sign, Entrance, and Channel servers.
## Three-Server Architecture
Erupe uses a multi-server architecture that mirrors the original Monster Hunter Frontier server design:
```
Client → Sign Server (Auth) → Entrance Server (World List) → Channel Server (Gameplay)
```
1. **Sign Server**: Authentication and account management
2. **Entrance Server**: World/server selection and character list
3. **Channel Servers**: Actual gameplay sessions, quests, and player interactions
## Sign Server
Handles authentication and account management.
### Configuration
```json
{
"Sign": {
"Enabled": true,
"Port": 53312
}
}
```
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `Enabled` | boolean | `true` | Enable the legacy sign server |
| `Port` | number | `53312` | Port for sign server (client default: 53312) |
### Details
- Located in [server/signserver/](../server/signserver/)
- Creates sign sessions with tokens for channel server authentication
- Legacy TCP-based protocol
- Required unless using SignV2
## SignV2 Server
Modern HTTP-based sign server (alternative to legacy sign server).
### Configuration
```json
{
"SignV2": {
"Enabled": false,
"Port": 8080
}
}
```
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `Enabled` | boolean | `false` | Enable the modern HTTP-based sign server |
| `Port` | number | `8080` | Port for SignV2 server |
### Details
- Located in [server/signv2server/](../server/signv2server/)
- HTTP-based authentication (easier to proxy/load balance)
- Alternative to legacy sign server
- **Only enable one sign server at a time** (Sign OR SignV2, not both)
## Channel Server
Handles actual gameplay sessions, quests, and player interactions.
### Configuration
```json
{
"Channel": {
"Enabled": true
}
}
```
| Setting | Type | Default | Description |
|---------|------|---------|-------------|
| `Enabled` | boolean | `true` | Enable channel servers (required for gameplay) |
### Details
- Located in [server/channelserver/](../server/channelserver/)
- Most complex component - handles all gameplay logic
- Multiple instances can run simultaneously
- Ports configured in Entrance server entries
- Features:
- Session management
- Packet handling
- Stage/room system
- Quest system
- Guild operations
- Special events (Raviente, Diva Defense, etc.)
See [CLAUDE.md](../CLAUDE.md#channel-server-internal-architecture) for detailed architecture.
## Entrance Server
Manages world/server selection and character lists.
### Configuration
```json
{
"Entrance": {
"Enabled": true,
"Port": 53310,
"Entries": [
{
"Name": "Newbie",
"Description": "",
"IP": "",
"Type": 3,
"Recommended": 2,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54001, "MaxPlayers": 100 },
{ "Port": 54002, "MaxPlayers": 100 }
]
}
]
}
}
```
### Settings Reference
| Setting | Type | Description |
|---------|------|-------------|
| `Enabled` | boolean | Enable entrance server (required for server list) |
| `Port` | number | Entrance server port (default: 53310) |
| `Entries` | array | List of worlds/servers shown to players |
### Entrance Entries
Each entry represents a "world" in the server list.
| Field | Type | Description |
|-------|------|-------------|
| `Name` | string | World name displayed to players (e.g., "Newbie", "Normal") |
| `Description` | string | World description (optional, usually empty) |
| `IP` | string | Override IP address (leave empty to use global `Host` setting) |
| `Type` | number | World type (see below) |
| `Recommended` | number | Recommendation badge: `0`=None, `2`=Recommended, `6`=Special |
| `AllowedClientFlags` | number | Client version flags (0 = all versions allowed) |
| `Channels` | array | List of channel servers in this world |
### World Types
| Type | Name | Purpose |
|------|------|---------|
| `1` | Normal | Standard gameplay world |
| `2` | Cities | Social/town areas |
| `3` | Newbie | For new players (typically recommended) |
| `4` | Tavern | Bar/tavern areas |
| `5` | Return | For returning players |
| `6` | MezFes | MezFes event world |
### Channel Configuration
Each world has multiple channels (like "servers" within a "world"):
```json
{
"Channels": [
{ "Port": 54001, "MaxPlayers": 100 },
{ "Port": 54002, "MaxPlayers": 100 }
]
}
```
| Field | Type | Description |
|-------|------|-------------|
| `Port` | number | Channel server port (must be unique across all channels) |
| `MaxPlayers` | number | Maximum players allowed in this channel |
| `CurrentPlayers` | number | Current player count (auto-updated at runtime) |
## Complete Server Configurations
### Minimal Setup (Single World, Single Channel)
```json
{
"Sign": {
"Enabled": true,
"Port": 53312
},
"SignV2": {
"Enabled": false
},
"Channel": {
"Enabled": true
},
"Entrance": {
"Enabled": true,
"Port": 53310,
"Entries": [
{
"Name": "Main",
"Type": 1,
"Recommended": 0,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54001, "MaxPlayers": 100 }
]
}
]
}
}
```
### Standard Setup (Multiple Worlds)
```json
{
"Sign": {
"Enabled": true,
"Port": 53312
},
"Channel": {
"Enabled": true
},
"Entrance": {
"Enabled": true,
"Port": 53310,
"Entries": [
{
"Name": "Newbie",
"Description": "",
"IP": "",
"Type": 3,
"Recommended": 2,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54001, "MaxPlayers": 100 },
{ "Port": 54002, "MaxPlayers": 100 }
]
},
{
"Name": "Normal",
"Description": "",
"IP": "",
"Type": 1,
"Recommended": 0,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54003, "MaxPlayers": 100 },
{ "Port": 54004, "MaxPlayers": 100 }
]
},
{
"Name": "Cities",
"Description": "",
"IP": "",
"Type": 2,
"Recommended": 0,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54005, "MaxPlayers": 100 }
]
}
]
}
}
```
### Large-Scale Setup
```json
{
"Sign": {
"Enabled": true,
"Port": 53312
},
"Channel": {
"Enabled": true
},
"Entrance": {
"Enabled": true,
"Port": 53310,
"Entries": [
{
"Name": "Newbie",
"Type": 3,
"Recommended": 2,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54001, "MaxPlayers": 150 },
{ "Port": 54002, "MaxPlayers": 150 },
{ "Port": 54003, "MaxPlayers": 150 }
]
},
{
"Name": "Normal",
"Type": 1,
"Recommended": 0,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54004, "MaxPlayers": 200 },
{ "Port": 54005, "MaxPlayers": 200 },
{ "Port": 54006, "MaxPlayers": 200 },
{ "Port": 54007, "MaxPlayers": 200 }
]
},
{
"Name": "Cities",
"Type": 2,
"Recommended": 0,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54008, "MaxPlayers": 100 },
{ "Port": 54009, "MaxPlayers": 100 }
]
},
{
"Name": "MezFes",
"Type": 6,
"Recommended": 6,
"AllowedClientFlags": 0,
"Channels": [
{ "Port": 54010, "MaxPlayers": 100 }
]
}
]
}
}
```
## Port Allocation
Default port assignments:
| Server | Port | Configurable |
|--------|------|--------------|
| Sign | 53312 | Yes |
| SignV2 | 8080 | Yes |
| Entrance | 53310 | Yes |
| Channels | 54001+ | Yes (per-channel) |
**Important:**
- All ports must be unique
- Firewall must allow inbound connections on these ports
- Client expects Sign on 53312 and Entrance on 53310 by default
## Firewall Configuration
### Linux (ufw)
```bash
# Allow sign server
sudo ufw allow 53312/tcp
# Allow entrance server
sudo ufw allow 53310/tcp
# Allow channel servers (range)
sudo ufw allow 54001:54010/tcp
```
### Linux (iptables)
```bash
# Sign server
sudo iptables -A INPUT -p tcp --dport 53312 -j ACCEPT
# Entrance server
sudo iptables -A INPUT -p tcp --dport 53310 -j ACCEPT
# Channel servers (range)
sudo iptables -A INPUT -p tcp --dport 54001:54010 -j ACCEPT
```
### Windows Firewall
```powershell
# Allow specific ports
New-NetFirewallRule -DisplayName "Erupe Sign" -Direction Inbound -Protocol TCP -LocalPort 53312 -Action Allow
New-NetFirewallRule -DisplayName "Erupe Entrance" -Direction Inbound -Protocol TCP -LocalPort 53310 -Action Allow
New-NetFirewallRule -DisplayName "Erupe Channels" -Direction Inbound -Protocol TCP -LocalPort 54001-54010 -Action Allow
```
## Load Balancing
For high-traffic servers, consider:
1. **Multiple Entrance Servers**: Run multiple entrance server instances behind a load balancer
2. **Distributed Channels**: Spread channel servers across multiple physical servers
3. **Database Connection Pooling**: Use PgBouncer for database connections
4. **SignV2 with Reverse Proxy**: Use nginx/HAProxy with SignV2 for better scaling
## Monitoring
Monitor server health:
```bash
# Check if servers are listening
netstat -tlnp | grep erupe
# Check open ports
ss -tlnp | grep -E '(53312|53310|54001)'
# Monitor connections per channel
watch -n 1 'netstat -an | grep ESTABLISHED | grep 54001 | wc -l'
```
## Troubleshooting
### Can't Connect to Sign Server
- Verify Sign server is enabled
- Check port 53312 is open
- Verify client is configured for correct IP/port
### World List Empty
- Verify Entrance server is enabled
- Check Entrance server port (53310)
- Ensure at least one Entry is configured
### Can't Enter World
- Verify Channel server is enabled
- Check channel ports are open
- Verify channel ports in Entrance entries match actual running servers
### Server Crashes on Startup
- Check all ports are unique
- Verify database connection (password not empty)
- Check logs for specific errors
## Related Documentation
- [Database](database.md) - Database configuration
- [Basic Settings](basic-settings.md) - Host and network settings
- [CLAUDE.md](../CLAUDE.md#architecture) - Detailed architecture overview