Announcements (Timed Notices)
Operator-posted timed notices every player sees - "Maintenance at 18:00" for the next 30 minutes. An operator posts one from the admin API (announce / announce-clear / announcements) with its text and an end time; everyone signed in gets it pushed, every player who signs in before it ends gets it at sign-in, and clearing it takes it down everywhere. The client hides each notice on time by itself; the popup is the game's. No player verb exists, so a notice cannot be forged. Held in memory on each node: a restart drops them.
Providers you can swap 1
Infrastructure seams. Crossplay ships a working implementation of each — replacing one changes where data lives or how it moves, never a game rule.
IAnnouncementClock provider
The clock notices end by (a seam so tests control time).
-
long UtcNowMs { get; }Now, unix ms UTC.
Services you call 1
Crossplay implements these. Resolve them from DI and call them from your own systems.
IAnnouncementService
Operator-posted timed notices. Game code may post too (it is trusted); players never can - there is no wire verb.
-
IReadOnlyList<ActiveAnnouncement> Active()The notices up now, oldest first.
-
bool Clear(long id)Takes a notice down and tells everyone signed in. False when no such notice is up.
-
int ClearAll()Takes every notice down. Returns how many were up.
-
bool TryPost(string text, long endsAtUtcMs, out long id, out string error)Posts a notice that ends at endsAtUtcMs and pushes it to everyone signed in. False with a reason when the text is empty, too long or holds control characters, the end is past or beyond MaxDurationMinutes, or MaxActive are up.
Configuration 1
Every tunable lives in an options object — there are no magic numbers to hunt for.
AnnouncementsOptions
Tuning for the Announcements piece (Crossplay:Announcements).
-
int MaxActive { get; set; }How many notices may be up at once.
-
double MaxDurationMinutes { get; set; }The longest a notice may stay up, in minutes (default a week).
-
int MaxTextLength { get; set; }The longest notice text, in characters.
Wire messages 2
The protocol this piece speaks. Ids are allocated per piece so they can never collide.
Announcement Server -> client: an operator's timed notice ("Maintenance at 18:00"). Sent to everyone signed in when it is posted, and again to each player who signs in before it ends, so a late arrival still sees it. The text is the operator's, shown as-is. There is no client -> server counterpart: a player cannot post or forge a notice.
AnnouncementCleared Server -> client: a notice was cleared before its end time. One that simply ends sends nothing.
Unity services you inject 1
Crossplay binds these in the client context. Inject and call them from your own MonoBehaviours and presenters.
IAnnouncementClient
Client SDK for Announcements - the operator's timed notices ("Maintenance at 18:00"). The server pushes each one when it is posted and again at sign-in while it is up; this client keeps the ones that are up and ends each on time by itself, timed from the server's "time left" so a wrong device clock cannot keep a notice up or hide it early. The text is the operator's, shown as-is; the popup is the game's. Pure SDK, no UI, no verbs - a player cannot post a notice.
-
event Action<Announcement> ShownA notice went up (or arrived at sign-in). Raised once per notice, on the main thread.
-
event Action<long> ClearedA notice ended: the operator cleared it, or its time ran out. Carries its Id.
-
IReadOnlyList<Announcement> ActiveThe notices up now, oldest first.