예제 #1
0
        static async Task triggerTimer(long actorId, string actorType, string handlerType, Param param)
        {
            try
            {
                var handler   = HotfixMgr.GetInstance <ITimerHandler>(handlerType);
                var agentType = handler.GetType().BaseType.GenericTypeArguments[0];
                if (agentType.GetInterface(typeof(IComponentActorAgent).FullName) != null)
                {
                    //actor
                    var agent = await ActorManager.GetOrNew(agentType, actorId);

                    var actor = (ComponentActor)agent.Owner;
                    _ = actor.SendAsync(() => handler.InternalHandleTimer(agent, param), false);
                }
                else if (agentType.GetInterface(typeof(IComponentAgent).FullName) != null)
                {
                    //component
                    var actorAgentType = HotfixMgr.GetType(actorType, agentType);
                    var compType       = agentType.BaseType.GenericTypeArguments[0];
                    var agent          = await ActorManager.GetOrNew(actorAgentType, actorId);

                    var actor = (ComponentActor)agent.Owner;
                    var comp  = await actor.GetComponent(compType);

                    _ = actor.SendAsync(() => handler.InternalHandleTimer(comp.GetAgent(agentType), param), false);
                }
            }
            catch (Exception e)
            {
                LOGGER.Error(e.ToString());
            }
        }
예제 #2
0
        public static async Task Remove(Channel channel)
        {
            if (channel != null)
            {
                channels.TryRemove(channel.Id, out var se);
                if (se == null)
                {
                    return;
                }

                LOGGER.Info("移除channel {}", channel.Id);
                var actor = await ActorManager.Get <ComponentActor>(channel.Id);

                if (actor != null)
                {
                    if (actor is IChannel chl)
                    {
                        _ = actor.SendAsync(chl.OnDisconnect);
                    }
                    if (actor.TransformAgent <IChannel>(out var chAgent))
                    {
                        _ = actor.SendAsync(chAgent.OnDisconnect);
                    }
                }
            }
        }
예제 #3
0
        protected override void ChannelRead0(IChannelHandlerContext ctx, IMessage msg)
        {
            if (!Settings.Ins.AppRunning)
            {
                return;
            }

            //直接在当前io线程处理
            IEventLoop group = ctx.Channel.EventLoop;

            group.Execute(async() =>
            {
                var handler = TcpHandlerFactory.GetHandler(msg.GetMsgId());
                LOGGER.Debug($"-------------server msg {msg.GetMsgId()} {msg.GetType()}");

                if (handler == null)
                {
                    LOGGER.Error("找不到对应的handler " + msg.GetMsgId());
                    return;
                }

                //握手
                var channel = ctx.Channel.GetAttribute(ChannelManager.Att_Channel).Get();
                if (channel != null)
                {
                    var actor = await ActorManager.Get <ComponentActor>(channel.Id);
                    if (actor != null)
                    {
                        if (actor is IChannel ise)
                        {
                            _ = actor.SendAsync(ise.Hand);
                        }
                        if (actor.TransformAgent <IChannel>(out var seAgent))
                        {
                            _ = actor.SendAsync(seAgent.Hand);
                        }
                    }
                }

                handler.Time = DateTime.Now;
                handler.Ctx  = ctx;
                handler.Msg  = msg;
                if (handler is TcpActorHandler actorHandler)
                {
                    actorHandler.Actor = await actorHandler.CacheActor();
                    if (actorHandler.Actor != null)
                    {
                        await actorHandler.Actor.SendAsync(actorHandler.ActionAsync);
                    }
                    else
                    {
                        LOGGER.Error($"handler actor 为空 {msg.GetMsgId()} {handler.GetType()}");
                    }
                }
                else
                {
                    await handler.ActionAsync();
                }
            });
        }
