Exemplo n.º 1
0
        public Monster(Int32 UniqId, MonsterInfo aInfo, Generator aGenerator)
            : base(UniqId)
        {
            this.Id     = (Int16)aInfo.Id;
            this.Name   = aInfo.Name;
            this.AIType = aInfo.AIType;
            mLook       = aInfo.Look;
            this.Level  = aInfo.Level;
            this.CurHP  = aInfo.Life;
            this.MaxHP  = aInfo.Life;

            this.Dexterity = aInfo.Dexterity;
            this.MinAtk    = (Int32)Math.Min(aInfo.MinAtk, aInfo.MaxAtk);
            this.MaxAtk    = (Int32)Math.Max(aInfo.MinAtk, aInfo.MaxAtk);
            this.Defence   = (UInt16)aInfo.Defense;
            this.Dodge     = aInfo.Dodge;
            this.AtkRange  = aInfo.AtkRange;
            this.ViewRange = aInfo.ViewRange;
            this.AtkSpeed  = aInfo.AtkSpeed;
            this.MoveSpeed = aInfo.MoveSpeed;

            this.MagicDef   = (Int32)aInfo.MagicDef;
            this.MagicAtk   = (Int32)aInfo.MaxAtk;
            this.MagicType  = (UInt16)aInfo.MagicType;
            this.MagicLevel = 0;

            if (aInfo.MagicType != 0)
            {
                this.AtkType = 21;
            }
            else
            {
                this.AtkType = 2;
            }

            this.DropMoney = (Int32)aInfo.DropMoney;
            this.DropHP    = (Int32)aInfo.DropHP;
            this.DropMP    = (Int32)aInfo.DropMP;
            DropArmet      = aInfo.DropArmet;
            DropNecklace   = aInfo.DropNecklace;
            DropArmor      = aInfo.DropArmor;
            DropRing       = aInfo.DropRing;
            DropWeapon     = aInfo.DropWeapon;
            DropShield     = aInfo.DropShield;
            DropShoes      = aInfo.DropShoes;

            mOnDie = aInfo.OnDie;

            mGenerator = aGenerator;
            //this.RespawnSpeed = RespawnSpeed;
            this.Disappeared = false;

            this.LastDieTime = -1;

            this.Timer          = new Timer();
            this.Timer.Interval = 500;
            this.Timer.Elapsed += new ElapsedEventHandler(Process);

            this.Brain = new MonsterAI(this, 500, MoveSpeed, AtkSpeed, ViewRange, 5, AtkRange);
        }
Exemplo n.º 2
0
        private static void OnTimedEvent(object source)
        {
            ScheduleTask task = source as ScheduleTask;

            if (task is MonsterTask)
            {
                MonsterTask monsterTask = task as MonsterTask;
                if (monsterTask.mapCode == 1)
                {
                    long ticks1 = TimeUtil.NOW();
                    SysConOut.WriteLine("----------------------------------时间触发器时间间隔----------------------------" + (ticks1 - ScheduleExecutor2.Instance.Oldticks).ToString());
                    ScheduleExecutor2.Instance.Oldticks = ticks1;
                }
            }
            if (task.InternalLock.TryEnter())
            {
                bool logRunTime = false;
                long nowTicks   = TimeUtil.CurrentTicksInexact;
                try
                {
                    task.run();
                }
                catch (System.Exception ex)
                {
                    LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString()));
                }
                finally
                {
                    logRunTime = task.InternalLock.Leave();
                }

                if (logRunTime)
                {
                    long finishTicks = TimeUtil.CurrentTicksInexact;
                    if (finishTicks - nowTicks > TimeUtil.SECOND)
                    {
                        try
                        {
                            MonsterTask monsterTask = task as MonsterTask;
                            if (null != monsterTask)
                            {
                                LogManager.WriteLog(LogTypes.Error, string.Format("{0} mapCode:{1},subMapCode:{2},执行时间:{3}毫秒"
                                                                                  , task.ToString(), monsterTask.mapCode, monsterTask.subMapCode, finishTicks - nowTicks));
                            }
                            else
                            {
                                LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时间:{1}毫秒", task.ToString(), finishTicks - nowTicks));
                            }
                        }
                        catch
                        {
                            //写日志异常就不记了
                        }
                    }
                }
            }
        }
