feat: game lobby service
This commit is contained in:
@@ -42,6 +42,16 @@ type LobbyMembershipRejectedEvent struct {
|
||||
GameID string
|
||||
}
|
||||
|
||||
// LobbyMembershipBlockedEvent is the independent Go representation of
|
||||
// `notification.LobbyMembershipBlockedEvent`. Reason carries the upstream
|
||||
// lifecycle event that triggered the cascade
|
||||
// (`permanent_blocked`, `deleted`).
|
||||
type LobbyMembershipBlockedEvent struct {
|
||||
GameID string
|
||||
MembershipUserID string
|
||||
Reason string
|
||||
}
|
||||
|
||||
// LobbyInviteCreatedEvent is the independent Go representation of
|
||||
// `notification.LobbyInviteCreatedEvent`.
|
||||
type LobbyInviteCreatedEvent struct {
|
||||
@@ -56,6 +66,20 @@ type LobbyInviteRedeemedEvent struct {
|
||||
InviteeUserID string
|
||||
}
|
||||
|
||||
// LobbyRaceNameRegistrationEligibleEvent is the independent Go
|
||||
// representation of `notification.LobbyRaceNameRegistrationEligibleEvent`.
|
||||
type LobbyRaceNameRegistrationEligibleEvent struct {
|
||||
GameID string
|
||||
RaceName string
|
||||
EligibleUntilMs int64
|
||||
}
|
||||
|
||||
// LobbyRaceNameRegisteredEvent is the independent Go representation of
|
||||
// `notification.LobbyRaceNameRegisteredEvent`.
|
||||
type LobbyRaceNameRegisteredEvent struct {
|
||||
RaceName string
|
||||
}
|
||||
|
||||
// GameTurnReadyEventToPayload converts GameTurnReadyEvent to FlatBuffers bytes
|
||||
// suitable for the authenticated gateway push transport.
|
||||
func GameTurnReadyEventToPayload(event *GameTurnReadyEvent) ([]byte, error) {
|
||||
@@ -272,6 +296,68 @@ func PayloadToLobbyMembershipRejectedEvent(data []byte) (result *LobbyMembership
|
||||
return &LobbyMembershipRejectedEvent{GameID: gameID}, nil
|
||||
}
|
||||
|
||||
// LobbyMembershipBlockedEventToPayload converts LobbyMembershipBlockedEvent
|
||||
// to FlatBuffers bytes suitable for the authenticated gateway push
|
||||
// transport.
|
||||
func LobbyMembershipBlockedEventToPayload(event *LobbyMembershipBlockedEvent) ([]byte, error) {
|
||||
if event == nil {
|
||||
return nil, errors.New("encode lobby membership blocked payload: event is nil")
|
||||
}
|
||||
if event.GameID == "" {
|
||||
return nil, errors.New("encode lobby membership blocked payload: game_id is empty")
|
||||
}
|
||||
if event.MembershipUserID == "" {
|
||||
return nil, errors.New("encode lobby membership blocked payload: membership_user_id is empty")
|
||||
}
|
||||
if event.Reason == "" {
|
||||
return nil, errors.New("encode lobby membership blocked payload: reason is empty")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(96)
|
||||
gameID := builder.CreateString(event.GameID)
|
||||
membershipUserID := builder.CreateString(event.MembershipUserID)
|
||||
reason := builder.CreateString(event.Reason)
|
||||
|
||||
notificationfbs.LobbyMembershipBlockedEventStart(builder)
|
||||
notificationfbs.LobbyMembershipBlockedEventAddGameId(builder, gameID)
|
||||
notificationfbs.LobbyMembershipBlockedEventAddMembershipUserId(builder, membershipUserID)
|
||||
notificationfbs.LobbyMembershipBlockedEventAddReason(builder, reason)
|
||||
offset := notificationfbs.LobbyMembershipBlockedEventEnd(builder)
|
||||
notificationfbs.FinishLobbyMembershipBlockedEventBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToLobbyMembershipBlockedEvent converts FlatBuffers payload bytes
|
||||
// into LobbyMembershipBlockedEvent.
|
||||
func PayloadToLobbyMembershipBlockedEvent(data []byte) (result *LobbyMembershipBlockedEvent, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode lobby membership blocked payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverNotificationDecodePanic("decode lobby membership blocked payload", &result, &err)
|
||||
|
||||
event := notificationfbs.GetRootAsLobbyMembershipBlockedEvent(data, 0)
|
||||
gameID, err := requiredNotificationString(event.GameId(), "game_id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode lobby membership blocked payload: %w", err)
|
||||
}
|
||||
membershipUserID, err := requiredNotificationString(event.MembershipUserId(), "membership_user_id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode lobby membership blocked payload: %w", err)
|
||||
}
|
||||
reason, err := requiredNotificationString(event.Reason(), "reason")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode lobby membership blocked payload: %w", err)
|
||||
}
|
||||
|
||||
return &LobbyMembershipBlockedEvent{
|
||||
GameID: gameID,
|
||||
MembershipUserID: membershipUserID,
|
||||
Reason: reason,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// LobbyInviteCreatedEventToPayload converts LobbyInviteCreatedEvent to
|
||||
// FlatBuffers bytes suitable for the authenticated gateway push transport.
|
||||
func LobbyInviteCreatedEventToPayload(event *LobbyInviteCreatedEvent) ([]byte, error) {
|
||||
@@ -374,6 +460,99 @@ func PayloadToLobbyInviteRedeemedEvent(data []byte) (result *LobbyInviteRedeemed
|
||||
}, nil
|
||||
}
|
||||
|
||||
// LobbyRaceNameRegistrationEligibleEventToPayload converts
|
||||
// LobbyRaceNameRegistrationEligibleEvent to FlatBuffers bytes suitable for
|
||||
// the authenticated gateway push transport.
|
||||
func LobbyRaceNameRegistrationEligibleEventToPayload(event *LobbyRaceNameRegistrationEligibleEvent) ([]byte, error) {
|
||||
if event == nil {
|
||||
return nil, errors.New("encode lobby race name registration eligible payload: event is nil")
|
||||
}
|
||||
if event.GameID == "" {
|
||||
return nil, errors.New("encode lobby race name registration eligible payload: game_id is empty")
|
||||
}
|
||||
if event.RaceName == "" {
|
||||
return nil, errors.New("encode lobby race name registration eligible payload: race_name is empty")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(96)
|
||||
gameID := builder.CreateString(event.GameID)
|
||||
raceName := builder.CreateString(event.RaceName)
|
||||
|
||||
notificationfbs.LobbyRaceNameRegistrationEligibleEventStart(builder)
|
||||
notificationfbs.LobbyRaceNameRegistrationEligibleEventAddGameId(builder, gameID)
|
||||
notificationfbs.LobbyRaceNameRegistrationEligibleEventAddRaceName(builder, raceName)
|
||||
notificationfbs.LobbyRaceNameRegistrationEligibleEventAddEligibleUntilMs(builder, event.EligibleUntilMs)
|
||||
offset := notificationfbs.LobbyRaceNameRegistrationEligibleEventEnd(builder)
|
||||
notificationfbs.FinishLobbyRaceNameRegistrationEligibleEventBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToLobbyRaceNameRegistrationEligibleEvent converts FlatBuffers
|
||||
// payload bytes into LobbyRaceNameRegistrationEligibleEvent.
|
||||
func PayloadToLobbyRaceNameRegistrationEligibleEvent(data []byte) (result *LobbyRaceNameRegistrationEligibleEvent, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode lobby race name registration eligible payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverNotificationDecodePanic("decode lobby race name registration eligible payload", &result, &err)
|
||||
|
||||
event := notificationfbs.GetRootAsLobbyRaceNameRegistrationEligibleEvent(data, 0)
|
||||
gameID, err := requiredNotificationString(event.GameId(), "game_id")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode lobby race name registration eligible payload: %w", err)
|
||||
}
|
||||
raceName, err := requiredNotificationString(event.RaceName(), "race_name")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode lobby race name registration eligible payload: %w", err)
|
||||
}
|
||||
|
||||
return &LobbyRaceNameRegistrationEligibleEvent{
|
||||
GameID: gameID,
|
||||
RaceName: raceName,
|
||||
EligibleUntilMs: event.EligibleUntilMs(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// LobbyRaceNameRegisteredEventToPayload converts LobbyRaceNameRegisteredEvent
|
||||
// to FlatBuffers bytes suitable for the authenticated gateway push transport.
|
||||
func LobbyRaceNameRegisteredEventToPayload(event *LobbyRaceNameRegisteredEvent) ([]byte, error) {
|
||||
if event == nil {
|
||||
return nil, errors.New("encode lobby race name registered payload: event is nil")
|
||||
}
|
||||
if event.RaceName == "" {
|
||||
return nil, errors.New("encode lobby race name registered payload: race_name is empty")
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(48)
|
||||
raceName := builder.CreateString(event.RaceName)
|
||||
|
||||
notificationfbs.LobbyRaceNameRegisteredEventStart(builder)
|
||||
notificationfbs.LobbyRaceNameRegisteredEventAddRaceName(builder, raceName)
|
||||
offset := notificationfbs.LobbyRaceNameRegisteredEventEnd(builder)
|
||||
notificationfbs.FinishLobbyRaceNameRegisteredEventBuffer(builder, offset)
|
||||
|
||||
return builder.FinishedBytes(), nil
|
||||
}
|
||||
|
||||
// PayloadToLobbyRaceNameRegisteredEvent converts FlatBuffers payload bytes
|
||||
// into LobbyRaceNameRegisteredEvent.
|
||||
func PayloadToLobbyRaceNameRegisteredEvent(data []byte) (result *LobbyRaceNameRegisteredEvent, err error) {
|
||||
if len(data) == 0 {
|
||||
return nil, errors.New("decode lobby race name registered payload: data is empty")
|
||||
}
|
||||
|
||||
defer recoverNotificationDecodePanic("decode lobby race name registered payload", &result, &err)
|
||||
|
||||
event := notificationfbs.GetRootAsLobbyRaceNameRegisteredEvent(data, 0)
|
||||
raceName, err := requiredNotificationString(event.RaceName(), "race_name")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("decode lobby race name registered payload: %w", err)
|
||||
}
|
||||
|
||||
return &LobbyRaceNameRegisteredEvent{RaceName: raceName}, nil
|
||||
}
|
||||
|
||||
func requiredNotificationString(value []byte, field string) (string, error) {
|
||||
if len(value) == 0 {
|
||||
return "", fmt.Errorf("%s is missing", field)
|
||||
|
||||
@@ -71,6 +71,26 @@ func TestNotificationPayloadRoundTrips(t *testing.T) {
|
||||
},
|
||||
decode: func(data []byte) (any, error) { return PayloadToLobbyInviteRedeemedEvent(data) },
|
||||
},
|
||||
{
|
||||
name: "lobby race name registration eligible",
|
||||
source: &LobbyRaceNameRegistrationEligibleEvent{
|
||||
GameID: "game-8",
|
||||
RaceName: "Skylancer",
|
||||
EligibleUntilMs: 1775208100000,
|
||||
},
|
||||
encode: func(value any) ([]byte, error) {
|
||||
return LobbyRaceNameRegistrationEligibleEventToPayload(value.(*LobbyRaceNameRegistrationEligibleEvent))
|
||||
},
|
||||
decode: func(data []byte) (any, error) { return PayloadToLobbyRaceNameRegistrationEligibleEvent(data) },
|
||||
},
|
||||
{
|
||||
name: "lobby race name registered",
|
||||
source: &LobbyRaceNameRegisteredEvent{RaceName: "Skylancer"},
|
||||
encode: func(value any) ([]byte, error) {
|
||||
return LobbyRaceNameRegisteredEventToPayload(value.(*LobbyRaceNameRegisteredEvent))
|
||||
},
|
||||
decode: func(data []byte) (any, error) { return PayloadToLobbyRaceNameRegisteredEvent(data) },
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
@@ -151,6 +171,20 @@ func TestNotificationPayloadEncodersRejectNilInputs(t *testing.T) {
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lobby race name registration eligible",
|
||||
call: func() error {
|
||||
_, err := LobbyRaceNameRegistrationEligibleEventToPayload(nil)
|
||||
return err
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "lobby race name registered",
|
||||
call: func() error {
|
||||
_, err := LobbyRaceNameRegisteredEventToPayload(nil)
|
||||
return err
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
|
||||
+14
-6
@@ -47,10 +47,10 @@ func UpdateMyProfileRequestToPayload(request *usermodel.UpdateMyProfileRequest)
|
||||
}
|
||||
|
||||
builder := flatbuffers.NewBuilder(128)
|
||||
raceName := builder.CreateString(request.RaceName)
|
||||
displayName := builder.CreateString(request.DisplayName)
|
||||
|
||||
userfbs.UpdateMyProfileRequestStart(builder)
|
||||
userfbs.UpdateMyProfileRequestAddRaceName(builder, raceName)
|
||||
userfbs.UpdateMyProfileRequestAddDisplayName(builder, displayName)
|
||||
offset := userfbs.UpdateMyProfileRequestEnd(builder)
|
||||
userfbs.FinishUpdateMyProfileRequestBuffer(builder, offset)
|
||||
|
||||
@@ -68,7 +68,7 @@ func PayloadToUpdateMyProfileRequest(data []byte) (result *usermodel.UpdateMyPro
|
||||
|
||||
request := userfbs.GetRootAsUpdateMyProfileRequest(data, 0)
|
||||
return &usermodel.UpdateMyProfileRequest{
|
||||
RaceName: string(request.RaceName()),
|
||||
DisplayName: string(request.DisplayName()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -236,7 +236,11 @@ func encodeAccount(builder *flatbuffers.Builder, account usermodel.Account) (fla
|
||||
|
||||
userID := builder.CreateString(account.UserID)
|
||||
email := builder.CreateString(account.Email)
|
||||
raceName := builder.CreateString(account.RaceName)
|
||||
userName := builder.CreateString(account.UserName)
|
||||
var displayName flatbuffers.UOffsetT
|
||||
if account.DisplayName != "" {
|
||||
displayName = builder.CreateString(account.DisplayName)
|
||||
}
|
||||
preferredLanguage := builder.CreateString(account.PreferredLanguage)
|
||||
timeZone := builder.CreateString(account.TimeZone)
|
||||
|
||||
@@ -248,7 +252,10 @@ func encodeAccount(builder *flatbuffers.Builder, account usermodel.Account) (fla
|
||||
userfbs.AccountViewStart(builder)
|
||||
userfbs.AccountViewAddUserId(builder, userID)
|
||||
userfbs.AccountViewAddEmail(builder, email)
|
||||
userfbs.AccountViewAddRaceName(builder, raceName)
|
||||
userfbs.AccountViewAddUserName(builder, userName)
|
||||
if displayName != 0 {
|
||||
userfbs.AccountViewAddDisplayName(builder, displayName)
|
||||
}
|
||||
userfbs.AccountViewAddPreferredLanguage(builder, preferredLanguage)
|
||||
userfbs.AccountViewAddTimeZone(builder, timeZone)
|
||||
if declaredCountry != 0 {
|
||||
@@ -284,7 +291,8 @@ func decodeAccount(account *userfbs.AccountView) (usermodel.Account, error) {
|
||||
result := usermodel.Account{
|
||||
UserID: string(account.UserId()),
|
||||
Email: string(account.Email()),
|
||||
RaceName: string(account.RaceName()),
|
||||
UserName: string(account.UserName()),
|
||||
DisplayName: string(account.DisplayName()),
|
||||
PreferredLanguage: string(account.PreferredLanguage()),
|
||||
TimeZone: string(account.TimeZone()),
|
||||
DeclaredCountry: string(account.DeclaredCountry()),
|
||||
|
||||
@@ -29,7 +29,7 @@ func TestUserRequestPayloadRoundTrips(t *testing.T) {
|
||||
t.Fatalf("get my account request mismatch: %#v", getDecoded)
|
||||
}
|
||||
|
||||
profileSource := &usermodel.UpdateMyProfileRequest{RaceName: "Nova Prime"}
|
||||
profileSource := &usermodel.UpdateMyProfileRequest{DisplayName: "NovaPrime"}
|
||||
profilePayload, err := UpdateMyProfileRequestToPayload(profileSource)
|
||||
if err != nil {
|
||||
t.Fatalf("encode update my profile request: %v", err)
|
||||
@@ -72,7 +72,8 @@ func TestAccountResponsePayloadRoundTrip(t *testing.T) {
|
||||
Account: usermodel.Account{
|
||||
UserID: "user-123",
|
||||
Email: "pilot@example.com",
|
||||
RaceName: "Pilot Nova",
|
||||
UserName: "player-abcdefgh",
|
||||
DisplayName: "PilotNova",
|
||||
PreferredLanguage: "en",
|
||||
TimeZone: "Europe/Kaliningrad",
|
||||
DeclaredCountry: "DE",
|
||||
@@ -342,14 +343,14 @@ func TestPayloadToAccountResponseRejectsMissingEntitlement(t *testing.T) {
|
||||
payload := buildAccountResponsePayload(func(builder *flatbuffers.Builder) flatbuffers.UOffsetT {
|
||||
userID := builder.CreateString("user-123")
|
||||
email := builder.CreateString("pilot@example.com")
|
||||
raceName := builder.CreateString("Pilot Nova")
|
||||
userName := builder.CreateString("player-abcdefgh")
|
||||
preferredLanguage := builder.CreateString("en")
|
||||
timeZone := builder.CreateString("Europe/Kaliningrad")
|
||||
|
||||
userfbs.AccountViewStart(builder)
|
||||
userfbs.AccountViewAddUserId(builder, userID)
|
||||
userfbs.AccountViewAddEmail(builder, email)
|
||||
userfbs.AccountViewAddRaceName(builder, raceName)
|
||||
userfbs.AccountViewAddUserName(builder, userName)
|
||||
userfbs.AccountViewAddPreferredLanguage(builder, preferredLanguage)
|
||||
userfbs.AccountViewAddTimeZone(builder, timeZone)
|
||||
userfbs.AccountViewAddCreatedAtMs(builder, 1)
|
||||
@@ -411,14 +412,14 @@ func TestPayloadToAccountResponseRejectsOverflowLimitValue(t *testing.T) {
|
||||
|
||||
userID := builder.CreateString("user-123")
|
||||
email := builder.CreateString("pilot@example.com")
|
||||
raceName := builder.CreateString("Pilot Nova")
|
||||
userName := builder.CreateString("player-abcdefgh")
|
||||
preferredLanguage := builder.CreateString("en")
|
||||
timeZone := builder.CreateString("Europe/Kaliningrad")
|
||||
|
||||
userfbs.AccountViewStart(builder)
|
||||
userfbs.AccountViewAddUserId(builder, userID)
|
||||
userfbs.AccountViewAddEmail(builder, email)
|
||||
userfbs.AccountViewAddRaceName(builder, raceName)
|
||||
userfbs.AccountViewAddUserName(builder, userName)
|
||||
userfbs.AccountViewAddPreferredLanguage(builder, preferredLanguage)
|
||||
userfbs.AccountViewAddTimeZone(builder, timeZone)
|
||||
userfbs.AccountViewAddEntitlement(builder, entitlementOffset)
|
||||
|
||||
Reference in New Issue
Block a user