예제 #4
0
        public async Task <bool> OnLoadSucceed(bool isReload)
        {
            try
            {
                HttpHandlerFactory.SetExtraHandlerGetter(HotfixMgr.GetHttpHandler);
                TcpHandlerFactory.SetExtraHandlerGetter(Geek.Server.Message.MsgFactory.Create, msgId => HotfixMgr.GetHandler <BaseTcpHandler>(msgId));

                if (isReload)
                {
                    //热更
                    LOGGER.Info("hotfix load success");
                    await ActorManager.ActorsForeach((actor) =>
                    {
                        actor.SendAsync(actor.ClearCacheAgent, false);
                        return(Task.CompletedTask);
                    });
                }
                else
                {
                    //起服
                    if (!await Start())
                    {
                        return(false);
                    }
                }
                return(true);
            }
            catch (Exception e)
            {
                LOGGER.Fatal("OnLoadSucceed执行异常");
                LOGGER.Fatal(e.ToString());
                return(false);
            }
        }
        public void DispatchEvent(int evtType, Func <int, TActor, Type, Task <bool> > checkDispatchFunc, Param param = null)
        {
            lineActor.SendAsync(async() =>
            {
                if (!eventHandlers.ContainsKey(evtType))
                {
                    return;
                }

                Event evt   = new Event();
                evt.EventId = evtType;
                evt.Data    = param;
                var list    = eventHandlers[evtType];
                foreach (var evtInfo in list)
                {
                    var actor = await ActorManager.Get <TActor>(evtInfo.ActorId);
                    if (actor == null)
                    {
                        continue;
                    }

                    var info = evtInfo; //需要存个临时变量
                    _        = actor.SendAsync(async() =>
                    {
                        try
                        {
                            var handler   = HotfixMgr.GetInstance <IEventListener>(info.AgentHandler);
                            var agentType = handler.GetType().BaseType.GenericTypeArguments[0];
                            if (agentType.GetInterface(typeof(IComponentActorAgent).FullName) != null)
                            {
                                //actor
                                if (checkDispatchFunc != null && !(await checkDispatchFunc(evtType, actor, null)))
                                {
                                    return;
                                }
                                await handler.InternalHandleEvent(actor.GetAgent(agentType), evt);
                            }
                            else if (agentType.GetInterface(typeof(IComponentAgent).FullName) != null)
                            {
                                //component
                                var compType = agentType.BaseType.GenericTypeArguments[0];
                                if (checkDispatchFunc != null && !(await checkDispatchFunc(evtType, actor, compType)))
                                {
                                    return;
                                }
                                var comp = await actor.GetComponent(compType);
                                await handler.InternalHandleEvent(actor.GetAgent(agentType), evt);
                            }
                        }
                        catch (Exception e)
                        {
                            LOGGER.Error(e.ToString());
                        }
                    }, false);
                }
            }, false);
        }
예제 #6
0
        async Task <bool> Start()
        {
            try
            {
                LOGGER.Info("start server......");
                await HttpServer.Start(Settings.Ins.HttpPort);

                await TcpServer.Start(Settings.Ins.TcpPort, Settings.Ins.UseLibuv);

                LOGGER.Info("init mongodb......" + Settings.Ins.MongoUrl);
                MongoDBConnection.Singleton.Connect(Settings.Ins.MongoDB, Settings.Ins.MongoUrl);

                LOGGER.Info("启动回存timer......");
                GlobalDBTimer.Singleton.Start();

                LOGGER.Info("注册所有组件......");
                ComponentTools.RegistAllComps();

                LOGGER.Info("load配置表...");
                (bool success, string msg) = GameDataManager.ReloadAll();
                if (!success)
                {
                    return(false);
                }

                LOGGER.Info("激活所有全局actor...");
                var taskList = new List <Task>();
                taskList.Add(activeActorAndItsComps <ServerActorAgent>(ServerActorID.GetID(ActorType.Normal)));
                //激活其他全局actor

                await Task.WhenAll(taskList);

                var serverActor = await ActorManager.GetOrNew <ServerActorAgent>(ServerActorID.GetID(ActorType.Normal));

                _ = serverActor.SendAsync(serverActor.CheckCrossDay);

                return(true);
            }catch (Exception e)
            {
                LOGGER.Fatal("起服失败\n" + e.ToString());
                return(false);
            }
        }
예제 #7
0
        /// <summary>
        /// actor永久消失,清除actor数据库数据,比如公会解散,玩家清档等
        /// </summary>
        public async Task Dieout()
        {
            if (GetAgent() is IDeadable deadable)
            {
                await deadable.Dieout();
            }

            ReadOnly = true;
            ConstCompTypeList.Clear();
            await Deactive();

            await ActorManager.Remove(ActorId, false);

            var list = ComponentMgr.Singleton.GetAllComps(this);
            var die  = new DieoutComp();

            die.Init(this);
            await die.Active();

            await die.Dieout(list);
        }
예제 #8
0
        public static async Task RemoveAll()
        {
            var taskList = new List <Task>();
            var list     = channels.Values;

            foreach (var ch in list)
            {
                _ = ch.Ctx.CloseAsync();
                var actor = await ActorManager.Get <ComponentActor>(ch.Id);

                if (actor != null)
                {
                    var task = actor.SendAsync(() => Task.Delay(1));
                    taskList.Add(task);
                }
                await Remove(ch);
            }
            //保证此函数执行完后所有actor队列为空
            if (await Task.WhenAll(taskList).WaitAsync(TimeSpan.FromSeconds(30)))
            {
                LOGGER.Error("remove all channel timeout");
            }
        }
