mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-22 07:32:32 +01:00
docs: adds documentation files for the major configurable options.
This commit is contained in:
356
CLAUDE.md
Normal file
356
CLAUDE.md
Normal 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
249
docs/README.md
Normal 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
89
docs/basic-settings.md
Normal 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
335
docs/commands.md
Normal 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
610
docs/configuration.md
Normal 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
219
docs/courses.md
Normal 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
409
docs/database.md
Normal 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
166
docs/development-mode.md
Normal 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
199
docs/discord-integration.md
Normal 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
161
docs/gameplay-options.md
Normal 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
201
docs/logging.md
Normal 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
|
||||
445
docs/server-configuration.md
Normal file
445
docs/server-configuration.md
Normal 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
|
||||
Reference in New Issue
Block a user