Exemplo n.º 3
0
        public void ThreadFunction()
        {
            while (true)
            {
                foreach (var s in TimerDict)
                {
                    ScheduleTask task = s.Key as ScheduleTask;
                    if (task.InternalLock.TryEnter())
                    {
                        bool logRunTime = false;
                        long nowTicks   = TimeUtil.CurrentTicksInexact;
                        try
                        {
                            task.run();
                        }
                        catch (System.Exception ex)
                        {
                            LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString()));
                        }
                        finally
                        {
                            logRunTime = task.InternalLock.Leave();
                        }

                        if (logRunTime)
                        {
                            long finishTicks = TimeUtil.CurrentTicksInexact;
                            if (finishTicks - nowTicks > TimeUtil.SECOND)
                            {
                                try
                                {
                                    MonsterTask monsterTask = task as MonsterTask;
                                    if (null != monsterTask)
                                    {
                                        LogManager.WriteLog(LogTypes.Error, string.Format("{0} mapCode:{1},subMapCode:{2},执行时间:{3}毫秒"
                                                                                          , task.ToString(), monsterTask.mapCode, monsterTask.subMapCode, finishTicks - nowTicks));
                                    }
                                    else
                                    {
                                        LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时间:{1}毫秒", task.ToString(), finishTicks - nowTicks));
                                    }
                                }
                                catch
                                {
                                    //写日志异常就不记了
                                }
                            }
                        }
                    }
                }
                Thread.Sleep(2000);
            }
        }
Exemplo n.º 4
0
        private static void OnTimedEvent(object source)
        {
            ScheduleTask task = source as ScheduleTask;

            if (task.InternalLock.TryEnter())
            {
                bool logRunTime = false;
                long nowTicks   = TimeUtil.CurrentTicksInexact;
                try
                {
                    task.run();
                }
                catch (Exception ex)
                {
                    LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString()), null, true);
                }
                finally
                {
                    logRunTime = task.InternalLock.Leave();
                }
                if (logRunTime)
                {
                    long finishTicks = TimeUtil.CurrentTicksInexact;
                    if (finishTicks - nowTicks > 1000L)
                    {
                        try
                        {
                            MonsterTask monsterTask = task as MonsterTask;
                            if (null != monsterTask)
                            {
                                LogManager.WriteLog(LogTypes.Error, string.Format("{0} mapCode:{1},subMapCode:{2},执行时间:{3}毫秒", new object[]
                                {
                                    task.ToString(),
                                    monsterTask.mapCode,
                                    monsterTask.subMapCode,
                                    finishTicks - nowTicks
                                }), null, true);
                            }
                            else
                            {
                                LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时间:{1}毫秒", task.ToString(), finishTicks - nowTicks), null, true);
                            }
                        }
                        catch
                        {
                        }
                    }
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// 周期性任务
        /// </summary>
        /// <param name="task">任务</param>
        /// <param name="delay">延迟开始时间(毫秒)</param>
        /// <param name="periodic">间隔周期时间(毫秒)</param>
        /// <returns></returns>
        public void scheduleExecute(ScheduleTask task, int delay, int periodic)
        {
            if (periodic < 15 || periodic > 86400 * 1000)
            {
                throw new Exception("不正确的调度时间间隔periodic = " + periodic);
            }

            if (delay <= 0)
            {
                delay = periodic;
            }
            lock (this)
            {
                Timer timer;
                if (!TimerDict.TryGetValue(task, out timer))
                {
                    int szDuetime = Global.GetRandomNumber(delay / 2, delay * 3 / 2);
                    timer = new Timer(OnTimedEvent, task, szDuetime, periodic);
                    TimerDict.Add(task, timer);
                    if (task is MonsterTask)
                    {
                        MonsterTask monsterTask = task as MonsterTask;
                        if (monsterTask.mapCode == 1)
                        {
                            SysConOut.WriteLine(string.Format("Duetime = {0} periodic = {1}", szDuetime, periodic));
                        }
                    }
                }
                else
                {
                    timer.Change(periodic, periodic);
                    if (task is MonsterTask)
                    {
                        MonsterTask monsterTask = task as MonsterTask;
                        if (monsterTask.mapCode == 1)
                        {
                            SysConOut.WriteLine(string.Format("periodic = {0} periodic = {1}", periodic, periodic));
                        }
                    }
                }
            }
        }
Exemplo n.º 6
0
        private static void OnTimedEvent(object source)
        {
            ScheduleTask task = source as ScheduleTask;

            if (task.InternalLock.TryEnter())
            {
                try
                {
                    task.run();
                }
                catch (System.Exception ex)
                {
                    LogManager.WriteLog(LogTypes.Error, string.Format("{0}执行时异常,{1}", task.ToString(), ex.ToString()));
                }
                finally
                {
                    task.InternalLock.Leave();
                }
            }
            else
            {
                try
                {
                    MonsterTask monsterTask = task as MonsterTask;
                    if (null != monsterTask)
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("{0}自身执行时间超过设定的时间间隔,本次执行取消,mapCode:{1},subMapCode:{2}"
                                                                          , task.ToString(), monsterTask.mapCode, monsterTask.subMapCode));
                    }
                    else
                    {
                        LogManager.WriteLog(LogTypes.Error, string.Format("{0}自身执行时间超过设定的时间间隔,本次执行取消", task.ToString()));
                    }
                }
                catch
                {
                    //写日志异常就不记了
                }
            }
        }
