Skip to content

Commit 99700cd

Browse files
committed
[feature] Add gameEventProposals and publish events on majority
1 parent be3d985 commit 99700cd

File tree

7 files changed

+78
-36
lines changed

7 files changed

+78
-36
lines changed

config/ssl-game-controller.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ game:
1313
multiple-card-step: 3
1414
multiple-foul-step: 3
1515
multiple-placement-failures: 5
16+
auto-ref-proposal-timeout: 5s
1617
default-division: DivA
1718
normal:
1819
half-duration: 5m

internal/app/controller/config.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ type ConfigGame struct {
3939
MultipleFoulStep int `yaml:"multiple-foul-step"`
4040
MultiplePlacementFailures int `yaml:"multiple-placement-failures"`
4141
MaxBots map[Division]int `yaml:"max-bots"`
42+
AutoRefProposalTimeout time.Duration `yaml:"auto-ref-proposal-timeout"`
4243
}
4344

4445
// ConfigNetwork holds configs for network communication
@@ -104,6 +105,7 @@ func DefaultConfig() (c Config) {
104105
c.Game.MultipleCardStep = 3
105106
c.Game.MultipleFoulStep = 3
106107
c.Game.MultiplePlacementFailures = 5
108+
c.Game.AutoRefProposalTimeout = 5 * time.Second
107109

108110
c.Game.Normal.HalfDuration = 5 * time.Minute
109111
c.Game.Normal.HalfTimeDuration = 5 * time.Minute

internal/app/controller/controller.go

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -93,16 +93,34 @@ func (c *GameController) ProcessGeometry(data *sslproto.SSL_GeometryData) {
9393
}
9494
}
9595

