Bots Find Their Bearings
For a while now the bots have been swinging at thin air, swords pointed roughly at their own kneecaps. As of this release they’ve remembered which way they’re facing, so fights with bot-controlled units are once again fights rather than interpretive dance.
Everything else is plumbing. Crash reporting, the auto-updater, and a few UI widgets have moved into the studio’s shared library, ready to be picked up by the next game without copy-paste. Nothing you’d notice from inside the tavern; just a tidier shed out back.
- GHA release + local
build.ps1: optionalbuildinput (0-99) trails the Android versionCode (new formulaMAJ*1_000_000 + MIN*10_000 + PAT*100 + BUILD), so a failed Play upload retries with a bumped suffix instead of burning a patch bump on the public version string. 1.4.6 build 0 lands at versionCode1040600; the old scheme’s10406stays strictly smaller, so monotonicity holds across the cutover. Closes #9. - Bots now swing in the direction they’re facing. The server-side bot loop was passing the bot’s own position as the
attack aim, so
aim - playerPoscollapsed to(0, 0)and the melee hit cone had no orientation; every swing whiffed and[ATTACK] facing=(0.0,0.0)filled the sim log. Aim is nowbot.Pos + bot.Facing * 40, matching the convention real clients already use. Fixes #8. Client.Core/UI/Button.csgains aLabelScaleopt-in property (defaults to 1.0 = current desktop behaviour, no change today). Mirrors the same shape Fusion picked up from core 1.2.0’sResinhead.Shared.Ui.UiMetrics.Scale(viewportHeight); the day Blight wants to scale labels for a phone or 4K target, the property is wired and callers can pair it withUiMetrics.Scale. The two ad-hocuiScale = sh / 200fcalls inGame1.cs(GAME OVER / YOU DIED overlays) deliberately untouched: they’re stylistic font scaling at a different baseline, not the touch-target problemUiMetricssolves.- Velopack auto-updater moves to core 1.1.0. Local
Client.Desktop/AutoUpdater.csdeleted; Game1’s desktop-only path constructsResinhead.Shared.Updates.AutoUpdater(s3Url)instead. Per-arch channel routing (osx-arm64 / osx-x64), no-op-when-not-Velopack-installed, and theUpdateStatelifecycle all live in the package now; Blight’s update-feed base URL is the only game-specific input. ExplicitVelopack 0.*reference dropped fromClient.Desktop.csproj; reaches Blight transitively viaResinhead.Sharedfrom now on. Behaviour unchanged at the user-facing level (same feed, same download flow, same restart). - Resinhead.Shared bumped to 1.0.0: the floating
0.0.*-*prerelease pin inShared/Shared.csprojswaps for a stable1.*range now that core has committed to API stability (strict semver honoured from 1.0 onwards). LocalShared/SentryBootstrap.csbecomes a thin per-game wrapper; the studio-neutral plumbing (DSN resolution, no-PII defaults, env-var scrubbing, session-tracking gating, environment detection,app/ridtags) lives inResinhead.Shared.Telemetry.SentryBootstrapand is parameterised byTelemetryOptions(game id, app kind, version, player-facing flag, opt-out hook, breadcrumb scrubber callback).BlightSettings.SendCrashReportsand the chat / lua.source breadcrumb scrubbing stay Blight-side as the wrapper’s option values;CaptureLuaErrorstays Blight-side because Lua is Blight’s scripting layer, not a studio concern. Behaviour at the Sentry dashboard is unchanged (same DSN, same release tagblight@$VERSION, same scrubbing posture, same session-tracking shape); just relocated. ExplicitSentry 5.*reference dropped;Resinhead.Sharedbrings Sentry transitively (currently 6.x) so Blight inherits the studio’s chosen Sentry version going forward. - Resinhead.Shared wiring:
nuget.configat the repo root declares the org’s private GitHub Packages feed; thebuildandbuild-androidjobs gainpermissions: packages: readand pipe the runner’sGITHUB_TOKENstraight into NuGet viaNUGET_USERNAME/NUGET_TOKENenv vars. Cross-repo auth works because resinhead-games/core granted this repo Read access on eachResinhead.*package’s settings page. (Initial attempt used aresinhead-games-packagesGitHub App +actions/create-github-app-token; the mint succeeds but the GitHub Packages NuGet download endpoint silently 403s App installation tokens despite REST API support. Same-orgGITHUB_TOKENis cleaner anyway: zero secrets to rotate. Postmortem in core/docs/nuget.md.) - Resinhead.Shared 0.0.1 referenced from
Shared/Shared.csprojas a floating prerelease range (0.0.*-*) so a localdotnet packof core into~/.nuget-resinhead-local/automatically shadows the published stable while iterating; see README.md and core/docs/nuget.md. Package is empty today (one internal placeholder class), so this is the proving run for the auth + restore pipeline rather than any actual code reuse; the moment something interesting wants to live in two games, that’s where it goes. - GHA release: per-locale Google Play notes now come from
docs/release/$VERSION.mdinstead of being pasted into the Play Console by hand. Newvalidatejob parses the file (50 locales as XML-tag blocks) and fails the pipeline early on empty/oversized bodies, duplicates, or known-bad tags (id-ID,he-IL). Thedistribute-googleplayjob then injects the parsedreleaseNotesarray into the track-update PUT, so notes attached at internal-upload time pre-fill the Console’s promote-to-prod dialog. 1.4.4 and 1.4.5 notes archived underdocs/release/as the parser fixtures, and 1.4.6 ships with an empty-body skeleton so the validator hard-fails until the cycle’s notes are actually written. - Sentry Release Health: turn on
AutoSessionTrackingforClient.DesktopandClient.Androidso each launch posts a session ping (release + environment + status; no payload data, scrubbing posture unchanged). Sentry now fills in crash-free-session rate, crash-free-user rate, and per-release adoption alongside the raw error feed. Gated to player-facing clients only; Facilitator (long-lived server, no meaningful “session”) and BotClient (CI tooling) stay off.