Exemplo n.º 7
0
        public static void GetMonstersInfo()
        {
            sLogger.Info("Loading monsters informations...");

            using (var connection = sDefaultPool.GetConnection())
            {
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = (
                        "SELECT `id`, `name`, `type`, `ai_type`, `look`, `level`, `life`, `escape_life`, " +
                        "`attack_user`, `attack_min`, `attack_max`, `defense`, `dexterity`, `dodge`, " +
                        "`magic_type`, `magic_def`, `magic_hitrate`, `view_range`, `attack_range`, " +
                        "`attack_speed`, `move_speed`, `run_speed`, " +
                        "`drop_armet`, `drop_necklace`, `drop_armor`, `drop_ring`, `drop_weapon`, `drop_shield`, `drop_shoes`, " +
                        "`drop_money`, `drop_hp`, `drop_mp`, `extra_exp`, `extra_damage` FROM `monstertype`");
                    command.Prepare();

                    sLogger.Debug("Executing SQL: {0}", GetSqlCommand(command));

                    using (var reader = command.ExecuteReader())
                    {
                        while (reader.Read())
                        {
                            MonsterInfo monster_type = new MonsterInfo
                            {
                                Id           = reader.GetInt32("id"),
                                Name         = reader.GetString("name"),
                                Type         = reader.GetByte("type"),
                                AIType       = reader.GetByte("ai_type"),
                                Look         = reader.GetUInt32("look"),
                                Level        = reader.GetByte("level"),
                                Life         = reader.GetUInt16("life"),
                                EscapeLife   = reader.GetUInt16("escape_life"),
                                AtkUser      = reader.GetByte("attack_user"),
                                MinAtk       = reader.GetUInt32("attack_min"),
                                MaxAtk       = reader.GetUInt32("attack_max"),
                                Defense      = reader.GetUInt32("defense"),
                                Dexterity    = reader.GetByte("dexterity"),
                                Dodge        = reader.GetByte("dodge"),
                                MagicType    = reader.GetUInt16("magic_type"),
                                MagicDef     = reader.GetUInt32("magic_def"),
                                MagicHitrate = reader.GetUInt32("magic_hitrate"),
                                ViewRange    = reader.GetByte("view_range"),
                                AtkRange     = reader.GetByte("attack_range"),
                                AtkSpeed     = reader.GetUInt16("attack_speed"),
                                MoveSpeed    = reader.GetUInt16("move_speed"),
                                RunSpeed     = reader.GetUInt16("run_speed"),
                                DropArmet    = reader.GetByte("drop_armet"),
                                DropNecklace = reader.GetByte("drop_necklace"),
                                DropArmor    = reader.GetByte("drop_armor"),
                                DropRing     = reader.GetByte("drop_ring"),
                                DropWeapon   = reader.GetByte("drop_weapon"),
                                DropShield   = reader.GetByte("drop_shield"),
                                DropShoes    = reader.GetByte("drop_shoes"),
                                DropMoney    = reader.GetUInt32("drop_money"),
                                DropHP       = reader.GetUInt32("drop_hp"),
                                DropMP       = reader.GetUInt32("drop_mp"),
                                ExtraExp     = reader.GetUInt16("extra_exp"),
                                ExtraDamage  = reader.GetUInt16("extra_damage")
                            };

                            AllMonsters.TryAdd(monster_type.Id, monster_type);
                        }
                    }
                }
            }


            String[] scripts = Directory.GetFiles(Program.RootPath + "/Drops", "*.lua");

            for (Int32 i = 0; i < scripts.Length; i++)
            {
                FileInfo file = new FileInfo(scripts[i]);
                Int32    uid  = Int32.Parse(file.Name.Replace(".lua", ""));

                try
                {
                    MonsterTask task = new MonsterTask(uid, file.FullName);

                    MonsterInfo info;
                    if (AllMonsters.TryGetValue(uid, out info))
                    {
                        info.OnDie = task;
                        AllMonsters.TryUpdate(uid, info, AllMonsters[uid]);
                    }
                }
                catch (SyntaxErrorException exc)
                {
                    sLogger.Error("Failed to load the task {0}. Error: {1}",
                                  uid, exc.Message);
                }
            }
        }
        private void AttackObjectsInRange(NecClient client, int damage)
        {
            float perHp = 100.0f;

            //Damage Players in range
            foreach (NecClient targetClient in client.map.clientLookup.GetAll())
            {
                if (targetClient == client)
                {
                    continue;                         //skip damaging yourself
                }
                if (targetClient.character.partyId == client.character.partyId && client.character.partyId != 0)
                {
                    continue;                                                                                              //skip damaging party members
                }
                //if (targetClient.Soul.CriminalLevel == 0 && client.CriminalOnlyDamage == true) continue; //skip attacking non criminal players.  TODO

                double distanceToCharacter = Distance(targetClient.character.x, targetClient.character.y,
                                                      client.character.x, client.character.y);
                _Logger.Debug(
                    $"target Character name [{targetClient.character.name}] distanceToCharacter [{distanceToCharacter}] Radius { /*[{monsterSpawn.Radius}]*/" 125 "} {targetClient.character.name}");
                if (distanceToCharacter > /*targetClient.Character.Radius +*/ 125)
                {
                    continue;
                }

                if (targetClient.character.hp.depleted)
                {
                    continue;
                }

                damage -= targetClient.character.battleParam.plusPhysicalDefence;
                if (damage < 0)
                {
                    damage = 1;             //pity damage
                }
                targetClient.character.hp.Modify(-damage, client.character.instanceId);
                perHp = (float)targetClient.character.hp.current / targetClient.character.hp.max * 100;
                _Logger.Debug(
                    $"CurrentHp [{targetClient.character.hp.current}] MaxHp[{targetClient.character.hp.max}] perHp[{perHp}]");
                RecvCharaUpdateHp cHpUpdate = new RecvCharaUpdateHp(targetClient.character.hp.current);
                _server.router.Send(targetClient, cHpUpdate.ToPacket());

                //logic to turn characters to criminals on criminal actions.  possibly should move to character task.
                client.character.criminalState += 1;
                if ((client.character.criminalState == 1) | (client.character.criminalState == 2) |
                    (client.character.criminalState == 3))
                {
                    IBuffer res40 = BufferProvider.Provide();
                    res40.WriteUInt32(client.character.instanceId);
                    res40.WriteByte(client.character.criminalState);

                    _Logger.Debug($"Setting crime level for Character {client.character.name} to {client.character.criminalState}");
                    router.Send(client.map, (ushort)AreaPacketId.recv_chara_update_notify_crime_lv, res40, ServerType.Area);
                    //Router.Send(client.Map, (ushort) AreaPacketId.recv_charabody_notify_crime_lv, res40, ServerType.Area, client);
                }

                if (client.character.criminalState > 255)
                {
                    client.character.criminalState = 255;
                }

                DamageTheObject(client, targetClient.character.instanceId, damage, perHp);
            }

            //Damage Monsters in range
            foreach (MonsterSpawn monsterSpawn in client.map.monsterSpawns.Values)
            {
                double distanceToObject =
                    Distance(monsterSpawn.x, monsterSpawn.y, client.character.x, client.character.y);
                //_Logger.Debug($"target Monster name [{monsterSpawn.name}] distanceToObject [{distanceToObject}] Radius [{monsterSpawn.radius}] {monsterSpawn.name}");
                if (distanceToObject > monsterSpawn.radius * 5
                    ) //increased hitbox for monsters by a factor of 5.  Beetle radius is 40
                {
                    continue;
                }

                if (monsterSpawn.hp.depleted)
                {
                    continue;
                }

                monsterSpawn.hp.Modify(-damage, client.character.instanceId);
                perHp = (float)monsterSpawn.hp.current / monsterSpawn.hp.max * 100;
                _Logger.Debug($"CurrentHp [{monsterSpawn.hp.current}] MaxHp[{monsterSpawn.hp.max}] perHp[{perHp}]");

                //just for fun. turn on inactive monsters
                if (monsterSpawn.active == false)
                {
                    monsterSpawn.active      = true;
                    monsterSpawn.spawnActive = true;
                    if (!monsterSpawn.taskActive)
                    {
                        MonsterTask monsterTask = new MonsterTask(_server, monsterSpawn);
                        if (monsterSpawn.defaultCoords)
                        {
                            monsterTask.monsterHome = monsterSpawn.monsterCoords[0];
                        }
                        else
                        {
                            monsterTask.monsterHome = monsterSpawn.monsterCoords.Find(x => x.coordIdx == 64);
                        }
                        monsterTask.Start();
                    }
                }

                DamageTheObject(client, monsterSpawn.instanceId, damage, perHp);
            }

            //Damage NPCs in range
            foreach (NpcSpawn npcSpawn in client.map.npcSpawns.Values)
            {
                double distanceToObject = Distance(npcSpawn.x, npcSpawn.y, client.character.x, client.character.y);
                // _Logger.Debug($"target NPC name [{npcSpawn.name}] distanceToObject [{distanceToObject}] Radius [{npcSpawn.radius}] {npcSpawn.name}");
                if (distanceToObject > npcSpawn.radius)
                {
                    continue;
                }

                //attacking an NPC is a misdimeanor crime for non-criminals.
                if ((client.character.criminalState == 0))
                {
                    client.character.criminalState += 1;
                    IBuffer res40 = BufferProvider.Provide();
                    res40.WriteUInt32(client.character.instanceId);
                    res40.WriteByte(client.character.criminalState);

                    router.Send(client.map, (ushort)AreaPacketId.recv_chara_update_notify_crime_lv, res40, ServerType.Area);
                }

                DamageTheObject(client, npcSpawn.instanceId, damage, perHp);
            }
        }
