Implement Castle Siege Mini-Map & Guild Commands (#730) - #941
Conversation
Adds the Phase 11 mini-map broadcast and guild-command relay: - CastleSiegeMiniMap gathers own-side player positions and alive gate/statue positions and pushes them every 3 seconds to online alliance masters of participating guilds, while the siege is in the Start state. - CastleSiegeGuildCommandAction lets an alliance master issue a directional command (type + coordinates) to every player on their own side. The issuer's side is always re-derived server-side from CastleSiegeContext rather than trusted from the client packet. - New view/handler plug-ins (ICastleSiegeMiniMapPlugIn, ICastleSiegeCommandPlugIn) follow the existing Castle Siege RemoteView/MessageHandler conventions. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
# Conflicts: # src/GameServer/Properties/PlugInResources.resx
ReviewOverall this is well-executed and fits the existing Castle Siege conventions closely: the handler mirrors I checked the wire format against the client ( Two things came out of that client comparison that I think need to change, plus a few smaller items. 1.
|
- Team is the client's command-group (squad) slot, not an audience field - relay request.Team unchanged instead of overwriting it with the issuer's side, and reject Team > 6 / unmapped Command bytes before they reach the client's unbounded GuildCommander[7] buffer. - Move the Start-state check inside ExecutionLock in CastleSiegeGuildCommandAction, matching CastleSiegeGateOperateAction. - Resolve the issuer's side the same way the recipient filter does (context.GetPlayerJoinSide), in both the guild-command action and the mini-map broadcast, so a crown-capture side swap can't cause a brief mismatch. - Add a 1s per-player cooldown on the guild-command handler. - Move the mini-map broadcast to run after the periodic NPC save in OnTickAsync, so a failing send can't skip it. - Cap mini-map player positions at 1000 per guild. - Reword the mini-map XML/doc comments to describe the push model that's actually implemented. - Revert an incidental whitespace diff in the generated resx designer. - Add CastleSiegeMiniMapRemoteViewTests covering the mini-map packets and, specifically, that ShowGuildCommandAsync relays Team unchanged. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
Thanks for the thorough review, especially for checking the wire format against the client, that caught something real. Addressed everything:
Left On your heads-up about the client dropping these packets today ( 123/123 tests passing, clean build. |
Summary
Implements Castle Siege Phase 11 (#730): the mini-map broadcast and guild-command relay.
CastleSiegeMiniMapgathers own-side player positions and alive gate/statue positions, and pushes them every 3 seconds to every online alliance master of a participating guild, while the siege is in theStartstate.CastleSiegeGuildCommandActionlets an alliance master issue a directional command (type + coordinates) to every player on their own side.ICastleSiegeMiniMapPlugIn/ICastleSiegeCommandPlugInview interfaces and matchingGameServer/RemoteView+GameServer/MessageHandlerplug-ins, following the existing Castle Siege conventions.Design decisions (spec doesn't fully cover the current codebase shape)
The original implementation plan for this phase predates phases 4-10, so a few things needed a concrete call rather than a literal reading, flagging these for review:
CastleGuildCommand.Teamis never trusted for authorization or audience selection. The issuer's actual side is always re-derived server-side fromCastleSiegeContext, so a spoofedTeambyte can't mis-target orders or leak to the wrong side.GuildMaster, where that guild'sCastleSiegeGuildParticipant.IsAllianceMasteristrueincontext.FinalGuildList.CastleSiegeState.Start. The spec says so explicitly for the mini-map; for guild commands this is inferred (commands are meaningless outside battle) rather than spec-mandated, worth confirming that's the intended behavior.CastleSiegeMiniMapNpcTypeonly definesGate/GuardianStatue, matching the wire format).Verification
dotnet build src/Startup/MUnique.OpenMU.Startup.csproj -c Debug: 0 errors.dotnet test tests/MUnique.OpenMU.Tests --filter FullyQualifiedName~CastleSiege: 106/106 passing (existing suite, confirms no regression, this PR doesn't add new automated tests yet, since the mini-map/command flow is push-based and harder to unit-test without a fuller integration harness; happy to add coverage if there's a preferred pattern from the recent Castle Siege PRs).Known minor items
A couple of small things worth a look, not blocking:
Start-state check is read once before acquiring the context lock and isn't re-checked once held, so a command could in theory land in the narrow window right as the state transitions away fromStart.🤖 Generated with Claude Code