Commit Graph

127 Commits

Author SHA1 Message Date
Houmgaor
1d507b3d11 fix: replace fmt.Sprintf in logger calls with structured fields and add LoopDelay default
fmt.Sprintf inside zap logger calls defeats structured logging,
making log aggregation and filtering harder. All 6 sites now use
proper zap fields (zap.Uint32, zap.Uint8, zap.String).

LoopDelay had no viper.SetDefault, so omitting it from config.json
caused a zero-value (0 ms) busy-loop in the recv loop. Default is
now 50 ms, matching config.example.json.
2026-02-22 16:32:43 +01:00
Houmgaor
6fbd294575 refactor(channelserver): eliminate *sql.Tx from repository interfaces
Hide transaction management inside repository implementations so
interfaces only expose domain types, enabling clean mocking and
decoupling handlers from PostgreSQL internals.

- Replace BeginTx + UpdateEventQuestStartTime with batch
  UpdateEventQuestStartTimes that manages its own transaction
- Remove tx parameter from CreateApplication, add composite
  CreateApplicationWithMail for atomic scout+mail operations
- Remove SendMailTx from MailRepo (sole caller migrated)
- Remove database/sql import from repo_interfaces.go
2026-02-21 14:56:59 +01:00
Houmgaor
bd8e30d570 refactor(channelserver): eliminate *sql.Rows from EventRepo.GetEventQuests
Return []EventQuest instead of a raw database cursor, removing the last
*sql.Rows leak from the repository layer. The handler now iterates a
slice, and makeEventQuest reads fields from the struct directly instead
of scanning rows twice. This makes the method fully mockable and
eliminates the risk of unclosed cursors.
2026-02-21 14:37:29 +01:00
Houmgaor
a9cca84bc3 refactor(channelserver): move remaining s.server.db calls into repositories
Eliminate the last three direct DB accesses from handler code:

- CharacterRepo.LoadSaveData: replaces db.Query in GetCharacterSaveData,
  using QueryRow instead of Query+Next for cleaner single-row access
- EventRepo.GetEventQuests, UpdateEventQuestStartTime, BeginTx: moves
  event quest enumeration and rotation queries behind the repo layer
