game_sync/worldsrv/gamesess.go

288 lines
7.8 KiB
Go

package main
import (
"fmt"
"mongo.games.com/game/protocol/webapi"
"sync"
"mongo.games.com/game/common"
"mongo.games.com/game/model"
"mongo.games.com/game/proto"
gamehall_proto "mongo.games.com/game/protocol/gamehall"
server_proto "mongo.games.com/game/protocol/server"
"mongo.games.com/game/srvdata"
"mongo.games.com/goserver/core/logger"
"mongo.games.com/goserver/core/netlib"
"mongo.games.com/goserver/srvlib"
libproto "mongo.games.com/goserver/srvlib/protocol"
)
type GameSessionListener interface {
OnGameSessionRegiste(*GameSession)
OnGameSessionUnregiste(*GameSession)
}
var GameSessionListenerSet = new(sync.Map)
func RegisteGameSessionListener(listener GameSessionListener) {
GameSessionListenerSet.Store(listener, listener)
}
func UnregisteGameSessionListener(listener GameSessionListener) {
GameSessionListenerSet.Delete(listener)
}
type GameSession struct {
*netlib.Session
srvId int
srvType int
state common.GameSessState
players map[int32]*Player
scenes map[int]*Scene
cps map[string]*model.CoinPoolSetting
gameIds []int32
}
// 构造函数
func NewGameSession(srvId, srvType int, s *netlib.Session) *GameSession {
gs := &GameSession{
Session: s,
srvId: srvId,
srvType: srvType,
state: common.GAME_SESS_STATE_ON,
players: make(map[int32]*Player),
scenes: make(map[int]*Scene),
cps: make(map[string]*model.CoinPoolSetting),
}
return gs
}
func (this *GameSession) RebindPlayerSnId(oldSnId, newSnId int32) {
if p, exist := this.players[oldSnId]; exist {
delete(this.players, oldSnId)
this.players[newSnId] = p
}
}
func (this *GameSession) GetSrvId() int32 {
if this.Session == nil {
return 0
}
attr := this.GetAttribute(srvlib.SessionAttributeServerInfo)
if attr != nil {
if srvInfo, ok := attr.(*libproto.SSSrvRegiste); ok && srvInfo != nil {
return srvInfo.GetId()
}
}
return 0
}
// 关闭其上的所有场景
func (this *GameSession) CloseAllScene() {
for sceneId, scene := range this.scenes {
scDestroyRoom := &gamehall_proto.SCDestroyRoom{
RoomId: proto.Int(sceneId),
OpRetCode: gamehall_proto.OpResultCode_Game_OPRC_Sucess_Game,
IsForce: proto.Int(1),
}
proto.SetDefaults(scDestroyRoom)
scene.Broadcast(int(gamehall_proto.GameHallPacketID_PACKET_SC_DESTROYROOM), scDestroyRoom, 0)
SceneMgrSingleton.DestroyScene(sceneId, true)
}
this.scenes = nil
this.players = nil
}
// 注册事件
func (this *GameSession) OnRegiste() {
GameSessionListenerSet.Range(func(key, val interface{}) bool {
if lis, ok := val.(GameSessionListener); ok {
lis.OnGameSessionRegiste(this)
}
return true
})
}
// 注销事件
func (this *GameSession) OnUnregiste() {
//销毁比赛
//MatchMgrSington.DestroyAllMatchByGameSession(this)
//解散房间
this.CloseAllScene()
GameSessionListenerSet.Range(func(key, val interface{}) bool {
if lis, ok := val.(GameSessionListener); ok {
lis.OnGameSessionUnregiste(this)
}
return true
})
}
// 负载因数
func (this *GameSession) GetLoadFactor() int {
return len(this.scenes)*20 + len(this.players)
}
// 设置状态
func (this *GameSession) SwitchState(state common.GameSessState) {
if state == this.state {
return
}
this.state = state
switch state {
case common.GAME_SESS_STATE_ON:
this.OnStateOn()
case common.GAME_SESS_STATE_OFF:
this.OnStateOff()
}
}
func (this *GameSession) OnStateOn() {
pack := &server_proto.ServerState{
SrvState: proto.Int(int(this.state)),
}
proto.SetDefaults(pack)
this.Send(int(server_proto.SSPacketID_PACKET_WG_SERVER_STATE), pack)
}
func (this *GameSession) OnStateOff() {
pack := &server_proto.ServerState{
SrvState: proto.Int(int(this.state)),
}
proto.SetDefaults(pack)
this.Send(int(server_proto.SSPacketID_PACKET_WG_SERVER_STATE), pack)
}
type AddSceneParam struct {
S *Scene
}
func (this *GameSession) AddScene(args *AddSceneParam) {
this.scenes[args.S.sceneId] = args.S
//send msg
msg := &server_proto.WGCreateScene{
Platform: args.S.limitPlatform.IdStr,
SceneId: int32(args.S.sceneId),
GameId: int32(args.S.gameId),
GameMode: int32(args.S.gameMode),
SceneMode: int32(args.S.sceneMode),
ReplayCode: args.S.replayCode,
DBGameFree: args.S.dbGameFree,
TotalOfGames: args.S.totalRound,
PlayerNum: int32(args.S.playerNum),
Creator: args.S.creator,
BaseScore: args.S.BaseScore,
Custom: args.S.CustomParam,
Match: args.S.MatchParam,
Params: args.S.params,
}
if args.S.GetRoomConfigId() != 0 {
cfg := PlatformMgrSingleton.GetConfig(args.S.limitPlatform.IdStr).RoomConfig[args.S.GetRoomConfigId()]
if cfg != nil {
for _, v := range cfg.GetReward() {
msg.Items = append(msg.Items, &server_proto.Item{
Id: v.GetItemId(),
Num: v.GetItemNum(),
})
}
for _, v := range cfg.GetCost() {
msg.CostItems = append(msg.CostItems, &server_proto.Item{
Id: v.GetItemId(),
Num: v.GetItemNum(),
})
}
}
}
if sp, ok := args.S.sp.(*ScenePolicyData); ok {
msg.EnterAfterStart = proto.Bool(sp.EnterAfterStart)
}
// 象棋游戏添加段位配置
if args.S.dbGameFree != nil && srvdata.GameFreeMgr.IsGameDif(int32(args.S.gameId), common.GameDifChess) {
msg.ChessRank = ChessRankMgrSington.GetChessRankArr(args.S.limitPlatform.Name, int32(args.S.gameId))
}
this.Send(int(server_proto.SSPacketID_PACKET_WG_CREATESCENE), msg)
logger.Logger.Tracef("WGCreateScene: %v", msg)
// 初始化水池
if args.S.limitPlatform != nil && args.S.dbGameFree != nil {
this.DetectCoinPoolSetting(args.S.limitPlatform.IdStr, args.S.dbGameFree.GetId(), args.S.groupId)
}
}
func (this *GameSession) DelScene(s *Scene) {
delete(this.scenes, s.sceneId)
}
func (this *GameSession) AddPlayer(p *Player) {
this.players[p.SnId] = p
}
func (this *GameSession) DelPlayer(p *Player) {
delete(this.players, p.SnId)
}
func (this *GameSession) GenCoinPoolSettingKey(platform string, groupId, gamefreeid, srvid int32) string {
var key string
if groupId != 0 {
key = fmt.Sprintf("%v+%v_%v", gamefreeid, groupId, srvid)
} else {
key = fmt.Sprintf("%v_%v_%v", gamefreeid, platform, srvid)
}
return key
}
func (this *GameSession) DetectCoinPoolSetting(platform string, gamefreeid, groupId int32) bool {
srvid := this.GetSrvId()
key := this.GenCoinPoolSettingKey(platform, groupId, gamefreeid, srvid)
if _, exist := this.cps[key]; !exist {
data := model.GetCoinPoolSetting(gamefreeid, srvid, groupId, platform)
if data == nil {
dbGameCoinPool := srvdata.PBDB_GameCoinPoolMgr.GetData(gamefreeid)
if dbGameCoinPool != nil {
data = model.NewCoinPoolSetting(platform, groupId, gamefreeid, srvid, dbGameCoinPool)
if data != nil {
err := model.UpsertCoinPoolSetting(data, nil) // 入库
if err == nil {
model.ManageCoinPoolSetting(data)
}
}
}
}
if data != nil {
this.cps[key] = data
//send msg
msg := &webapi.CoinPoolSetting{
Platform: platform,
GameFreeId: gamefreeid,
ServerId: srvid,
GroupId: groupId,
InitValue: data.InitValue,
LowerLimit: data.LowerLimit,
UpperLimit: data.UpperLimit,
QuDu: data.QuDu,
UpperOdds: data.UpperOdds,
UpperOddsMax: data.UpperOddsMax,
LowerOdds: data.LowerOdds,
LowerOddsMax: data.LowerOddsMax,
ProfitRate: data.ProfitRate,
CtrlRate: data.CtrlRate,
InitNoviceValue: data.InitNoviceValue,
ResetTime: data.ResetTime,
Switch: data.Switch,
}
proto.SetDefaults(msg)
this.Send(int(server_proto.SSPacketID_PACKET_WG_COINPOOLSETTING), msg)
}
}
return true
}
// SendToGame 给某个游戏服务发消息
func SendToGame(gameId int, packetId int, pack interface{}) {
gameServers := GameSessMgrSington.GetGameServerSess(gameId)
if len(gameServers) == 0 {
gameServers = GameSessMgrSington.GetGameServerSess(common.GameId_Unknow)
}
for _, value := range gameServers {
value.Send(packetId, pack)
}
}