1306 Commits
Author SHA1 Message Date
evilight 2653c465d1 world: pace the mob AI and respawn sweeps instead of spinning
MobAIThread and MobRespawnThread both ran `while (true)` around a sweep of every
zone with no delay at all, so each of them pinned a full core for the lifetime of
the world server. Measured in the container: 195% total CPU with

    tid 229  aiThread       106% of one core
    tid 231  respawnThread  106% of one core

and nothing else above 1%. The 100 ms check in the respawn loop only throttles how
often a mob may respawn, it never paused the loop.

Both sweeps now run at a fixed rate (AI_TICK_INTERVAL_MS / RESPAWN_TICK_INTERVAL_MS,
100 ms by default) by sleeping the remainder of each tick. MobAI.DetermineAction
already gates individual actions on timestamps (lastAttackTime, nextCastTime,
patrol delays), so pacing the sweep removes the busy spin without changing the AI
behaviour; raise the constants to trade reaction time for CPU.
2026-10-10 16:23:39 +08:00
evilight 97eff6517e login: probe the world port with a bind test instead of lsof
LoginServer.exec() -> checkServerHealth() -> isPortInUse() shelled out to
`lsof -i tcp:<port>` through /bin/bash and read the child's stdout until EOF.
There is no timeout and no waitFor(), so a child that blocks is fatal: in the
container lsof was observed stuck in uninterruptible I/O (D state) while it was
scanning the busy world server. The login server then never returned from its
startup path, the accept loop never started, and clients could open a TCP
connection to 6000 and wait forever for the 100 byte DH handshake, surfacing as
"Failed to open a server connection" after the client's own timeout. A container
restart was the only way out.

Replace the external probe with a bind probe: it cannot hang, needs no external
tool, and SO_REUSEADDR still does not allow stealing a port that is actively
listening, so a successful bind keeps meaning "free".
2026-10-10 16:06:55 +08:00
evilight 9f3ec7c553 graceful shutdown: ./shutdown flushes players, then stops the servers
The stock scripts stop the game with SIGKILL (mbkill.sh runs kill -9) and
'./reboot' only calls mbrestart.sh, so anything still parked in a character's
deferred database job is thrown away: experience is written five minutes after
it is earned and stats/skills thirty seconds after they change
(engine.jobs.DatabaseUpdateJob). PlayerCharacter.updateDatabase() is an empty
stub, so there was no write-out path at all.

Added engine.gameManager.GracefulShutdown:
  flushAllPlayers()      - writes skills/powers, stat modifiers and experience
                           for every online character
  announce(String)       - server wide flash message
  registerShutdownHook() - flush on an orderly SIGTERM (SIGKILL cannot be
                           intercepted by design)
  gracefulStop(int)      - countdown, flush, then stop the login and world
                           servers

Added the './shutdown [seconds]' dev command (engine.devcmd.cmds.ShutdownCmd,
default 60s, ADMIN only like every other dev command), registered together with
the shutdown hook in WorldServer.main and LoginServer.main.

