| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643 |
- using DeepCore;
- using DeepCore.GameData.Zone;
- using DeepCore.Log;
- using DeepCrystal.RPC;
- using DeepMMO.Protocol;
- using DeepMMO.Server.AreaManager;
- using DeepMMO.Server.Connect;
- using DeepMMO.Server.SystemMessage;
- using DeepCore.IO;
- using DeepMMO.Server.GameEvent;
- using System;
- using System.Collections.Generic;
- using System.Threading.Tasks;
- using DeepCore.GameEvent;
- using DeepCore.GameEvent.Message;
- using DeepCore.Game3D.Host.Instance;
- using System.Collections.Concurrent;
- using System.IO;
- using DeepCore.GameData;
- namespace DeepMMO.Server.Area
- {
- public class AreaService : IService
- {
- public Random random { get; private set; } = new Random();
- public IDisposable sync_state_timer { get; private set; }
- public IRemoteService area_manager;
- private TypeCodec session_battle_codec;
- public BattleCodec BattleClientCodec { get; }
- public string ServerGroupId;
-
- public AreaService(ServiceStartInfo start) : base(start)
- {
- ServerGroupId = start.Config["groupID"];
- this.BattleClientCodec = new BattleCodec(RPGServerBattleManager.Templates);
- this.session_battle_codec = base.ServerCodec.Factory.GetCodec(typeof(SessionBattleAction));
-
- }
- protected override void OnDisposed()
- {
- }
- protected override async Task OnStartAsync()
- {
- this.area_manager = await ServerNames.GetOrCreateAreaManagerServiceAsync(this, ServerGroupId);
- this.sync_state_timer = this.Provider.CreateTimer(timer_SyncState, this,
- TimeSpan.FromSeconds(0),
- TimeSpan.FromSeconds(TimerConfig.timer_sec_AreaStateNotify));
- await area_manager.CallAsync<RegistAreaResponse>(new RegistAreaRequest()
- {
- areaName = SelfAddress.ServiceName,
- areaNode = SelfAddress.ServiceNode,
- });
- }
- protected override async Task OnStopAsync(ServiceStopInfo reason)
- {
- this.sync_state_timer.Dispose();
- foreach (var item in zoneNodes)
- {
- await item.Value.DoStopAsync();
- }
- }
- public override bool GetState(TextWriter sb)
- {
- ForEachZones(node =>
- {
- sb.WriteLine(CUtils.SequenceChar('-', 100));
- node.GetStatus(sb);
- sb.WriteLine(CUtils.SequenceChar('-', 100));
- });
- return true;
- }
- protected virtual void timer_SyncState(object obj)
- {
- this.area_manager.Invoke(new AreaStateNotify()
- {
- areaName = SelfAddress.ServiceName,
- areaNode = SelfAddress.ServiceNode,
- roleCount = this.PlayerCount,
- zoneCount = this.ZoneNodeCount,
- cpuPercent = 1, // TODO
- memoryMB = 1, // TODO
- });
- this.LogState();
- }
- //[RpcHandler(typeof(SystemStaticServicesStartedNotify))]
- //public virtual void rpc_HandleSystem(SystemStaticServicesStartedNotify shutdown)
- //{
- // area_manager.CallAsync<RegistAreaResponse>(new RegistAreaRequest()
- // {
- // areaName = SelfAddress.ServiceName,
- // areaNode = SelfAddress.ServiceNode,
- // });
- //}
- //-----------------------------------------------------------------------------------------------------------------------------
- [RpcHandler(typeof(ServerGameEventNotify))]
- public virtual void rpc_event_notify(ServerGameEventNotify ntf)
- {
- var emsg = EventMessage.FromBytes(ntf.EventMessageData);
- if (ntf.Broadcast)
- {
- foreach (var node in zoneNodes)
- {
- node.Value.EventMgr?.OnReceiveMessage(emsg);
- }
- }
- else
- {
- var mgr = EventManagerFactory.Instance.GetEventManager(ntf.To);
- mgr?.OnReceiveMessage(emsg);
- }
- }
- //-----------------------------------------------------------------------------------------------------------------------------
- #region __CreateObject__
- //--------------------------------------------------------------------------------------------------------------------------------
- protected virtual AreaZonePlayer CreateZonePlayer(AreaZoneNode node, RoleEnterZoneRequest enter)
- {
- return new AreaZonePlayer(this, node, enter);
- }
- protected virtual AreaZoneNode CreateZoneNode(CreateZoneNodeRequest create, MapTemplateData map)
- {
- return new AreaZoneNode(this, create, map);
- }
- public virtual UnitInfo GetDefaultUnitTemplate()
- {
- return RPGServerBattleManager.DataRoot.Templates.GetUnit(95559);
- }
- public virtual AreaZoneNode GetDefaultZoneNode()
- {
- return random.GetRandomInArray(this.ZoneNodes);
- }
- #endregion
- //-----------------------------------------------------------------------------------------------------------------------------
- #region __ClientToArea__
- //--------------------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// Client -> Session -> Area
- /// </summary>
- [RpcHandler(typeof(SessionBattleAction), true)]
- public virtual void client_rpc_Handle(BinaryMessage action)
- {
- try
- {
- using (var buffer = MemoryStreamObjectPool.AllocAutoRelease(action.DataSegment))
- using (var input = IOStreamObjectPool.AllocInputAutoRelease(base.ServerCodec.Factory, buffer))
- {
- var roleID = input.GetUTF();
- var player = GetPlayer(roleID);
- if (player == null)
- {
- return;
- }
- //drop 4 for bytes size//
- buffer.Position += 4;
- player.client_rpc_Handle(buffer);
- }
- }
- catch (Exception e)
- {
- log.Error(e.Message, e);
- }
- }
- public override void OnWormholeTransported(RemoteAddress from, object message)
- {
- if (message is BinaryMessage bin)
- {
- client_rpc_Handle(bin);
- }
- else if (message is SessionBattleAction ser)
- {
- var player = GetPlayer(ser.roleID);
- if (player == null)
- {
- player.client_rpc_Handle(ser.clientBattleAction);
- }
- }
- }
- #endregion
- //-----------------------------------------------------------------------------------------------------------------------------
- #region __LogicToArea__
- //--------------------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 创建副本
- /// </summary>
- /// <param name="create"></param>
- /// <param name="cb"></param>
- [RpcHandler(typeof(CreateZoneNodeRequest), typeof(CreateZoneNodeResponse), ServerNames.AreaManagerType)]
- public async Task<CreateZoneNodeResponse> area_manager_rpc_CreateZone(CreateZoneNodeRequest create)
- {
- try
- {
- var maptemp = RPGServerTemplateManager.Instance.GetMapTemplate(create.mapTemplateID);
- if (maptemp == null) throw new Exception("No MapTemplate : " + create.mapTemplateID);
- var zoneUUID = create.managerZoneUUID;
- if (zoneNodes.ContainsKey(zoneUUID))
- {
- throw new Exception(string.Format("node instance id ({0}) already exist!", zoneUUID));
- }
- AreaZoneNode node = this.CreateZoneNode(create, maptemp);
- zoneNodes.TryAdd(zoneUUID, node);
- var z = await node.DoStartAsync();
- // log.InfoFormat("Scene Started : {0} : {1}", z.UUID, z.Data);
- return (new CreateZoneNodeResponse()
- {
- areaName = SelfAddress.ServiceName,
- areaNode = SelfAddress.ServiceNode,
- zoneUUID = zoneUUID,
- TemplateID = maptemp.zone_template_id,
- });
- }
- catch (Exception e)
- {
- log.Error("CreateZone failed, error: " + e.Message, e);
- return (new CreateZoneNodeResponse()
- {
- s2c_code = CreateZoneNodeResponse.CODE_ERROR,
- s2c_msg = e.Message,
- });
- }
- }
- /// <summary>
- /// 销毁副本
- /// </summary>
- /// <param name="stop"></param>
- /// <param name="cb"></param>
- [RpcHandler(typeof(DestoryZoneNodeRequest), typeof(DestoryZoneNodeResponse), ServerNames.AreaManagerType)]
- public async Task<DestoryZoneNodeResponse> area_manager_rpc_DestroyZone(DestoryZoneNodeRequest stop)
- {
- try
- {
- if (this.zoneNodes.TryRemove(stop.zoneUUID, out var node))
- {
- //删除场景实例的所有玩家
- node.ZoneNode.ForEachPlayers((p) =>
- {
- try
- {
- using (var player = p.Client as AreaZonePlayer)
- {
- log.Error("DestoryZoneNode Have Player : " + player.RoleUUID);
- players.TryRemove(player.RoleUUID, out var pp);
- }
- }
- catch (Exception err)
- {
- log.Error(err.Message, err);
- }
- });
- await node.DoStopAsync();
- return (new DestoryZoneNodeResponse() { s2c_msg = "done" });
- }
- else
- {
- return (new DestoryZoneNodeResponse() { s2c_msg = "done" });
- }
- }
- catch (Exception e)
- {
- log.Error("DestroyZone failed, error: " + e.Message, e);
- return (new DestoryZoneNodeResponse() { s2c_code = Response.CODE_ERROR, s2c_msg = e.Message });
- }
- }
- /// <summary>
- /// 玩家进入副本
- /// </summary>
- /// <param name="enter"></param>
- /// <param name="cb"></param>
- [RpcHandler(typeof(RoleEnterZoneRequest), typeof(RoleEnterZoneResponse), ServerNames.AreaManagerType)]
- public async Task<RoleEnterZoneResponse> area_manager_rpc_PlayerEnter(RoleEnterZoneRequest enter)
- {
- try
- {
- var node = this.FindZoneNode(enter);
- if (node == null)
- {
- //TODO 分配一个默认场景
- node = this.GetDefaultZoneNode();
- }
- //场景不存在//
- if (node == null)
- {
- return new RoleEnterZoneResponse()
- {
- s2c_code = RoleEnterZoneResponse.CODE_ZONE_NOT_EXIST,
- s2c_msg = $"PlayerEnter: ZoneNotExistException: roleID={enter.roleUUID} zone={enter.expectZoneUUID}"
- };
- }
- if (this.players.TryGetOrCreate(enter.roleUUID, out var player, (uuid) => this.CreateZonePlayer(node, enter)))
- {
- if (player.ZoneNode == node)
- {
- var replace = await node.DoPlayerEnterReplace(player, enter);
- if (replace.IsSuccess) { return replace; }
- this.players.TryGetOrCreate(enter.roleUUID, out player, (uuid) => this.CreateZonePlayer(node, enter));
- return await node.DoPlayerEnterAsync(player, enter);
- }
- else
- {
- return new RoleEnterZoneResponse()
- {
- s2c_code = RoleEnterZoneResponse.CODE_ZONE_NOT_EXIST,
- s2c_msg = $"PlayerEnter: ZoneNotExistException: roleID={enter.roleUUID} zone={enter.expectZoneUUID}"
- };
- }
- }
- else
- {
- return await node.DoPlayerEnterAsync(player, enter);
- }
- }
- catch (Exception e)
- {
- log.Error(e.Message, e);
- return new RoleEnterZoneResponse() { s2c_code = Response.CODE_ERROR, s2c_msg = e.Message };
- }
- }
- /// <summary>
- /// 玩家离开副本
- /// </summary>
- /// <param name="leave"></param>
- /// <param name="cb"></param>
- [RpcHandler(typeof(RoleLeaveZoneRequest), typeof(RoleLeaveZoneResponse), ServerNames.AreaManagerType)]
- public async Task<RoleLeaveZoneResponse> area_manager_rpc_PlayerLeave(RoleLeaveZoneRequest leave)
- {
- try
- {
- if (this.players.TryRemove(leave.roleID, out var player))
- {
- using (player)
- {
- AreaZoneNode node = player.ZoneNode;
- if (node == null)
- {
- return (new RoleLeaveZoneResponse()
- {
- s2c_code = RoleLeaveZoneResponse.CODE_ROLE_NOT_EXIST,
- s2c_msg = $"PlayerLeave: ZoneNotExistException: roleID={leave.roleID} zone={player.ZoneUUID}"
- });
- }
- return await node.DoPlayerLeaveAsync(player, leave);
- }
- }
- else
- {
- return (new RoleLeaveZoneResponse()
- {
- s2c_code = RoleLeaveZoneResponse.CODE_ROLE_NOT_EXIST,
- s2c_msg = $"PlayerLeave: PlayerNotExistException: roleID=roleID={leave.roleID} zone={leave.zoneUUID}"
- });
- }
- }
- catch (Exception e)
- {
- log.Error(e.Message, e);
- return (new RoleLeaveZoneResponse() { s2c_code = Response.CODE_ERROR, s2c_msg = e.Message });
- }
- }
- [RpcHandler(typeof(GetRolePositionRequest), typeof(GetRolePositionResponse), ServerNames.AreaManagerType)]
- public async Task<GetRolePositionResponse> area_manager_rpc_GetRolePosition(GetRolePositionRequest req)
- {
- var resp = new GetRolePositionResponse();
- if (players.TryGetValue(req.roleUUID, out var role))
- {
- return await role.ZoneNode.DoGetPlayerPosition(role, req);
- }
- else
- {
- resp.s2c_code = GetRolePositionResponse.CODE_ROLE_NOT_EXIST;
- return resp;
- }
- }
- //-----------------------------------------------------------------------------------------------------------------------------
- /// <summary>
- /// 玩家数据改变
- /// </summary>
- /// <param name="changed"></param>
- [RpcHandler(typeof(RoleDataChangedNotify))]
- public void logic_rpc_PlayerNetStateChanged(RoleDataChangedNotify changed)
- {
- AreaZonePlayer player;
- AreaZoneNode node;
- try
- {
- if (TryGetPlayer(changed.roleID, out player, out node))
- {
- player.logic_rpc_Handle(changed.roleData);
- }
- }
- catch (Exception e)
- {
- log.Error(e.Message, e);
- }
- }
- /// <summary>
- /// 玩家断开连接
- /// </summary>
- /// <param name="disconnect"></param>
- [RpcHandler(typeof(SessionDisconnectNotify))]
- public void logic_rpc_Handle(SessionDisconnectNotify disconnect)
- {
- AreaZonePlayer player;
- AreaZoneNode node;
- try
- {
- if (TryGetPlayer(disconnect.roleID, out player, out node))
- {
- node.DoPlayerDisconnect(player);
- }
- }
- catch (Exception e)
- {
- log.Error(e.Message, e);
- }
- }
- /// <summary>
- /// 玩家重新连接
- /// </summary>
- /// <param name="disconnect"></param>
- [RpcHandler(typeof(SessionReconnectNotify))]
- public void logic_rpc_Handle(SessionReconnectNotify reconnect)
- {
- AreaZonePlayer player;
- AreaZoneNode node;
- try
- {
- if (TryGetPlayer(reconnect.roleID, out player, out node))
- {
- node.DoPlayerReconnect(player);
- }
- }
- catch (Exception e)
- {
- log.Error(e.Message, e);
- }
- }
- [RpcHandler(typeof(SessionBeginLeaveRequest), typeof(SessionBeginLeaveResponse))]
- public async Task<SessionBeginLeaveResponse> logic_rpc_Handle(SessionBeginLeaveRequest leave)
- {
- try
- {
- if (this.players.TryGetValue(leave.roleID, out var player))
- {
- var node = player.ZoneNode;
- if (node != null)
- {
- await node.DoPlayerBeginLeaveAsync(player);
- return (new SessionBeginLeaveResponse() { s2c_code = Response.CODE_OK });
- }
- }
- return (new SessionBeginLeaveResponse() { s2c_code = Response.CODE_ERROR });
- }
- catch (Exception e)
- {
- log.Warn(e.Message, e);
- return (new SessionBeginLeaveResponse() { s2c_code = Response.CODE_ERROR, s2c_msg = e.Message });
- }
- }
- #endregion
- //-----------------------------------------------------------------------------------------------------------------------------
- #region __ZoneAndPlayer__
- //--------------------------------------------------------------------------------------------------------------------------------
- private ConcurrentDictionary<string, AreaZoneNode> zoneNodes = new ConcurrentDictionary<string, AreaZoneNode>();
- private ConcurrentDictionary<string, AreaZonePlayer> players = new ConcurrentDictionary<string, AreaZonePlayer>();
- public int PlayerCount
- {
- get { { return players.Count; } }
- }
- public int ZoneNodeCount
- {
- get { { return zoneNodes.Count; } }
- }
- public List<AreaZoneNode> ZoneNodes
- {
- get { { return new List<AreaZoneNode>(zoneNodes.Values); } }
- }
- public List<AreaZonePlayer> ZonePlayers
- {
- get { { return new List<AreaZonePlayer>(players.Values); } }
- }
- public void ForEachPlayers(Action<AreaZonePlayer> action)
- {
- using (var list = CollectionObjectPool<AreaZonePlayer>.AllocList())
- {
- { list.AddRange(players.Values); }
- foreach (var p in list) { action(p); }
- }
- }
- public void ForEachZones(Action<AreaZoneNode> action)
- {
- using (var list = CollectionObjectPool<AreaZoneNode>.AllocList())
- {
- { list.AddRange(zoneNodes.Values); }
- foreach (var z in list) { action(z); }
- }
- }
- public AreaZoneNode GetZoneNode(string zoneUUID)
- {
- if (zoneNodes.TryGetValue(zoneUUID, out var ret))
- {
- return ret;
- }
- return null;
- }
- public AreaZoneNode FindZoneNode(RoleEnterZoneRequest enter)
- {
- {
- if (enter.expectZoneUUID != null && zoneNodes.TryGetValue(enter.expectZoneUUID, out var node))
- {
- return node;
- }
- if (enter.expectMapTemplateID != 0)
- {
- foreach (var e in zoneNodes.Values)
- {
- if (e.MapTemplateID == enter.expectMapTemplateID)
- {
- return e;
- }
- }
- }
- }
- return null;
- }
- public AreaZonePlayer GetPlayer(string roleID)
- {
- if (roleID != null && players.TryGetValue(roleID, out var ret))
- {
- return ret;
- }
- return null;
- }
- public bool TryGetPlayer(string roleID, out AreaZonePlayer player, out AreaZoneNode node)
- {
- if (roleID != null && players.TryGetValue(roleID, out player))
- {
- node = player.ZoneNode;
- // if (node == null)
- // {
- // throw new Exception("PlayerLeave: InstanceNotExistException: " + player.ZoneUUID);
- // }
- return true;
- }
- player = null;
- node = null;
- // else
- // {
- // //throw new Exception("PlayerLeave: PlayerNotExistException roleID: " + roleID);
- // }
- return false;
- }
- /// <summary>
- /// 异步执行战斗场景内交互代码
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="zoneUUID"></param>
- /// <param name="func"></param>
- /// <returns></returns>
- public Task<T> QueueZoneTaskAsync<T>(string zoneUUID, Func<InstanceZone, T> func)
- {
- if (zoneNodes.TryGetValue(zoneUUID, out var node))
- {
- return node.ZoneNode.QueueSceneTaskAsync<T>(func);
- }
- return Task.FromResult<T>(func(null));
- }
- /// <summary>
- /// 异步执行战斗场景内交互代码
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="roleUUID"></param>
- /// <param name="func"></param>
- /// <returns></returns>
- public Task<T> QueuePlayerTaskAsync<T>(string roleUUID, Func<InstancePlayer, T> func)
- {
- if (roleUUID != null && players.TryGetValue(roleUUID, out var player))
- {
- var node = player.ZoneNode;
- return node.ZoneNode.QueuePlayerTaskAsync<T>(roleUUID, func);
- }
- return Task.FromResult<T>(func(null));
- }
- /// <summary>
- /// 异步执行战斗场景内交互代码
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="zoneUUID"></param>
- /// <param name="func"></param>
- /// <returns></returns>
- public Task<T> QueueZoneTaskAsync<T>(string zoneUUID, Func<AreaZoneNode, InstanceZone, T> func)
- {
- if (zoneNodes.TryGetValue(zoneUUID, out var node))
- {
- return node.ZoneNode.QueueSceneTaskAsync<T>(z => func(node, z));
- }
- return Task.FromResult<T>(func(null, null));
- }
- /// <summary>
- /// 异步执行战斗场景内交互代码
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="roleUUID"></param>
- /// <param name="func"></param>
- /// <returns></returns>
- public Task<T> QueuePlayerTaskAsync<T>(string roleUUID, Func<AreaZonePlayer, InstancePlayer, T> func)
- {
- if (roleUUID != null && players.TryGetValue(roleUUID, out var player))
- {
- var node = player.ZoneNode;
- return node.ZoneNode.QueuePlayerTaskAsync<T>(roleUUID, p => func(player, p));
- }
- return Task.FromResult<T>(func(null, null));
- }
- #endregion
- //-----------------------------------------------------------------------------------------------------------------------------
- }
- }
|