package main import ( "slices" "time" "mongo.games.com/goserver/core/logger" "mongo.games.com/goserver/core/module" "mongo.games.com/goserver/core/timer" "mongo.games.com/game/common" "mongo.games.com/game/model" "mongo.games.com/game/protocol/gamehall" "mongo.games.com/game/protocol/server" ) func init() { RegisteGameSessionListener(CustomRoomMgrSingle) module.RegisteModule(CustomRoomMgrSingle, time.Second*3, 0) } var CustomRoomMgrSingle = &CustomRoomMgr{ data: make(map[string]*CustomMgr), list: make(map[string]map[int32]struct{}), } type CustomRoomInfo struct { Platform string SystemConfigId int32 Handle timer.TimerHandle *gamehall.PrivateRoomInfo *Scene } func (c *CustomRoomInfo) Notify(tp common.ListOpType) { if c.PrivateRoomInfo == nil || c.Scene != nil { return } pack := &gamehall.SCGetPrivateRoomList{ Tp: int32(tp), Datas: []*gamehall.PrivateRoomInfo{c.PrivateRoomInfo}, } PlayerNotifySingle.SendToClient(common.NotifyPrivateRoomList, c.Platform, int(gamehall.GameHallPacketID_PACKET_SC_GETPRIVATEROOMLIST), pack) logger.Logger.Tracef("CustomRoomInfo NotifyPrivateRoom: %v", pack) } type CustomMgr struct { List map[int32]*CustomRoomInfo // 满人房间假数据 DestroyTime map[int32]time.Time // 空房间最后解散时间,配置id:解散时间 } type CustomRoomMgr struct { common.BaseClockSinker data map[string]*CustomMgr list map[string]map[int32]struct{} } func (c *CustomRoomMgr) ModuleName() string { return "CustomRoomMgr" } func (c *CustomRoomMgr) Init() { } func (c *CustomRoomMgr) Update() { for k, v := range c.list { for kk := range v { c.tryCreate(k, kk) } } c.list = make(map[string]map[int32]struct{}) } func (c *CustomRoomMgr) Shutdown() { module.UnregisteModule(c) } func (c *CustomRoomMgr) OnGameSessionRegiste(session *GameSession) { for _, v := range PlatformMgrSingleton.GetPlatforms() { if v == nil { continue } plt := PlatformMgrSingleton.GetPlatform(v.IdStr) if plt == nil { continue } for _, info := range PlatformMgrSingleton.GetConfig(plt.IdStr).RoomConfigSystem { if info == nil { continue } gf := PlatformMgrSingleton.GetGameFree(plt.IdStr, info.GetGameFreeId()) if gf == nil || !gf.GetStatus() || info.GetOn() == common.Off { continue } roomConfig := PlatformMgrSingleton.GetConfig(plt.IdStr).RoomConfig[info.GetRoomConfigId()] if roomConfig == nil || roomConfig.GetOn() == common.Off { return } if len(session.gameIds) == 0 || slices.Contains(session.gameIds, gf.GetDbGameFree().GetGameId()) { c.TouchCreate(plt.IdStr, info.GetId()) } } } } func (c *CustomRoomMgr) OnGameSessionUnregiste(session *GameSession) { } func (c *CustomRoomMgr) TouchCreate(plt string, configId int32) { m := c.list[plt] if m == nil { m = make(map[int32]struct{}) c.list[plt] = m } c.list[plt][configId] = struct{}{} } func (c *CustomRoomMgr) GetRoomList(plt string) []*gamehall.PrivateRoomInfo { d := c.data[plt] if d == nil { return nil } var ret []*gamehall.PrivateRoomInfo for _, v := range d.List { if v != nil && v.PrivateRoomInfo != nil { ret = append(ret, v.PrivateRoomInfo) } } return ret } func (c *CustomRoomMgr) tryCreate(plt string, configId int32) { logger.Logger.Tracef("尝试创建竞技馆系统房间 %v CloseCustomRoomCreate:%v", configId, model.GameParamData.CloseCustomRoomCreate) cfg := PlatformMgrSingleton.GetConfig(plt).RoomConfigSystem[configId] if model.GameParamData.CloseCustomRoomCreate || cfg == nil || cfg.GetOn() == common.Off { return } c.TryDestroy(plt, configId) m := c.data[plt] if m == nil { m = &CustomMgr{ List: make(map[int32]*CustomRoomInfo), DestroyTime: make(map[int32]time.Time), } c.data[plt] = m } _, ok := m.List[cfg.GetId()] if ok { return } c.UpdateCreate(plt, cfg.GetId(), true) } func (c *CustomRoomMgr) TryDestroy(plt string, configId int32) { logger.Logger.Tracef("尝试解散竞技馆系统房间 %v", configId) cfg := PlatformMgrSingleton.GetConfig(plt).RoomConfigSystem[configId] if cfg == nil { return } v, ok := c.data[plt] if !ok || v == nil { return } info := v.List[configId] if info != nil { timer.StopTimer(info.Handle) if info.Scene != nil && !info.deleting { info.SendGameDestroy(true) } if info.Scene == nil { c.Release(plt, configId) } } if cfg.GetState() == 2 { // 假房间立刻删除 c.Release(plt, configId) } } func (c *CustomRoomMgr) Release(plt string, configId int32) { logger.Logger.Tracef("释放竞技馆房间创建记录 %v", configId) v, ok := c.data[plt] if !ok || v == nil { return } info := v.List[configId] if info != nil { timer.StopTimer(info.Handle) info.Notify(common.ListDel) } delete(v.List, configId) v.DestroyTime[configId] = time.Now() } func (c *CustomRoomMgr) UpdateCreate(plt string, configId int32, mustCreate bool) { cfg := PlatformMgrSingleton.GetConfig(plt).RoomConfigSystem[configId] if cfg == nil { return } gf := PlatformMgrSingleton.GetGameFree(plt, cfg.GetGameFreeId()) if gf == nil || !gf.GetStatus() || cfg.GetOn() == common.Off { // 游戏没开 return } roomConfig := PlatformMgrSingleton.GetConfig(plt).RoomConfig[cfg.GetRoomConfigId()] if roomConfig == nil || roomConfig.GetOn() == common.Off { return } m := c.data[plt] if m == nil { m = &CustomMgr{ List: make(map[int32]*CustomRoomInfo), DestroyTime: make(map[int32]time.Time), } c.data[plt] = m } _, ok := m.List[cfg.GetId()] if ok { return } info := &CustomRoomInfo{ Platform: plt, SystemConfigId: cfg.GetId(), } m.List[cfg.GetId()] = info destroyTime := m.DestroyTime[cfg.GetId()] subTime := time.Duration(0) if !destroyTime.IsZero() { subTime = time.Duration(cfg.GetAutoCreateTime())*time.Second - time.Now().Sub(destroyTime) } if subTime < 0 || mustCreate { subTime = 0 } f := func(fn func()) { b, _ := timer.AfterTimer(func(h timer.TimerHandle, ud interface{}) bool { fn() return true }, nil, subTime) m.List[cfg.GetId()].Handle = b } if cfg.GetAutoCreate() == 1 || mustCreate { logger.Logger.Tracef("Update 竞技馆系统房间创建 %v", configId) f(func() { gf = PlatformMgrSingleton.GetGameFree(plt, cfg.GetGameFreeId()) if gf == nil || !gf.GetStatus() || cfg.GetOn() == common.Off { c.Release(plt, cfg.GetId()) return } roomConfig = PlatformMgrSingleton.GetConfig(plt).RoomConfig[cfg.GetRoomConfigId()] if roomConfig == nil || roomConfig.GetOn() == common.Off { c.Release(plt, cfg.GetId()) return } cfg = PlatformMgrSingleton.GetConfig(plt).RoomConfigSystem[configId] if cfg == nil || cfg.GetOn() == common.Off { c.Release(plt, cfg.GetId()) return } switch cfg.GetState() { case 1: // 系统房间 csp := CoinSceneMgrSingleton.GetCoinScenePool(cfg.GetPlatform(), cfg.GetGameFreeId()) roomId := SceneMgrSingleton.GenOnePrivateSceneId() scene := SceneMgrSingleton.CreateScene(&CreateSceneParam{ CreateId: 0, RoomId: roomId, SceneMode: common.SceneModePrivateMatch, TotalRound: int(cfg.GetRound()), Params: common.CopySliceInt32ToInt64(csp.dbGameRule.GetParams()), Platform: PlatformMgrSingleton.GetPlatform(cfg.GetPlatform()), GF: csp.dbGameFree, PlayerNum: cfg.GetPlayerNum(), Channel: roomConfig.GetOnChannelName(), CustomParam: &server.CustomParam{ RoomTypeId: roomConfig.GetRoomType(), RoomConfigId: roomConfig.GetId(), CostType: 1, Voice: cfg.GetVoice(), }, RoomConfigSystem: cfg, IsRecruit: true, }) if scene != nil { logger.Logger.Tracef("竞技馆系统房间创建成功 roomId:%v", scene.sceneId) csp.AddScene(scene) info.Scene = scene } else { logger.Logger.Warnf("竞技馆系统房间创建失败 roomConfigSystemId:%v", cfg.GetId()) c.Release(plt, cfg.GetId()) } default: // 假房间 roomId := SceneMgrSingleton.GenOnePrivateSceneId() info.PrivateRoomInfo = &gamehall.PrivateRoomInfo{ GameFreeId: cfg.GetGameFreeId(), GameId: gf.GetDbGameFree().GetGameId(), RoomTypeId: roomConfig.GetRoomType(), RoomConfigId: roomConfig.GetId(), RoomId: int32(roomId), NeedPassword: 0, CurrRound: int32(common.RandInt(1, int(cfg.GetRound()))), MaxRound: cfg.GetRound(), CurrNum: cfg.GetPlayerNum(), MaxPlayer: cfg.GetPlayerNum(), CreateTs: time.Now().Unix(), State: 1, CostType: 1, } for i := 0; i < int(cfg.GetPlayerNum()); i++ { info.PrivateRoomInfo.Players = append(info.PrivateRoomInfo.Players, &gamehall.PrivatePlayerInfo{ SnId: 0, Name: "", UseRoleId: common.RandInt32Slice(common.RolesIDs), }) } info.Notify(common.ListAdd) logger.Logger.Tracef("竞技馆假房间创建成功 %v", info.PrivateRoomInfo) if cfg.FullTime <= 0 { cfg.FullTime = int32(model.GameParamData.SceneMaxIdle) } if cfg.FullTime < 3 { cfg.FullTime = 3 // 至少3秒 } b, _ := timer.AfterTimer(func(h timer.TimerHandle, ud interface{}) bool { logger.Logger.Tracef("竞技馆假房间解散 %v", info) c.Release(plt, configId) c.UpdateCreate(plt, configId, false) return true }, nil, time.Duration(cfg.GetFullTime())*time.Second) info.Handle = b } }) } }