package gamelogic import ( "encoding/json" "fmt" "math/rand" "time" "bet24.com/servers/games/spinplay/config" "bet24.com/servers/insecureframe/frame" "bet24.com/servers/insecureframe/gate" "bet24.com/utils" ) type tablesink struct { table frame.Table gameScene *GameScene roomInfo config.RoomInfo logic *cardlogic LastOpraTime time.Time //记录操作时间点 privateData string } func newTableSink(table frame.Table, data string) *tablesink { ts := new(tablesink) ts.privateData = data ts.table = table ts.logic = newCardLogic() ts.gameScene = newGameScene(table.GetTableID()) err := json.Unmarshal([]byte(data), &ts.roomInfo) if err != nil { found := false for _, v := range config.Rooms.Rooms { if data == v.RoomName { ts.roomInfo = v found = true break } } if !found { ts.roomInfo = config.Rooms.Rooms[0] } } return ts } func (ts *tablesink) Destroy() { ts.table.LogWithTableId("------tablesink: Destroy-------") } func (ts *tablesink) OnGetMinGold() int { return ts.roomInfo.MinGold } func (ts *tablesink) OnGetMaxGold() int { return ts.roomInfo.MaxGold } func (ts *tablesink) OnGameMessage(userIndex int32, msg, data string) bool { switch msg { case CMD_TABLECHAT: ts.recvChatMsg(userIndex, data) case CMD_CANCLE_AUTO: ts.recvCancleAutoMsg(userIndex, data) case CMD_AUTO: ts.recvAutoMsg(userIndex, data) case CMD_ACTION: return ts.recvAction(userIndex, data) default: ts.table.LogWithTableId("tablesink.OnGameMessage %s\n%s", msg, data) return false } return true } func (ts *tablesink) OnUserEnterTable(userIndex int32, chairId int) { usr := gate.GetUserInfo(userIndex) if usr == nil { ts.table.LogWithTableId("tablesink.OnUserEnterTable user not exist") return } ts.table.LogWithTableId("tablesink.OnUserEnterTable chair[%d]: %d:%s ", chairId, usr.GetUserId(), usr.GetUserNickName()) if ts.table.GetUserChipOrGoldByUser(usr) < ts.roomInfo.MinGold { ts.table.LogWithTableId("----玩家:%d 金币不足: %d ", usr.GetUserId(), ts.table.GetUserChipOrGoldByUser(usr)) ts.table.KickUser(userIndex, true) return } //下发房间配置 d, _ := json.Marshal(ts.roomInfo.RoomInfoBase) ts.table.SendGameData(userIndex, CMD_ROOMINFO, string(d)) //有玩家进桌, 更新在线 if !Stopping { go func() { frame.UpdateRoomOnline(ts.roomInfo.RoomName, ts.roomInfo.RoomID-1) }() } ts.gameScene.Players[chairId].userID = usr.GetUserId() ts.gameScene.Players[chairId].isEndToStart = false // 机器人,100ms后准备 if usr.IsRobot() { ts.table.SetTimer(TIMER_READY_0+chairId, 100) } if !usr.IsRobot() { ts.table.NotifySceneChanged(chairId) } else { ts.gameScene.Players[chairId].robotType = rand.Intn(2) } } func (ts *tablesink) OnUserExitTable(userIndex int32, chairId int) { //用户离开要判断是否为游戏玩家,不是游戏玩家不做业务逻辑处理 usr := ts.table.GetPlayer(userIndex) if usr == nil { ts.table.LogWithTableId("tablesink.OnUserExitTable,usr[%d] not exist", userIndex) return } ts.table.LogWithTableId("tablesink.OnUserExitTable chair[%d]: %d:%s", chairId, usr.GetUserId(), usr.GetUserNickName()) ts.gameScene.Players[chairId].isEndToStart = false ts.gameScene.Players[chairId].initData(0, 0) //有玩家离开, 更新在线 if !Stopping { go func() { frame.UpdateRoomOnline(ts.roomInfo.RoomName, ts.roomInfo.RoomID-1) }() } if ts.gameScene.Phase == Phase_Free || ts.gameScene.Phase == Phase_End { ts.table.KillTimer(TIMER_READY_0 + chairId) if ts.gameScene.Phase != Phase_End { ts.table.SetTimer(TIMER_ADD_ROBOT, 1000) } go ts.checkAndStartGame() } } // 用户离线 func (ts *tablesink) OnUserOffline(chairId int) { usr := ts.table.GetUserByChair(chairId) if usr == nil { ts.table.LogWithTableId("tablesink.OnUserOffline user not exist") return } ts.table.LogWithTableId("tablesink.OnUserOffline %d:%s", usr.GetUserId(), usr.GetUserNickName()) } // 用户重进 func (ts *tablesink) OnUserReplay(chairId int) { usr := ts.table.GetUserByChair(chairId) if usr == nil { ts.table.LogWithTableId("tablesink.OnUserOffline user not exist") return } ts.table.LogWithTableId("tablesink.OnUserReplay %d:%s", usr.GetUserId(), usr.GetUserNickName()) //下发房间配置 d, _ := json.Marshal(ts.roomInfo.RoomInfoBase) ts.table.SendGameData(usr.GetUserIndex(), CMD_ROOMINFO, string(d)) ts.gameScene.Players[chairId].AutoOut = false } // 准备 func (ts *tablesink) OnUserReady(userIndex int32, chairId int) { defer utils.TimeCost(fmt.Sprintf("tablesink.OnUserReady %d", userIndex))() usr := gate.GetUserInfo(userIndex) if usr == nil { ts.table.LogWithTableId("tablesink.OnUserReady user not exist") return } userGold := ts.table.GetUserChipOrGoldByUser(usr) if userGold < ts.roomInfo.MinGold || (ts.roomInfo.MaxGold > 0 && userGold > ts.roomInfo.MaxGold) { ts.table.LogWithTableId("tablesink.OnUserReady 玩家:%d 金币不足, T出去 ", usr.GetUserId()) ts.table.KickUser(usr.GetUserIndex(), !usr.IsRobot()) return } ts.table.LogWithTableId("tablesink.OnUserReady chair[%d]: %d:%s", chairId, usr.GetUserId(), usr.GetUserNickName()) ts.table.KillTimer(TIMER_READY_0 + chairId) if ts.gameScene.Phase != Phase_End || ts.gameScene.Players[chairId].isEndToStart { ts.table.SetTimer(TIMER_ADD_ROBOT, 1000) } if !usr.IsRobot() && ts.gameScene.Players[chairId].isEndToStart { ts.table.NotifySceneChanged(chairId) } ts.checkAndStartGame() } // 取消准备 func (ts *tablesink) OnUserCancelReady(userIndex int32, chairId int) { usr := gate.GetUserInfo(userIndex) if usr == nil { ts.table.LogWithTableId("tablesink.OnUserCancelReady user not exist") return } ts.table.LogWithTableId("tablesink.OnUserCancelReady %d:%s", usr.GetUserId(), usr.GetUserNickName()) } func (ts *tablesink) OnGetChairScene(chairId int, isPlayer bool) string { now := time.Now() ts.gameScene.LeftSec = ts.getSecond(ts.gameScene.Phase)/1000 - int(now.Sub(ts.LastOpraTime).Seconds()) return ts.gameScene.getScene(chairId, isPlayer, false) } func (ts *tablesink) OnGetChairCount() int { return CHAIR_COUNT } func (ts *tablesink) OnTimer(timerId int) { switch timerId { case TIMER_READY_0: fallthrough case TIMER_READY_1: fallthrough case TIMER_READY_2: fallthrough case TIMER_READY_3: ts.checkUserReadyStatus(timerId - TIMER_READY_0) case TIMER_ADD_ROBOT: ts.checkIsNeedRobot() case TIMER_START_GAME: ts.checkStartGame() case TIMER_GAME: ts.dealGameTimeOut() case TIMER_START_ACTION: ts.dealStartAction() case TIMER_ROUND_END: ts.dealRoundEnd() case TIMER_ROBOT_0: fallthrough case TIMER_ROBOT_1: fallthrough case TIMER_ROBOT_2: fallthrough case TIMER_ROBOT_3: ts.onTimerRobotAction(timerId - TIMER_ROBOT_0) case TIMER_REMOVE_ROBOT: ts.removeOneRobot() case TIMER_KICK_USER_0: fallthrough case TIMER_KICK_USER_1: fallthrough case TIMER_KICK_USER_2: fallthrough case TIMER_KICK_USER_3: ts.table.KickUserByChair(timerId-TIMER_KICK_USER_0, true) } } func (ts *tablesink) DumpScene() { ts.gameScene.dump() } func (ts *tablesink) GetGoldLimit() (min, max int) { return ts.roomInfo.MinGold, ts.roomInfo.MaxGold } func (ts *tablesink) IsDual() bool { return false } func (ts *tablesink) IsAllRobot() bool { return false }