mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-11 00:14:00 +00:00
feat(multiplayer): deliver allocated server rosters
This commit is contained in:
@@ -69,6 +69,11 @@ const AssignmentSelectSQL = `SELECT match_id, player_id, allocation_id, server_i
|
||||
FROM assignments
|
||||
WHERE match_id = $1 AND player_id = $2 AND expires_at > $3`
|
||||
|
||||
const AssignmentRosterSelectSQL = `SELECT allocation_id, server_id, join_authorisation
|
||||
FROM assignments
|
||||
WHERE match_id = $1 AND server_id = $2 AND expires_at > $3
|
||||
ORDER BY slot, player_id`
|
||||
|
||||
func validateDurableAssignment(assignment DurableAssignment) error {
|
||||
if assignment.MatchID == "" || assignment.PlayerID == "" || assignment.AllocationID == "" || assignment.ServerID == "" || assignment.Slot < 0 || assignment.Slot > 5 || (assignment.Region != "EU" && assignment.Region != "NA") || assignment.ClientBuild == "" || assignment.ProtocolVersion < 1 || (assignment.Transport != "enet" && assignment.Transport != "steam_sdr") || assignment.Endpoint == "" || assignment.JoinAuthorisation == "" || len(assignment.ManifestDigest) == 0 || assignment.ExpiresAt.IsZero() || assignment.Revision < 0 {
|
||||
return fmt.Errorf("invalid durable assignment")
|
||||
@@ -187,3 +192,43 @@ func GetAssignment(ctx context.Context, db *sql.DB, playerID, matchID string, no
|
||||
}
|
||||
return assignment, nil
|
||||
}
|
||||
|
||||
// GetAssignmentRoster returns the complete signed roster for an allocated
|
||||
// server. It is intentionally server-scoped rather than player-scoped and is
|
||||
// called only after workload authentication at the API boundary. All rows
|
||||
// must belong to one allocation; a partial or mixed allocation is unsafe to
|
||||
// hand to the game process.
|
||||
func GetAssignmentRoster(ctx context.Context, db *sql.DB, matchID, serverID string, now time.Time) ([][]byte, error) {
|
||||
if db == nil || matchID == "" || serverID == "" || now.IsZero() {
|
||||
return nil, fmt.Errorf("invalid assignment roster arguments")
|
||||
}
|
||||
rows, err := db.QueryContext(ctx, AssignmentRosterSelectSQL, matchID, serverID, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var allocationID string
|
||||
var roster [][]byte
|
||||
for rows.Next() {
|
||||
var rowAllocation, rowServer, encoded string
|
||||
if err := rows.Scan(&rowAllocation, &rowServer, &encoded); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if rowServer != serverID || rowAllocation == "" || (allocationID != "" && allocationID != rowAllocation) {
|
||||
return nil, fmt.Errorf("assignment roster contains mixed allocation")
|
||||
}
|
||||
decoded, err := base64.RawURLEncoding.DecodeString(encoded)
|
||||
if err != nil || len(decoded) == 0 {
|
||||
return nil, fmt.Errorf("assignment roster contains invalid envelope")
|
||||
}
|
||||
allocationID = rowAllocation
|
||||
roster = append(roster, decoded)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(roster) == 0 {
|
||||
return nil, sql.ErrNoRows
|
||||
}
|
||||
return roster, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user