| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527 |
- package gamelogic
- import (
- "encoding/json"
- "fmt"
- "math/rand"
- "strconv"
- "time"
- "bet24.com/servers/games/baloot/config"
- "bet24.com/servers/insecureframe/frame"
- "bet24.com/servers/insecureframe/gate"
- ladder "bet24.com/servers/micros/ladderservice/proto"
- waterpool "bet24.com/servers/micros/waterpool/proto"
- "bet24.com/utils"
- "github.com/google/uuid"
- )
- type tablesink struct {
- table frame.Table
- gameScene *GameScene
- simulator *simulatorScene
- roomInfo config.RoomInfo
- privateData string
- logic *cardlogic
- LastOpraTime time.Time //记录操作时间点
- uniqueId string // 唯一标识
- roomType string // "","PrivateRoom","Match"
- surrenderInfo *SurrenderInfo // 投降消息
- allPassCount int
- }
- func newTableSink(table frame.Table, data string) *tablesink {
- ts := new(tablesink)
- ts.table = table
- ts.privateData = data
- ts.logic = newCardLogic()
- found := false
- err := json.Unmarshal([]byte(data), &ts.roomInfo)
- if err != nil {
- for _, v := range config.Rooms.Rooms {
- if data == v.RoomName {
- ts.roomInfo = v
- found = true
- break
- }
- }
- if !found {
- ts.roomInfo = config.NewUserRoom.RoomInfo
- found = true
- }
- } else {
- found = true
- }
- if !found {
- ts.roomInfo = config.NewUserRoom.RoomInfo
- }
- ts.uniqueId = uuid.New().String()
- ts.allPassCount = 0
- ts.gameScene = newGameScene(table.GetTableID(), ts.roomInfo.ScoreToWin, ts.roomInfo.MaxSurrenderCount)
- ts.surrenderInfo = newSurrenderInfo()
- return ts
- }
- func (ts *tablesink) Destroy() {
- ts.table.LogWithTableId("------tablesink: Destroy-------")
- }
- 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)
- case CMD_SYNCDATA:
- return ts.recvSyncData(userIndex, data)
- case CMD_SURRENDER:
- return ts.recvSurrender(userIndex, data)
- case CMD_SURRENDER_RESULT:
- return ts.recvSurrenderResult(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())
- //下发房间配置
- d, _ := json.Marshal(ts.roomInfo.RoomInfoBase)
- ts.table.SendGameData(userIndex, CMD_ROOMINFO, string(d))
- ts.table.SetTimer(TIMER_READY_0+chairId, SEC_READY)
- //有玩家进桌, 更新在线
- go func() {
- frame.UpdateRoomOnline(ts.roomInfo.RoomName, ts.roomInfo.RoomID-1)
- }()
- ts.gameScene.Players[chairId].isEndToStart = false
- ts.gameScene.Players[chairId].userID = usr.GetUserId()
- if usr.IsRobot() {
- ts.table.SetTimer(TIMER_READY_0+chairId, 100)
- }
- // 如果比赛场,可以查询玩家当前分数、底分和局数
- if ts.table.GetOwner() == -1 {
- ts.table.LogWithTableId("userScore:%d,baseScore:%d,setCount:%d", usr.GetScore(), usr.GetBaseScore(), usr.GetSetCount())
- ts.gameScene.Players[chairId].MatchScore = usr.GetScore()
- ts.gameScene.Players[chairId].IsValid = true
- }
- if config.Server.IsLadderRoom > 0 {
- data := ladder.GetUserLadderInfo(usr.GetUserId(), GAMEID)
- if data != nil {
- ts.gameScene.Players[chairId].LadderInfo = *data
- ts.gameScene.Players[chairId].LastWinCount = ladder.GetUserConsecutiveWinCount(usr.GetUserId(), GAMEID)
- info := ts.gameScene.getPlayerLadderInfo()
- ts.table.SendGameData(-1, CMD_LADDERINFO, info)
- } else {
- ts.table.LogWithTableId("User:%d, LadderInfo is nil", usr.GetUserId())
- }
- }
- if !usr.IsRobot() && ts.table.GetOwner() <= 0 {
- ts.table.NotifySceneChanged(chairId)
- }
- if usr.IsRobot() {
- ts.gameScene.Players[chairId].robotType = rand.Intn(3)
- friendId := ts.gameScene.Players[getFriendChair(chairId)].userID
- if friendId != 0 {
- friend := ts.table.GetPlayerByUserId(friendId)
- if friend != nil {
- ts.gameScene.Players[chairId].robotType = ts.gameScene.Players[getFriendChair(chairId)].robotType
- }
- }
- ts.gameScene.Players[chairId].robotActionProb = 100 - 50*ts.gameScene.Players[chairId].robotType
- ts.gameScene.Players[chairId].robotType = RobotType_Cautious
- ts.gameScene.Players[chairId].robotActionProb = 100
- }
- }
- func (ts *tablesink) OnUserExitTable(userIndex int32, chairId int) {
- usr := ts.table.GetUserByChair(chairId)
- if usr == nil {
- ts.table.LogWithTableId("tablesink.OnUserExitTable user not exist")
- return
- }
- ts.table.LogWithTableId("tablesink.OnUserExitTable chair[%d]: %d:%s", chairId, usr.GetUserId(), usr.GetUserNickName())
- ts.gameScene.Players[chairId].isEndToStart = false
- //有玩家离开, 更新在线
- 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 && !usr.IsRobot() {
- ts.table.SetTimer(TIMER_ADD_ROBOT, 500)
- }
- go ts.checkAndStartGame()
- } else {
- // 没有参与游戏?
- p := &ts.gameScene.Players[chairId]
- if !p.IsValid {
- return
- }
- if ts.table.IsPrivate() {
- return
- }
- //游戏中离开,逃跑
- p.IsValid = false
- ts.writeScore(p.userID, p.EndScore, 0, 0, ScoreType_Flee, ts.roomInfo.RoomName, p.isRobot)
- go ts.table.WriteBetRecordWithSetcount(usr.GetUserId(), ts.gameScene.Players[chairId].bet, 0, 1.0, "fleeGold", "flee", ts.roomInfo.RoomName, 1)
- for i := 0; i < CHAIR_COUNT; i++ {
- p := &ts.gameScene.Players[i]
- if !p.IsValid {
- continue
- }
- p.EndScore = p.bet
- ts.writeScore(p.userID, p.bet, 0, 0, ScoreType_Return, ts.roomInfo.RoomName, p.isRobot)
- }
- ts.gameScene.Phase = Phase_End
- ts.endGame()
- ts.table.NotifySceneChanged(-1)
- ts.uniqueId = uuid.New().String()
- ts.gameScene.initData(ts.table.GetTableID(), ts.roomInfo.ScoreToWin, ts.roomInfo.MaxSurrenderCount)
- }
- }
- 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
- if ts.surrenderInfo.canDoSurrender(chairId) {
- userIndex := ts.table.GetUserByChair(chairId).GetUserIndex()
- ts.table.SendGameData(userIndex, CMD_SURRENDER_RESULT, ts.surrenderInfo.getSurrenderInfo())
- }
- }
- 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 金币不足,站起", usr.GetUserId())
- if usr.IsRobot() {
- ts.table.KickUser(usr.GetUserIndex(), false)
- } else {
- ts.table.UserWatch(usr.GetUserIndex())
- }
- 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_GameEnd || ts.gameScene.Players[chairId].isEndToStart {
- ts.table.SetTimer(TIMER_ADD_ROBOT, 500)
- }
- if !usr.IsRobot() && ts.gameScene.Players[chairId].isEndToStart {
- if config.Server.IsLadderRoom > 0 {
- data := ladder.GetUserLadderInfo(usr.GetUserId(), GAMEID)
- if data != nil {
- ts.gameScene.Players[chairId].LadderInfo = *data
- info := ts.gameScene.getPlayerLadderInfo()
- ts.table.SendGameData(-1, CMD_LADDERINFO, info)
- } else {
- ts.table.LogWithTableId("User:%d, LadderInfo is nil", usr.GetUserId())
- }
- }
- 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) OnGetPrivateRoomScene(chairId int) string {
- now := time.Now()
- ts.gameScene.LeftSec = ts.getSecond(ts.gameScene.Phase)/1000 - int(now.Sub(ts.LastOpraTime).Seconds())
- str := ts.gameScene.getScene(chairId, true, true)
- return str
- }
- 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_GAME:
- ts.dealGameTimeOut()
- case TIMER_REMOVE_ROBOT:
- ts.removeOneRobot()
- case TIMER_ADD_ROBOT:
- ts.checkIsNeedRobot()
- case TIMER_SEND_LEFT_CARD:
- ts.sendLeftCard()
- case TIMER_START_OUT_CARD:
- ts.onPlayerFirstOutCard()
- case TIMER_NEWROUND:
- ts.onTimerNewRound()
- case TIMER_ROBOT_ACTION_0:
- fallthrough
- case TIMER_ROBOT_ACTION_1:
- fallthrough
- case TIMER_ROBOT_ACTION_2:
- fallthrough
- case TIMER_ROBOT_ACTION_3:
- ts.onTimerRobotAction(timerId - TIMER_ROBOT_ACTION_0)
- case TIMER_AUTO_ACTION_0:
- fallthrough
- case TIMER_AUTO_ACTION_1:
- fallthrough
- case TIMER_AUTO_ACTION_2:
- fallthrough
- case TIMER_AUTO_ACTION_3:
- ts.onTimerAutoAction(timerId - TIMER_AUTO_ACTION_0)
- case TIMER_ALL_PASS:
- ts.onTimerBuyFailed()
- case TIMER_BUY_CHANGE:
- ts.gameScene.Index++
- ts.table.NotifySceneChanged(-1)
- case TIMER_DOUBLE_CHANGE:
- ts.gameScene.initAllPlayerLastAction()
- ts.gameScene.Index++
- ts.table.NotifySceneChanged(-1)
- ts.resetGameTimer()
- case TIMER_DELAY_END:
- ts.table.EndGame()
- case TIMER_START_GAME:
- ts.checkStartGame()
- case TIMER_SAWA:
- ts.onTimerSawa()
- case TIMER_CORRECTFINISH:
- ts.onTimerCorrectFinish()
- case TIMER_CORRECTDELAY:
- // 轮次结束也要清理收牌信息
- ts.gameScene.newOutCardRound()
- // 进入SetEnd阶段
- ts.enterGameEndPhase(true)
- case TIMER_SURRENDER:
- index := ts.table.GetUserByChair(getFriendChair(ts.surrenderInfo.WhoseSurrender)).GetUserIndex()
- data := Surrender_Failed
- ts.recvSurrenderResult(index, fmt.Sprintf("%d", data))
- case TIMER_ROBOT_SURRENDER:
- index := ts.table.GetUserByChair(getFriendChair(ts.surrenderInfo.WhoseSurrender)).GetUserIndex()
- data := Surrender_Success
- ts.recvSurrenderResult(index, fmt.Sprintf("%d", data))
- case TIMER_ROBOT_REPLY:
- start := rand.Intn(4)
- for i := 0; i < CHAIR_COUNT; i++ {
- c := (start + i) % CHAIR_COUNT
- r := rand.Intn(100)
- if r <= 60 && ts.gameScene.Players[c].isRobot {
- ts.sendRobotChatAction(RobotChatAction_Reply, ts.gameScene.Players[c].userID, -1, 0)
- break
- }
- }
- case TIMER_ROBOT_SEND_CHAT_0:
- fallthrough
- case TIMER_ROBOT_SEND_CHAT_1:
- fallthrough
- case TIMER_ROBOT_SEND_CHAT_2:
- fallthrough
- case TIMER_ROBOT_SEND_CHAT_3:
- chairId := timerId - TIMER_ROBOT_SEND_CHAT_0
- if ts.gameScene.Players[chairId].outTimeCount >= 2 {
- return
- }
- if ts.gameScene.WhoseTurn == chairId {
- start := rand.Intn(4)
- for i := 0; i < CHAIR_COUNT; i++ {
- c := (start + i) % CHAIR_COUNT
- if c == chairId {
- continue
- }
- if ts.gameScene.Players[c].isRobot {
- if ts.gameScene.Players[chairId].outTimeCount == 1 {
- ts.sendRobotChatAction(RobotChatAction_MuiltyTimeOut, ts.gameScene.Players[c].userID, ts.gameScene.Players[chairId].userID, 0)
- }
- break
- }
- }
- ts.gameScene.Players[chairId].outTimeCount++
- }
- }
- }
- func (ts *tablesink) checkStartGame() {
- if !ts.canStartGame(false) {
- if ts.table.GetOwner() <= 0 {
- ts.table.NotifySceneChanged(-1)
- }
- return
- }
- start := rand.Intn(4)
- for i := 0; i < CHAIR_COUNT; i++ {
- c := (start + i) % CHAIR_COUNT
- r := rand.Intn(100)
- if r <= 30 && ts.gameScene.Players[c].isRobot {
- ts.sendRobotChatAction(RobotChatAction_EnterRoom, ts.gameScene.Players[c].userID, -1, 0)
- ts.table.SetTimer(TIMER_ROBOT_REPLY, 1500)
- break
- }
- }
- ts.gameScene.setNextBanker()
- ts.gameScene.gameInit(getPreviousChair(ts.gameScene.Banker))
- controlType := ts.checkNeedControlPlayer()
- if controlType <= waterpool.PoolControl_Normal {
- ts.checkNeedControlRobot()
- }
- if !ts.table.IsPrivate() {
- ts.gameScene.initMaxDoubling(ts.roomInfo.IsDoublingMode)
- }
- if ts.roomInfo.RoomID == 0 && !ts.table.IsPrivate() {
- for i := 0; i < CHAIR_COUNT; i++ {
- usr := ts.table.GetUserByChair(i)
- if usr == nil {
- continue
- }
- if !usr.IsRobot() {
- ts.gameScene.Banker = getNextChair(i)
- ts.gameScene.WhoseTurn = i
- ts.gameScene.FirstActionChair = i
- break
- }
- }
- }
- ts.gameStart()
- ts.table.StartGame()
- if ts.roomInfo.IsDoublingMode {
- if getCardValue(ts.gameScene.PublicCard) == CardValueJ {
- ts.addDoublingData(Doubling_PublicCard_J)
- ts.sendShowDoublingMsg([]int{Doubling_PublicCard_J})
- }
- }
- ts.table.LogWithTableId("tablesink.startGame[%d]", ts.table.GetTableID())
- }
- func (ts *tablesink) DumpScene() {
- ts.gameScene.dump(true)
- }
- func (ts *tablesink) GetGoldLimit() (min, max int) {
- return ts.roomInfo.MinGold, ts.roomInfo.MaxGold
- }
- func (ts *tablesink) IsDual() bool {
- return ts.roomInfo.IsDual > 0
- }
- func (ts *tablesink) OnBaseScoreChanged(baseScore int) {
- ts.roomInfo.BaseScore = baseScore
- d, _ := json.Marshal(ts.roomInfo.RoomInfoBase)
- ts.table.SendGameData(-1, CMD_ROOMINFO, string(d))
- }
- func (ts *tablesink) SetPrivateRoomParam(param int, value string) {
- ts.table.LogWithTableId("tablesink.SetPrivateRoomParam %d:%s", param, value)
- switch param {
- case frame.Param_Target:
- t, err := strconv.Atoi(value)
- if err == nil {
- ts.roomInfo.ScoreToWin = t
- ts.uniqueId = uuid.New().String()
- ts.gameScene.initData(ts.table.GetTableID(), ts.roomInfo.ScoreToWin, ts.roomInfo.MaxSurrenderCount)
- }
- case frame.Param_PlayTimeout:
- t, err := strconv.Atoi(value)
- if err == nil {
- ts.roomInfo.SecPlay = t
- }
- }
- }
- func (ts *tablesink) OnPrivateRoomStatusChanged(oldStatus, newStatus int) {
- ts.table.LogWithTableId("OnPrivateRoomStatusChanged %d->%d", oldStatus, newStatus)
- ts.roomType = ts.table.PrivateRoomGetRoomType()
- ts.table.LogWithTableId("tablesink.OnPrivateRoomStatusChanged roomType:%s", ts.roomType)
- }
- func (ts *tablesink) OnPrivateRoomDismissed() {
- ts.table.LogWithTableId("OnPrivateRoomDismissed ")
- }
- func (ts *tablesink) IsAllRobot() bool {
- bExist := false
- for i := 0; i < CHAIR_COUNT; i++ {
- usr := ts.table.GetUserByChair(i)
- if usr == nil {
- continue
- }
- bExist = true
- if !usr.IsRobot() {
- return false
- }
- }
- return bExist
- }
|