- UserRepo.BanUser: consolidates permanent/temporary ban upserts into a
  single method with nil/*time.Time semantics
2026-02-21 14:08:01 +01:00
Houmgaor
3b044fb987 fix(channelserver): handle silently swallowed DB scan and exec errors
Several handlers discarded errors from rows.Scan() and db.Exec(),
masking data corruption or connection issues. Scan failures in diva
schedule, event quests, and trend weapons are now logged or returned.
InitializeWarehouse now surfaces its insert error to the caller.
2026-02-21 13:49:25 +01:00
Houmgaor
2757a5432f refactor(channelserver): extract QuestCache from Server struct
The quest cache fields (lock, data map, expiry map) were spread across
Server with manual lock management. The old read path also missed the
RLock entirely, creating a data race. Encapsulating in a dedicated type
fixes the race and reduces Server's field count by 2.
2026-02-21 13:35:04 +01:00
Houmgaor
f689770e94 fix(channelserver): handle db.Begin() error in event quest enumeration
A failed Begin() returned a nil tx that would panic on the next
tx.Exec() call. Now logs the error, closes rows, and returns an
empty response gracefully.
2026-02-21 13:30:25 +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
7c444b023b refactor(channelserver): replace magic numbers with named protocol constants
Extract numeric literals into named constants across quest handling,
save data parsing, rengoku skill layout, diva event timing, guild info,
achievement trophies, RP accrual rates, and semaphore IDs. Adds
constants_quest.go for quest-related constants shared across functions.

Pure rename/extract with zero behavior change.
2026-02-20 19:50:28 +01:00
Houmgaor
bf983966a0 refactor(channelserver): migrate inline queries to helpers and define named constants
Migrate 6 character data handlers to use the existing loadCharacterData
and saveCharacterData helpers, eliminating duplicate inline SQL:
- LoadFavoriteQuest, SaveFavoriteQuest, LoadDecoMyset, LoadMezfesData,
  LoadHunterNavi, GetEquipSkinHist

Define named constants replacing magic numbers across handlers:
- Achievement trophy tiers, broadcast/message types, diva phase
  durations, RP accrual rates, kill log layout, semaphore bases,
  quest stage/loading screen IDs

Update anti-patterns doc with accurate line counts, evidence-based
softlock analysis, and revised refactoring priorities.
2026-02-20 19:46:57 +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
c2eba51b29 fix(channelserver): add max-size guards to binary blob save handlers
A malicious or buggy client could send arbitrarily large payloads
that get written directly to PostgreSQL, wasting disk and memory.
Each save handler now rejects payloads exceeding a generous upper
bound derived from the known data format sizes.

Covers all remaining items from #158: partner, hunternavi,
savemercenary, scenariodata, platedata, platebox, platemyset,
rengokudata, mezfes, savefavoritequest, house_furniture, mission.

Closes #158
2026-02-19 00:28:28 +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
47f7a1f636 fix(channelserver): handle bare Exec errors and filter expected ErrNoRows
138 bare db.Exec calls across 22 handler files silently dropped write
errors. Each is now wrapped with error check and zap logging.

4 QueryRow sites that legitimately return sql.ErrNoRows during normal
operation (new player mezfes, festa rankings, empty guild item box)
now filter it out to reduce log noise.
2026-02-17 23:33:44 +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
85cdac036e fix: validate quest file existence in seasonConversion fallbacks
The final fallback in seasonConversion blindly constructed a filename
without checking if it existed on disk. When the file was missing,
handleMsgSysGetFile would send doAckBufFail, but the original Frontier
client does not gracefully handle this during quest loading — causing a
softlock instead of showing the built-in error dialog.

Now every fallback path validates file existence before returning, and
also tries the opposite time-of-day variant as a last resort. If no
file variant exists at all, the original filename is returned with a
warning log so the failure ack is still sent.
2026-02-17 01:19:26 +01:00
Houmgaor
10e09630a6 fix: send failure ack for missing quest/scenario files instead of crashing client
When a quest or scenario file was missing, handleMsgSysGetFile sent nil
data via doAckBufSucceed, which crashed the game client. Now sends
doAckBufFail so the client can handle the missing file gracefully.

Closes #109
2026-02-16 18:35:44 +01:00
Houmgaor
1398383a8d fix(lint): automated linting, with simple formatter. 2025-10-19 22:43:05 +02:00
wish
8d1c6a79e2 S6 compatibility fix 2025-05-04 01:47:30 +10:00
wish
f2862ea4b8 prevent concurrent map write to questCache 2025-03-08 11:41:57 +11:00
wish
d26ae4563e fix G1 compatibility 2024-03-17 16:35:16 +11:00
wish
864586a40b exclude 0 values on EnumerateQuest 2024-02-19 17:37:40 +11:00
wish
7549fe63e6 conform Event Quest body size & auto change gathering points 2024-02-19 17:35:24 +11:00
wish
6ec9d9d869 add AutoBackportQuest DebugOption 2024-02-11 23:22:42 +11:00
wish
bbf4fa2472 further tune value configuration 2024-02-10 03:07:13 +11:00
wish
59eafbe3d5 fix EnumerateQuest rotation 2024-01-16 19:50:41 +11:00
wish
6b54e40cc6 add tuneValue comments 2024-01-14 14:13:11 +11:00
wish
1a6a9da308 add logging to EnumerateQuest 2024-01-14 14:09:51 +11:00
wish
0ea0dc217b simplify config 2023-12-31 12:51:24 +11:00
wish
7e5fd73496 rename Event Quest cycling 'duration' to 'days' 2023-11-26 13:06:49 +11:00
wish
a0970de48c review pass for Event Quest cycling 2023-11-26 13:02:17 +11:00
Matthew
524009039c Merge branch 'main' into main 2023-11-19 14:34:30 -05:00
Matthew
46587b8d01 fix: Fix variables 2023-11-19 14:27:53 -05:00
Matthew
ffb0d25a43 docs: Fixed and cleaned a bit of the documentation 2023-11-19 13:48:43 -05:00
Matthew
858a9adb17 chore: Removed debug code 2023-11-19 13:45:30 -05:00
Matthew
6bd2b637a7 refactor: Moved quest duration variables to uint8 2023-11-19 13:44:11 -05:00
Matthew
3778d03402 feat: Default to always active if inactive time is not set 2023-11-19 13:39:59 -05:00
Matthew
47ca302384 feat: Cycle simulation (simulate cycles if beyond a single set) 2023-11-18 03:18:35 -05:00
wish
c554943140 Merge pull request #96 from matthe815/seasons-fix
Fix: Re-add Seasons & Bug Fixes
2023-11-18 15:45:14 +11:00
wish
490aecd94b rewrite comments & change quest flag code 2023-11-18 15:44:59 +11:00
Matthew
c20380b79d fix: Continue instead of ending event quest parsing if an error occurs on a single quest 2023-11-17 22:27:50 -05:00
Matthew
a34a0e42b2 fix: Commit to database via unique index rather than quest_id 2023-11-17 22:21:48 -05:00
Matthew
50d3ec36b2 chore: Fix formatting 2023-11-17 22:21:15 -05:00
Matthew
233990f452 refactor: Change event quest updating to use transactions rather than directly commiting 2023-11-17 22:18:07 -05:00
Matthe815
6384d79a7a fix: Removed unnecessary condition 2023-11-16 11:29:31 -05:00
Matthe815
2e2d129871 docs: Fix annotation for custom quest conditions 2023-11-16 11:10:46 -05:00
wish
72bda06916 implement Quest caching 2023-11-16 21:51:28 +11:00
wish
8c69a98c58 remove arbitrary test code 2023-11-16 21:31:31 +11:00