61 Commits

Author SHA1 Message Date
Houmgaor
835f97d3c2 fix(shutdown): force-stop on second SIGINT during countdown
A second Ctrl+C/SIGINT while the 10-second shutdown countdown is
running now exits immediately instead of being silently dropped.
The signal channel is buffered to 2 so the second signal is captured,
and the countdown select exits via os.Exit(1) on receipt.
2026-03-18 21:36:24 +01:00
Houmgaor
7657ddbd50 fix: prevent startup panics on databases missing base tables
The catch-up migration now creates the servers table if missing, like
sign_sessions. Startup cleanup queries in main.go use Exec instead of
MustExec so missing tables log warnings rather than panicking.
2026-03-16 00:04:45 +01:00
Houmgaor
c3d089cca1 chore: update version string from 9.3b to 9.3.0 2026-03-10 11:44:52 +01:00
Houmgaor
69ad4ca54a fix: diagnose specific database connection errors at startup
Instead of a generic "Failed to ping" message, detect the actual
cause and show a targeted fix:
- net error → PostgreSQL not reachable, check if it's running
- pq 28P01 → wrong password, update config.json
- pq 3D000 → database doesn't exist, create it
2026-03-05 23:25:00 +01:00
Houmgaor
ba7ec122f8 revert: remove SQLite support
An MMO server without multiplayer defeats the purpose. PostgreSQL
is the right choice and Docker Compose already solves the setup
pain. This reverts the common/db wrapper, SQLite schema, config
Driver field, modernc.org/sqlite dependency, and all repo type
changes while keeping the dashboard, wizard, and CI improvements
from the previous commit.
2026-03-05 23:05:55 +01:00
Houmgaor
ecfe58ffb4 feat: add SQLite support, setup wizard enhancements, and live dashboard
Add zero-dependency SQLite mode so users can run Erupe without
PostgreSQL. A transparent db.DB wrapper auto-translates PostgreSQL
SQL ($N placeholders, now(), ::casts, ILIKE, public. prefix,
TRUNCATE) for SQLite at runtime — all 28 repo files use the wrapper
with no per-query changes needed.

Setup wizard gains two new steps: quest file detection with download
link, and gameplay presets (solo/small/community/rebalanced). The API
server gets a /dashboard endpoint with auto-refreshing stats.

CI release workflow now builds and pushes Docker images to GHCR
alongside binary artifacts on tag push.

Key changes:
- common/db: DB/Tx wrapper with 6 SQL translation rules
- server/migrations/sqlite: full SQLite schema (0001-0005)
- config: Database.Driver field ("postgres" or "sqlite")
- main.go: SQLite connection with WAL mode, single writer
- server/setup: quest check + preset selection steps
- server/api: /dashboard with live stats
- .github/workflows: Docker in release, deduplicate docker.yml
2026-03-05 18:00:30 +01:00
Houmgaor
d38fef08bb refactor(discordbot): introduce Session interface for testability
Extract a Session interface from *discordgo.Session so DiscordBot methods
can be tested with a mock — no live Discord connection required. Add
AddHandler, RegisterCommands, and UserID methods to DiscordBot so
external callers (main.go, sys_channel_server.go) no longer reach
through bot.Session directly. Rewrite tests with a mockSession,
raising discordbot coverage from 12.5% to 66.7%.
2026-02-27 11:45:20 +01:00
Houmgaor
bcdc4e0b7e fix(setup): reduce friction in installation procedure
- Add Language default ("jp") so missing field no longer produces empty
  string, and include language selector in setup wizard
- Add --setup flag to re-run wizard even when config.json exists,
  providing a recovery path for corrupted configs
- Auto-apply seed data on fresh databases so users who skip the wizard
  still get shops, events, and gacha
- Fix stale docs referencing non-existent init/setup.sh and
  schemas/patch-schema/ in docker/README, CONTRIBUTING, and README
2026-02-23 23:39:49 +01:00
Houmgaor
27fb0faa1e feat(db): add embedded auto-migrating schema system
Replace 4 independent schema management code paths (Docker shell
script, setup wizard pg_restore, test helpers, manual psql) with a
single migration runner embedded in the server binary.

The new server/migrations/ package uses Go embed to bundle all SQL
schemas. On startup, Migrate() creates a schema_version tracking
table, detects existing databases (auto-marks baseline as applied),
and runs pending migrations in transactions.

