Skip to content

chadrach/Azerothcore-deck

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Azerothcore-deck

Suspend-aware modifications to the DadsMmoLab WoW 3.3.5a + AzerothCore + Playerbots stack so a Steam Deck can be put to sleep mid-session and resumed without breaking the world.

Problem

AzerothCore stores time-based events (creature respawns, mail expiry, daily/weekly resets, instance lockouts) as absolute Unix timestamps and compares them against GameTime::GetGameTime(). When the deck enters S3 suspend, the wall clock keeps advancing while the worldserver process is frozen. On resume the server wakes into a future where everything that should have ticked during sleep is past due — respawn storms, premature mail expiry, scripted-event pile-ups, and the WoW client's ~30s ping timeout has already killed the connection.

Approach

Two coordinated mechanisms, one C++ patch and one systemd hook:

  1. Within-day suspend (typical: morning → evening pickup) — a patch to GameTime.cpp detects suspends by sampling the divergence between CLOCK_BOOTTIME (advances during suspend) and CLOCK_MONOTONIC (does not), accumulates the suspend duration into a SuspendOffset, and subtracts it from every wall-clock value the server exposes. The world's perceived clock pauses during sleep; all existing comparisons against GameTime::GetGameTime() automatically see frozen time. No call-site changes.

  2. Cross-reset suspend (overnight, multi-day, deck-in-a-drawer) — a systemd-sleep hook records the next daily-quest-reset deadline (plus a 15-minute grace) before suspend, and on resume cleanly tears down the Docker stack if we slept past it. The launcher script picks up the kill flag and exits, prompting the user to relaunch on next play. This bounds the regime the C++ patch handles to <24h and eliminates the risk of dozens of reset events firing in a single tick after weeks of abandonment.

A World::Update diff clamp at 1000 ms is added defensively to protect anything that consumes the raw tick diff (session timeouts, AI ticks) from a single huge update.

Contents

Path Purpose
bootstrap.sh One-shot installer: clones source, applies patches, builds the worldserver, installs the launcher and systemd hook. Run once after the upstream DadsMmoLab install-wow.sh has set the deck up (see Install below).
patches/0001-gametime-suspend-aware.patch C++ patch to src/server/game/Time/GameTime.cpp (suspend detection + offset) and src/server/game/World/World.cpp (diff clamp). Applies cleanly against mod-playerbots/azerothcore-wotlk branch Playerbot.
systemd/10-wow-server Installed to /etc/systemd/system-sleep/10-wow-server. Runs pre/post around suspend; enforces the daily-reset shutdown cap.
launcher/wow-playerbots-launcher.sh Installed to ~/wow-playerbots-launcher.sh. Replaces the upstream Dad's MMO Lab launcher with a version that watches for the sleep hook's flags, exits cleanly on long-suspend kill, and drives ydotool to dismiss the disconnect dialog and re-enter world on short-suspend resume.

Install

Starting point. This bootstrap assumes you've already run the upstream DadsMmoLab install-wow.sh on your deck once before, for any option. We rely on its side effects — Docker installed, git installed, the pacman keyring populated, SteamOS dev mode enabled, sudo password set — but not on its output. If you've never run it, run it once (the lightest option is fine, you don't have to play through it) and then come back here.

About any existing Playerbots install. This bootstrap does not upgrade or migrate a pre-existing ~/wow-server-playerbots/ from a previous DadsMmoLab Playerbots run. It clones and builds its own copy from scratch against the patched source. If that directory already exists, the bootstrap will detect it and prompt — answer yes to remove it and get a clean rebuild. There's no need to manually delete anything first.

git clone https://github.com/chadrach/Azerothcore-deck.git
cd Azerothcore-deck
bash bootstrap.sh

Build time: 2–4 hours for the worldserver compile. Keep the deck plugged in.

Verification

After install, verify with these tests in increasing order of confidence:

  1. Suspend detection log line. Tail docker logs -f $(docker ps --format '{{.Names}}' | grep worldserver). Suspend the deck for 60 seconds via systemctl suspend, then wake it. You should see Suspend detected: paused for ~60 seconds. Cumulative offset now ~60 seconds. in the log.

  2. Same-day respawn freeze. In-game: kill a creature with a known 5-minute respawn (any city guard). Suspend the deck for 30 minutes. Resume. The creature should still be dead and respawn only after 5 in-game minutes elapse from when you killed it, not immediately on wake.

  3. Auto-reconnect. With the WoW client in-world, suspend for 5 minutes. Resume. The launcher should see /run/wow-resumed, check the socket, and ydotool-press Enter twice. If this works reliably you're done; if not you'll need to manually click Reconnect.

  4. Daily-reset cap near miss. Start a session at 14:00. Suspend at 14:30. Resume at 17:00. The hook computed next-reset = 03:00 tomorrow; 17:00 is comfortably before it, so the server stays up and resume is seamless.

  5. Daily-reset cap crossed. Start a session at 22:00. Suspend at 22:30. Resume at 08:00 the next morning. The hook computed next-reset = 03:00 that night; 08:00 is past it, so docker compose down fires and /run/wow-killed is created. The launcher prints the long-suspend message, force-quits WoW, and exits. Manually relaunch — dailies are properly reset for the new day.

  6. Long abandonment. Suspend the deck for a few days. On resume, same path as test 5 — clean shutdown, no respawn storm, no event pile-up. Confirm with docker ps that the stack is fully down before relaunching.

How the source is assembled

At install time, bootstrap.sh does a fresh --depth 1 clone of two upstream repos into ~/wow-server-playerbots/:

  • mod-playerbots/azerothcore-wotlk branch Playerbot — the worldserver source.
  • mod-playerbots/mod-playerbots branch master — the Playerbots module, dropped into modules/mod-playerbots/.

Our patch (patches/0001-gametime-suspend-aware.patch) is then applied with git apply against that fresh clone before the Docker build kicks off. We do not vendor the upstream source in this repo and we do not maintain forks — every install pulls upstream HEAD of the Playerbot branch fresh, so upstream bug fixes flow through automatically. If upstream ever drifts to where the patch no longer applies cleanly, the bootstrap fails loudly with a clear message; the troubleshooting section below covers that case.

Troubleshooting

  • Patch fails to apply. The upstream mod-playerbots/azerothcore-wotlk Playerbot branch has drifted. Either rebase the patch on the current HEAD or pin the bootstrap to a known-good commit via git clone ... && git checkout <sha>.
  • No "Suspend detected" log line after waking. The clock_gettime(CLOCK_BOOTTIME) call returned an error, or growth was below the 2-second noise threshold (e.g., the deck only slept for one second). For real suspends this should always fire.
  • ydotool reconnect does nothing. The ydotoold.service may not be running. Check with systemctl status ydotoold and sudo systemctl enable --now ydotoold. In Gaming Mode under Wayland, xdotool will not work — ydotool is required.
  • systemd hook didn't run. Check journalctl -u systemd-suspend.service -b 0 and journalctl -t wow-sleep-hook -b 0. Verify the hook is executable and at the right path: ls -la /etc/systemd/system-sleep/10-wow-server.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages