@@ -980,6 +980,28 @@ func validateUniqueTeamIDs(teams []TeamConfig) string {
980980 return ""
981981}
982982
983+ // resolvePreset validates and looks up a preset in the server-owned
984+ // registry. Returns the team list on success, or nil and an
985+ // error message describing why the preset was rejected. The server is
986+ // the source of truth for team configuration; the client's preset
987+ // label must match an entry the operator registered.
988+ func resolvePreset (preset string , presets map [string ][]TeamConfig ) ([]TeamConfig , string ) {
989+ if preset == "" {
990+ return nil , "preset is required"
991+ }
992+ teams , ok := presets [preset ]
993+ if ! ok {
994+ return nil , "unknown preset: " + preset
995+ }
996+ if len (teams ) == 0 {
997+ return nil , "preset misconfigured: no teams"
998+ }
999+ if duplicateID := validateUniqueTeamIDs (teams ); duplicateID != "" {
1000+ return nil , "preset misconfigured: duplicate team id " + duplicateID
1001+ }
1002+ return teams , ""
1003+ }
1004+
9831005// generateInviteCodeWithRetry generates an invite code with collision check.
9841006// Retries up to maxRetries times if collision detected.
9851007// Returns the code and whether generation succeeded.
@@ -1108,46 +1130,16 @@ func processCreateLobbyCommands(
11081130 CreatedAt : now ,
11091131 }
11101132
1111- // Resolve preset against the server-owned registry. Unknown or
1112- // empty presets are rejected; the server is the source of truth
1113- // for team configuration, not the client.
1114- if payload .Preset == "" {
1115- state .Logger ().Warn ().Str ("player_id" , playerID ).Msg ("create lobby rejected: empty preset" )
1116- state .CreateLobbyResults .Emit (CreateLobbyResult {
1117- RequestID : payload .RequestID ,
1118- IsSuccess : false ,
1119- Message : "preset is required" ,
1120- })
1121- continue
1122- }
1123- presetTeams , ok := config .LobbyPresets [payload .Preset ]
1124- if ! ok {
1125- state .Logger ().Warn ().Str ("preset" , payload .Preset ).Msg ("create lobby rejected: unknown preset" )
1126- state .CreateLobbyResults .Emit (CreateLobbyResult {
1127- RequestID : payload .RequestID ,
1128- IsSuccess : false ,
1129- Message : "unknown preset: " + payload .Preset ,
1130- })
1131- continue
1132- }
1133- if duplicateID := validateUniqueTeamIDs (presetTeams ); duplicateID != "" {
1134- state .Logger ().Error ().
1133+ presetTeams , errMsg := resolvePreset (payload .Preset , config .LobbyPresets )
1134+ if errMsg != "" {
1135+ state .Logger ().Warn ().
1136+ Str ("player_id" , playerID ).
11351137 Str ("preset" , payload .Preset ).
1136- Str ("team_id" , duplicateID ).
1137- Msg ("preset has duplicate team id; rejecting create" )
1138- state .CreateLobbyResults .Emit (CreateLobbyResult {
1139- RequestID : payload .RequestID ,
1140- IsSuccess : false ,
1141- Message : "preset misconfigured: duplicate team id " + duplicateID ,
1142- })
1143- continue
1144- }
1145- if len (presetTeams ) == 0 {
1146- state .Logger ().Error ().Str ("preset" , payload .Preset ).Msg ("preset has no teams" )
1138+ Msg ("create lobby rejected: " + errMsg )
11471139 state .CreateLobbyResults .Emit (CreateLobbyResult {
11481140 RequestID : payload .RequestID ,
11491141 IsSuccess : false ,
1150- Message : "preset misconfigured: no teams" ,
1142+ Message : errMsg ,
11511143 })
11521144 continue
11531145 }
0 commit comments