Repository navigation
Conversation
…tle siege The game publishes blocked logins, received letters and characters which entered the game, and the castle siege events tell when the next battle takes place. /discord notify turns direct messages in Discord on or off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
…d events /announce, /kick and /ban are allowed for users with the GM role and a linked game master character, and every use is posted to the staff alerts channel. Linked users opt in to direct messages with /notify. The bot can create a scheduled event for the next castle siege. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
…s and scheduled events Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
Deploying openmudocs with
|
| Latest commit: |
e3e0875
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://878ec86d.openmudocs.pages.dev |
| Branch Preview URL: | https://claude-sweet-cray-w8crms-m6.openmudocs.pages.dev |
sven-n
left a comment
There was a problem hiding this comment.
Part of a review pass over the whole Discord stack. This PR has the most privileged surface in the set, so the authorisation path got the closest look.
The GM gate is correctly layered and I couldn't find a way through it: /announce, /kick and /ban each require both the Discord GM role and that the linked account's selected character has CharacterStatus.GameMaster, where the selected character is verified to belong to that account by M4's SelectCharacterAsync. Every use is logged and mirrored to the staff channel, and the answers are ephemeral. The hasGameMasterRole parameter being passed in rather than determined inside the command class also keeps it testable, which DiscordGameMasterCommandsTest takes advantage of.
Three comments inline. The friend-notification one is the only one I'd call important, and it's throughput rather than a bug.
One smaller observation not worth its own thread: AccountLoginBlockedEvent is published only from the already-logged-in paths in LoginAction, not on a failed password. That makes the "login attempt on your account" DM narrower than its name suggests — useful as-is (it tells a player someone knows their account name and is trying it while they're online), but someone extending this later may well read the event name as covering all blocked logins.
Generated by Claude Code
…rms-m6 The migration AddAccountNotifications is generated again, so that it follows the other migrations. The next castle siege is calculated in the time zone of the server, which master added to the schedule. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
- The friends who get a direct message when a character enters the game are determined with two queries instead of several per friend, and with none when the character has no friends. - /announce is limited to 200 characters, a failing game server doesn't stop the announcement on the others, and the answer tells on how many game servers it was shown. A failing game server doesn't stop /kick and /ban either. - The remarks explain that the GM role is only a filter, and that the game master status of the character is the actual check. - A failed command gets an answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
Milestone M6 of the Discord integration (#1104). Stacked on #1161 (M5).
What
/announce <text>callsIGameServer.SendGlobalMessageAsync(golden notice) on all game servers./kick <character>callsDisconnectPlayerAsyncand/ban <character>callsBanPlayerAsync. Each goes to the game servers until one succeeds; the Dapr clients broadcast.CharacterStatus.GameMaster. This uses the new light queryIPlayerContext.GetCharacterStatusAsync.StaffAlerts, routed to#staff-alertsby the layout.AccountNotificationTypesflags onAccountExternalLink, with a migration and compiled models. Toggled with/notify type enabledin Discord or/discord notify login|letter|friendin game. New game events are published directly by the game:AccountLoginBlockedEvent: login with the correct password while the account is already logged in. The account is resolved with the newGetAccountIdByLoginNameAsync.LetterReceivedEvent: published byLetterSendAction.PlayerEnteredGameEvent: published byGameServerContext. Friends with the opt-in are notified unless the player is invisible, checked withIFriendServer.GetOnlineServerIdAsync.CastleSiegeStateChangedEventgets the optionalNextBattleStartUtc/NextBattleEndUtc, from the newCastleSiegeSchedule.GetNextPeriod.Bot__CreateScheduledEvents=truethe bot creates or updates an external scheduled event "Castle Siege" on the hosted Discord. It needs the Create Events permission.## Settingsheading. It's restored on M5 and merged forward.Notes
Tests
DiscordGameMasterCommandsTest: role and GM checks, announcing to all servers, kick/ban routing, staff alert text.DiscordDirectMessagesTest: opt-in, letter, blocked login, friend online and invisible friend.CastleSiegeNextBattleTest: next battle this week and next week, unscheduled state./discord notifytoggling, and serialization of the new events.Not tested against a real Discord bot or a real PostgreSQL database.
🤖 Generated with Claude Code
https://claude.ai/code/session_01USFZ9xErMB1EwkpfdUHzoZ
Generated by Claude Code