Exemplo n.º 9
0
        public void Enter(NecClient client, MapPosition mapPosition = null)
        {
            if (client.map != null)
            {
                client.map.Leave(client);
            }
            client.map = this;

            _Logger.Info(client, $"Entering Map: {id}:{fullName}");
            // If position is passed in use it and set character position, if null then use map default coords
            // If this isn't set here, the wrong coords are in character until send_movement_info updates it.
            if (mapPosition != null)
            {
                client.character.x       = mapPosition.x;
                client.character.y       = mapPosition.y;
                client.character.z       = mapPosition.z;
                client.character.heading = mapPosition.heading;
            }
            //set character coords to default map entry coords If arriving form another map.
            else if (client.character.mapId != id)
            {
                client.character.x       = x;
                client.character.y       = y;
                client.character.z       = z;
                client.character.heading = orientation;
            }

            client.character.mapId     = id;
            client.character.mapChange = false;
            clientLookup.Add(client);
            _Logger.Debug($"Client Lookup count is now : {clientLookup.GetAll().Count}  for map  {id} ");
            _Logger.Debug($"Character State for character {client.character.name} is {client.character.state}");
            //Send your character data to the other living or dead players on the map.

            //on successful map entry, update the client database position
            if (!_server.database.UpdateCharacter(client.character))
            {
                _Logger.Error("Could not update the database with current known player position");
            }
            if (!_server.database.UpdateSoul(client.soul))
            {
                _Logger.Error("Could not update the database with soul details ");
            }

            //ToDo  move all this rendering logic to Send_Map_Entry.   We dont need a copy of this logic on every map instance.
            RecvDataNotifyCharaData myCharacterData = new RecvDataNotifyCharaData(client.character, client.soul.name);

            //dead
            //you are dead here.  only getting soul form characters. sorry bro.
            if (client.character.state.HasFlag(CharacterState.SoulForm))
            {
                foreach (NecClient otherClient in clientLookup.GetAll())
                {
                    if (otherClient == client)
                    {
                        continue;
                    }
                    if (otherClient.character.state.HasFlag(CharacterState.SoulForm))
                    {
                        _server.router.Send(myCharacterData, otherClient);
                    }
                }
            }
            else //Bro, you alive! You gon see living characters!
            {
                foreach (NecClient otherClient in clientLookup.GetAll())
                {
                    if (otherClient == client)
                    {
                        continue;
                    }
                    if (otherClient.character.state.HasFlag(CharacterState.SoulForm))
                    {
                        continue;
                    }
                    _server.router.Send(myCharacterData, otherClient);
                }
            }

            if (client.union != null)
            {
                RecvDataNotifyUnionData myUnionData = new RecvDataNotifyUnionData(client.character, client.union.name);
                _server.router.Send(this, myUnionData, client);
            }

            Task.Delay(TimeSpan.FromSeconds(10)).ContinueWith
                (t1 =>
            {
                foreach (MonsterSpawn monsterSpawn in monsterSpawns.Values)
                {
                    if (monsterSpawn.active)
                    {
                        monsterSpawn.spawnActive = true;
                        if (!monsterSpawn.taskActive)
                        {
                            MonsterTask monsterTask = new MonsterTask(_server, monsterSpawn);
                            if (monsterSpawn.defaultCoords)
                            {
                                monsterTask.monsterHome = monsterSpawn.monsterCoords[0];
                            }
                            else
                            {
                                monsterTask.monsterHome = monsterSpawn.monsterCoords.Find(x => x.coordIdx == 64);
                            }
                            monsterTask.Start();
                        }
                        else
                        {
                            if (monsterSpawn.monsterVisible)
                            {
                                _Logger.Debug($"MonsterTask already running for [{monsterSpawn.name}]");
                                RecvDataNotifyMonsterData monsterData = new RecvDataNotifyMonsterData(monsterSpawn);
                                _server.router.Send(monsterData, client);
                                if (!monsterSpawn.GetAgro())
                                {
                                    monsterSpawn.MonsterMove(_server, client, monsterSpawn.monsterWalkVelocity, 2,
                                                             0);
                                }
                            }
                        }
                    }
                }
            }
                );
        }