96-
func (c *GameController) ProcessAutoRefRequests(request refproto.AutoRefToControllerRequest) error {
96+
func (c *GameController) ProcessAutoRefRequests(id string, request refproto.AutoRefToControllerRequest) error {
9797
c.Mutex.Lock()
9898
defer c.Mutex.Unlock()
99-
log.Print("Received request from autoRef: ", request)
99+
log.Printf("Received request from autoRef '%v': %v", id, request)
100100

101101
if request.GameEvent != nil {
102102
details := NewGameEventDetails(*request.GameEvent)
103103
gameEventType := details.EventType()
104104
event := Event{GameEvent: &GameEvent{Type: gameEventType, Details: details}}
105-
c.OnNewEvent(event)
105+
106+
if c.Engine.State.GameEventBehavior[event.GameEvent.Type] == GameEventBehaviorMajority {
107+
validUntil := c.Engine.TimeProvider().Add(c.Config.Game.AutoRefProposalTimeout)
108+
newProposal := GameEventProposal{GameEvent: *event.GameEvent, ProposerId: id, ValidUntil: validUntil}
109+
c.Engine.State.GameEventProposals = append(c.Engine.State.GameEventProposals, &newProposal)
110+
111+
totalProposals := 0
112+
for _, proposal := range c.Engine.State.GameEventProposals {
113+
if proposal.GameEvent.Type == event.GameEvent.Type && proposal.ValidUntil.After(c.Engine.TimeProvider()) {
114+
totalProposals++
115+
}
116+
}
117+
majority := int(math.Floor(float64(len(c.AutoRefServer.Clients)) / 2.0))
118+
if totalProposals > majority {
119+
c.OnNewEvent(event)
120+
}
121+
} else {
122+
c.OnNewEvent(event)
123+
}
106124
}
107125

108126
return nil
@@ -218,7 +236,23 @@ func (c *GameController) publishNetwork() {
218236
}
219237

220238
func (c *GameController) OnNewEvent(event Event) {
221-
if c.outstandingTeamChoice == nil && event.GameEvent != nil {
239+
240+
if event.GameEvent != nil && !c.Engine.disabledGameEvent(event.GameEvent.Type) && c.askForTeamDecisionIfRequired(event) {
241+
return
242+
}
243+
244+
err := c.Engine.Process(event)
245+
if err != nil {
246+
log.Println("Could not process event:", event, err)
247+
} else {
248+
c.historyPreserver.Save(c.Engine.History)
249+
c.publish()
250+
}
251+
}
252+
253+
func (c *GameController) askForTeamDecisionIfRequired(event Event) (handled bool) {
254+
handled = false
255+
if c.outstandingTeamChoice == nil {
222256
var byTeamProto refproto.Team
223257
var choiceType refproto.ControllerToTeamRequest_AdvantageChoice_Foul
224258
if event.GameEvent.Details.BotCrashUnique != nil {
@@ -241,18 +275,11 @@ func (c *GameController) OnNewEvent(event Event) {
241275
} else {
242276
c.outstandingTeamChoice = &TeamChoice{Team: forTeam, Event: event, IssueTime: c.Engine.TimeProvider()}
243277
go c.timeoutTeamChoice()
244-
return
278+
handled = true
245279
}
246280
}
247281
}
248-
249-
err := c.Engine.Process(event)
250-
if err != nil {
251-
log.Println("Could not process event:", event, err)
252-
} else {
253-
c.historyPreserver.Save(c.Engine.History)
254-
c.publish()
255-
}
282+
return
256283
}
257284

258285
func (c *GameController) timeoutTeamChoice() {

internal/app/controller/engine.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ func (e *Engine) SendCommand(command RefCommand, forTeam Team) {
6161
if len(e.State.GameEvents) > 0 {
6262
e.State.GameEvents = []*GameEvent{}
6363
}
64+
if len(e.State.GameEventProposals) > 0 {
65+
e.State.GameEventProposals = []*GameEventProposal{}
66+
}
6467
e.State.PlacementPos = nil
6568
e.State.NextCommand = CommandUnknown
6669
e.State.NextCommandFor = TeamUnknown

internal/app/controller/state.go

Lines changed: 28 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -247,26 +247,6 @@ type TeamInfo struct {
247247
Connected bool `json:"connected"`
248248
}
249249

250-
// State of the game
251-
type State struct {
252-
Stage Stage `json:"stage"`
253-
Command RefCommand `json:"command"`
254-
CommandFor Team `json:"commandForTeam"`
255-
GameEvents []*GameEvent `json:"gameEvents"`
256-
StageTimeElapsed time.Duration `json:"stageTimeElapsed"`
257-
StageTimeLeft time.Duration `json:"stageTimeLeft"`
258-
MatchTimeStart time.Time `json:"matchTimeStart"`
259-
MatchDuration time.Duration `json:"matchDuration"`
260-
TeamState map[Team]*TeamInfo `json:"teamState"`
261-
Division Division `json:"division"`
262-
PlacementPos *Location `json:"placementPos"`
263-
AutoContinue bool `json:"autoContinue"`
264-
NextCommand RefCommand `json:"nextCommand"`
265-
NextCommandFor Team `json:"nextCommandFor"`
266-
AutoRefsConnected []string `json:"autoRefsConnected"`
267-
GameEventBehavior map[GameEventType]GameEventBehavior `json:"gameEventBehavior"`
268-
}
269-
270250
type GameEventBehavior string
271251

272252
const (
@@ -275,6 +255,34 @@ const (
275255
GameEventBehaviorOff GameEventBehavior = "off"
276256
)
277257

258+
// GameEventProposal holds a proposal for a game event from an autoRef
259+
type GameEventProposal struct {
260+
ProposerId string
261+
GameEvent GameEvent
262+
ValidUntil time.Time
263+
}
264+
265+
// State of the game
266+
type State struct {
267+
Stage Stage `json:"stage"`
268+
Command RefCommand `json:"command"`
269+
CommandFor Team `json:"commandForTeam"`
270+
GameEvents []*GameEvent `json:"gameEvents"`
271+
StageTimeElapsed time.Duration `json:"stageTimeElapsed"`
272+
StageTimeLeft time.Duration `json:"stageTimeLeft"`
273+
MatchTimeStart time.Time `json:"matchTimeStart"`
274+
MatchDuration time.Duration `json:"matchDuration"`
275+
TeamState map[Team]*TeamInfo `json:"teamState"`
276+
Division Division `json:"division"`
277+
PlacementPos *Location `json:"placementPos"`
278+
AutoContinue bool `json:"autoContinue"`
279+
NextCommand RefCommand `json:"nextCommand"`
280+
NextCommandFor Team `json:"nextCommandFor"`
281+
AutoRefsConnected []string `json:"autoRefsConnected"`
282+
GameEventBehavior map[GameEventType]GameEventBehavior `json:"gameEventBehavior"`
283+
GameEventProposals []*GameEventProposal `json:"gameEventProposals"`
284+
}
285+
278286
// NewState creates a new state, initialized for the start of a new game
279287
func NewState() (s *State) {
280288
s = new(State)

internal/app/controller/testdata/config.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ game:
1313
multiple-card-step: 3
1414
multiple-foul-step: 3
1515
multiple-placement-failures: 5
16+
auto-ref-proposal-timeout: 5s
1617
default-division: DivA
1718
normal:
1819
half-duration: 5m

internal/app/rcon/autoRefServer.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import (
1111
)
1212

1313
type AutoRefServer struct {
14-
ProcessRequest func(refproto.AutoRefToControllerRequest) error
14+
ProcessRequest func(string, refproto.AutoRefToControllerRequest) error
1515
*Server
1616
}
1717

@@ -21,7 +21,7 @@ type AutoRefClient struct {
2121

2222
func NewAutoRefServer() (s *AutoRefServer) {
2323
s = new(AutoRefServer)
24-
s.ProcessRequest = func(refproto.AutoRefToControllerRequest) error { return nil }
24+
s.ProcessRequest = func(string, refproto.AutoRefToControllerRequest) error { return nil }
2525
s.Server = NewServer()
2626
s.ConnectionHandler = s.handleClientConnection
2727
return
@@ -128,7 +128,7 @@ func (s *AutoRefServer) handleClientConnection(conn net.Conn) {
128128
continue
129129
}
130130
}
131-
if err := s.ProcessRequest(req); err != nil {
131+
if err := s.ProcessRequest(client.Id, req); err != nil {
132132
client.Reject(err.Error())
133133
} else {
134134
client.Ok()

0 commit comments

Comments
 (0)