印度包网
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

438 lines
10 KiB

package game
import (
"container/list"
"errors"
"fmt"
"math"
"reflect"
"server/call"
"server/common"
"server/pb"
"sync"
"github.com/liangdas/mqant-modules/room"
"github.com/liangdas/mqant/gate"
"github.com/liangdas/mqant/log"
"github.com/liangdas/mqant/module"
)
var (
RoomMap sync.Map
tableIndex uint = 1
)
const (
RoomTypeCash = iota + 1
RoomTypePractice
)
const (
GameTypeRoom = iota + 1 // 房间模式
GameTypeMillion // 百人场
)
type GameRoom struct {
Config *common.ConfigGameRoom
NewSubTable func() SubTable
Queue *call.ExecQueue
SubAdd func(t *Table)
SubMine func(t *Table)
*room.Room
PlayerCount *int64
Cards []int
TableList []*TableList
TableListPlaying []*TableList
TableListSingle *TableList // 单独匹配的房间,玩家与机器人游戏
RoomType int // 练习场/cash场
RoomName string
Tables sync.Map
}
type TableList struct {
*list.List
Index int
}
func GetRoom(id int) *GameRoom {
r, ok := RoomMap.Load(id)
if !ok {
return nil
}
return r.(*GameRoom)
}
func NewRoom(c *common.ConfigGameRoom) *GameRoom {
app := call.GetCaller().GetApp()
roomID := c.RoomID
roomType := c.RoomType
roomName := c.RoomName
// max := c.MaxPlayer
r := &GameRoom{
Room: room.NewRoom(app),
Config: c,
PlayerCount: new(int64),
NewSubTable: NewTable,
RoomType: roomType,
Queue: call.NewQueue(),
RoomName: roomName,
}
r.OnInit(app, roomID)
// r.GetMatchConfig()
// r.GetBroadcastConfig()
// r.GetWaterConfig()
// if ThisGameType == GameTypeRoom {
// for i := 0; i < max; i++ {
// list := list.New()
// r.TableList = append(r.TableList, &TableList{List: list, Index: i})
// }
// for i := 0; i < max; i++ {
// list := list.New()
// r.TableListPlaying = append(r.TableListPlaying, &TableList{List: list, Index: i})
// }
// } else if ThisGameType == GameTypeMillion {
r.TableList = append(r.TableList, &TableList{List: list.New(), Index: 0})
// }
r.TableListSingle = &TableList{List: list.New()}
RoomMap.Store(roomID, r)
return r
}
func (r *GameRoom) Reload(c *common.ConfigGameRoom) {
// 标识桌子配置有改动
r.Queue.AddQueue(func() {
r.Config = c
// r.GetMatchConfig()
// r.GetBroadcastConfig()
// if r.GameType == common.GameTypeRoom {
// l := len(r.TableList)
// diff := c.MaxPlayer - l
// if diff > 0 {
// for i := 0; i < diff; i++ {
// list := list.New()
// r.TableList = append(r.TableList, &TableList{List: list, Index: i + l})
// }
// for i := 0; i < diff; i++ {
// list := list.New()
// r.TableListPlaying = append(r.TableListPlaying, &TableList{List: list, Index: i + l})
// }
// } else if diff < 0 {
// if c.MaxPlayer == 0 {
// r.TableList = nil
// r.TableListPlaying = nil
// } else {
// r.TableList = r.TableList[:l+diff]
// r.TableListPlaying = r.TableListPlaying[:l+diff]
// }
// }
// }
r.Tables.Range(func(key, value interface{}) bool {
t := value.(*Table)
t.ChangeConfig()
return true
})
})
}
func (r *GameRoom) GetTableID() string {
if tableIndex > math.MaxUint32 {
tableIndex = 2
}
t := tableIndex
tableIndex++
return fmt.Sprintf("%v", t)
}
func (r *GameRoom) Enter(uid int, session gate.Session, ct common.CurrencyType, tid ...int) {
// 顺序进入游戏
r.Queue.AddQueue(func() {
var err error
if ThisGameType == GameTypeMillion {
err = r.MatchMillionTable(uid, session, ct)
}
// else {
// err = r.Match(uid, tid...)
// }
if err != nil {
call.SendNR(uid, int(pb.GameProtocol_EnterGameResp), &pb.GameCommonResp{Result: 1})
}
})
}
func (r *GameRoom) NewTable(module module.App, tableId string) (room.BaseTable, error) {
t := &Table{
app: module,
Room: r,
Players: map[string]room.BasePlayer{},
Config: *r.Config,
}
opts := []room.Option{
room.TableId(tableId),
room.DestroyCallbacks(func(table room.BaseTable) error {
log.Info("回收了房间: %v", table.TableId())
_ = r.DestroyTable(table.TableId())
return nil
}),
}
opts = append(opts, room.TimeOut(1200))
if ThisGameType == GameTypeMillion {
opts = append(opts, room.Capaciity(2000))
opts = append(opts, room.SendMsgCapaciity(2000))
}
opts = append(opts, room.Update(t.Update))
opts = append(opts, room.NoFound(func(msg *room.QueueMsg) (value reflect.Value, e error) {
//return reflect.ValueOf(t.doSay), nil
return reflect.Zero(reflect.ValueOf("").Type()), errors.New("no found handler")
}))
opts = append(opts, room.SetRecoverHandle(func(msg *room.QueueMsg, err error) {
log.Error("Recover %v Error: %v", msg.Func, err.Error())
}))
opts = append(opts, room.SetErrorHandle(func(msg *room.QueueMsg, err error) {
log.Error("Error %v Error: %v", msg.Func, err.Error())
}))
t.OnInit(t, opts...)
t.Register("nf", t.NF) // 下一帧执行
return t, nil
}
func FindTable(uid int) *Table {
data, ok := AllPlayers.Load(uid)
if !ok {
return nil
}
p := data.(*Player)
return p.T
}
func FindPlayer(session gate.Session) *Player {
uid := int(session.GetUserIdInt64())
data, ok := AllPlayers.Load(uid)
if !ok {
return nil
}
p := data.(*Player)
p.T.PutQueue("nf", func() {
p.Refresh(session)
})
return p
}
// AddOne 保证在queue中运行
func (r *GameRoom) AddOne(t *Table) {
if len(t.Lists) == 0 {
return
}
if r.SubAdd != nil {
r.SubAdd(t)
return
}
log.Debug("table %v add one,list:%+v", t.TableId(), t.List)
list := t.List
lists := t.Lists
// 当前列表已清空
if list == nil {
list = lists[0]
t.List = list
t.Ele = list.PushBack(t)
return
}
list.Remove(t.Ele)
t.List = nil
index := list.Index
if index != len(lists)-1 {
t.List = lists[index+1]
t.Ele = lists[index+1].PushBack(t)
}
log.Debug("table %v finish add one,list:%+v", t.TableId(), t.List)
}
func (r *GameRoom) MineOne(t *Table) {
if len(t.Lists) == 0 {
return
}
r.Queue.AddQueue(func() {
log.Debug("table %v mine one,list:%+v", t.TableId(), t.List)
if r.SubMine != nil {
r.SubMine(t)
return
}
list := t.List
lists := t.Lists
// 当前是满人状态
if list == nil {
newList := lists[len(lists)-1]
t.List = newList
t.Ele = newList.PushBack(t)
return
}
index := list.Index
list.Remove(t.Ele)
// 当前已在第一个列表
if index > 0 {
newList := lists[index-1]
t.List = newList
t.Ele = newList.PushBack(t)
}
log.Debug("table %v finish mine one,list:%+v", t.TableId(), t.List)
})
}
// ChangeOne 换到另一个list
func (r *GameRoom) ChangeOne(t *Table) {
if len(t.Lists) == 0 || len(r.TableListPlaying) == 0 {
return
}
r.Queue.AddQueue(func() {
target := r.TableList
if t.Lists[0] == r.TableList[0] {
target = r.TableListPlaying
}
t.Lists = target
list := t.List
if list == nil {
return
}
list.Remove(t.Ele)
index := list.Index
newList := target[index]
t.List = newList
t.Ele = newList.PushBack(t)
})
}
func (r *GameRoom) RemoveOne(table *Table) {
r.Queue.AddQueue(func() {
list := table.List
if list == nil {
return
}
list.Remove(table.Ele)
table.List = nil
})
}
// func (r *GameRoom) Match(uid int, tid ...int) error {
// log.Debug("GameRoom %v match:%v", r.RoomId(), uid)
// find := false
// con := r.MatchConfig
// // 单人匹配
// if con[0].MatchType == common.MatchTypeSingle {
// for e := r.TableListSingle.Front(); e != nil; e = e.Next() {
// table := e.Value.(*Table)
// log.Debug("single player %v checking table %v", uid, table.TableId())
// find = true
// r.TableListSingle.Remove(e)
// table.Run()
// table.PutQueue("enter", uid)
// break
// }
// if !find {
// r.CreateAndEnterTable(uid, true)
// }
// return nil
// }
// // 根据匹配策略顺序匹配
// for _, v := range con {
// // if v.TableState == 0 {
// // continue
// // }
// list := r.TableList
// if v.TableState == 2 {
// list = r.TableListPlaying
// }
// empty := v.EmptyPositionNumber[0]
// if empty < 1 || empty > len(list) {
// continue
// }
// l := list[len(list)-empty]
// // l.Lock()
// log.Debug("index:%v,mc:%+v", len(list)-empty, v)
// for e := l.Front(); e != nil; e = e.Next() {
// table := e.Value.(*Table)
// log.Debug("player %v checking table %v", uid, table.TableId())
// if tid != nil && table.TableIDInt() == tid[0] {
// continue
// }
// // 屏蔽自己提前离开的房间
// if p := table.GetPlayer(uid); p != nil {
// continue
// }
// find = true
// // 如果存在队列则处理一下队列
// if len(r.TableList) > 1 {
// r.AddOne(table)
// }
// // table.Run()
// table.PutQueue("enter", uid)
// break
// }
// if find {
// break
// }
// // l.Unlock()
// }
// // 创建房间
// if !find {
// r.CreateAndEnterTable(uid, false)
// }
// return nil
// }
// MatchMillionTable 百人场进场方式
func (r *GameRoom) MatchMillionTable(uid int, session gate.Session, ct common.CurrencyType) error {
log.Debug("GameRoom %v match:%v,ct:%v", r.RoomId(), uid, ct)
find := false
for i := 0; i < len(r.TableList); i++ {
l := r.TableList[i].List
for e := l.Front(); e != nil; e = e.Next() {
table := e.Value.(*Table)
find = true
table.PutQueue("nf", func() {
table.Enter(uid, session, ct)
})
break
}
}
// 创建房间
if !find {
r.CreateAndEnterTable(uid, session, ct, false)
}
return nil
}
func (r *GameRoom) CreateAndEnterTable(uid int, session gate.Session, ct common.CurrencyType, isSingle bool) {
table, err := r.CreateById(call.GetCaller().GetApp(), r.GetTableID(), r.NewTable)
if err != nil {
log.Error("err:%v", err)
return
}
log.Debug("create table:%v isSingle:%v", table.TableId(), isSingle)
t := table.(*Table)
sub := r.NewSubTable()
sub.Init(t)
t.SubTable = sub
t.Init()
t.IsSingle = isSingle
t.Reset()
if !isSingle {
if ThisGameType == GameTypeMillion {
t.List = r.TableList[0]
t.Ele = r.TableList[0].PushBack(t)
} else {
t.List = r.TableList[1]
t.Ele = r.TableList[1].PushBack(t)
t.Lists = r.TableList
}
}
table.Run()
table.PutQueue("nf", func() {
t.Enter(uid, session, ct)
})
r.Tables.Store(t.TableIDInt(), t)
}