Exemplo n.º 10
0
        public void Enter(NecClient client, MapPosition mapPosition = null)
        {
            if (client.Map != null)
            {
                client.Map.Leave(client);
            }

            Logger.Info(client, $"Entering Map: {Id}:{FullName}");
            // If position is passed in use it and set character position, if null then use map default coords
            // If this isn't set here, the wrong coords are in character until send_movement_info updates it.
            if (mapPosition != null)
            {
                client.Character.X       = mapPosition.X;
                client.Character.Y       = mapPosition.Y;
                client.Character.Z       = mapPosition.Z;
                client.Character.Heading = mapPosition.Heading;
            }
            else
            {
                client.Character.X       = this.X;
                client.Character.Y       = this.Y;
                client.Character.Z       = this.Z;
                client.Character.Heading = this.Orientation;
            }

            client.Map                 = this;
            client.Character.MapId     = Id;
            client.Character.mapChange = false;
            ClientLookup.Add(client);
            Logger.Debug($"Client Lookup count is now : {ClientLookup.GetAll().Count}  for map  {this.Id} ");

            RecvDataNotifyCharaData myCharacterData = new RecvDataNotifyCharaData(client.Character, client.Soul.Name);

            _server.Router.Send(this, myCharacterData, client);
            if (client.Union != null)
            {
                RecvDataNotifyUnionData myUnionData = new RecvDataNotifyUnionData(client.Character, client.Union.Name);
                _server.Router.Send(this, myUnionData, client);
            }

            foreach (MonsterSpawn monsterSpawn in this.MonsterSpawns.Values)
            {
                if (monsterSpawn.Active == true)
                {
                    monsterSpawn.SpawnActive = true;
                    if (!monsterSpawn.TaskActive)
                    {
                        MonsterTask monsterTask = new MonsterTask(_server, monsterSpawn);
                        if (monsterSpawn.defaultCoords)
                        {
                            monsterTask.monsterHome = monsterSpawn.monsterCoords[0];
                        }
                        else
                        {
                            monsterTask.monsterHome = monsterSpawn.monsterCoords.Find(x => x.CoordIdx == 64);
                        }
                        monsterTask.Start();
                    }
                    else
                    {
                        if (monsterSpawn.MonsterVisible)
                        {
                            Logger.Debug($"MonsterTask already running for [{monsterSpawn.Name}]");
                            RecvDataNotifyMonsterData monsterData = new RecvDataNotifyMonsterData(monsterSpawn);
                            _server.Router.Send(monsterData, client);
                            if (!monsterSpawn.GetAgro())
                            {
                                monsterSpawn.MonsterMove(_server, client, monsterSpawn.MonsterWalkVelocity, (byte)2,
                                                         (byte)0);
                            }
                        }
                    }
                }
            }

            //on successful map entry, update the client database position
            if (!_server.Database.UpdateCharacter(client.Character))
            {
                Logger.Error("Could not update the database with current known player position");
            }
        }