-
Notifications
You must be signed in to change notification settings - Fork 3
/
lobby.go
141 lines (136 loc) · 3.99 KB
/
lobby.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
package main
import (
"bufio"
"fmt"
"os"
"strings"
pubnub "github.com/pubnub/go"
)
func hereNow(channel string, pn *pubnub.PubNub) int { // Return count of occupants for a channel.
res, _, err := pn.HereNow().
Channels([]string{channel}).
Execute()
if err != nil {
panic(err)
}
return res.TotalOccupancy
}
func newLobby(lobby string, username string, pn *pubnub.PubNub) {
var (
guestName string
hostName string
isHost bool
)
data := make(map[string]interface{})
lobby, username = userInput(lobby, username)
lobbylistener := pubnub.NewListener()
endLobby := make(chan bool)
go func() {
for {
select {
case status := <-lobbylistener.Status:
switch status.Category {
case pubnub.PNConnectedCategory:
game_occupants := hereNow(lobby, pn)
lobby_occupants := hereNow(lobby+"_lobby", pn)
if game_occupants > 0 || lobby_occupants > 2 {
fmt.Println("Game already in progress! Please try another lobby.")
fmt.Print("Game: ")
fmt.Println(game_occupants)
fmt.Print("Lobby: ")
fmt.Println(lobby_occupants)
pn.RemoveListener(lobbylistener)
pn.Unsubscribe().
Channels([]string{lobby + "_lobby"}).
Execute()
newLobby(lobby, username, pn) // Start over if the game is in progress.
return
}
if lobby_occupants == 0 {
isHost = true
fmt.Println("Waiting for guest...")
} else if lobby_occupants == 1 { // Player will be guest. Send username to host.
fmt.Println("Waiting for host...")
data["guestName"] = username
guestName = username
pn.Publish().
Channel(lobby + "_lobby").
Message(data).
Execute()
}
}
case message := <-lobbylistener.Message:
if msg, ok := message.Message.(map[string]interface{}); ok {
if !isHost {
if val, ok := msg["hostName"]; ok { // When the guest receives the host username then the game is ready to start.
hostName = val.(string)
endLobby <- true
return
}
} else {
if val, ok := msg["guestName"]; ok { // The host receives the guest username then the host sends the host username and starts a game.
guestName = val.(string)
data["hostName"] = username
hostName = username
pn.Publish().
Channel(lobby + "_lobby").
Message(data).
Execute()
endLobby <- true
return
}
}
}
}
}
}()
pn.AddListener(lobbylistener)
pn.Subscribe().
Channels([]string{lobby + "_lobby"}).
Execute()
<-endLobby // Remove the listener and unsubscribe from the channel used for the game lobby.
pn.RemoveListener(lobbylistener)
pn.Unsubscribe().
Channels([]string{lobby + "_lobby"}).
Execute()
startGame(isHost, lobby, strings.Title(hostName), strings.Title(guestName), pn)
}
func userInput(lobby string, username string) (string, string) {
var (
newlobby string
newUsername string
err error
)
reader := bufio.NewReader(os.Stdin)
if lobby == "" { // Ask for lobby name.
fmt.Print("Enter Lobby Name: ")
} else {
fmt.Print("Enter Lobby Name (" + lobby + "): ")
}
newlobby, err = reader.ReadString('\n')
if err != nil {
panic(err)
}
newlobby = strings.Replace(newlobby, "\n", "", -1) // Convert CRLF to LF.
if newlobby != "" { // Use last lobby name when the player does not provide a lobby.
lobby = newlobby
}
if username == "" { // Ask for username.
fmt.Print("Enter Your Name: ")
} else {
fmt.Print("Enter Your Name (" + username + "): ")
}
newUsername, err = reader.ReadString('\n')
if err != nil {
panic(err)
}
newUsername = strings.Replace(newUsername, "\n", "", -1) // Convert CRLF to LF.
if newUsername != "" { // Use last username when the player does not provide a username.
username = newUsername
}
if (lobby == "") || (username == "") { // The player must have a lobby and username.
fmt.Println("You Must Provide a Lobby and Name! ")
userInput(lobby, username) // Start over.
}
return lobby, username
}