Key changes:
- Consolidated init.sql + 9.2-update + 33 patches into 0001_init.sql
- Setup wizard simplified to single "Apply schema" checkbox
- Test helpers use migrations.Migrate() instead of pg_restore
- Docker no longer needs schema volume mounts or init script
- Seed data (shops, events, gacha) embedded and applied via API
- Future migrations just add 0002_*.sql files — no manual steps
2026-02-23 21:19:21 +01:00
Houmgaor
6a7db47723 feat(setup): add web-based first-run configuration wizard
When config.json is missing, Erupe now launches a temporary HTTP server
on port 8080 serving a guided setup wizard instead of exiting with a
cryptic error. The wizard walks users through database connection,
schema initialization (pg_restore + SQL migrations), and server settings,
then writes config.json and continues normal startup without restart.
2026-02-23 20:55:56 +01:00
Houmgaor
b96cd0904b fix: ease onboarding with startup warnings and doc corrections
- Warn at startup when quest files are missing (clients crash without
  them) and point users to the download link
- Fix Host config description: it's the advertised IP, not a bind
  address — 0.0.0.0 was wrong advice
- Load bundled schemas (shops, events, gacha) in Docker init so new
  users get working demo data out of the box
- Renumber duplicate patch schema 28 → 32 to resolve numbering
  collision
- Fix patch schema example filename to use hyphens matching actual
  files
2026-02-23 20:23:08 +01:00
Houmgaor
53b5bb3b96 refactor(channelserver): remove Channels fallbacks, use Registry as sole cross-channel API
main.go always sets both Channels and Registry together, making the
Channels fallback paths dead code. This removes:

- Server.Channels field from the Server struct
- 3 if/else fallback blocks in handlers_session.go (replaced with
  Registry.FindChannelForStage, SearchSessions, SearchStages)
- 1 if/else fallback block in handlers_guild_ops.go (replaced with
  Registry.NotifyMailToCharID)
- 3 method fallbacks in sys_channel_server.go (WorldcastMHF,
  FindSessionByCharID, DisconnectUser now delegate directly)

Updates anti-patterns.md #6 to "accepted design" — Session struct is
appropriate for this game server's handler pattern, and cross-channel
coupling is now fully routed through the ChannelRegistry interface.
2026-02-22 16:16:44 +01:00
Houmgaor
f17cb96b52 refactor(config): rename package _config to config with cfg alias
The config package used `package _config` with a leading underscore,
which is unconventional in Go. Rename to `package config` (matching the
directory name) and use `cfg` as the standard import alias across all
93 importing files.
2026-02-21 13:20:15 +01:00
Houmgaor
f9d9260274 fix(channelserver): configure DB pool and add transactions for guild ops
sqlx.Open was called with no pool configuration, risking PostgreSQL
connection exhaustion under load. Set max open/idle conns and lifetimes.

CreatePost INSERT + soft-delete UPDATE were two separate queries with
no transaction, risking inconsistent state on partial failure.

CollectAdventure used SELECT then UPDATE without a lock, allowing
concurrent guild members to double-collect. Now uses SELECT FOR UPDATE
within a transaction.
2026-02-21 00:29:09 +01:00
Houmgaor
5f3c843082 refactor(config): eliminate ErupeConfig global variable
Replace the mutable global `_config.ErupeConfig` with dependency
injection across 79 files. Config is now threaded through existing
paths: `ClientContext.RealClientMode` for packet encoding, `s.server.
erupeConfig` for channel handlers, and explicit parameters for utility
functions. This removes hidden coupling, enables test parallelism
without global save/restore, and prevents low-level packages from
reaching up to the config layer.

