/
player.go
149 lines (125 loc) · 2.69 KB
/
player.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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package main
import (
"log"
)
type PlayerCmd int
type PlayerId uint64
var (
PlayerCmdGameSelectEntity = PlayerCmd(0)
)
type PlayerError struct {
PlayerErrorString string
}
func (p *PlayerError) Error() string { return p.PlayerErrorString }
var (
PlayerErrorDisconnected = &PlayerError{"Player's connection has been disconnected"}
)
type PlayerAction struct {
World *PlayerWorldAction
Game *PlayerGameAction
Player *Player
}
type PlayerWorldAction struct {
}
type PlayerGameAction struct {
Command PlayerCmd
EntityId EntityId
}
// Player object
type Player struct {
id PlayerId
conn Connection
reader chan MessageIn
toPlayer chan interface{}
setGameCtrl chan *GamePlayerCtrl
gameCtrl GamePlayerCtrl
}
// Creates a new intance of the player object, and attaches the
// existing connection to the player.
func NewPlayer(id PlayerId, c Connection) *Player {
p := &Player{
id: id,
conn: c,
}
p.reader = make(chan MessageIn)
p.toPlayer = make(chan interface{}, 10)
p.setGameCtrl = make(chan *GamePlayerCtrl)
p.conn.AttachReader(p.reader)
return p
}
// Returns the player's id
func (p Player) GetId() PlayerId {
return p.id
}
// Terminates the player's connection
func (p *Player) Disconnect() {
if p.conn != nil {
p.conn.Close()
}
if p.toPlayer != nil {
close(p.toPlayer)
}
if p.setGameCtrl != nil {
close(p.setGameCtrl)
}
p.conn = nil
p.toPlayer = nil
p.setGameCtrl = nil
}
// Event handler for a player. Will process events as they are
// received from the player, world, or game
func (p *Player) Run(w *World) {
defer func() { log.Println("Player ", p.id, " event loop terminating") }()
for {
select {
case msg, ok := <-p.reader:
if !ok {
return
}
if msg.Act != nil {
ctrl := GetPlayerActionFromMessage(msg, p)
// forward the control onto the world or game
if ctrl.Game != nil && p.gameCtrl != nil {
p.gameCtrl <- ctrl
}
if ctrl.World != nil {
w.playerAction <- ctrl
}
}
case msg, ok := <-p.toPlayer:
if !ok {
return
}
if p.conn == nil {
return
}
p.conn.Send(msg)
case ctrl, ok := <-p.setGameCtrl:
if !ok {
return
}
if ctrl == nil {
p.gameCtrl = nil
continue
}
p.gameCtrl = *ctrl
}
}
}
// Pushes the message to the player asynchronously
func (p *Player) SendToPlayer(msg interface{}) error {
if p.toPlayer == nil {
return PlayerErrorDisconnected
}
p.toPlayer <- msg
return nil
}
// Sets the channel a player should use to use to send controls
// to the the game at on.
func (p *Player) SetGameCtrl(ctrlChan *GamePlayerCtrl) error {
if p.setGameCtrl == nil {
return PlayerErrorDisconnected
}
p.setGameCtrl <- ctrlChan
return nil
}