| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630 |
- package gamelogic
- import (
- "encoding/json"
- "time"
- "bet24.com/log"
- "bet24.com/redis"
- "bet24.com/servers/games/fish/bullet"
- "bet24.com/servers/games/fish/config"
- "bet24.com/servers/games/fish/fish"
- "bet24.com/servers/games/fish/fishcommon"
- "bet24.com/servers/games/fish/prizepool"
- "bet24.com/servers/insecureframe/frame"
- item "bet24.com/servers/micros/item_inventory/proto"
- waterpool "bet24.com/servers/micros/waterpool/proto"
- "bet24.com/servers/user"
- )
- const room_seconds = 300
- type effecting struct {
- startTime int
- effectType int
- endTime int
- }
- func (e *effecting) expired() bool {
- if e.endTime == 0 {
- return false
- }
- return int(time.Now().Unix()) > e.endTime
- }
- type tablesink struct {
- table frame.Table
- privateData string
- roomInfo config.RoomInfo
- Users []*fishuser // 每个位置上的玩家
- fishmgr *fish_manager
- bulletmgr *bullet_manager
- stopped bool // 当人员离开后,下次定时器处理则可以停了
- groupState bool //是否鱼群来了
- recordmgr *RecordManager
- fishGroup *fish.FishGroup
- fishDrop *room_fish_drop
- groupTime int
- endTime int
- systemOdds int
- firstFishLog bool
- effecting []*effecting // 全局效果中
- prizePool *prizepool.PrizePool
- broadcastPoolValue bool
- newbieExtra *newbie_extra
- }
- func newTableSink(table frame.Table, data string) *tablesink {
- ts := new(tablesink)
- ts.table = table
- ts.privateData = data
- 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]
- }
- }
- ts.Users = make([]*fishuser, fishcommon.SEAT_COUNT)
- ts.fishmgr = newFishManager(ts.roomInfo.RoomName)
- ts.bulletmgr = newBulletManager()
- ts.fishDrop = newRoomFishDrop(ts.roomInfo.RoomName)
- ts.groupState = false
- ts.prizePool = prizepool.GetPrizePool(ts.roomInfo.RoomName, ts.roomInfo.BulletMin)
- ts.broadcastPoolValue = true
- ts.newbieExtra = newNewbieExtra(ts.roomInfo.RoomName)
- ts.table.SetTimer(fishcommon.TIMER_WRITESCORE, fishcommon.TIME_WRITESCORE)
- ts.table.SetTimer(fishcommon.TIMER_UPDATAWATERPOOL, fishcommon.TIME_UPDATAWATERPOOL)
- ts.start(true)
- return ts
- }
- func (ts *tablesink) start(byCreate bool) {
- ts.table.LogWithTableId("tablesink.start %d", ts.table.GetTableID())
- ts.fishmgr.clear(byCreate)
- ts.systemOdds = redis.String_GetInt("fish:sysodds")
- ts.table.LogWithTableId("tablesink.start systemOdds = %d", ts.systemOdds)
- ts.groupState = false
- ts.stopped = false
- ts.recordmgr = newRecordManager(ts.roomInfo.RoomName, ts.table.GetTableID(), ts.table)
- ts.fishGroup = fish.NewFishGroup(ts.roomInfo.GetGroup())
- totalSec := room_seconds
- if ts.roomInfo.RoomSecond > 0 {
- totalSec = ts.roomInfo.RoomSecond
- }
- ts.firstFishLog = true
- ts.effecting = nil
- for i := 0; i < fishcommon.SEAT_COUNT; i++ {
- if ts.Users[i] == nil {
- continue
- }
- ts.Users[i].clearSpecial()
- }
- startTime := int(time.Now().Unix())
- if byCreate {
- startTime -= fishcommon.CREATE_FORWARD_SECONDES
- }
- ts.broadcastScene()
- ts.endTime = startTime + totalSec
- if ts.fishGroup != nil {
- // time.AfterFunc(time.Duration(totalSec*1000-ts.fishGroup.Duration)*time.Millisecond, ts.groupCome)
- ts.groupTime = ts.endTime - ts.fishGroup.Duration/1000
- } else {
- ts.groupTime = 9999999999
- }
- ts.table.LogWithTableId("tablesink.start() now = %d,startTime = %d,groupTime = %d", time.Now().Unix(), startTime, ts.groupTime)
- // 启动定时器,产生鱼群
- ts.loop100ms()
- ts.loop1s()
- ts.loop5s()
- //time.AfterFunc(time.Duration(totalSec)*time.Second, ts.end)
- ts.table.StartGame()
- }
- func (ts *tablesink) groupCome() {
- if ts.fishGroup == nil {
- return
- }
- ts.table.LogWithTableId("tablesink.groupCome fishKey = %d", ts.fishmgr.fishkey)
- ts.fishGroup.FishKey = ts.fishmgr.fishkey
- ts.groupState = true
- ts.groupTime = int(time.Now().Unix())
- // 产生鱼群并下发
- for _, v := range ts.fishGroup.Fishes {
- for i := 0; i < v.Count; i++ {
- ts.fishmgr.addFish(v.FishID, i*v.Delay+v.GroupDelay)
- }
- }
- ts.sendGroup(-1, true)
- }
- func (ts *tablesink) end() {
- ts.table.LogWithTableId("tablesink.end")
- if ts.clearEffecting() {
- ts.broadcastEffecting()
- }
- ts.stopped = true
- // 清理数据
- // ...
- if ts.roomInfo.Demo == 0 {
- ts.recordmgr.dumpRecord()
- ts.recordmgr.flush()
- }
- // 如果还有人
- userCount := 0
- for i := 0; i < fishcommon.SEAT_COUNT; i++ {
- if ts.Users[i] == nil {
- continue
- }
- if ts.table.GetPlayerByUserId(ts.Users[i].userId) == nil {
- ts.Users[i] = nil
- continue
- }
- userCount++
- }
- ts.table.EndGame()
- if userCount > 0 {
- time.AfterFunc(2*time.Second, func() {
- ts.start(false)
- })
- } else {
- ts.table.CloseTable()
- }
- }
- // 主循环
- func (ts *tablesink) loop100ms() {
- if ts.stopped {
- ts.table.LogWithTableId("tablesink.loop100ms stopping %d", ts.table.GetTableID())
- return
- }
- // 如果鱼群来了,则不产生鱼了
- ts.checkFish()
- time.AfterFunc(100*time.Millisecond, ts.loop100ms)
- }
- func (ts *tablesink) loop1s() {
- if ts.stopped {
- ts.table.LogWithTableId("tablesink.loop1s stopping %d", ts.table.GetTableID())
- return
- }
- now := int(time.Now().Unix())
- if now >= ts.endTime {
- ts.end()
- return
- }
- if now >= ts.groupTime && !ts.groupState {
- ts.groupCome()
- }
- time.AfterFunc(time.Second, ts.loop1s)
- if ts.checkEffecting() {
- ts.broadcastEffecting()
- }
- if ts.broadcastPoolValue {
- ts.broadcastPoolValue = false
- ts.broadcastPool()
- }
- }
- func (ts *tablesink) loop5s() {
- if ts.stopped {
- ts.table.LogWithTableId("tablesink.loop5s stopping %d", ts.table.GetTableID())
- return
- }
- // 如果鱼群来了,则不产生鱼了
- time.AfterFunc(5*time.Second, ts.loop5s)
- ts.checkIdle()
- }
- func (ts *tablesink) Destroy() {
- ts.table.LogWithTableId("------tablesink:Destroy-------")
- //close(ts.stopChan)
- }
- func (ts *tablesink) OnUserEnterTable(userIndex int32, chairId int) {
- u, _ := ts.table.GetUser(userIndex)
- if u == nil {
- ts.table.LogWithTableId("tablesink.OnUserEnterTable %d not exist", userIndex)
- return
- }
- ts.newbieExtra.onUserEnter(u.GetUserId())
- ts.Users[chairId] = newFishUser(u.GetUserId(), ts.roomInfo.BulletMin, ts.roomInfo.BulletMax, ts.newbieExtra)
- ts.sendConfig(userIndex)
- // 处理炮台相关
- // ...
- ts.broadCastUserInfo(u)
- gameScene := ts.getChairScene()
- ts.table.SendGameData(userIndex, fishcommon.GAME_SCENE, gameScene)
- // 如果鱼群来了
- if ts.groupState {
- ts.sendGroup(userIndex, false)
- }
- }
- func (ts *tablesink) OnUserExitTable(userIndex int32, chairId int) {
- u, _ := ts.table.GetUser(userIndex)
- if u == nil {
- ts.table.LogWithTableId("tablesink.OnUserExitTable %d not exist", userIndex)
- return
- }
- fUser := ts.getRoomUser(u.GetUserId())
- if fUser != nil {
- ts.doWriteUserGold(fUser)
- value, bet := fUser.getWaterPoolValueAndClear()
- if fUser.isInControl() {
- go waterpool.UpdataUserWaterPool(u.GetUserId(), value, fishcommon.GAME_NAME, waterpool.RoomType_Normal, ts.roomInfo.RoomID)
- } else {
- go waterpool.AddBet(u.GetUserGold(), bet, false, fishcommon.GAMEID, ts.roomInfo.RoomName)
- go waterpool.ReducePool(u.GetUserGold(), value+bet, false, fishcommon.GAMEID, ts.roomInfo.RoomName)
- }
- }
- ts.newbieExtra.onUserExit(u.GetUserId())
- ts.Users[chairId] = nil
- }
- func (ts *tablesink) OnUserOffline(chairId int) {
- }
- func (ts *tablesink) OnUserReplay(chairId int) {
- }
- func (ts *tablesink) OnUserReady(userIndex int32, chairId int) {
- }
- func (ts *tablesink) OnUserCancelReady(userIndex int32, chairId int) {
- }
- func (ts *tablesink) getChairScene() string {
- var gameScene fishcommon.GameScene
- gameScene.RoomID = ts.table.GetTableID()
- gameScene.BossAfter = ts.getBossAfter()
- gameScene.Effecting = ts.getEffecting()
- // user
- gameScene.Users = make([]fishcommon.GameScene_User, fishcommon.SEAT_COUNT)
- for i := 0; i < fishcommon.SEAT_COUNT; i++ {
- if ts.Users[i] == nil {
- gameScene.Users[i].UserId = -1
- } else {
- gameScene.Users[i].UserId = ts.Users[i].userId
- gameScene.Users[i].CannonId = ts.Users[i].CannonId
- gameScene.Users[i].Bullet = ts.Users[i].BulletId
- }
- }
- // fish
- if !ts.groupState {
- gameScene.Fishes = ts.fishmgr.fish_list
- for _, v := range gameScene.Fishes {
- v.Age = v.GetAge()
- }
- }
- d, _ := json.Marshal(gameScene)
- return string(d)
- }
- func (ts *tablesink) OnGetChairScene(chairId int, isPlayer bool) string {
- return ""
- }
- func (ts *tablesink) OnGetPrivateRoomScene(chairId int) string {
- return ts.OnGetChairScene(chairId, true)
- }
- func (ts *tablesink) OnGetChairCount() int {
- return fishcommon.SEAT_COUNT
- }
- func (ts *tablesink) OnTimer(timerId int) {
- switch timerId {
- case fishcommon.TIMER_WRITESCORE:
- ts.onTimerWriteScore()
- case fishcommon.TIMER_UPDATAWATERPOOL:
- ts.updataUserExtraOdds()
- default:
- ts.table.LogWithTableId("tablesink.OnTimer unhandled timer[%d]", timerId)
- }
- }
- func (ts *tablesink) DumpScene() {
- log.Release(ts.getChairScene())
- }
- func (ts *tablesink) GetGoldLimit() (min, max int) {
- return ts.roomInfo.RoomMin, ts.roomInfo.RoomMax
- }
- func (ts *tablesink) IsDual() bool {
- return false
- }
- func (ts *tablesink) OnBaseScoreChanged(baseScore int) {
- }
- func (ts *tablesink) SetPrivateRoomParam(param int, value string) {
- ts.table.LogWithTableId("tablesink.SetPrivateRoomParam %d:%s", param, value)
- }
- func (ts *tablesink) OnPrivateRoomStatusChanged(oldStatus, newStatus int) {
- ts.table.LogWithTableId("OnPrivateRoomStatusChanged %d->%d", oldStatus, newStatus)
- }
- func (ts *tablesink) OnPrivateRoomDismissed() {
- ts.table.LogWithTableId("OnPrivateRoomDismissed ")
- }
- func (ts *tablesink) getBossAfter() int {
- return ts.fishmgr.getBossAfter()
- }
- func (ts *tablesink) getEffecting() []int {
- var ret []int
- for _, v := range ts.effecting {
- ret = append(ret, v.effectType)
- }
- return ret
- }
- func (ts *tablesink) broadCastUserInfo(usr *user.UserInfo) {
- msg := fishcommon.UPDATE_USER_INFO
- userInfo := ts.getRoomUser(usr.GetUserId())
- if userInfo == nil {
- return
- }
- var data fishcommon.UpdateUserInfo
- data.UserId = usr.GetUserId()
- data.Gold = usr.GetUserGold()
- data.BulletID = userInfo.BulletId
- data.Cannon = userInfo.CannonId
- data.Essence = userInfo.Essence
- d, _ := json.Marshal(data)
- ts.broadcastData(msg, string(d))
- }
- func (ts *tablesink) broadCastUseItem(useItem fishcommon.UseItem) {
- msg := fishcommon.USE_ITEM
- d, _ := json.Marshal(useItem)
- ts.broadcastData(msg, string(d))
- }
- func (ts *tablesink) sendGroup(userIndex int32, locked bool) {
- msg := fishcommon.GROUP_COME
- now := int(time.Now().Unix())
- passMs := (now - ts.groupTime) * 1000
- for i := 0; i < len(ts.effecting); i++ {
- if ts.effecting[i].effectType == item.SpecialEffect_Frozen {
- passMs = (ts.effecting[i].startTime - ts.groupTime) * 1000
- }
- }
- data := ts.fishGroup.GetJson(passMs)
- ts.table.SendGameData(userIndex, msg, data)
- }
- func (ts *tablesink) BroadcastUserInfo(userID int) {
- usr := ts.table.GetPlayerByUserId(userID)
- if usr != nil {
- ts.broadCastUserInfo(usr)
- }
- }
- func (ts *tablesink) broadcastScene() {
- msg := fishcommon.GAME_SCENE
- gameScene := ts.getChairScene()
- ts.broadcastData(msg, gameScene)
- }
- func (ts *tablesink) broadcastEffecting() {
- msg := fishcommon.EFFECTING
- d, _ := json.Marshal(ts.getEffecting())
- ts.broadcastData(msg, string(d))
- }
- func (ts *tablesink) isFrozening() bool {
- for i := 0; i < len(ts.effecting); i++ {
- if ts.effecting[i].effectType == item.SpecialEffect_Frozen {
- return true
- }
- }
- return false
- }
- func (ts *tablesink) addEffecting(effectType int, duration int) {
- if duration == 0 {
- return
- }
- now := int(time.Now().Unix())
- deltaTime := duration
- defer func(dt int) {
- if effectType == item.SpecialEffect_Frozen && !ts.groupState {
- ts.groupTime += dt
- ts.endTime += dt
- ts.fishmgr.pauseForFrozen(int64(dt))
- }
- ts.broadcastEffecting()
- }(deltaTime)
- for _, v := range ts.effecting {
- if v.effectType == effectType {
- deltaTime = duration - (v.endTime - now)
- v.endTime = now + duration
- return
- }
- }
- ts.effecting = append(ts.effecting, &effecting{effectType: effectType, startTime: now, endTime: now + duration})
- }
- func (ts *tablesink) checkEffecting() bool {
- ret := false
- for i := 0; i < len(ts.effecting); i++ {
- if ts.effecting[i].expired() {
- ts.effecting = append(ts.effecting[:i], ts.effecting[i+1:]...)
- ret = true
- }
- }
- return ret
- }
- func (ts *tablesink) clearEffecting() bool {
- if len(ts.effecting) > 0 {
- ts.effecting = nil
- return true
- } else {
- return false
- }
- }
- func (ts *tablesink) sendPoolEnergy(userId int) {
- if ts.prizePool == nil {
- return
- }
- u := ts.table.GetPlayerByUserId(userId)
- if u == nil {
- return
- }
- var poolEnergy struct {
- Energy int
- FullEnergy int
- }
- poolEnergy.Energy = ts.prizePool.GetUserEnergy(userId)
- poolEnergy.FullEnergy = ts.prizePool.FullEnergy
- d, _ := json.Marshal(poolEnergy)
- go ts.table.SendGameData(u.GetUserIndex(), fishcommon.POOL_ENERGY, string(d))
- }
- func (ts *tablesink) checkFish() {
- // 如果当前处于冰冻期,则不检查生成
- if ts.isFrozening() {
- return
- }
- fishes := ts.fishmgr.generateFish(ts.groupState)
- for _, fish := range fishes {
- if ts.firstFishLog {
- ts.firstFishLog = false
- ts.table.LogWithTableId("first fish generateFish %d", fish.FishID)
- }
- fish.Age = fish.GetAge()
- msg := fishcommon.ADD_FISH
- d, _ := json.Marshal(fish)
- data := string(d)
- ts.broadcastData(msg, data)
- }
- }
- func (ts *tablesink) checkIdle() {
- var idleUserIds []int
- for i := 0; i < fishcommon.SEAT_COUNT; i++ {
- if ts.Users[i] == nil {
- continue
- }
- if ts.Users[i].isIdled() {
- idleUserIds = append(idleUserIds, i)
- }
- }
- for _, v := range idleUserIds {
- ts.table.LogWithTableId("tablesink.checkIdle removing user chair[%d]", v)
- ts.table.KickUserByChair(v, true)
- }
- }
- // 额外概率后续根据需求做修改,先给一个值做测试
- func (ts *tablesink) updataUserExtraOdds() {
- ts.table.SetTimer(fishcommon.TIMER_UPDATAWATERPOOL, fishcommon.TIME_UPDATAWATERPOOL)
- go ts.doUpdateUserExtraOddsOdds()
- }
- func (ts *tablesink) doUpdateUserExtraOddsOdds() {
- for i := 0; i < fishcommon.SEAT_COUNT; i++ {
- if ts.Users[i] == nil {
- continue
- }
- u := ts.table.GetUserByUserId(ts.Users[i].userId)
- if u == nil {
- continue
- }
- bulletInfo := bullet.GetBullet(ts.Users[i].getBulletId())
- if bulletInfo == nil {
- ts.table.LogWithTableId("bulletInfo is nil")
- continue
- }
- value, bet := ts.Users[i].getWaterPoolValueAndClear()
- if ts.Users[i].isInControl() {
- waterpool.UpdataUserWaterPool(u.GetUserId(), value, fishcommon.GAME_NAME, waterpool.RoomType_Normal, ts.roomInfo.RoomID)
- } else {
- waterpool.AddBet(u.GetUserGold(), bet, false, fishcommon.GAMEID, ts.roomInfo.RoomName)
- waterpool.ReducePool(u.GetUserGold(), value+bet, false, fishcommon.GAMEID, ts.roomInfo.RoomName)
- }
- poolType, usrOdds := waterpool.GetUserPoolType(u.GetUserId(), fishcommon.GAMEID, waterpool.GameType_Normal, ts.roomInfo.RoomMin,
- u.GetUserGold(), false, bulletInfo.Odds)
- ts.table.LogWithTableId("userId:%d, poolType:%d, userodds:%d", u.GetUserId(), poolType, usrOdds)
- if poolType != waterpool.PoolControl_Normal {
- ts.Users[i].setUserExtraOdd(usrOdds, true)
- } else {
- waterType, sysOdds := waterpool.GetControlProb(u.GetUserGold(), false, fishcommon.GAMEID, ts.roomInfo.RoomName)
- ts.table.LogWithTableId("userId:%d, waterType:%d, sysodds:%d", u.GetUserId(), waterType, sysOdds)
- if waterType == waterpool.PoolControl_Normal {
- ts.Users[i].setUserExtraOdd(0, false)
- } else {
- ts.Users[i].setUserExtraOdd(sysOdds, false)
- }
- }
- }
- }
- func (ts *tablesink) IsAllRobot() bool {
- return false
- }
|