Verified on a MagicBox container: ant builds clean, the boot log shows
"shutdown hook registered for WorldServer"/"LoginServer", and kill -TERM on the
world server logs "WorldServer is terminating, flushing player data" ->
"flush finished, saved=0 failed=0" -> clean exit.
2026-10-10 13:47:16 +08:00
MagicBot 3649c629b7 Revert "DamageType defined as in JSON"
This reverts commit 1c31070fc8.
2024-04-01 12:04:12 -04:00
MagicBot 1c31070fc8 DamageType defined as in JSON 2024-04-01 12:01:59 -04:00
MagicBot bff41967db Revert "Out of combat mode when patrolling."
This reverts commit d3692d0fb7.
2023-09-08 13:07:15 -04:00
MagicBot d3692d0fb7 Out of combat mode when patrolling. 2023-09-08 13:04:29 -04:00
FatBoy 074a799d01 added health recovery to mobs 2023-08-22 20:58:52 -05:00
FatBoy 36ffd08a72 guard minions logic work 2023-08-22 20:52:45 -05:00
FatBoy 58f828b3cd items removed properly from inventory, NPCs nop longer stock base items 2023-08-22 20:52:26 -05:00
FatBoy e5fba340fb guard minion AI restored to follow captain attack commands 2023-08-21 20:24:49 -05:00
FatBoy ea2241732a fixed bug where pet persisted through dismissal 2023-08-21 20:02:26 -05:00
FatBoy 2b83db7bba moved initial loadInventory call to runAfterLoad 2023-08-21 19:48:44 -05:00
FatBoy f636f4d2ec optimized equipment dropping system 2023-08-21 19:36:46 -05:00
FatBoy 8fb6c43c66 alternative loot drop limitation 2023-08-21 19:21:50 -05:00
MagicBot e331f7e2ff Unused methods removed. 2023-08-21 14:26:50 -04:00
MagicBot b8217a8858 Remove unused variable from signature. 2023-08-21 14:11:22 -04:00
MagicBot 50f81396c7 Cleanup of PERSIST db call. 2023-08-21 14:01:28 -04:00
MagicBot 0bca57686d New npc creation work. 2023-08-21 14:00:00 -04:00
MagicBot df6b9e48d3 New npc creation work. 2023-08-21 13:47:47 -04:00
MagicBot 291cb97a22 New npc creation work. 2023-08-21 13:34:42 -04:00
MagicBot 740e75f8e4 New less ungodly NPC constructor. 2023-08-21 13:26:13 -04:00
MagicBot b7bbf8d369 Interest manager updates when moving 64 units. 2023-08-21 05:02:49 -04:00
MagicBot abf450d6ea Use character load range for dirty flag. 2023-08-21 04:52:02 -04:00
MagicBot 9072fc2788 Lock for dirtyload integration. 2023-08-21 04:40:11 -04:00
MagicBot 14968dbb3b Unused variables removed. 2023-08-21 04:21:28 -04:00
MagicBot c79d9ae891 Unused lastXYZ timers set but never used. 2023-08-21 04:19:20 -04:00
MagicBot dbca131a0f Set dirty out to load range. 2023-08-20 20:38:44 -04:00
MagicBot 621d78172d Threadsafe is needed for the flag. 2023-08-20 20:37:24 -04:00
MagicBot 50e962b77e dirtyFlag integration. 2023-08-20 20:14:28 -04:00
MagicBot 07aeb6e58d dirtyFlag integration. 2023-08-20 20:02:16 -04:00
MagicBot f6e2c6c618 dirtyFlag integration. 2023-08-20 19:35:18 -04:00
MagicBot 44b5b98597 dirtyFlag integration. 2023-08-20 19:20:22 -04:00
MagicBot ca21c3d266 dirtyFlag integration. 2023-08-20 19:07:26 -04:00
MagicBot c1f613a1a5 Flag set to true when created. 2023-08-20 18:57:22 -04:00
MagicBot 6923251a88 dirtyflag chosen as solution. 2023-08-20 18:56:09 -04:00
MagicBot 8222cb8530 Remove distance early exit. 2023-08-20 18:29:44 -04:00
MagicBot 0eae76180b Update state of npc. 2023-08-20 17:23:50 -04:00
MagicBot f0cfb69752 Update state of npc. 2023-08-20 17:16:18 -04:00
MagicBot 2e7d2b5bcf Update state of npc. 2023-08-20 17:12:20 -04:00
MagicBot 09b346dcb2 Update state of npc. 2023-08-20 17:01:58 -04:00
MagicBot 46d07b386b Update state of npc. 2023-08-20 16:55:15 -04:00
MagicBot b21e9dc59e Moving items out of constructor. 2023-08-20 16:38:10 -04:00
MagicBot 2c9fc405e9 More unused junk removed. 2023-08-20 16:28:21 -04:00
MagicBot a0a3d34578 Unused lock removed. 2023-08-20 16:25:44 -04:00
MagicBot 8ba4ed20c8 loc set to bindloc after npc returned. 2023-08-20 16:18:51 -04:00
MagicBot 5e474851a8 bugfix: Setting loc before loc is defined in abstract constructor. 2023-08-20 16:00:08 -04:00
MagicBot c69e68cb27 Npc name override moved to runafterload. 2023-08-20 15:37:11 -04:00
MagicBot 2d0116a9d9 inLined single line methods for code clarity. 2023-08-20 15:26:24 -04:00
MagicBot bed99dce62 aiAgentType enumeration defined. 2023-08-20 15:10:31 -04:00