-
Notifications
You must be signed in to change notification settings - Fork 0
/
team_mode.go
125 lines (107 loc) · 2.5 KB
/
team_mode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
package game
import (
"sort"
"github.com/sauerbraten/waiter/pkg/protocol/nmc"
"github.com/sauerbraten/waiter/pkg/protocol/playerstate"
)
type TeamMode interface {
Teams() map[string]*Team
ForEachTeam(func(*Team))
Join(*Player)
ChangeTeam(*Player, string, bool)
Leave(*Player)
HandleFrag(fragger, victim *Player)
}
type teamMode struct {
s Server
teamsByName map[string]*Team
otherTeamsAllowed bool
keepTeams bool
}
var _ TeamMode = &teamMode{}
func withTeams(s Server, otherTeamsAllowed, keepTeams bool, teams ...*Team) *teamMode {
teamsByName := map[string]*Team{}
for _, team := range teams {
teamsByName[team.Name] = team
}
return &teamMode{
s: s,
teamsByName: teamsByName,
otherTeamsAllowed: otherTeamsAllowed,
keepTeams: keepTeams,
}
}
func (m *teamMode) selectTeam(p *Player) *Team {
if m.keepTeams {
for _, t := range m.teamsByName {
if p.Team.Name == t.Name {
return t
}
}
}
return m.selectWeakestTeam()
}
func (m *teamMode) selectWeakestTeam() *Team {
teams := []*Team{}
for _, team := range m.teamsByName {
teams = append(teams, team)
}
sort.Sort(BySizeAndScore(teams))
return teams[0]
}
func (m *teamMode) Join(p *Player) {
team := m.selectTeam(p)
team.Add(p)
m.s.Broadcast(nmc.SetTeam, p.CN, p.Team.Name, -1)
}
func (*teamMode) Leave(p *Player) {
p.Team.Remove(p)
}
func (m *teamMode) HandleFrag(fragger, victim *Player) {
victim.Die()
if fragger.Team == victim.Team {
fragger.Frags--
} else {
fragger.Frags++
}
m.s.Broadcast(nmc.Died, victim.CN, fragger.CN, fragger.Frags, fragger.Team.Frags)
}
func (m *teamMode) ForEachTeam(do func(t *Team)) {
for _, team := range m.teamsByName {
do(team)
}
}
func (m *teamMode) Teams() map[string]*Team {
return m.teamsByName
}
func (m *teamMode) ChangeTeam(p *Player, newTeamName string, forced bool) {
reason := -1 // = none = silent
if p.State != playerstate.Spectator {
if forced {
reason = 1 // = forced
} else {
reason = 0 // = voluntary
}
}
setTeam := func(old, new *Team) {
if p.State == playerstate.Alive {
m.HandleFrag(p, p)
}
old.Remove(p)
new.Add(p)
m.s.Broadcast(nmc.SetTeam, p.CN, p.Team.Name, reason)
}
// try existing teams first
for name, team := range m.teamsByName {
if name == newTeamName {
// todo: check privileges and team balance
setTeam(p.Team, team)
return
}
}
if m.otherTeamsAllowed {
newTeam := NewTeam(newTeamName)
m.teamsByName[newTeamName] = newTeam
setTeam(p.Team, newTeam)
}
}