mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-13 12:02:02 +00:00
fix(multiplayer): reconcile authoritative initial connections
This commit is contained in:
+22
-6
@@ -15,6 +15,7 @@ const (
|
||||
type ConnectParticipant struct {
|
||||
PlayerID string
|
||||
Team int
|
||||
Slot int
|
||||
Connected bool
|
||||
}
|
||||
|
||||
@@ -22,6 +23,7 @@ type InitialConnectAction string
|
||||
|
||||
const (
|
||||
InitialConnectWait InitialConnectAction = "WAIT"
|
||||
InitialConnectStart InitialConnectAction = "START"
|
||||
InitialConnectCancel InitialConnectAction = "CANCEL"
|
||||
InitialConnectStartWithBot InitialConnectAction = "START_WITH_BOTS"
|
||||
)
|
||||
@@ -57,6 +59,9 @@ func PlanInitialConnect(playlist Playlist, readyAt, now time.Time, participants
|
||||
switch decision.Action {
|
||||
case InitialConnectWait:
|
||||
return plan, nil
|
||||
case InitialConnectStart:
|
||||
plan.MatchState = Live
|
||||
return plan, nil
|
||||
case InitialConnectCancel:
|
||||
plan.MatchState = Cancelled
|
||||
return plan, nil
|
||||
@@ -86,16 +91,18 @@ func EvaluateInitialConnect(playlist Playlist, readyAt, now time.Time, participa
|
||||
if playlist != Ranked && playlist != Casual || readyAt.IsZero() || len(participants) == 0 {
|
||||
return InitialConnectDecision{}, fmt.Errorf("invalid initial-connect policy input")
|
||||
}
|
||||
if now.Before(readyAt.Add(InitialConnectWindow)) {
|
||||
return InitialConnectDecision{Action: InitialConnectWait}, nil
|
||||
if playlist == Ranked && len(participants) != 6 || playlist == Casual && (len(participants) < 2 || len(participants) > 6) {
|
||||
return InitialConnectDecision{}, fmt.Errorf("invalid initial-connect roster size")
|
||||
}
|
||||
missing := make([]ConnectParticipant, 0)
|
||||
connected := make([]string, 0)
|
||||
teamConnected := map[int]bool{}
|
||||
seen := make(map[string]bool, len(participants))
|
||||
for _, participant := range participants {
|
||||
if participant.PlayerID == "" || participant.Team < 0 {
|
||||
if participant.PlayerID == "" || participant.Team < 0 || participant.Team > 1 || participant.Slot < 0 || participant.Slot > 5 || participant.Slot/3 != participant.Team || seen[participant.PlayerID] {
|
||||
return InitialConnectDecision{}, fmt.Errorf("invalid participant")
|
||||
}
|
||||
seen[participant.PlayerID] = true
|
||||
if participant.Connected {
|
||||
connected = append(connected, participant.PlayerID)
|
||||
teamConnected[participant.Team] = true
|
||||
@@ -103,10 +110,19 @@ func EvaluateInitialConnect(playlist Playlist, readyAt, now time.Time, participa
|
||||
missing = append(missing, participant)
|
||||
}
|
||||
}
|
||||
if playlist == Ranked {
|
||||
if len(participants) != 6 {
|
||||
return InitialConnectDecision{}, fmt.Errorf("ranked requires six participants")
|
||||
if len(missing) == 0 {
|
||||
if playlist == Casual && len(participants) < 6 {
|
||||
if !teamConnected[0] || !teamConnected[1] {
|
||||
return InitialConnectDecision{}, fmt.Errorf("casual bot roster requires a human on each team")
|
||||
}
|
||||
return InitialConnectDecision{Action: InitialConnectStartWithBot, Innocent: sortedIDs(connected)}, nil
|
||||
}
|
||||
return InitialConnectDecision{Action: InitialConnectStart, Innocent: sortedIDs(connected)}, nil
|
||||
}
|
||||
if now.Before(readyAt.Add(InitialConnectWindow)) {
|
||||
return InitialConnectDecision{Action: InitialConnectWait}, nil
|
||||
}
|
||||
if playlist == Ranked {
|
||||
return InitialConnectDecision{Action: InitialConnectCancel, NoShows: rankedNoShows(missing, now, priorAbandons), Innocent: sortedIDs(connected)}, nil
|
||||
}
|
||||
if now.Before(readyAt.Add(CasualBotStartAfter)) {
|
||||
|
||||
Reference in New Issue
Block a user