Feature: destroy room after user disconnected

This commit is contained in:
2020-04-30 20:15:31 +08:00
parent e0177b1467
commit b87ec69b40
6 changed files with 77 additions and 42 deletions
+15 -3
View File
@@ -19,16 +19,21 @@ type ConnManager struct {
getReadyCh chan message.GetReadyMsg
chatCh chan message.ChatMsg
exitCh chan bool
destroyCh chan int
roomID int
}
func NewConnManager(playersCount int,
func NewConnManager(roomID int,
playersCount int,
gameRecvCh chan message.GameMsgRecv,
gameSendCh chan message.GameMsgSend,
tableOrderCh chan int,
gameResultCh chan message.GameResultMsg,
getReadyCh chan message.GetReadyMsg,
chatCh chan message.ChatMsg,
exitCh chan bool) *ConnManager {
exitCh chan bool,
destroyCh chan int) *ConnManager {
connManager := ConnManager{playersCount: playersCount,
conns: make([]*websocket.Conn, 0),
gameRecvCh: gameRecvCh,
@@ -38,13 +43,15 @@ func NewConnManager(playersCount int,
getReadyCh: getReadyCh,
chatCh: chatCh,
exitCh: exitCh,
destroyCh: destroyCh,
roomID: roomID,
}
go connManager.Broadcaster()
return &connManager
}
func (m *ConnManager) AddConn(conn *websocket.Conn) {
index:= len(m.conns)
index := len(m.conns)
msg := message.TableOrderMsg{
MsgType: config.TableOrderMsgType,
TableOrder: index,
@@ -83,6 +90,8 @@ func (m *ConnManager) Broadcaster() {
}
case msg := <-m.exitCh:
if msg {
log.Println("broadcaster exit")
m.destroyCh <- m.roomID
return
}
}
@@ -109,16 +118,19 @@ func (m *ConnManager) checkConn(c *websocket.Conn) {
for _, conn := range m.conns {
conn.Close()
}
m.exitCh <- true
}
func (m *ConnManager) connListener(conn *websocket.Conn, gameRecvCh chan message.GameMsgRecv, chatCh chan message.ChatMsg) {
for {
log.Println("waiting msg")
commonMsg := message.CommonMsg{}
_, msg, err := conn.ReadMessage()
if err != nil {
//TODO: handle when user force exit
m.checkConn(conn)
log.Println("failed to read message")
return
}
err = json.Unmarshal(msg, &commonMsg)
if err != nil {
+12 -2
View File
@@ -19,6 +19,7 @@ type Hall struct {
players map[int]int
maxRoomSize int
destroyCh chan int
}
var hall *Hall = nil
@@ -33,13 +34,15 @@ func GetHall() *Hall {
}
func NewHall(maxRoomSize int) *Hall {
return &Hall{maxRoomSize: maxRoomSize, rooms: map[int]*Room{}, players: map[int]int{}}
hall:=Hall{maxRoomSize: maxRoomSize, rooms: map[int]*Room{}, players: map[int]int{}, destroyCh: make(chan int)}
go hall.roomController()
return &hall
}
func (h *Hall) CreateRoom(userID int, passwd string) int {
for i := 0; i < h.maxRoomSize; i++ {
if !h.hasRoom(i) {
room := NewRoom(rule.NewJinzhouRule())
room := NewRoom(i, rule.NewJinzhouRule(), h.destroyCh)
room.Start()
room.password = passwd
room.playerCount = 1
@@ -97,3 +100,10 @@ func (h *Hall) hasRoom(roomID int) bool {
func (h *Hall) destroyRoom(roomID int) {
delete(h.rooms, roomID)
}
func (h *Hall) roomController() {
for {
roomID := <-h.destroyCh
h.destroyRoom(roomID)
}
}
+8 -3
View File
@@ -8,6 +8,7 @@ import (
)
type Room struct {
roomID int
connManager *ConnManager
mahjongManager *game.MahjongManager
@@ -18,11 +19,13 @@ type Room struct {
getReadyCh chan message.GetReadyMsg
chatCh chan message.ChatMsg
destroyCh chan int
password string
playerCount int
}
func NewRoom(rule rule.MahjongRule) *Room {
func NewRoom(roomID int, rule rule.MahjongRule, destroyCh chan int) *Room {
gameRecvChannel := make(chan message.GameMsgRecv)
gameSendChannel := make(chan message.GameMsgSend)
tableOrderChannel := make(chan int)
@@ -31,14 +34,16 @@ func NewRoom(rule rule.MahjongRule) *Room {
chatChannel := make(chan message.ChatMsg)
exitChannel := make(chan bool)
return &Room{
roomID: roomID,
gameRecvCh: gameRecvChannel,
gameSendCh: gameSendChannel,
tableOrderCh: tableOrderChannel,
gameResultCh: gameResultChannel,
getReadyCh: getReadyChannel,
chatCh: chatChannel,
connManager: NewConnManager(4, gameRecvChannel, gameSendChannel, tableOrderChannel, gameResultChannel, getReadyChannel, chatChannel, exitChannel),
mahjongManager: game.NewMahjongManager(gameRecvChannel, gameSendChannel, tableOrderChannel, gameResultChannel, getReadyChannel, chatChannel, rule),
destroyCh: destroyCh,
connManager: NewConnManager(roomID, 4, gameRecvChannel, gameSendChannel, tableOrderChannel, gameResultChannel, getReadyChannel, chatChannel, exitChannel, destroyCh),
mahjongManager: game.NewMahjongManager(gameRecvChannel, gameSendChannel, tableOrderChannel, gameResultChannel, getReadyChannel, chatChannel, exitChannel, rule),
}
}
+35 -25
View File
@@ -20,6 +20,7 @@ type MahjongManager struct {
gameResultCh chan message.GameResultMsg
getReadyCh chan message.GetReadyMsg
chatCh chan message.ChatMsg
exitCh chan bool
lastTableOrder int
currentTableOrder int
@@ -38,6 +39,7 @@ func NewMahjongManager(gameRecvCh chan message.GameMsgRecv,
gameResultCh chan message.GameResultMsg,
getReadyCh chan message.GetReadyMsg,
chatCh chan message.ChatMsg,
exitCh chan bool,
r rule.MahjongRule) *MahjongManager {
mahjong := MahjongManager{}
mahjong.rules = r
@@ -50,6 +52,7 @@ func NewMahjongManager(gameRecvCh chan message.GameMsgRecv,
mahjong.gameResultCh = gameResultCh
mahjong.getReadyCh = getReadyCh
mahjong.chatCh = chatCh
mahjong.exitCh = exitCh
return &mahjong
}
@@ -64,31 +67,38 @@ func (m MahjongManager) GetFirstPlayer() {
func (m *MahjongManager) gameLoop(gameRecvCh chan message.GameMsgRecv, gameSendCh chan message.GameMsgSend) {
for {
msg := <-gameRecvCh
log.Printf("player:[%d], action:[%d] ", msg.TableOrder, msg.Action)
switch msg.Action {
case config.Start:
//inform each player their order
m.tableOrderCh <- m.firstPlayer
m.handleStart()
case config.Ready:
m.handleReady(msg)
case config.Discard:
m.handleDiscard(msg, false)
case config.Chow:
m.handleChow(msg)
case config.Pong:
m.handlePong(msg)
case config.ExposedKong:
m.handleExposedKong(msg)
case config.ConcealedKong:
m.handleConcealedKong(msg)
case config.AddedKong:
m.handleAddedKong(msg)
case config.Win:
m.handleWin(msg)
case config.Cancel:
m.handleCancel(msg)
select {
case e := <-m.exitCh:
if e {
return
}
case msg := <-gameRecvCh:
log.Printf("player:[%d], action:[%d] ", msg.TableOrder, msg.Action)
switch msg.Action {
case config.Start:
//inform each player their order
m.tableOrderCh <- m.firstPlayer
m.handleStart()
case config.Ready:
m.handleReady(msg)
case config.Discard:
m.handleDiscard(msg, false)
case config.Chow:
m.handleChow(msg)
case config.Pong:
m.handlePong(msg)
case config.ExposedKong:
m.handleExposedKong(msg)
case config.ConcealedKong:
m.handleConcealedKong(msg)
case config.AddedKong:
m.handleAddedKong(msg)
case config.Win:
m.handleWin(msg)
case config.Cancel:
m.handleCancel(msg)
}
}
}
}
+2 -3
View File
@@ -4,7 +4,6 @@ import (
"encoding/json"
"github.com/c-my/MahjongServer/container"
"github.com/c-my/MahjongServer/controller"
"github.com/c-my/MahjongServer/rule"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
"io/ioutil"
@@ -30,8 +29,8 @@ func wsHandler(w http.ResponseWriter, r *http.Request) {
func main() {
configure := readConfig()
room = container.NewRoom(rule.NewJinzhouRule())
room.Start()
//room = container.NewRoom(rule.NewJinzhouRule())
//room.Start()
router := mux.NewRouter()
+5 -6
View File
@@ -17,12 +17,11 @@ type RoomInfoMsg struct {
}
type GameResultMsg struct {
MsgType int `json:"msg_type"`
Winner int `json:"winner"`
FinalTile model.Tile `json:"final_tile"`
PlayerTile []model.PlayerTile `json:"player_tile"`
UserList []UserInfo `json:"user_list"`
MsgType int `json:"msg_type"`
Winner int `json:"winner"`
FinalTile model.Tile `json:"final_tile"`
PlayerTile []model.PlayerTile `json:"player_tile"`
UserList []UserInfo `json:"user_list"`
}
type GetReadyMsg struct {