mirror of
https://github.com/djdevin/recflare.git
synced 2026-09-08 14:41:28 -07:00
[notify] add documentation on push shapes
This commit is contained in:
@@ -0,0 +1,581 @@
|
||||
/**
|
||||
* The `Msg` bodies the client expects behind each {@link NotificationType}.
|
||||
*
|
||||
* Recovered from the client's Utf8Json generated formatters (see `recnet-patcher`,
|
||||
* `il2cpp-tools/dtoshape.py`), not from a spec. Three properties of that decoder decide how
|
||||
* much these matter:
|
||||
*
|
||||
* - **Every key is accepted in three casings** — Original, camelCase and all-lowercase. So
|
||||
* `RoomId`, `roomId` and `roomid` are the same field. The spelling used below is the
|
||||
* client's own canonical one.
|
||||
* - **Unknown members are dropped in silence.** A typo'd key behaves exactly like an omitted
|
||||
* one, which is why a wrong payload shows up as a blank UI rather than an error.
|
||||
* - **A missing nested object is worse than a missing scalar.** Several handlers dereference
|
||||
* one level down with no null guard, so omitting a nested field surfaces as a bare
|
||||
* `NullReferenceException` in the client. Send a stub rather than nothing.
|
||||
*
|
||||
* Field *names* below are verified. Where a payload's type mapping could not be pinned down
|
||||
* as confidently as its key list, the interface says so on the member.
|
||||
*/
|
||||
|
||||
/** How a balance came to change. Log/telemetry only on the purchase frame — see below. */
|
||||
export enum BalanceAddType {
|
||||
Invalid = 0,
|
||||
DirectBalanceWithMultiplier = 1,
|
||||
FromGiftBox = 2,
|
||||
NUXChallenge = 10,
|
||||
AllNUXChallenges = 11,
|
||||
DailyChallenge = 100,
|
||||
AllDailyChallenges = 101,
|
||||
FinishActivity = 200,
|
||||
RecRoyaleMatchFinished = 250,
|
||||
ChecklistCredit = 303,
|
||||
WonGame = 1000,
|
||||
LostGame = 1001,
|
||||
WonGameRateLimited = 1002,
|
||||
WonGamePartial = 1003,
|
||||
LevelUp = 1100,
|
||||
Registered = 1200,
|
||||
CreatorReward = 1300,
|
||||
CommercePurchase = 1400,
|
||||
CommercePurchaseRevoked = 1401,
|
||||
ManualRefund = 2000,
|
||||
ManualThanks = 2010,
|
||||
ManualApology = 2020,
|
||||
}
|
||||
|
||||
/**
|
||||
* Which store a balance belongs to. Note the **wire key is `Platform`, not `BalanceType`** —
|
||||
* the client's property is called `BalanceType` but carries a `[DataMember]` rename, so
|
||||
* `balanceType` on the wire is dropped and the balance silently reads as `SteamPurchased`.
|
||||
*
|
||||
* Balances are held per `(CurrencyType, Platform)` pair, so this also selects which bucket a
|
||||
* balance frame updates. `RecNetPurchased` is the one to use for a self-hosted store.
|
||||
*/
|
||||
export enum BalancePlatform {
|
||||
NonPurchasedNotUsableInP2P = -2,
|
||||
NonPurchasedDefault = -1,
|
||||
SteamPurchased = 0,
|
||||
OculusPurchased = 1,
|
||||
PlayStationPurchased = 2,
|
||||
MicrosoftPurchased = 3,
|
||||
RecNetPurchased = 4,
|
||||
IOSPurchased = 5,
|
||||
GooglePlayPurchased = 6,
|
||||
PicoPurchased = 8,
|
||||
PlayStationNonPurchasedP2P = 100,
|
||||
NonPlayStationNonPurchasedP2P = 101,
|
||||
NonPurchasedEarnedByP2P = 1000,
|
||||
}
|
||||
|
||||
export enum CurrencyType {
|
||||
Invalid = 0,
|
||||
LaserTagTickets = 1,
|
||||
RecCenterTokens = 2,
|
||||
LostSkullsGold = 100,
|
||||
DraculaSilver = 101,
|
||||
RecRoyaleSeason1 = 200,
|
||||
RoomCurrency = 300,
|
||||
ProgressionEvent = 400,
|
||||
}
|
||||
|
||||
/** Why a player was kicked/banned/warned. Shared by ModerationKick and ModerationUnkick. */
|
||||
export enum KickReportCategory {
|
||||
Moderator = -1,
|
||||
Unknown = 0,
|
||||
DeprecatedMicrophoneAbuse = 1,
|
||||
Harassment = 2,
|
||||
Cheating = 3,
|
||||
DeprecatedImmatureBehavior = 4,
|
||||
AFK = 5,
|
||||
Misc = 6,
|
||||
Underage = 7,
|
||||
VoteKick = 10,
|
||||
MisleadingPurchases = 11,
|
||||
CoCUnderage = 100,
|
||||
CoCSexual = 101,
|
||||
CoCDiscrimination = 102,
|
||||
CoCTrolling = 103,
|
||||
CoCNameOrProfile = 104,
|
||||
InappropriateClothing = 200,
|
||||
IssuingInaccurateReports = 1000,
|
||||
}
|
||||
|
||||
export enum LogoutReason {
|
||||
Unknown = 0,
|
||||
UserInitiated = 1,
|
||||
SessionTakeover = 2,
|
||||
ForciblyLoggedOut = 3,
|
||||
Banned = 4,
|
||||
}
|
||||
|
||||
/** The error the client renders when a `GoTo` fails. */
|
||||
export enum GoToFailureError {
|
||||
UnknownError = -1,
|
||||
Success = 0,
|
||||
NoSuchGame = 1,
|
||||
PlayerNotOnline = 2,
|
||||
InsufficientSpace = 3,
|
||||
EventNotStarted = 4,
|
||||
EventAlreadyFinished = 5,
|
||||
BlockedFromRoom = 7,
|
||||
JuniorNotAllowed = 11,
|
||||
Banned = 12,
|
||||
AlreadyInBestInstance = 13,
|
||||
InsufficientRelationship = 14,
|
||||
UpdateRequired = 16,
|
||||
AlreadyInTargetInstance = 17,
|
||||
UGCNotAllowed = 19,
|
||||
NoSuchRoom = 20,
|
||||
RoomIsNotActive = 22,
|
||||
RoomBlockedByCreator = 23,
|
||||
RoomIsPrivate = 25,
|
||||
RoomInstanceIsPrivate = 26,
|
||||
DeviceClassNotSupported = 30,
|
||||
DeviceClassNotSupportedByRoomOwner = 31,
|
||||
MovementModeNotSupportedByRoomOwner = 32,
|
||||
EventIsPrivate = 35,
|
||||
EventIsFull = 36,
|
||||
RoomInviteExpired = 40,
|
||||
NoAvailableRegion = 45,
|
||||
}
|
||||
|
||||
// ---- Payloads ------------------------------------------------------------------
|
||||
|
||||
/** `StorefrontBalancePurchase` (62). */
|
||||
export interface PurchaseBalanceModificationPayload {
|
||||
BalanceAddType: BalanceAddType
|
||||
/**
|
||||
* The change, **for display only** — the client does not apply it. Its handler logs a
|
||||
* line and then stores {@link Balance} outright, so a correct `Delta` with a stale
|
||||
* `Balance` leaves the player's balance wrong.
|
||||
*/
|
||||
Delta: number
|
||||
/** The post-transaction total. Absolute, and the only field that changes client state. */
|
||||
Balance: number
|
||||
Platform: BalancePlatform
|
||||
CurrencyType: CurrencyType
|
||||
}
|
||||
|
||||
/** `StorefrontBalanceUpdate` (61) — a bare set of one bucket to an absolute value. */
|
||||
export interface BalanceResponsePayload {
|
||||
Balance: number
|
||||
CurrencyType: CurrencyType
|
||||
Platform: BalancePlatform
|
||||
}
|
||||
|
||||
/** One element of the `StorefrontBalanceAdd` (60) batch. */
|
||||
export interface RewardBalanceModificationPayload {
|
||||
BalanceAddType: BalanceAddType
|
||||
BaseAward: number
|
||||
BonusAward: number
|
||||
RateLimit: number
|
||||
CurrentCount: number
|
||||
Total: number
|
||||
Platform: BalancePlatform
|
||||
BalanceInGiftBox: boolean
|
||||
}
|
||||
|
||||
/** `ConsumableMappingAdded` (70) / `ConsumableMappingRemoved` (71). */
|
||||
export interface ConsumableMappingPayload {
|
||||
Id: number
|
||||
ConsumableItemDesc: string
|
||||
Count: number
|
||||
InitialCount: number
|
||||
/** ISO-8601. */
|
||||
CreatedAt: string
|
||||
ActiveDurationMinutes: number | null
|
||||
IsActive: boolean
|
||||
IsTransferable: boolean
|
||||
}
|
||||
|
||||
/** `ModerationKick` (22) and `ModerationUnkick`. Room bans go out as this with `IsBan`. */
|
||||
export interface ModerationKickPayload {
|
||||
ReportCategory: KickReportCategory
|
||||
/** Seconds. */
|
||||
Duration: number
|
||||
GameSessionId: number
|
||||
IsHostKick: boolean
|
||||
Message: string
|
||||
PlayerIdReporter: number | null
|
||||
IsBan: boolean
|
||||
IsVoiceModAutoban: boolean
|
||||
IsWarning: boolean
|
||||
VoteKickReason: string
|
||||
/** ISO-8601. */
|
||||
TimeoutStartedAt: string | null
|
||||
}
|
||||
|
||||
/** `ModerationKickAttemptFailed` (23) — a vote-kick that didn't carry. */
|
||||
export interface ModerationKickFailedPayload {
|
||||
ReportCategory: KickReportCategory
|
||||
YesVotes: number
|
||||
NoVotes: number
|
||||
PlayerIdReported: number
|
||||
}
|
||||
|
||||
/** `ServerMaintenance` (25). */
|
||||
export interface ServerMaintenancePayload {
|
||||
StartsInMinutes: number
|
||||
}
|
||||
|
||||
/** `Logout` (6). */
|
||||
export interface LogoutPayload {
|
||||
Reason: LogoutReason
|
||||
}
|
||||
|
||||
/** `MessageDeleted` (3) — the id of the message to drop. */
|
||||
export interface MessageDeletedPayload {
|
||||
Id: number
|
||||
}
|
||||
|
||||
/** `MessageReceived` (2). */
|
||||
export interface MessageReceivedPayload {
|
||||
Id: number
|
||||
FromPlayerId: number
|
||||
/** ISO-8601. */
|
||||
SentTime: string
|
||||
Type: number
|
||||
Data: string
|
||||
RoomId: number | null
|
||||
PlayerEventId: number | null
|
||||
}
|
||||
|
||||
/** `RelationshipChanged` (1). */
|
||||
export interface RelationshipChangedPayload {
|
||||
/** Note the spelling — capital `ID`, unlike every other id key on the wire. */
|
||||
PlayerID: number
|
||||
RelationshipType: number
|
||||
Muted: boolean
|
||||
Ignored: boolean
|
||||
Favorited: boolean
|
||||
}
|
||||
|
||||
/** `PlayerEventDeleted` (82) / `PlayerEventResponseDeleted` (84). */
|
||||
export interface PlayerEventIdPayload {
|
||||
PlayerEventId: number
|
||||
}
|
||||
|
||||
/** `PlayerEventResponseChanged` (83). */
|
||||
export interface PlayerEventResponsePayload {
|
||||
PlayerEvent: Record<string, unknown>
|
||||
PlayerEventResponse: Record<string, unknown>
|
||||
}
|
||||
|
||||
/** `PlayerEventCreated` (80) / `PlayerEventUpdated` (81). */
|
||||
export interface PlayerEventPayload {
|
||||
Tags: unknown[]
|
||||
PlayerEventId: number
|
||||
CreatorPlayerId: number
|
||||
RoomId: number
|
||||
SubRoomId: number | null
|
||||
ClubId: number | null
|
||||
Name: string
|
||||
Description: string
|
||||
ImageName: string
|
||||
/** ISO-8601. */
|
||||
StartTime: string
|
||||
/** ISO-8601. */
|
||||
EndTime: string
|
||||
AttendeeCount: number
|
||||
Accessibility: number
|
||||
IsMultiInstance: boolean
|
||||
SupportMultiInstanceRoomChat: boolean
|
||||
DefaultBroadcastPermissions: number
|
||||
CanRequestBroadcastPermissions: number
|
||||
BroadcastingRoomInstanceId: number | null
|
||||
}
|
||||
|
||||
/** `PlayerProgressionLevelUpdate`. `XP` is progress into the level, not a lifetime total. */
|
||||
export interface PlayerProgressionLevelPayload {
|
||||
PlayerId: number
|
||||
Level: number
|
||||
XP: number
|
||||
}
|
||||
|
||||
/** `ProgressionEventsRecordUpdate`. */
|
||||
export interface ProgressionEventRecordPayload {
|
||||
AccountId: number
|
||||
Xp: number
|
||||
GameMinutesToday: number
|
||||
RewardsCollected: number
|
||||
BonusRewardsCollected: number
|
||||
/** ISO-8601. */
|
||||
XpBoostLastPurchasedAt: string | null
|
||||
}
|
||||
|
||||
/**
|
||||
* `SubscriptionUpdateProfile` (`"AccountUpdate"`) — the public projection of an account.
|
||||
* The `Obscured*` CodeStage wrappers on the client side serialise as their plain underlying
|
||||
* value, so nothing special is needed on the wire.
|
||||
*/
|
||||
export interface AccountUpdatePayload {
|
||||
AccountId: number
|
||||
UserName: string
|
||||
DisplayName: string
|
||||
DisplayEmoji: string
|
||||
ProfileImage: string
|
||||
BannerImage: string
|
||||
TreatAsJunior: boolean
|
||||
HasBirthday: boolean
|
||||
PersonalPronouns: number
|
||||
IdentityFlags: number
|
||||
/** Lowercase-camel on the client's canonical spelling, unlike its neighbours. */
|
||||
createdAt: string
|
||||
IsJunior: boolean | null
|
||||
}
|
||||
|
||||
/**
|
||||
* `SubscriptionUpdateSelfProfile` (`"SelfAccountUpdate"`) — the owner-only projection: the
|
||||
* six private fields **first**, then every field of {@link AccountUpdatePayload}. That order
|
||||
* is not cosmetic; the client's decoder emits a derived DTO's own members before its base's.
|
||||
*/
|
||||
export interface SelfAccountUpdatePayload extends AccountUpdatePayload {
|
||||
Email: string
|
||||
Phone: string
|
||||
/** ISO-8601. Its absence is what caused the under-13 junior crash. */
|
||||
Birthday: string | null
|
||||
JuniorState: number
|
||||
ParentAccountId: number | null
|
||||
AvailableUsernameChanges: number
|
||||
}
|
||||
|
||||
/** `ChatMessageReceived` and `PlayerLeftChat` — same shape. */
|
||||
export interface ChatMessagePayload {
|
||||
ChatMessageId: number
|
||||
ChatThreadId: number
|
||||
SenderPlayerId: number
|
||||
/** ISO-8601. */
|
||||
TimeSent: string
|
||||
Contents: string
|
||||
ModerationState: number
|
||||
}
|
||||
|
||||
/** `ClubMembershipUpdate`. */
|
||||
export interface ClubMembershipPayload {
|
||||
ClubId: number
|
||||
MembershipType: number
|
||||
}
|
||||
|
||||
/** `CreatorClubSubscriptionUpdate`. */
|
||||
export interface CreatorClubSubscriptionPayload {
|
||||
CreatorAccountId: number
|
||||
ClubId: number
|
||||
MembershipType: number
|
||||
}
|
||||
|
||||
/** `RoomCurrencyCreated` / `RoomCurrencyModified`. */
|
||||
export interface RoomCurrencyPayload {
|
||||
CurrencyId: string
|
||||
RoomId: number | null
|
||||
Name: string
|
||||
Description: string
|
||||
CurrencyType: CurrencyType
|
||||
Limit: number
|
||||
ImageName: string
|
||||
/** ISO-8601. */
|
||||
CreatedAt: string
|
||||
/** ISO-8601. */
|
||||
ModifiedAt: string
|
||||
}
|
||||
|
||||
/** `RoomCurrencyDeleted`. */
|
||||
export interface RoomCurrencyDeletedPayload {
|
||||
CurrencyId: string
|
||||
}
|
||||
|
||||
/** `LocalRoomKeyCreated` (120). */
|
||||
export interface LocalRoomKeyPayload {
|
||||
RoomKeyId: number
|
||||
ReplicationId: string
|
||||
RoomId: number
|
||||
Name: string
|
||||
Description: string
|
||||
Price: number
|
||||
PurchaseCurrencyId: string | null
|
||||
/** ISO-8601. */
|
||||
CreatedAt: string
|
||||
ImageName: string
|
||||
}
|
||||
|
||||
/** `LocalRoomKeyDeleted` (121). */
|
||||
export interface LocalRoomKeyDeletedPayload {
|
||||
RoomKeyId: number
|
||||
}
|
||||
|
||||
/** `AnnouncementUpdate`. */
|
||||
export interface AnnouncementPayload {
|
||||
AnnouncementId: number
|
||||
AnnouncementType: number
|
||||
Title: string
|
||||
Body: string
|
||||
ImageName: string
|
||||
LinkType: number
|
||||
LinkName: string
|
||||
LinkButtonLabel: string
|
||||
LinkUri: string
|
||||
Platform: number
|
||||
/** ISO-8601. */
|
||||
CreatedAt: string
|
||||
}
|
||||
|
||||
/** `AnnouncementDelete`. */
|
||||
export interface AnnouncementDeletePayload {
|
||||
AnnouncementId: number
|
||||
}
|
||||
|
||||
/** `CommunityBoardAnnouncementUpdate` (96) — the board's single current announcement. */
|
||||
export interface CommunityBoardAnnouncementPayload {
|
||||
Message: string
|
||||
MoreInfoUrl: string
|
||||
}
|
||||
|
||||
/** `ReputationUpdate`. */
|
||||
export interface ReputationPayload {
|
||||
AccountId: number
|
||||
IsCheerful: boolean
|
||||
SelectedCheer: number | null
|
||||
CheerCredit: number
|
||||
CheerGeneral: number
|
||||
CheerHelpful: number
|
||||
CheerCreative: number
|
||||
CheerGreatHost: number
|
||||
CheerSportsman: number
|
||||
}
|
||||
|
||||
/** `PhotonAccessToken`. */
|
||||
export interface PhotonAccessTokenPayload {
|
||||
RoomInstanceId: number
|
||||
PhotonAccessToken: string
|
||||
Permissions: unknown[]
|
||||
}
|
||||
|
||||
/** `KeepsakeInstanceAdded` / `KeepsakeInstanceRemoved`. */
|
||||
export interface KeepsakeInstancePayload {
|
||||
KeepsakeInstanceId: string
|
||||
KeepsakeCategoryConfigId: number
|
||||
PlacedByAccountId: number
|
||||
RoomId: number
|
||||
SubRoomId: number | null
|
||||
}
|
||||
|
||||
/** `PlayerCustomAvatarItemModerated`. */
|
||||
export interface CustomAvatarItemPayload {
|
||||
CustomAvatarItemId: string
|
||||
CreatorAccountId: number
|
||||
Name: string
|
||||
Description: string
|
||||
Price: number
|
||||
Accessibility: number
|
||||
IsFeatured: boolean
|
||||
BaseAvatarItemId: number | null
|
||||
BaseAvatarItemColor: string
|
||||
DesignFilename: string
|
||||
ThumbnailImageFilename: string
|
||||
/** ISO-8601. */
|
||||
CreatedAt: string
|
||||
/** ISO-8601. */
|
||||
ModifiedAt: string
|
||||
}
|
||||
|
||||
/** `GoToFailure`. */
|
||||
export interface GoToFailurePayload {
|
||||
Error: GoToFailureError
|
||||
}
|
||||
|
||||
/** `AppVersionUpdate` — the live replacement for the dead `ModerationUpdateRequired` (21). */
|
||||
export interface AppVersionUpdatePayload {
|
||||
ActivePlatforms: unknown
|
||||
}
|
||||
|
||||
/** `IncentivizedReferralUpdate`. */
|
||||
export interface IncentivizedReferralPayload {
|
||||
InviteeAccountId: number
|
||||
/** ISO-8601. */
|
||||
CreatedAt: string
|
||||
/** ISO-8601. */
|
||||
VerifiedAt: string | null
|
||||
}
|
||||
|
||||
/** `InfluencerSupportedUpdate`. */
|
||||
export interface InfluencerSupportedPayload {
|
||||
SupportedInfluencerId: number | null
|
||||
}
|
||||
|
||||
/** `StringAutoLocalizationJob`. */
|
||||
export interface StringAutoLocalizationJobPayload {
|
||||
Scope: string
|
||||
Status: number
|
||||
}
|
||||
|
||||
/** `SubscriptionUpdateGameSession` (`"RoomInstanceUpdate"`). */
|
||||
export interface RoomInstanceUpdatePayload {
|
||||
RoomInstanceId: number
|
||||
RoomId: number
|
||||
SubRoomId: number
|
||||
Location: string
|
||||
EventId: number
|
||||
ClubId: number
|
||||
RoomCode: string
|
||||
/** Canonical spelling is lower-camel here, unlike its neighbours. */
|
||||
photonRegionId: string
|
||||
PhotonRoomId: string
|
||||
Name: string
|
||||
MaxCapacity: number
|
||||
IsFull: boolean
|
||||
IsPrivate: boolean
|
||||
IsInProgress: boolean
|
||||
EncryptVoiceChat: boolean
|
||||
RoomInstanceType: number
|
||||
MatchmakingPolicy: number
|
||||
}
|
||||
|
||||
/**
|
||||
* `GiftPackageReceived` (30), `GiftPackageReceivedImmediate` (31) and
|
||||
* `GiftPackageRewardSelectionReceived` (32) all carry this. Note `BalanceType` here is NOT
|
||||
* the renamed-to-`Platform` field seen on the balance payloads — it is its own member and
|
||||
* keeps its name; `Platform` is a separate key on the same object.
|
||||
*/
|
||||
export interface GiftPackagePayload {
|
||||
Id: number | null
|
||||
FromPlayerId: number | null
|
||||
ConsumableItemDesc: string
|
||||
AvatarItemType: number | null
|
||||
AvatarItemDesc: string
|
||||
EquipmentPrefabName: string
|
||||
EquipmentModificationGuid: string
|
||||
CurrencyType: CurrencyType
|
||||
Currency: number
|
||||
Xp: number
|
||||
GiftContext: number
|
||||
GiftRarity: number
|
||||
Message: string
|
||||
Platform: number
|
||||
PlatformsToSpawnOn: unknown
|
||||
BalanceType: BalancePlatform | null
|
||||
}
|
||||
|
||||
/** `gift.manualconsumed`. */
|
||||
export interface GiftManualConsumedPayload {
|
||||
GiftPackageId: number
|
||||
}
|
||||
|
||||
/** `RewardSelectionReceived` — distinct from the gift-package frames above. */
|
||||
export interface RewardSelectionPayload {
|
||||
RewardSelectionId: number
|
||||
RewardType: number
|
||||
Message: string
|
||||
GiftContext: number
|
||||
GiftDrop1: unknown
|
||||
GiftDrop2: unknown
|
||||
GiftDrop3: unknown
|
||||
Subscriber_GiftDrop3: unknown
|
||||
/** ISO-8601. */
|
||||
CreatedAt: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Channels whose handler takes no argument at all — the client refetches rather than reading
|
||||
* the frame. Send `{}`; anything else is ignored.
|
||||
*/
|
||||
export type NoPayload = Record<string, never>
|
||||
@@ -13,12 +13,32 @@
|
||||
* Lives in the `notify` worker (the hub owner); other workers import it to send a
|
||||
* typed notification instead of a magic number. No runtime dependencies, so it's safe
|
||||
* to import as a value from another worker's bundle.
|
||||
*
|
||||
* ## How this was verified
|
||||
*
|
||||
* Every member below was checked against the client's own subscription table, recovered by
|
||||
* static analysis of `GameAssembly.dll` (see `recnet-patcher`, `il2cpp-tools/regall.py`).
|
||||
* The client registers each channel by key — a decimal string for numeric ids, a name for
|
||||
* the rest — and **a key with no subscriber is dropped in silence**: the frame parses, no
|
||||
* handler runs, nothing is logged. So "the client ignores this" is indistinguishable from
|
||||
* "the server never sent it" at runtime, which is why the status is recorded here instead.
|
||||
*
|
||||
* Members marked `@deadOnClient` have no subscriber in the build this was taken from
|
||||
* (20230414-era, `GameAssembly.dll` 156,069,888 bytes). They are kept because they name a
|
||||
* real client enum member and may come back in another build — but sending one today is a
|
||||
* no-op. Everything not so marked was confirmed to have a live handler.
|
||||
*/
|
||||
export enum NotificationType {
|
||||
RelationshipChanged = 1,
|
||||
MessageReceived = 2,
|
||||
MessageDeleted = 3,
|
||||
/**
|
||||
* @deadOnClient No subscriber, and unlike its neighbours it has no wire-name twin either —
|
||||
* the string `PresenceHeartbeat…` does not appear anywhere in the client's metadata. The
|
||||
* heartbeat response has nowhere to land in this build.
|
||||
*/
|
||||
PresenceHeartbeatResponse = 4,
|
||||
/** Also reachable as the wire name `"PlayerPrivileges.Refresh"` — same handler. */
|
||||
RefreshLogin = 5,
|
||||
Logout = 6,
|
||||
SubscriptionUpdateProfile = 'AccountUpdate',
|
||||
@@ -28,6 +48,9 @@ export enum NotificationType {
|
||||
* sends both on connect and after a profile mutation — everyone gets the public frame,
|
||||
* the owner additionally gets this one. Named after its twin rather than after a client
|
||||
* enum member, since the client's enum doesn't list it; the WIRE name is what matters.
|
||||
*
|
||||
* Confirmed live: the client subscribes `"SelfAccountUpdate"` and the payload is the
|
||||
* public account DTO plus six owner-only fields. See `SelfAccountUpdatePayload`.
|
||||
*/
|
||||
SubscriptionUpdateSelfProfile = 'SelfAccountUpdate',
|
||||
SubscriptionUpdatePresence = 'PresenceUpdate',
|
||||
@@ -39,16 +62,29 @@ export enum NotificationType {
|
||||
* stringifies whatever it is given, so `15` would go out as the unrelated `"15"`.
|
||||
*/
|
||||
SubscriptionUpdateRoom = 'RoomUpdate',
|
||||
/** Unverified: nothing sends it here, and the reference's hub never puts it on the wire. */
|
||||
/** @deadOnClient No subscriber under `16` and no wire-name twin. */
|
||||
SubscriptionUpdateRoomPlaylist = 16,
|
||||
ModerationQuitGame = 20,
|
||||
/**
|
||||
* @deadOnClient Nothing listens on `21`. {@link AppVersionUpdate} is the live channel
|
||||
* that does this job — same handler class, addressed by name.
|
||||
*/
|
||||
ModerationUpdateRequired = 21,
|
||||
ModerationKick = 22,
|
||||
ModerationKickAttemptFailed = 23,
|
||||
/**
|
||||
* @deadOnClient Not present in this build at all: no subscriber on `24`, and the string
|
||||
* `"ModerationRoomBan"` does not exist in the client's metadata, so neither spelling can
|
||||
* be dispatched. To ban from a room, use {@link ModerationKick} with `IsBan: true`.
|
||||
*/
|
||||
ModerationRoomBan = 'ModerationRoomBan',
|
||||
ServerMaintenance = 25,
|
||||
GiftPackageReceived = 30,
|
||||
GiftPackageReceivedImmediate = 31,
|
||||
/**
|
||||
* Carries a gift package like its two neighbours. Distinct from
|
||||
* {@link RewardSelectionReceived}, which is a different channel with a different payload.
|
||||
*/
|
||||
GiftPackageRewardSelectionReceived = 32,
|
||||
/**
|
||||
* A player's level/XP changed — `{ PlayerId, Level, XP }`, where XP is the progress into
|
||||
@@ -56,9 +92,13 @@ export enum NotificationType {
|
||||
* wire name and its enum has no number for this one at all. It pushes the frame both when
|
||||
* progression changes and when the player reads it back, which is how a client that just
|
||||
* connected gets its bar right.
|
||||
*
|
||||
* Confirmed live, and the three-field payload confirmed against the client's formatter.
|
||||
*/
|
||||
PlayerProgressionLevelUpdate = 'PlayerProgressionLevelUpdate',
|
||||
/** @deadOnClient No subscriber under `40` and no wire-name twin. */
|
||||
ProfileJuniorStatusUpdate = 40,
|
||||
/** Takes no payload — the client refetches. */
|
||||
RelationshipsInvalid = 50,
|
||||
StorefrontBalanceAdd = 60,
|
||||
StorefrontBalanceUpdate = 61,
|
||||
@@ -70,12 +110,67 @@ export enum NotificationType {
|
||||
PlayerEventDeleted = 82,
|
||||
PlayerEventResponseChanged = 83,
|
||||
PlayerEventResponseDeleted = 84,
|
||||
/** @deadOnClient No subscriber under `85` and no wire-name twin. */
|
||||
PlayerEventStateChanged = 85,
|
||||
ChatMessageReceived = 'ChatMessageReceived',
|
||||
CommunityBoardUpdate = 95,
|
||||
/**
|
||||
* STRING-valued, and this one is easy to get wrong: the client's enum *does* have a
|
||||
* member numbered `95`, but nothing subscribes to `"95"` — the live subscription is on
|
||||
* the name. Sending the number is a silent no-op.
|
||||
*/
|
||||
CommunityBoardUpdate = 'CommunityBoardUpdate',
|
||||
/**
|
||||
* Numeric, unlike its `CommunityBoard` sibling above — `96` genuinely has a subscriber.
|
||||
* Do not "unify" these two; they were checked separately. Note the *announcement list*
|
||||
* has its own name-addressed channels ({@link AnnouncementUpdate} /
|
||||
* {@link AnnouncementDelete}); this one is the board's single current announcement.
|
||||
*/
|
||||
CommunityBoardAnnouncementUpdate = 96,
|
||||
/** Takes no payload — the client refetches. */
|
||||
InventionModerationStateChanged = 100,
|
||||
/** Takes no payload — the client refetches. */
|
||||
FreeGiftButtonItemsAdded = 110,
|
||||
LocalRoomKeyCreated = 120,
|
||||
LocalRoomKeyDeleted = 121,
|
||||
|
||||
// ---- Name-addressed channels with no client enum member ------------------
|
||||
// These have no number at all: the client subscribes them purely by name. Grouped
|
||||
// separately so the numeric block above stays a faithful mirror of the client enum.
|
||||
|
||||
/** Client version gate. The live replacement for {@link ModerationUpdateRequired}. */
|
||||
AppVersionUpdate = 'AppVersionUpdate',
|
||||
AnnouncementUpdate = 'AnnouncementUpdate',
|
||||
AnnouncementDelete = 'AnnouncementDelete',
|
||||
ClubMembershipUpdate = 'ClubMembershipUpdate',
|
||||
CreatorClubSubscriptionUpdate = 'CreatorClubSubscriptionUpdate',
|
||||
CommerceSubscriptionUpdate = 'CommerceSubscriptionUpdate',
|
||||
/** Takes no payload — the client refetches `api/config/v2`. */
|
||||
GameConfigRefresh = 'GameConfig.Refresh',
|
||||
/** Takes no payload — the client refetches. */
|
||||
PlayerSettingsRefresh = 'PlayerSettings.Refresh',
|
||||
/** Matchmaking told the client its `GoTo` failed; payload is a single error code. */
|
||||
GoToFailure = 'GoToFailure',
|
||||
IncentivizedReferralUpdate = 'IncentivizedReferralUpdate',
|
||||
InfluencerSupportedUpdate = 'InfluencerSupportedUpdate',
|
||||
KeepsakeInstanceAdded = 'KeepsakeInstanceAdded',
|
||||
KeepsakeInstanceRemoved = 'KeepsakeInstanceRemoved',
|
||||
/** The un-kick; same payload type as {@link ModerationKick}. */
|
||||
ModerationUnkick = 'ModerationUnkick',
|
||||
/** Hands the client a Photon token for a room instance. */
|
||||
PhotonAccessToken = 'PhotonAccessToken',
|
||||
PlayerCustomAvatarItemModerated = 'PlayerCustomAvatarItemModerated',
|
||||
/** Same payload type as {@link ChatMessageReceived}. */
|
||||
PlayerLeftChat = 'PlayerLeftChat',
|
||||
ProgressionEventsRecordUpdate = 'ProgressionEventsRecordUpdate',
|
||||
ReputationUpdate = 'ReputationUpdate',
|
||||
/** Distinct from {@link GiftPackageRewardSelectionReceived} — different payload. */
|
||||
RewardSelectionReceived = 'RewardSelectionReceived',
|
||||
RoomCommentDeleted = 'RoomCommentDeleted',
|
||||
RoomCurrencyCreated = 'RoomCurrencyCreated',
|
||||
RoomCurrencyModified = 'RoomCurrencyModified',
|
||||
RoomCurrencyDeleted = 'RoomCurrencyDeleted',
|
||||
StringAutoLocalizationJob = 'StringAutoLocalizationJob',
|
||||
WebsiteInventionPurchase = 'WebsiteInventionPurchase',
|
||||
GiftManualConsumed = 'gift.manualconsumed',
|
||||
PushToDevice = 'rrs.pushtodevice',
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user