Commit Graph

63 Commits

Author SHA1 Message Date
Houmgaor
a1dfdd330a feat(scenario): add JSON scenario support and JKR type-3 compressor
Closes #172. Scenario files in bin/scenarios/ can now be authored as
.json instead of .bin — the server compiles them to wire format on
load, falling back to .bin if no .json is present.

- Add ParseScenarioBinary / CompileScenarioJSON in scenario_json.go;
  supports sub-header format (strings as UTF-8, metadata as base64),
  inline format, and raw JKR blobs.
- Add PackSimple JKR type-3 (LZ77) compressor in jpk_compress.go,
  ported from ReFrontier JPKEncodeLz.cs; round-trip tested against
  UnpackSimple.
- Fix off-by-one in processDecode (jpk.go): last literal byte was
  silently dropped for data that does not end on a back-reference.
- Wire loadScenarioBinary into handleMsgSysGetFile replacing the
  inline os.ReadFile call; mirrors the existing loadQuestBinary pattern.
- Rewrite docs/scenario-format.md with full container/sub-header spec
  and JSON schema examples.
2026-03-20 13:55:40 +01:00
Houmgaor
5c2fde5cfd feat(rengoku): validate and log Hunting Road config on startup
Port ECD encryption/decryption from ReFrontier (C#) and FrontierTextHandler
(Python) into common/decryption. The cipher uses a 32-bit LCG key stream with
an 8-round Feistel-like nibble transformation and CFB chaining; all six key
sets are supported, key 4 being the default for all MHF files.

On startup, loadRengokuBinary now decrypts (ECD) and decompresses (JKR) the
binary to validate pointer bounds and entry counts, then logs a structured
summary (floor counts, spawn table counts, unique monster IDs). Failures are
non-fatal — the encrypted blob is still cached and served to clients unchanged,
preserving existing behaviour. Closes #173.
2026-03-19 23:59:34 +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
a68d76c55f test: add coverage tests to reach 65% total coverage
Add 16 test files across 4 packages covering previously untested
handler paths: guild board operations, house/warehouse management,
tower/tenrouirai progress, diva schedule, festa info, cafe duration,
API error paths, sign server responses, and byteframe boundaries.
2026-02-26 23:17:12 +01:00
Houmgaor
48639942f6 style: run gofmt across entire codebase
330 non-vendor files had minor formatting inconsistencies
(comment alignment, whitespace). No logic changes.
2026-02-23 21:28:30 +01:00
Houmgaor
7af41a7796 fix(decryption): eliminate data race in JPK decompression
Package-level globals mShiftIndex and mFlag were shared across
concurrent goroutines calling UnpackSimple from quest handlers.
Replace with a local jpkState struct scoped to each decompression
call. Add concurrent safety test validated with -race.
2026-02-23 20:01:38 +01:00
Houmgaor
f640cfee27 fix: log SJIS decoding errors instead of silently discarding them
Add SJISToUTF8Lossy() that wraps SJISToUTF8() and logs decode errors at
slog.Debug level. Replace all 31 call sites across 17 files that previously
discarded the error with `_, _ =`. This makes garbled text from malformed
SJIS client data debuggable without adding noise at default log levels.
2026-02-22 17:01:22 +01:00
Houmgaor
2acbb5d03a feat(channelserver): implement monthly guild item claim tracking
Players could never claim monthly guild items because the handler
always returned 0x01 (claimed). Now tracks per-character per-type
(standard/HLC/EXC) claim timestamps in the stamps table, comparing
against the current month boundary to determine claim eligibility.

Adds MonthStart() to gametime, extends StampRepo with
GetMonthlyClaimed/SetMonthlyClaimed, and includes schema migration
31-monthly-items.sql.
2026-02-22 16:46:57 +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
ac59188488 refactor(byteframe): replace read-overflow panic with sticky error
ByteFrame previously panicked on out-of-bounds reads, which crashed
the server when parsing malformed client packets. Now sets a sticky
error (checked via Err()) and returns zero values, matching the
encoding/binary scanner pattern. The session recv loop checks Err()
after parsing to reject malformed packets gracefully.

Also replaces remaining panic("Not implemented") stubs in network
packet Build/Parse methods with proper error returns.
2026-02-20 20:00:54 +01:00
Houmgaor
d32e77efba refactor: replace panic calls with structured error handling
Replace ~25 panic() calls in non-fatal code paths with proper
s.logger.Error + return patterns. Panics in handler code crashed
goroutines (caught by defer/recover but still disruptive) instead
of failing gracefully.

Key changes:
- SJISToUTF8 now returns (string, error); all 30+ callers updated
- Handler DB/IO panics replaced with log + return/ack fail
- Unhandled switch-case panics replaced with logger.Error
- Sign server Accept() panic replaced with log + continue
- Dead unreachable panic in guild_model.go removed
- deltacomp patch error logs and returns partial data

Panics intentionally kept: ByteFrame sentinel, unimplemented
packet stubs, os.Exit in main.go.
2026-02-20 19:11:41 +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
2bd5f98f32 docs: add doc.go files and godoc comments to all packages
Add package-level documentation (doc.go) to all 22 first-party
packages and godoc comments to ~150 previously undocumented
exported symbols across common/, network/, and server/.
2026-02-18 21:39:13 +01:00
Houmgaor
c64dabc3ba fix: check all Close() return values for errcheck lint
Add explicit error discards (_ =) for Close() calls on network
connections, SQL rows, and file handles across 28 files. Also add
.golangci.yml with standard linter defaults to match CI configuration.
2026-02-17 23:57:14 +01:00
Houmgaor
46bbb6adf9 fix: resolve all remaining lint errors (errcheck) across 49 files
Fix unchecked error returns on bf.Seek(), db.Exec(), QueryRow().Scan(),
pkt.Build(), logger.Sync(), and binary.Write() calls. The linter now
passes with 0 errors, build compiles, and all tests pass with -race.
2026-02-17 18:07:38 +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
645c4ddd38 test: increase code coverage from 45.1% to 48.3%
Add unit tests across multiple packages:
- byteframe: SetBE/SetLE byte order switching
- config: Mode.String() for all safe version ranges
- mhfpacket: 28 Parse methods, 5 Build methods, empty packet builds,
  variable-length packets, NOT IMPLEMENTED error paths, UpdateWarehouse
- network: PacketID.String() for known IDs, out-of-range, and all valid
- channelserver: handleMsgMhfGetPaperData (6 switch cases), grpToGR
  (11 input values), gacha handlers, TimeGameAbsolute, equipSkinHistSize
  (4 config branches), guild mission handlers, dumpSaveData disabled path
- entranceserver: makeHeader with various inputs
2026-02-17 17:32:54 +01:00
Houmgaor
a7b0deaa42 fix: resolve data race in token.RNG global
Wrap *rand.Rand in a mutex-protected SafeRand type to make the global
RNG safe for concurrent use across goroutines. The previous bare
*rand.Rand caused data races detected by go test -race.
2026-02-16 18:19:18 +01:00
Houmgaor
9b69564c49 fix: prevent server crash on unsupported Shift-JIS characters (#116)
UTF8ToSJIS panicked when encountering characters outside the Shift-JIS
range (emoji, Lenny faces, cuneiform, etc.), crashing the server when
such characters were sent via the Discord relay channel.

Replace the panic with graceful filtering that drops unmappable runes
and preserves valid content. Also fix ToNGWord index-out-of-range panic
on empty encoder output.

Closes #116
2026-02-16 18:16:42 +01:00
Houmgaor
a6cf550fdb tests(common): comprehensive code coverage for common 2025-10-27 12:59:22 +01:00
Houmgaor
c55f23442b fix(lint): fixing go static check failing. 2025-10-19 22:52:58 +02:00
wish
632aa081b9 decode SMC table 2024-07-16 00:57:59 +10:00
wish
0caaeac3af initial ngword commit 2024-07-15 01:07:50 +10:00
wish
c74ce4b07f simplify reused code 2024-02-25 14:22:21 +11:00
wish
a9b9c94347 fix RNG 2024-02-21 03:46:15 +11:00
wish
9f19358c8b fix Warehouse serialisation across versions 2024-02-20 21:04:29 +11:00
wish
db364110eb Merge branch 'main' into feature/warehouse-v2 2024-02-20 17:50:04 +11:00
wish
771f240d13 implement course 31 2024-02-10 17:45:40 +11:00
wish
4fbfd569df Merge pull request #111 from ZeruLight/feature/moderation
feature/moderation
2024-01-11 23:04:29 +11:00
wish
ba7321b535 fix stringstack & MoveStage error 2024-01-10 19:29:51 +11:00
wish
2135c443d8 add ban chat command 2024-01-03 19:30:57 +11:00
wish
0ea0dc217b simplify config 2023-12-31 12:51:24 +11:00
wish
fd02a12ae9 add DefaultCourses DevModeOption 2023-12-31 10:22:27 +11:00
wish
7e34862e25 Merge remote-tracking branch 'origin/main' into feature/warehouse-v2
# Conflicts:
#	server/channelserver/handlers.go
2023-12-13 11:38:05 +11:00
wish
b6e7f019de update mhfmon names 2023-12-03 19:56:18 +11:00
wish
4ce65e47e6 revert stringstack.go changes 2023-12-03 17:50:01 +11:00
wish
a846a71ca3 rewrite stringstack.go 2023-11-27 20:45:03 +11:00
wish
bcf2ba40e5 fix possible integer bounding issues 2023-11-20 00:13:49 +11:00
wish
641032f862 implement hunt data logging (partial #82) 2023-10-08 19:25:48 +11:00
wish
a9f280a2ef initial warehouse-v2 concept commit 2023-10-01 03:17:51 +11:00
wish
6f9974fa26 update Golang dependencies 2023-08-20 15:30:24 +10:00
wish
0bd4658a23 golang formatting pass 2023-07-03 20:31:53 +10:00
Matthe815
c3fb6aa821 refactor: Remove more debug code 2023-07-03 02:58:10 -04:00
Matthe815
a065643783 feature: JPK encryption and databased events 2023-07-03 02:50:38 -04:00
wish
35b383cba6 Merge pull request #72 from ZeruLight/fix/dynamic-tune-vals
dynamic tune values
2023-07-01 23:59:57 +10:00
wish
796927ac61 add PS3_TROP to constant courses 2023-06-20 21:42:06 +10:00
wish
2c8391b5a4 various Tower changes 2023-06-11 18:51:56 +10:00
wish
f5ae129cad implement psn linking capability 2023-04-15 11:00:49 +10:00