예제 #9
0
        public async Task <bool> Stop()
        {
            try
            {
                await QuartzTimer.Stop();

                await ChannelManager.RemoveAll();

                await GlobalDBTimer.Singleton.OnShutdown();

                await ActorManager.RemoveAll();

                await TcpServer.Stop();

                await HttpServer.Stop();

                return(true);
            }catch (Exception e)
            {
                LOGGER.Fatal(e.ToString());
                return(false);
            }
        }
예제 #10
0
        protected override void ChannelRead0(IChannelHandlerContext ctx, IMessage msg)
        {
            if (!Settings.Ins.AppRunning)
            {
                return;
            }

            //直接在当前io线程处理
            IEventLoop group = ctx.Channel.EventLoop;

            group.Execute(async() =>
            {
                try
                {
                    var handler = TcpHandlerFactory.GetHandler(msg.GetMsgId());
                    LOGGER.Debug($"-------------get msg {msg.GetMsgId()} {msg.GetType()}");

                    if (handler == null)
                    {
                        LOGGER.Error("找不到对应的handler " + msg.GetMsgId());
                        return;
                    }

                    //握手
                    var channel = ctx.Channel.GetAttribute(ChannelManager.Att_Channel).Get();
                    if (channel != null)
                    {
                        var actor = await ActorManager.Get <ComponentActor>(channel.Id);
                        if (actor != null)
                        {
                            if (actor is IChannel ise)
                            {
                                _ = actor.SendAsync(ise.Hand);
                            }
                            if (actor.TransformAgent <IChannel>(out var seAgent))
                            {
                                _ = actor.SendAsync(seAgent.Hand);
                            }
                        }
                    }

                    handler.Time = DateTime.Now;
                    handler.Ctx  = ctx;
                    handler.Msg  = msg;

                    if (handler.GetType().Assembly != msg.GetType().Assembly)
                    {
                        //仅热更瞬间有极小几率触发
                        LOGGER.Debug("热更过程替换msg和handler 重新构造msg让msg和handler来自同一个dll");
                        var data   = msg.Serialize();
                        var newMsg = TcpHandlerFactory.GetMsg(msg.GetMsgId());
                        newMsg.Deserialize(data);
                        handler.Msg = newMsg;
                    }

                    if (handler is TcpActorHandler actorHandler)
                    {
                        actorHandler.Actor = await actorHandler.CacheActor();
                        if (actorHandler.Actor != null)
                        {
                            await actorHandler.Actor.SendAsync(actorHandler.ActionAsync);
                        }
                        else
                        {
                            LOGGER.Error($"handler actor 为空 {msg.GetMsgId()} {handler.GetType()}");
                        }
                    }
                    else
                    {
                        await handler.ActionAsync();
                    }
                }
                catch (Exception e)
                {
                    LOGGER.Error(e.ToString());
                }
            });
        }
예제 #11
0
        async Task activeActorAndItsComps <TActorAgent>(long actorId) where TActorAgent : IComponentActorAgent
        {
            var actor = await ActorManager.GetOrNew <TActorAgent>(actorId);

            await((ComponentActor)actor.Owner).ActiveAllComps();
        }
예제 #12
0
        async Task timerLoop()
        {
            var random    = new System.Random();
            int onceDelta = 1000;
            int delayTime = 0;
            int saveTime  = random.Next(Settings.Ins.DataFlushTimeMin, Settings.Ins.DataFlushTimeMax);

            while (delayTime < saveTime * 1000)
            {
                //不能一次性delay,退出程序时监听不到
                await Task.Delay(onceDelta);

                delayTime += onceDelta;
                if (!Working)
                {
                    break;
                }
            }

            while (Working)
            {
                var start = DateTime.Now;

                await StateComponent.TimerSave();

                var delta = DateTime.Now - start;
                LOGGER.Info("db timer save state time:{}毫秒", delta.TotalMilliseconds);
                if (!Working)
                {
                    break;
                }

                await ActorManager.CheckIdle();

                delta = DateTime.Now - start;
                LOGGER.Info("db timer loop time:{}毫秒", delta.TotalMilliseconds);

                if (!Working)
                {
                    break;
                }

                int delay = 10000;
                if (delta.TotalSeconds < saveTime)
                {
                    delay = (saveTime - (int)delta.TotalSeconds) * 1000;
                }

                delayTime = 0;
                while (delayTime < delay)
                {
                    await Task.Delay(onceDelta);

                    delayTime += onceDelta;
                    if (!Working)
                    {
                        break;
                    }
                }
            }
            LOGGER.Info("exit db timer loop...");
        }