using DeepCore; using DeepCore.GameData.Zone.ZoneEditor; using DeepCore.GameEvent; using DeepCore.IO; using DeepCore.Log; using DeepCrystal.RPC; using DeepMMO.Data; using DeepMMO.Protocol; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using DeepCore.GameEvent.Message; using DeepCore.Net; using DeepMMO.Protocol.Client; using DeepMMO.Server.GameEvent; namespace DeepMMO.Server.AreaManager { public class AreaManager : IService { protected readonly Logger log; protected readonly Random random = new Random(); private readonly int LINE_MAX = 50;//场景分线硬上限 private IDisposable mTimer; public EventManager EventMgr { get; private set; } public string ServerGID { get; set; } public AreaManager(ServiceStartInfo start) : base(start) { ServerGID = start.Config["groupID"]; this.log = LoggerFactory.GetLogger(GetType().Name); this.areas = new ValueSortedMap>(AreaGroupComparison); Console.WriteLine("AreaManager 初始化 GroupID: " + start.Config["groupID"]); } protected override void OnDisposed() { Console.WriteLine("AreaManager OnDisposed GroupID: " + ServerGID); } protected override Task OnStartAsync() { EventMgr = EventManagerFactory.Instance.CreateEventManager(nameof(AreaManager), SelfAddress.ServiceName); if (EventMgr != null) { EventMgr.PutObject("Service", this); EventMgr.Start(); mTimer = Provider.CreateTimer(OnEventTick, this, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(TimerConfig.timer_sec_EventUpdateTime)); } return Task.FromResult(0); } //protected override async Task OnStartAsync() //{ // EventMgr = EventManagerFactory.Instance.CreateEventManager(nameof(AreaManager), SelfAddress.ServiceName); // if (EventMgr != null) // { // EventMgr.PutObject("Service", this); // EventMgr.Start(); // mTimer = Provider.CreateTimer(OnEventTick, this, // TimeSpan.FromSeconds(0), // TimeSpan.FromSeconds(TimerConfig.timer_sec_EventUpdateTime)); // } // //请求动态创建场景 // if (areas.Count == 0) // { // var getRemote = await ServerNames.GetOrCreateAreaServiceAsync(this, ServerGID); // if (getRemote != null) // { // var node = areas.GetOrAdd(getRemote.Address.ServiceNode, (n) => new ValueSortedMap(AreaComparison)); // node.TryAddOrUpdate(getRemote.Address.ServiceName, new AreaInfo(getRemote)); // } // } //} protected override Task OnStopAsync(ServiceStopInfo reason) { EventMgr?.Dispose(); mTimer?.Dispose(); return Task.FromResult(0); } private void OnEventTick(object state) { EventMgr?.Update(); } public virtual void AreaSyncState(AreaStateNotify st) { if (areas.TryGetValue(st.areaNode, out var group)) { areas.MarkSort(); if (group.TryGetValue(st.areaName, out var area)) { group.MarkSort(); area.state = st; } } this.LogState(); } public override bool GetState(TextWriter sb) { sb.WriteLine(CUtils.SequenceChar('-', 100)); foreach (var group in areas.ToSortedArray()) { foreach (var area in group.ToSortedArray()) { area.WriteState(sb); } } sb.WriteLine(CUtils.SequenceChar('-', 100)); return true; } //------------------------------------------------------------------------------------------------------------------------------------ #region RPC [RpcHandler(typeof(BatchCreateZoneLineRequest), typeof(BatchCreateZoneLineResponse))] public virtual Task logic_rpc_Handle(BatchCreateZoneLineRequest create) { //log.Info(create); return BatchCreateZoneLine(create); } [RpcHandler(typeof(CreateZoneNodeRequest), typeof(CreateZoneNodeResponse))] public virtual Task logic_rpc_Handle(CreateZoneNodeRequest create) { //log.Info(create); return CreateZone(create); } [RpcHandler(typeof(DestoryZoneNodeRequest), typeof(DestoryZoneNodeResponse))] public virtual Task logic_rpc_Handle(DestoryZoneNodeRequest stop) { //log.Info(stop); return DestoryZone(stop); } [RpcHandler(typeof(RoleEnterZoneRequest), typeof(RoleEnterZoneResponse))] public virtual Task logic_rpc_Handle(RoleEnterZoneRequest req) { //log.Info(req); return RoleEnter(req); } [RpcHandler(typeof(RoleLeaveZoneRequest), typeof(RoleLeaveZoneResponse))] public virtual Task logic_rpc_Handle(RoleLeaveZoneRequest req) { //log.Info(req); return RoleLeave(req); } [RpcHandler(typeof(ServerGameEventNotify))] public virtual void rpc_event_notify(ServerGameEventNotify ntf) { EventMgr?.OnReceiveMessage(EventMessage.FromBytes(ntf.EventMessageData)); } //------------------------------------------------------------------------------------------------------------------------------------ /// /// 添加一个Area负载 /// /// [RpcHandler(typeof(RegistAreaRequest), typeof(RegistAreaResponse), ServerNames.AreaServiceType)] public virtual Task area_rpc_RegistAreaAsync(RegistAreaRequest reg) { return AreaRegist(reg); } [RpcHandler(typeof(AreaStateNotify), ServerNames.AreaServiceType)] public virtual void area_rpc_AreaStateNotify(AreaStateNotify notify) { AreaSyncState(notify); } [RpcHandler(typeof(AreaZoneGameOverNotify), ServerNames.AreaServiceType)] public virtual void area_rpc_AreaGameOverHandle(AreaZoneGameOverNotify stop) { //log.Info("AreaMgr receive " + stop + " " + stop.zoneUUID); zones.SetZoneCloseFlag(stop.zoneUUID); } [RpcHandler(typeof(AreaZoneDestoryNotify), ServerNames.AreaServiceType)] public virtual void area_rpc_AreaGameOverHandle(AreaZoneDestoryNotify stop) { //TODO flag destory //log.Info("AreaMgr recive " + stop + " " + stop.zoneUUID); DestoryZone(stop); } //-------------------------------------------------- [RpcHandler(typeof(RoleNameChangedNotify))] public virtual void logic_rpc_Handle(RoleNameChangedNotify ntf) { var role = GetRole(ntf.roleId); if (role != null) { role.enter.roleDisplayName = ntf.newName; } } //------------------------------------------------------------------------------------------------------------------------------------ [RpcHandler(typeof(GetAllRoleRequest), typeof(GetAllRoleResponse))] public virtual void logic_rpc_Handle(GetAllRoleRequest req, OnRpcReturn cb) { RoleInfo[] roleList = GetAllRoles(); HashMap uuidMap = new HashMap(); for (int i = 0; i < roleList.Length; ++i) { var rold = roleList[i]; uuidMap.Add(rold.uuid, new OnlinePlayerData() { name = rold.enter.roleDisplayName, serverGroupId = rold.enter.servergroupID }); } cb(new GetAllRoleResponse() { uuidMap = uuidMap }); } [RpcHandler(typeof(QueryZoneAreaNameRequest), typeof(QueryZoneAreaNameResponse))] public Task logic_rpc_Handle(QueryZoneAreaNameRequest req) { var zone = GetZone(req.zoneUUID); return Task.FromResult(new QueryZoneAreaNameResponse { s2c_code = zone != null ? Response.CODE_OK : Response.CODE_ERROR, areaName = zone?.area.key }); } [RpcHandler(typeof(GetZonesInfoRequest), typeof(GetZonesInfoResponse))] public virtual void logic_rpc_Handle(GetZonesInfoRequest req, OnRpcReturn cb) { GetZonesInfoResponse rsp = new GetZonesInfoResponse(); //指定场景的所有线. var lt = GetZoneList(req.servergroupID, req.mapID); if (lt != null) { List snaps = new List(); rsp.snaps = snaps; ZoneInfoSnap snap = null; ZoneInfo info = null; for (int i = 0; i < lt.Count; i++) { //获取所有线的信息. info = lt[i]; if (info != null && info.close == false) { snap = new ZoneInfoSnap(); snap.curPlayerCount = info.currentRoleCount; snap.playerMaxCount = info.map_data.max_players; snap.lineIndex = info.lineIndex; snap.playerFullCount = info.map_data.full_players; snap.uuid = info.uuid; snaps.Add(snap); } } } cb(rsp); } /// /// 批量获取场景分线 /// /// /// [RpcHandler(typeof(GetBatchZonesInfoRequest), typeof(GetBatchZonesInfoResponse))] public virtual void logic_rpc_Handle(GetBatchZonesInfoRequest req, OnRpcReturn cb) { GetBatchZonesInfoResponse rsp = new GetBatchZonesInfoResponse(); rsp.snapDic = new HashMap>(); foreach (var item in req.mapIDList) { var lt = GetZoneList(req.servergroupID, item); if (lt != null) { ZoneInfoSnap snap = null; ZoneInfo info = null; List snaps = new List(); for (int i = 0; i < lt.Count; i++) { //获取所有线的信息. info = lt[i]; if (info != null && info.close == false) { snap = new ZoneInfoSnap(); snap.curPlayerCount = info.currentRoleCount; snap.playerMaxCount = info.map_data.max_players; snap.lineIndex = info.lineIndex; snap.playerFullCount = info.map_data.full_players; snap.uuid = info.uuid; snaps.Add(snap); } } rsp.snapDic.Add(item, snaps); } } cb(rsp); } [RpcHandler(typeof(GetRolePositionRequest), typeof(GetRolePositionResponse))] public virtual async Task logic_rpc_Handle(GetRolePositionRequest req) { if (roles.ContainsKey(req.roleUUID) == false) { return new GetRolePositionResponse() { s2c_code = GetRolePositionResponse.CODE_ROLE_NOT_EXIST }; } var role = roles.Get(req.roleUUID); var zone = role.zone; if (zone == null) { return (new GetRolePositionResponse() { s2c_code = GetRolePositionResponse.CODE_ZONE_NOT_EXIST }); } var resp = await zone.area.service.CallAsync(req); resp.line = zone.lineIndex; resp.zoneId = zone.map_data.id; resp.zoneUUID = zone.uuid; return resp; } #endregion //------------------------------------------------------------------------------------------------------------------------------------ #region ZoneManager private readonly ValueSortedMap> areas; private readonly HashMap roles = new HashMap(); private readonly ZoneMap zones = new ZoneMap(); public virtual async Task RoleEnter(RoleEnterZoneRequest req) { if (roles.ContainsKey(req.roleUUID)) { return (new RoleEnterZoneResponse() { s2c_code = RoleEnterZoneResponse.CODE_ROLE_ALREADY_IN_ZONE }); } var roleInfo = new RoleInfo(req.roleUUID, req); //先添加以防止二次进入// roles.Add(roleInfo.uuid, roleInfo); try { var zone = await this.LookingForExpectZone(req); if (zone == null || zone.close) { roles.Remove(req.roleUUID); return (new RoleEnterZoneResponse() { s2c_code = RoleEnterZoneResponse.CODE_ZONE_NOT_EXIST }); } //-------------------------------------------------------------------------------- //分配线. req.expectLineIndex = zone.lineIndex; req.expectZoneUUID = zone.uuid; zone.AddTeamID(req.teamID); //-------------------------------------------------------------------------------- var rsp = await zone.area.service.CallAsync(req); if (Response.CheckSuccess(rsp)) { zone.currentRoleCount++; zone.area.currentRoleCount++; roleInfo.zone = zone; } else { roles.Remove(req.roleUUID); log.Error(rsp); } return rsp; } catch (Exception err) { roles.Remove(req.roleUUID); return (new RoleEnterZoneResponse() { s2c_code = RoleEnterZoneResponse.CODE_ERROR, s2c_msg = err.Message }); } } public virtual async Task RoleLeave(RoleLeaveZoneRequest req) { var role = roles.RemoveByKey(req.roleID); if (role == null) { return (new RoleLeaveZoneResponse() { s2c_code = RoleLeaveZoneResponse.CODE_ROLE_NOT_EXIST }); } var zone = role.zone; if (zone == null) { return (new RoleLeaveZoneResponse() { s2c_code = RoleLeaveZoneResponse.CODE_ZONE_NOT_EXIST }); } //最后才删除// zone.currentRoleCount--; zone.area.currentRoleCount--; req.zoneUUID = zone.uuid; var rsp = await zone.area.service.CallAsync(req); if (!Response.CheckSuccess(rsp)) { log.Error(rsp); } zone.RemoveTeamID(role.enter.teamID); return rsp; } public virtual async Task LookingForExpectZone(RoleEnterZoneRequest req) { ZoneInfo zone = null; #region 返回上一个场景. //返回上一次的场景,如果没有统一返回上一次的公共场景. if (!string.IsNullOrEmpty(req.expectZoneUUID)) { //根据提供的UUID寻找场景// zone = GetZone(req.expectZoneUUID); if (zone != null && !zone.close) { if (zone.currentRoleCount < zone.map_data.max_players) { return (zone); } } return await LookingForPublicZone(req.lastPublicMapUUID, req.lastPublicMapID, req.lastPublicPos, req); } #endregion else { var temp = RPGServerTemplateManager.Instance.GetMapTemplate(req.expectMapTemplateID); if (temp == null)//场景不存在,往公共场景扔. { return await LookingForPublicZone(req.lastPublicMapUUID, req.lastPublicMapID, new ZonePosition(), req); } //优先判断公会场景// if (!string.IsNullOrEmpty(req.guildUUID)) { ZoneInfo guildZone = GetGuildZone(req.guildUUID); if (guildZone != null && !guildZone.close) { if (guildZone.currentRoleCount < guildZone.map_data.max_players) { return (guildZone); } else//公会场景人数大于人数时候,不再能进入场景. { return await LookingForPublicZone(req.lastPublicMapUUID, req.lastPublicMapID, req.lastPublicPos, req); } } else //创建公会场景. { //新创建一个场景// var rsp = await this.CreateZone(new CreateZoneNodeRequest() { //serverID = req.serverID, serverGroupID = req.servergroupID, mapTemplateID = req.expectMapTemplateID, createRoleID = req.roleUUID, teamID = req.teamID, guildUUID = req.guildUUID, reason = "LookingForAreaRequest dispatch", expandData = RPGServerTemplateManager.Instance.GetCreateZoneExpandData(req), expectAreaNode = req.roleSessionNode, }); if (Response.CheckSuccess(rsp)) { return (GetZone(rsp.zoneUUID)); } else { return await LookingForPublicZone(req.lastPublicMapUUID, req.lastPublicMapID, req.lastPublicPos, req); } } } //ROOMKEY. if (!string.IsNullOrEmpty(req.roomKey)) { zone = GetRoomZone(req.roomKey); if (zone != null && !zone.close) { return (zone); } } //分配至队伍场景/ if (req.teamID != null) { zone = LookingForExpectServerGroupZone(req.servergroupID, z => { return z.currentRoleCount < temp.max_players && z.map_data.zone_template_id == req.expectMapTemplateID && z.ContainTeamID(req.teamID); }); if (zone != null && !zone.close) { return (zone); } } //根据EXPECT MAP来. if (RPGServerTemplateManager.Instance.IsPublicMap(temp)) { return await LookingForPublicZone(null, req.expectMapTemplateID, req.roleScenePos, req); } else { //新创建一个场景// var rsp = await this.CreateZone(new CreateZoneNodeRequest() { //serverID = req.serverID, serverGroupID = req.servergroupID, mapTemplateID = temp.id, createRoleID = req.roleUUID, teamID = req.teamID, reason = "LookingForAreaRequest dispatch", expandData = RPGServerTemplateManager.Instance.GetCreateZoneExpandData(req), roomKey = req.roomKey, expectAreaNode = req.roleSessionNode, }); if (Response.CheckSuccess(rsp)) { return (GetZone(rsp.zoneUUID)); } else { return await LookingForPublicZone(req.lastPublicMapUUID, req.lastPublicMapID, req.lastPublicPos, req); } } } } protected virtual async Task LookingForPublicZone(string publicmapUUID, int publicmapID, ZonePosition pos, RoleEnterZoneRequest req) { //没有统一返回上一次的公共场景. req.roleScenePos = pos; ZoneInfo zone = GetZone(publicmapUUID); if (zone != null && !zone.close) { if (zone.currentRoleCount < zone.map_data.max_players) { return (zone); } } //找当前存在的公共场景. var temp = RPGServerTemplateManager.Instance.GetMapTemplate(publicmapID); if (temp == null) { temp = RPGServerTemplateManager.Instance.GetDefaultMapData(req); req.lastPublicPos = new ZonePosition(); } zone = LookingForExpectServerGroupZone(req.servergroupID, z => { return z.currentRoleCount < temp.full_players && z.map_data.zone_template_id == temp.id; }, (a, b) => { if (req.roleSessionNode == a.nodeName) return -1; if (req.roleSessionNode == b.nodeName) return 1; return 0; }); if (zone != null && !zone.close) { return (zone); } //创建一个公共场景. var rsp = await this.CreateZone(new CreateZoneNodeRequest() { serverGroupID = req.servergroupID, //serverID = req.serverID, mapTemplateID = temp.id, reason = "LookingForAreaRequest dispatch", expandData = RPGServerTemplateManager.Instance.GetCreateZoneExpandData(req), roomKey = req.roomKey, expectAreaNode = req.roleSessionNode, }); if (Response.CheckSuccess(rsp)) { return (GetZone(rsp.zoneUUID)); } else { return (null); } } /// /// 根据地图ID,和Area名字选择合适Zone /// /// /// 必要条件 /// 可选条件 /// protected ZoneInfo LookingForExpectServerGroupZone(string serverGroupID, Predicate condition, Comparison expect = null) { var map = zones.GetAllZones(); if (map != null) { var zones = new List(map); return LookingForExpectZone(zones, condition, expect); } return null; } /// /// 选取预期场景 /// /// /// 必要条件 /// 可选条件 /// protected virtual ZoneInfo LookingForExpectZone(List zones, Predicate condition, Comparison expect = null) { for (int i = zones.Count - 1; i >= 0; --i) { var z = zones[i]; if (z.close || !condition(z)) { zones.RemoveAt(i); } } if (zones.Count > 0) { if (expect != null) { zones.Sort(expect); } return zones[0]; } return null; } /// /// 负载均衡排序 /// /// /// /// public virtual int AreaComparison(AreaInfo a, AreaInfo b) { if (a.state == null) return -1; if (b.state == null) return 1; return a.state.roleCount - b.state.roleCount; } public virtual int AreaGroupComparison(ValueSortedMap a, ValueSortedMap b) { var ac = a.Values.Sum(area => area.currentRoleCount); var bc = b.Values.Sum(area => area.currentRoleCount); return ac - bc; } public virtual async Task AreaRegist(RegistAreaRequest reg) { IRemoteService svc; try { svc = await base.Provider.GetAsync(new RemoteAddress(reg.areaName, reg.areaNode)); if (svc != null) { Console.WriteLine(" AreaManager areas 添加节点:"+ svc.Address.ServiceNode+" Name:"+ svc.Address.ServiceName); var node = areas.GetOrAdd(svc.Address.ServiceNode, (n) => new ValueSortedMap(AreaComparison)); node.TryAddOrUpdate(svc.Address.ServiceName, new AreaInfo(svc)); return new RegistAreaResponse(); } else { return new RegistAreaResponse() { s2c_code = RegistAreaResponse.CODE_ERROR }; } } catch (Exception err) { log.Error(err.Message, err); throw; } } /// /// 分配一个空闲的Area /// /// /// public virtual AreaInfo AreaDispatch(string expectNodeName) { ////请求动态创建场景 //if (areas.Count == 0) //{ // var getRemote = await ServerNames.GetOrCreateAreaServiceAsync(this, ServerGID); // if (getRemote != null) // { // var node = areas.GetOrAdd(getRemote.Address.ServiceNode, (n) => new ValueSortedMap(AreaComparison)); // node.TryAddOrUpdate(getRemote.Address.ServiceName, new AreaInfo(getRemote)); // } //} // TODO 场景最大人数负载 if (areas.Count > 0) { if (expectNodeName != null && areas.TryGetValue(expectNodeName, out var group)) { if (group.Count > 0) { return group.First; } } group = areas.First; if (group.Count > 0) { return group.First; } } throw new Exception("No Area !!!:::::"+ ServerGID); } /// /// 创建场景 /// /// /// public virtual async Task CreateZone(CreateZoneNodeRequest create) { //if (dungeon_scheduler.IsMapOpen(create.mapTemplateID)) { var area = AreaDispatch(create.expectAreaNode); if (area != null) { create.managerZoneUUID = (Guid.NewGuid().ToString()); //先添加以防止二次进入// var map_data = RPGServerTemplateManager.Instance.GetMapTemplate(create.mapTemplateID); var scene_data = RPGServerBattleManager.Instance.GetSceneAsCache(map_data.zone_template_id); ZoneInfo info = new ZoneInfo(create.managerZoneUUID, area, map_data, scene_data, create.serverGroupID, create.guildUUID, create.expectAreaNode) { roomKey = create.roomKey }; zones.AddZone(info); area.currentZoneCount++; var rsp = await area.service.CallAsync(create); if (!Response.CheckSuccess(rsp)) { zones.RemoveZone(create.managerZoneUUID); area.currentZoneCount--; } else { log.InfoFormat("CreateZone: {0} : TotalZoneCount={1}", scene_data, zones.Count); } return rsp; } else { return (new CreateZoneNodeResponse() { s2c_code = CreateZoneNodeResponse.CODE_ERROR, }); } } } /// /// 销毁场景 /// /// /// public virtual async Task DestoryZone(DestoryZoneNodeRequest stop) { ZoneInfo zone = zones.RemoveZone(stop.zoneUUID); if (zone != null) { //log.Log("DestoryZone: " + stop.zoneUUID + " " + stop); zones.RemoveZone(stop.zoneUUID); zone.area.currentZoneCount--; return await zone.area.service.CallAsync(stop); } else { return (new DestoryZoneNodeResponse() { s2c_code = Response.CODE_ERROR, }); } } /// /// 批量创建场景分线 /// /// /// public virtual async Task BatchCreateZoneLine(BatchCreateZoneLineRequest create) { BatchCreateZoneLineResponse response = new BatchCreateZoneLineResponse(); response.zoneList = new List(); foreach (var item in create.zoneList) { var result = await CreateZone(item); ZoneInfoSnap zone = new ZoneInfoSnap(); zone.lineIndex = GetZone(result.zoneUUID).lineIndex; zone.TemplateID = result.TemplateID; zone.uuid = result.zoneUUID; response.zoneList.Add(zone); } return response; } public virtual bool DestoryZone(AreaZoneDestoryNotify stop) { try { ZoneInfo zone = zones.RemoveZone(stop.zoneUUID); if (zone != null) { //log.Log("DestoryZone: " + stop.zoneUUID + " " + stop); zone.area.currentZoneCount--; zone.area.service.Call(new DestoryZoneNodeRequest() { reason = stop.reason, zoneUUID = stop.zoneUUID }, (rsp, err) => { //log.Log("DestoryZone: " + stop.zoneUUID + " " + rsp); }); return true; } } catch (Exception err) { log.Error(err.Message, err); throw err; } return false; } public virtual RoleInfo GetRole(string roleID) { RoleInfo ret; if (roleID != null && roles.TryGetValue(roleID, out ret)) { return ret; } return null; } public virtual ZoneInfo GetZone(string zoneUUID) { return zones.GetZone(zoneUUID); } public virtual ZoneInfo GetZone(int mapId, int lineId) { return zones.GetZone(mapId, lineId); } public ZoneInfo GetGuildZone(string guildUUID) { return zones.GetGuildZone(guildUUID); } public ZoneInfo GetRoomZone(string roomKey) { return zones.GetRoomZone(roomKey); } public List GetZoneList(string serverGroupID, int mapID) { return zones.GetZoneList(serverGroupID, mapID); } public RoleInfo[] GetAllRoles() { var ret = new List(roles.Values); return ret.ToArray(); } public List GetAllZones() { return zones.GetAllZones(); } //------------------------------------------------------------------------------------------------------------------------------------ public class AreaInfo { public readonly IRemoteService service; public readonly string key; public int currentRoleCount { get; internal set; } public int currentZoneCount { get; internal set; } public AreaStateNotify state { get; internal set; } public AreaInfo(IRemoteService svc) { this.service = svc; this.key = svc.Address.ServiceName; this.currentRoleCount = 0; this.currentZoneCount = 0; } public void WriteState(TextWriter sb) { sb.WriteLine("AreaState : " + service.Address.FullPath); sb.WriteLine(" role = " + currentRoleCount); sb.WriteLine(" zone = " + currentZoneCount); if (state != null) { sb.WriteLine(" cpu = " + state.cpuPercent); sb.WriteLine(" memory = " + state.memoryMB + "(MB)"); } } } public class ZoneInfo { public readonly string uuid; public readonly AreaInfo area; public readonly MapTemplateData map_data; public readonly SceneData scene_data; public int currentRoleCount { get; internal set; } public string serverGroupID { get; internal set; } public int lineIndex { get; set; } public string guildUUID { get; set; } public string roomKey { get; internal set; } public bool close { get; internal set; } public string nodeName { get; internal set; } private HashMap TeamIDData = new HashMap(); public ZoneInfo(string uuid, AreaInfo parent, MapTemplateData map_data, SceneData sdata, string serverGroupID, string guildUUID, string nodeName) { this.uuid = uuid; this.area = parent; this.map_data = map_data; this.scene_data = sdata; this.currentRoleCount = 0; this.serverGroupID = serverGroupID; this.guildUUID = guildUUID; this.lineIndex = 1; this.roomKey = roomKey; this.nodeName = nodeName; } public void AddTeamID(string teamID) { if (teamID == null) return; TeamIDData.TryGetValue(teamID, out var count); count++; TeamIDData.Put(teamID, count); } public bool ContainTeamID(string teamID) { if (teamID == null) return false; return TeamIDData.ContainsKey(teamID); } public void RemoveTeamID(string teamID) { if (teamID == null) return; TeamIDData.TryGetValue(teamID, out var count); count--; TeamIDData.Put(teamID, count); if (count <= 0) TeamIDData.Remove(teamID); } public List GetTeamIDList() { return TeamIDData.Keys.ToList(); } } public class RoleInfo { public readonly string uuid; public readonly RoleEnterZoneRequest enter; public ZoneInfo zone { get; internal set; } public RoleInfo(string uuid, RoleEnterZoneRequest req) { this.uuid = uuid; this.enter = req; } } public class ZoneMap { /// /// 所有场景信息 /// private readonly Dictionary zones = new Dictionary(); ///// ///// 所有场景信息 ///// //private readonly Dictionary zonesMap = new Dictionary(); /// /// 所有场景信息> /// private readonly Dictionary> zonesLineMap = new Dictionary>(); /// /// 公会场景集合> /// private readonly Dictionary> guildZones = new Dictionary>(); /// /// 特殊场景信息 > /// private readonly Dictionary roomZones = new Dictionary(); public int Count { get => zones.Count; } public void AddZone(ZoneInfo zone) { zones.Add(zone.uuid, zone); //--------------------------------------------------------------------------------------------- if (RPGServerTemplateManager.Instance.IsPublicMap(zone.map_data)) { Dictionary lt = null; if (!zonesLineMap.TryGetValue(zone.map_data.id, out lt)) { lt = new Dictionary(); zonesLineMap.Add(zone.map_data.id, lt); } AddLine(zone, lt); } //--------------------------------------------------------------------------------------------- if (zone.guildUUID != null) { AddGuildZone(zone.guildUUID, zone); } if (!string.IsNullOrEmpty(zone.roomKey)) { roomZones.Add(zone.roomKey, zone); } } public ZoneInfo GetRoomZone(string roomKey) { if (string.IsNullOrEmpty(roomKey)) { return null; } if (roomZones.TryGetValue(roomKey, out var ret)) { //if (ret.close != true) return ret; } return null; } public ZoneInfo RemoveZone(string uuid) { if (string.IsNullOrEmpty(uuid)) return null; ZoneInfo info; string guildUUID = null; if (zones.TryGetValue(uuid, out info)) { guildUUID = info.guildUUID; zones.Remove(uuid); //--------------------------------------------------------------------------------------------- //分线表删除. zonesLineMap.TryGetValue(info.map_data.id, out var lt); RemoveLine(info.uuid, lt); //--------------------------------------------------------------------------------------------- //公会场景表删除. RemoveGuildZone(uuid, guildUUID); if (!string.IsNullOrEmpty(info.roomKey)) { roomZones.Remove(info.roomKey); } } return info; } public void Clear() { zones.Clear(); zonesLineMap.Clear(); roomZones.Clear(); } // public Dictionary Values() // { // return zones; // } public ZoneInfo GetZone(string uuid) { ZoneInfo ret = null; if (!string.IsNullOrEmpty(uuid) && zones.TryGetValue(uuid, out ret)) { //if (ret.close != true) return ret; } return null; } public ZoneInfo GetZone(int mapId, int lineId) { foreach (var item in zones) { if (item.Value.map_data.id == mapId && item.Value.lineIndex == lineId) { return item.Value; } } return null; } public bool TryGetValue(string uuid, out ZoneInfo zoneinfo) { return zones.TryGetValue(uuid, out zoneinfo); } public void SetZoneCloseFlag(string uuid) { var zone = GetZone(uuid); if (zone != null) zone.close = true; } private void AddLine(ZoneInfo zone, Dictionary lt) { if (lt == null) { lt = new Dictionary(); zone.lineIndex = 1; lt.Add(zone.lineIndex, zone);//默认分线1 return; } else { //遍历当前中所有分线信息 for (int i = 1; i <= lt.Count; i++) { //获取当前不存在的分线ID if (!lt.ContainsKey(i)) { zone.lineIndex = i; lt.Add(zone.lineIndex, zone); return; } } //创建新的分线ID zone.lineIndex = lt.Count + 1; lt.Add(zone.lineIndex, zone);//默认分线1 return; //bool insert = false; //for (int i = 0; i < lt.Count; i++) //{ // if (lt[i] == null) // { // insert = true; // lt[i] = zone; // zone.lineIndex = i + 1; // break; // } //} //if (insert == false) //{ // lt.Add(zone.lineIndex, zone); //} } } private void RemoveLine(string uuid, Dictionary lt) { if (lt == null || lt.Count == 0) return; foreach (var item in lt) { if (item.Value.uuid == uuid) { lt.Remove(item.Key); return; } } } private void AddGuildZone(string guildUUID, ZoneInfo zone) { if (!guildZones.TryGetValue(guildUUID, out var submap)) { submap = new Dictionary(); guildZones.Add(guildUUID, submap); } submap.Add(zone.uuid, zone); } private void RemoveGuildZone(string uuid, string guilduuid) { if (string.IsNullOrEmpty(guilduuid)) return; if (string.IsNullOrEmpty(guilduuid) == false) { guildZones.TryGetValue(guilduuid, out var submap); if (submap != null) { submap.Remove(uuid); if (submap.Count == 0) guildZones.Remove(guilduuid); } } } public ZoneInfo GetGuildZone(string uuid) { if (string.IsNullOrEmpty(uuid)) return null; ZoneInfo ret; if (guildZones.TryGetValue(uuid, out var submap)) { foreach (var item in submap) { ret = item.Value; //if (ret.close != true) return ret; } } return null; } /// /// 获取当前Group内,指定场景的分线信息. /// /// /// /// public List GetZoneList(string serverGroupID, int mapID) { Dictionary lt; List ret; if (zonesLineMap.TryGetValue(mapID, out lt)) { ret = new List(); foreach (var item in lt) { ret.Add(item.Value); } return ret; } return null; } public List GetZones(int templateID) { var all = new List(this.zones.Values); var ret = new List(); foreach (var zoneInfo in all) { if (zoneInfo.map_data.id == templateID /*&& zoneInfo.close != true*/) { ret.Add(zoneInfo); } } return ret; } public List GetAllZones() { return new List(this.zones.Values); //var all = new List(this.zones.Values); //var ret = new List(); //foreach (var zoneInfo in all) //{ // // if (zoneInfo.close != true) // { // ret.Add(zoneInfo); // } //} //return ret; } } //------------------------------------------------------------------------------------------------------------------------------------ #endregion //------------------------------------------------------------------------------------------------------------------------------------ } }