Key changes:
- Enrich ClientContext with RealClientMode for packet files
- Add mode parameter to CryptConn, mhfitem, mhfcourse functions
- Convert handlers_commands init() to lazy sync.Once initialization
- Delete global var, init(), and helper functions from config.go
- Update all tests to pass config explicitly
2026-02-20 17:07:42 +01:00
Houmgaor
754b5a3bff feat(channelserver): decouple channel servers for independent operation (#33)
Enable multiple Erupe instances to share a single PostgreSQL database
without destroying each other's state, fix existing data races in
cross-channel access, and lay groundwork for future distributed
channel server deployments.

Phase 1 — DB safety:
- Scope DELETE FROM servers/sign_sessions to this instance's server IDs
- Fix ci++ bug where failed channel start shifted subsequent IDs

Phase 2 — Fix data races in cross-channel access:
- Lock sessions map in FindSessionByCharID and DisconnectUser
- Lock stagesLock in handleMsgSysLockGlobalSema
- Snapshot sessions/stages under lock in TransitMessage types 1-4
- Lock channel when finding mail notification targets

Phase 3 — ChannelRegistry interface:
- Define ChannelRegistry interface with 7 cross-channel operations
- Implement LocalChannelRegistry with proper locking
- Add SessionSnapshot/StageSnapshot immutable copy types
- Delegate WorldcastMHF, FindSessionByCharID, DisconnectUser to Registry
- Migrate LockGlobalSema and guild mail handlers to use Registry
- Add comprehensive tests including concurrent access

Phase 4 — Per-channel enable/disable:
- Add Enabled *bool to EntranceChannelInfo (nil defaults to true)
- Skip disabled channels in startup loop, preserving ID stability
- Add IsEnabled() helper with backward-compatible default
- Update config.example.json with Enabled field
2026-02-19 18:13:34 +01:00
Houmgaor
2a0e3e2c84 fix: re-enable CI lint job and fix ~65 lint errors (partial)
Re-enable the golangci-lint job in CI (disabled Oct 2025), update to
Go 1.25 and golangci-lint-action v7. Fix errcheck, gosimple S1009,
staticcheck SA4031 and SA2001 errors across 54 files. Remaining ~39
lint errors will be addressed in follow-up commits.
2026-02-17 17:59:00 +01:00
Houmgaor
d2b5bb72f8 refactor: extract gametime package, replace fmt.Printf with zap logging
Move time utilities (TimeAdjusted, TimeMidnight, TimeWeekStart, TimeWeekNext,
TimeGameAbsolute) from channelserver into common/gametime to break the
inappropriate dependency where signserver, entranceserver, and api imported
the 38K-line channelserver package just for time functions.

Replace all fmt.Printf debug logging in sys_session.go and handlers_object.go
with structured zap logging for consistent observability.
2026-02-17 17:54:51 +01:00
Houmgaor
90c8a50316 fix(main): wrong configuration in last commit. 2025-10-18 19:24:24 +02:00
Houmgaor
f410cbd48b chore: minor files update. 2025-10-18 18:57:16 +02:00
stratic-dev
d123182a2f Renamed signv2 to api and enabled it by default 2024-03-15 19:37:55 +00:00
wish
0d28637095 support long messages, rename to RelayChannel, move commands out of main 2024-01-01 21:22:51 +11:00
wish
b3a265e218 Merge remote-tracking branch 'origin/main' into feature/discord-login 2023-12-31 22:38:08 +11:00
wish
0ea0dc217b simplify config 2023-12-31 12:51:24 +11:00
Matthew
38b57c6d98 refactor: Change to using rand.Read instead of whatever the hell else was before 2023-11-27 01:08:40 -05:00
Matthew
226adddc43 feat: Generate hashes for Discord and allow password resets 2023-11-26 16:47:54 -05:00
wish
22b1d1b716 Merge pull request #99 from rockisch/dev-proxy
Add dev proxy config
2023-11-26 20:53:55 +11:00
wish
a2f488e5e3 move ProxyPort config out of DevMode 2023-11-26 20:50:08 +11:00
rockisch
e39630564e Add dev proxy config 2023-11-22 00:01:04 -03:00
wish
2f8d09b09e more GuildTresure optimisation 2023-10-24 21:21:21 +11:00
wish
f23da6fba5 remove Season from database 2023-07-18 23:00:00 +10:00
wish
1f93419cb7 add support for more versions 2023-07-03 00:30:44 +10:00
wish
b4df642ee3 add ClientMode config option 2023-06-18 20:31:18 +10:00
wish
23138b2d5b update versioning 2023-04-11 21:08:00 +10:00
wish
f0db7f0a19 finalise 9.2 2023-04-01 17:58:26 +11:00
wish
ce30c1231d remove countdown on auto restart 2023-03-09 22:23:45 +11:00
wish
dcab41a6c7 rework logging code 2023-03-09 22:05:32 +11:00
wish
d5dc15fc93 implement guild semaphore locking 2023-03-09 17:31:43 +11:00
wish
cfe6bd118c update startup logging 2023-03-05 22:24:33 +11:00
wish
aa3deca70a remove obsolete LauncherServer 2022-12-31 01:57:16 +11:00
wish
f8e21483ef escape db connection arguments 2022-12-24 00:09:38 +11:00
wish
ec2ff61199 update versioning 2022-11-07 08:43:46 +11:00
wish
492e64d0d0 rename sign server and merge conflicts 2022-11-07 08:37:40 +11:00
rockisch
7f45d09d96 implement new sign server 2022-11-05 20:28:52 -03:00
wish
77f8f2019d finalise 9.1 2022-11-02 23:44:35 +11:00
wish
fda2e74442 persist cafe time 2022-10-24 16:51:56 +11:00
wish
77ed0564ce normalise config 2022-10-24 16:00:58 +11:00
wish
f346c181d3 add versioning print 2022-10-12 19:27:35 +11:00
Eclipse
2f123d96df Implemented the ability to enable/disable entrance, sign, and channel servers 2022-09-22 20:51:18 -04:00
Eclipse
44a42a3365 Implemented the ability to enable and disable commands in configuration as well as increased scope of the config to the entire project. 2022-09-18 14:15:11 -04:00