/// <summary>
        /// Конструктор - основной (с аргументом)
        /// </summary>
        /// <param name="name">Наименование интерфейса (рабочего потока)</param>
        /// <param name="bIsActive">Признак необходимости запуска рабочего потока(асинхронное обращение к БД)</param>
        public DbInterface(string name, bool bIsActive = true)
        {
            lockListeners          = new object();
            lockConnectionSettings = new object();

            //listeners = new DbInterfaceListener[maxListeners];
            m_dictListeners = new Dictionary <int, DbInterfaceListener> ();

            _connected     = false;
            _needReconnect = RECONNECT.SOFT;

            if (bIsActive == true)
            {
                dbThread      = new Thread(new ParameterizedThreadStart(DbInterface_ThreadFunction));
                dbThread.Name = name;
                //Name = name;
                dbThread.IsBackground = true;

                _eventDbInterface_ThreadFunctionRun = new ManualResetEvent(false);
            }
            else
            {
                _name = name;
            }
        }
Exemple #2
0
        public void Reconnect(RECONNECT msg)
        {
            if (Account == null)
            {
                string[] labels    = new string[] { "{CLIENT_NAME}" };
                string[] arguments = new string[] { Account.Name };

                SendMessage(new FAILURE
                {
                    ErrorId          = (int)FailureIDs.JSON_DIALOG,
                    ErrorDescription =
                        JSONErrorIDHandler.
                        FormatedJSONError(
                            errorID: ErrorIDs.LOST_CONNECTION,
                            labels: labels,
                            arguments: arguments
                            )
                });

                Manager.TryDisconnect(this, DisconnectReason.LOST_CONNECTION);
                return;
            }

            Log.Info($"[({(int)DisconnectReason.RECONNECT}) {DisconnectReason.RECONNECT.ToString()}] Reconnect player '{Account.Name} (Account ID: {Account.AccountId})' to {msg.Name}.");

            Save();

            SendMessage(msg);
        }
Exemple #3
0
        public void _(string accId, RECONNECT msg)
        {
            string response = $"[{time[1]}] [{nameof(Client)}] Reconnect\t->\tplayer id {accId} to {msg.Name}";

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.WriteLine(response);
            Console.ResetColor();
        }
 protected void setConnectionSettings(object cs)
 {
     _needReconnect = (_needReconnect == RECONNECT.NOT_REQ)
         ? RECONNECT.SOFT
             : EqualeConnectionSettings(cs) == true
                 ? RECONNECT.SOFT
                     : IsEmptyConnectionSettings == true
                         ? RECONNECT.SOFT
                             : RECONNECT.NEW;
 }
        protected override bool Process(Player player, RealmTime time, string[] args)
        {
            if (player.Owner is Vault)
            {
                player.SendInfo($"You cant summon player {args[0]} in your vault.");
                return(false);
            }

            foreach (ClientData i in GameServer.Manager.ClientManager.Values)
            {
                Player target = i.Client.Player;

                if (target.Name.EqualsIgnoreCase(args[0]))
                {
                    Message msg;

                    if (target.Owner == player.Owner)
                    {
                        target.Move(player.X, player.Y);

                        msg = new GOTO
                        {
                            ObjectId = target.Id,
                            Position = new Position(player.X, player.Y)
                        };

                        target.UpdateCount++;

                        player.SendInfo($"Player {target.Name} was moved to near you.");
                    }
                    else
                    {
                        msg = new RECONNECT
                        {
                            GameId      = player.Owner.Id,
                            Host        = "",
                            IsFromArena = false,
                            Key         = player.Owner.PortalKey,
                            KeyTime     = -1,
                            Name        = player.Owner.Name,
                            Port        = -1
                        };

                        player.SendInfo($"Player {target.Name} is connecting to {player.Owner.Name}.");
                    }

                    i.Client.SendMessage(msg);

                    return(true);
                }
            }

            player.SendError($"An error occurred: player '{args[0]}' couldn't be found.");
            return(false);
        }
Exemple #6
0
        public bool Reconnect(RECONNECT msg)
        {
            try
            {
                Log.Info($"[({(int)DisconnectReason.RECONNECT}) {DisconnectReason.RECONNECT.ToString()}] Reconnect player '{Account.Name} (Account ID: {Account.AccountId})' to {msg.Name}.");

                Save();

                SendMessage(msg);
            }
            catch (NullReferenceException) { }

            return(true);
        }
Exemple #7
0
        public async void Reconnect(RECONNECT msg)
        {
            if (this == null)
            {
                return;
            }

            if (Account == null)
            {
                string[] labels    = new string[] { "{CLIENT_NAME}" };
                string[] arguments = new string[] { Account.Name };

                SendMessage(new FAILURE
                {
                    ErrorId          = Type.JSON_DIALOG,
                    ErrorDescription =
                        JSONErrorIDHandler.
                        FormatedJSONError(
                            errorID: ErrorIDs.LOST_CONNECTION,
                            labels: labels,
                            arguments: arguments
                            )
                });

                await task;

                Disconnect(DisconnectReason.LOST_CONNECTION);
                return;
            }

            _(Account.AccountId, msg);

            Save();

            await task;

            task.Dispose();

            SendMessage(msg);
        }
        private void DbInterface_ThreadFunction(object data)
        {
            object request;
            bool   result;
            bool   reconnection /* = false*/;
            Thread threadGetData;

            // Массив объектов синхронизации текущего потока и подпотока ожидания
            // 0 - внешний инициатор, 1 - внутренний (при большом количестве отмененных запросов)
            WaitHandle [] waitHandleGetData = new WaitHandle [] {
                _eventDbInterface_ThreadFunctionRun
                , new AutoResetEvent(false)
            };
            int iReason        = -1
            , counterFillError = -1
            , counterDataError = -1;;

            while (threadIsWorking)
            {
                switch (iReason = WaitHandle.WaitAny(waitHandleGetData))
                {
                case 0:
                    (waitHandleGetData [iReason] as ManualResetEvent).Reset();
                    break;

                default:
                    break;
                }

                lock (lockConnectionSettings) // атомарно читаю и сбрасываю флаг, чтобы при параллельной смене настроек не сбросить повторно выставленный флаг
                {
                    reconnection = !(_needReconnect == RECONNECT.NOT_REQ);
                }

                if (reconnection == true)
                {
                    Disconnect();
                    _connected = false;
                    if (threadIsWorking == true)
                    {
                        _connected     = Connect();
                        _needReconnect = _connected == true
                            ? RECONNECT.NOT_REQ
                                : RECONNECT.SOFT;
                    }
                    else
                    {
                        _needReconnect = RECONNECT.SOFT; // выставлять флаг можно без блокировки
                    }
                }
                else
                {
                    ;
                }

                if (_connected == false) // не удалось подключиться - не пытаемся получить данные
                {
                    continue;
                }
                else
                {
                    ;
                }

                Timeout = Constants.MAX_WATING / 1000;

                //Logging.Logg().Debug("DbInterface::DbInterface_ThreadFunction () - m_listListeners.Count = " + m_listListeners.Count);

                lock (lockListeners) {
                    // в новом цикле - новое состояние для прерывания
                    counterFillError = 0;
                    counterDataError = 0;

                    //??? внутри цикла при аварийном прерывании из словаря удаляется элемент
                    foreach (KeyValuePair <int, DbInterfaceListener> pair in m_dictListeners)
                    {
                        if (pair.Value.State == STATE_LISTENER.READY)
                        {
                            continue;
                        }
                        else
                        {
                            ;
                        }

                        request = pair.Value.requestDB;

                        if ((request == null) ||
                            (!(request.ToString().Length > 0)))
                        {
                            continue;
                        }
                        else
                        {
                            ;
                        }

                        result           = false;
                        pair.Value.State = STATE_LISTENER.BUSY;

                        //Logging.Logg().Debug("DbInterface::DbInterface_ThreadFunction () - GetData(...) - request = " + request);

                        try {
                            threadGetData = new Thread(new ParameterizedThreadStart((obj) => {
                                try {
                                    result = GetData(pair.Value.dataTable, request);
                                } catch (ApplicationException e) {
                                    // штатное завершение по превышению установленного лимита времени или другой ошибке (getData_OnFillError)
                                    counterFillError++;
                                } finally {
                                }
                            }))
                            {
                                IsBackground = true
                                , Priority   = ThreadPriority.AboveNormal
                            };
                            threadGetData.Start();

                            if (threadGetData.Join(Constants.MAX_WATING) == false)
                            {
                                counterFillError++;
                                GetDataCancel();

                                if (threadGetData.Join(Constants.WAIT_TIME_MS) == false)
                                {
                                    threadGetData.Abort(string.Format(@"Аварийное завершение подпотока получения данных..."));
                                }
                                else
                                {
                                    ;
                                }
                            }
                            else
                            {
                                //// сброс счетчика при успехе
                                //    counterFillError = 0
                                ;
                            }
                        } catch (ThreadAbortException ae) {
                            counterFillError = m_dictListeners.Count + 1;

                            Logging.Logg().Exception(ae, string.Format(@"::DbInterface_ThreadFunction () - {0}:{1}"
                                                                       , Name, pair.Key)
                                                     , Logging.INDEX_MESSAGE.NOT_SET);

                            Thread.ResetAbort();
                        } catch (Exception e) {
                            counterFillError++;

                            Logging.Logg().Exception(e, string.Format(@"DbInterface_ThreadFunction () - {0}:{1}"
                                                                      , Name, pair.Key)
                                                     , Logging.INDEX_MESSAGE.NOT_SET);
                        } finally {
                            // result(false) - признак возникновения исключения
                            pair.Value.SetResult(result);
                            counterFillError += result == false ? (m_dictListeners.Count + 1) : 0;
                            counterDataError += pair.Value.Error == true ? 1 : 0;

                            threadGetData = null;
                        }

                        if (counterFillError > m_dictListeners.Count)
                        {
                            Logging.Logg().Error($"DbInterface_ThreadFunction () - {Name}:{pair.Key} - аврийное завершение цикла обработки запросов подписчиков..."
                                                 , Logging.INDEX_MESSAGE.NOT_SET);

                            break;
                        }
                        else
                        {
                            ;
                        }

                        //Logging.Logg().Debug("DbInterface::DbInterface_ThreadFunction () - result = GetData(...) - pair.Value.dataPresent = " + pair.Value.dataPresent + @", pair.Value.dataError = " + pair.Value.dataError.ToString ());
                    } // foreach

                    _needReconnect = counterFillError > 1
                        ? counterFillError > m_dictListeners.Count
                            ? RECONNECT.HARD
                                : RECONNECT.SOFT
                                    : RECONNECT.NOT_REQ;

                    if ((!(_needReconnect == RECONNECT.NOT_REQ)) ||
                        (counterDataError > 0))
                    {
                        //??? установить в сигнальное состояние для дальнейшего использования
                        (waitHandleGetData[1] as AutoResetEvent).Set();
                    }
                    else
                    {
                        ;
                    }
                } // lock
            }     // while

            try {
                foreach (WaitHandle eventAuto in waitHandleGetData)
                {
                    eventAuto.Close();
                }
            } catch (Exception e) {
                Logging.Logg().Exception(e, "DbInterface::DbInterface_ThreadFunction () - выход...", Logging.INDEX_MESSAGE.NOT_SET);
            } finally {
            }

            Disconnect();
        }
        public override void Commands(Player player, string command)
        {
            string callback = null;
            string task     = null;

            var isTask = false;

            if (command.Length >= 6)
            {
                var taskStart         = command;
                var taskOriginalNames = GameTask.Tasks.Keys.ToList();
                var taskToLowerNames  = taskOriginalNames.Select(names => names.ToLower()).ToList();

                if (taskStart.Contains("start "))
                {
                    taskStart = taskStart.Substring(6);
                }

                task   = taskToLowerNames.Contains(taskStart) ? taskOriginalNames.FirstOrDefault(name => name.ToLower() == taskStart) : null;
                isTask = task != null;
            }

            var acc  = player.Client.Account;
            var cost = player.GetBlessingPrice();

            if (!isTask)
            {
                switch (command)
                {
                    #region "Uptime"
                case "uptime":
                {
                    TimeSpan uptime     = DateTime.Now - GameServer.Uptime;
                    double   thisUptime = uptime.TotalMinutes;
                    if (thisUptime <= 1)
                    {
                        callback = "Server started recently.";
                    }
                    else if (thisUptime > 1 && thisUptime <= 59)
                    {
                        callback = string.Format("Uptime: {0}{1}{2}{3}.",
                                                 $"{uptime.Minutes:n0}",
                                                 (uptime.Minutes >= 1 && uptime.Minutes < 2) ? " minute" : " minutes",
                                                 uptime.Seconds < 1 ? "" : $" and {uptime.Seconds:n0}",
                                                 uptime.Seconds < 1 ? "" : (uptime.Seconds >= 1 && uptime.Seconds < 2) ? " second" : " seconds");
                    }
                    else
                    {
                        callback = string.Format("Uptime: {0}{1}{2}{3}{4}{5}.",
                                                 $"{uptime.Hours:n0}",
                                                 (uptime.Hours >= 1 && uptime.Hours < 2) ? " hour" : " hours",
                                                 uptime.Minutes < 1 ? "" : $", {uptime.Minutes:n0}",
                                                 uptime.Minutes < 1 ? "" : (uptime.Minutes >= 1 && uptime.Minutes < 2) ? " minute" : " minutes",
                                                 uptime.Seconds < 1 ? "" : $" and {uptime.Seconds:n0}",
                                                 uptime.Seconds < 1 ? "" : (uptime.Seconds >= 1 && uptime.Seconds < 2) ? " second" : " seconds");
                    }
                }
                break;

                    #endregion
                    #region "Online"
                case "online":
                {
                    int serverMaxUsage     = Settings.NETWORKING.MAX_CONNECTIONS;
                    int serverCurrentUsage = GameServer.Manager.GetManager.Clients.Count;
                    int worldCurrentUsage  = player.Owner.Players.Keys.Count;
                    callback = $"Server: {serverCurrentUsage}/{serverMaxUsage} player{(serverCurrentUsage > 1 ? "s" : "")} | {player.Owner.Name}: {worldCurrentUsage} player{(worldCurrentUsage > 1 ? "s" : "")}.";
                }
                break;

                    #endregion
                    #region "Tasks"
                case "task":
                case "tasks":
                    callback = "Yeah! There are several tasks to do in-game and you can also receive wonderful rewards! Do you want more 'tasks info'?";
                    break;

                case "task info":
                case "tasks info":
                    callback = "The tasks are based in star requirement and some could be repeated. Tell me when you are 'ready' to begin any of them.";
                    break;

                case "ready":
                    var gameTasks     = SplitList(GameTask.Tasks.Keys.ToList(), 5).ToList();
                    var gameTaskNames = new List <string>();

                    foreach (var i in gameTasks)
                    {
                        gameTaskNames.Add(Utils.ToCommaSepString(i.ToArray()));
                    }

                    player.SendHelp("Tasks:");

                    foreach (var j in gameTaskNames)
                    {
                        player.SendHelp($"- {j}");
                    }

                    callback = "So far I have the following tasks, check your chat box and say the name of task to me to start. Remember, you can only handle one task per time until completed.";
                    break;

                case "task status":
                    if (player.ActualTask == null)
                    {
                        callback = "You are in none task at this moment.";
                    }
                    else
                    {
                        var getTaskMonsters = player.MonsterCaches.Where(monster => monster.TaskLimit != -1);
                        var taskData        = new List <string>();

                        foreach (var i in GameTask.Tasks[player.ActualTask].MonsterDatas)
                        {
                            var mob = getTaskMonsters.FirstOrDefault(monster => monster.ObjectId == i.ObjectId);

                            if (mob == null)
                            {
                                taskData.Add($"- [0/{i.Total}] Defeat {i.Total} x {i.ObjectId}.");
                            }
                            else
                            {
                                taskData.Add($"- [{mob.TaskCount}/{i.Total}] Defeat {i.Total} x {mob.ObjectId}{(mob.TaskCount >= i.Total ? " (OK!)" : "")}.");
                            }
                        }

                        player.SendHelp($"[Task] {player.ActualTask}:");

                        foreach (var j in taskData)
                        {
                            player.SendHelp(j);
                        }

                        callback = $"You are doing the '{player.ActualTask}' task and your status are displaying at chat box. You can ask for 'task reward' when you finish this task.";
                    }
                    break;

                case "task reward":
                    if (player.ActualTask == null)
                    {
                        callback = "There is no reward for people who didn't finish any task with me. Come back here later...";
                    }
                    else
                    {
                        var currentTask     = GameTask.Tasks[player.ActualTask];
                        var getTaskMonsters = player.MonsterCaches.Where(monster => monster.TaskLimit != -1);
                        var success         = 0;

                        foreach (var i in currentTask.MonsterDatas)
                        {
                            var mob = getTaskMonsters.FirstOrDefault(monster => monster.ObjectId == i.ObjectId);

                            if (mob == null)
                            {
                                continue;
                            }

                            if (mob.TaskCount >= i.Total)
                            {
                                success++;
                            }
                        }

                        if (success == currentTask.MonsterDatas.Count)
                        {
                            foreach (var i in currentTask.MonsterDatas)
                            {
                                var mob = getTaskMonsters.FirstOrDefault(monster => monster.ObjectId == i.ObjectId);

                                if (mob == null)
                                {
                                    continue;
                                }

                                mob.TaskCount = mob.TaskLimit = -1;
                            }

                            var gifts = player.Client.Account.Gifts.ToList();

                            for (var i = 0; i < currentTask.RewardDatas.Count; i++)
                            {
                                for (var j = 0; j < currentTask.RewardDatas[i].Total; j++)
                                {
                                    gifts.Add(GameServer.Manager.GameData.IdToObjectType[currentTask.RewardDatas[i].ObjectId]);
                                }
                            }

                            callback = $"Congratulations {player.Name}! You have finished the task '{player.ActualTask}'.";

                            currentTask.Bonus?.Invoke(player);
                            currentTask.GetAchievement(player.ActualTask, player);

                            player.Client.Account.Gifts = gifts.ToArray();
                            player.Client.Account.FlushAsync();
                            player.Client.Account.Reload();
                            player.ActualTask = null;
                            player.MonsterCaches.Clear();
                            player.SaveToCharacter();
                        }
                        else
                        {
                            callback = "You didn't finish your task properly, ask me for 'task status' for more details.";
                        }
                    }
                    break;

                    #endregion
                    #region "Help"
                case "help":
                    callback = "You can ask me about 'uptime', 'online', 'tasks', 'check bless', 'bless' and 'fame' for more details.";
                    break;

                    #endregion
                    #region "Access Dream Island"
                case "dream island":
                    callback = "Do you want to access Dream Island? If you want then say 'access dream island' to proceed.";
                    break;

                case "access dream island":
                    RemovePlayer(player);
                    Callback(player, command, false);     // player only (self)
                    Leave(player, true);

                    player.Client.Reconnect(new networking.outgoing.RECONNECT()
                    {
                        Host   = "",
                        Port   = Settings.GAMESERVER.GAME_PORT,
                        GameId = (int)WorldID.DREAM_ISLAND,
                        Name   = "Dream Island",
                        Key    = Empty <byte> .Array,
                    });
                    return;

                    #endregion
                    #region "Event: vip"
                case "vip":
                    var eventvip = new DateTime(2019, 1, 18, 12, 59, 59);

                    if (DateTime.UtcNow > eventvip)
                    {
                        callback = "The event already over, try again later.";
                    }
                    else
                    {
                        if (player.AccountType != (int)AccountType.REGULAR)
                        {
                            callback = "You already have VIP perks.";
                        }
                        else
                        {
                            var _outgoing = new List <Message>();
                            var _world    = GameServer.Manager.GetWorld(player.Owner.Id);
                            var days      = 7;

                            var _notification = new NOTIFICATION
                            {
                                Color    = new ARGB(0xFFFFFF),
                                ObjectId = player.Id,
                                Text     = "{\"key\":\"blank\",\"tokens\":{\"data\":\"Success!\"}}"
                            };

                            _outgoing.Add(_notification);

                            var _showeffect = new SHOWEFFECT
                            {
                                Color      = new ARGB(0xffddff00),
                                EffectType = EffectType.Nova,
                                PosA       = new Position {
                                    X = 2
                                }
                            };

                            _outgoing.Add(_showeffect);

                            player.Owner.BroadcastMessage(_outgoing, null);

                            acc.AccountLifetime = DateTime.UtcNow;
                            acc.AccountLifetime = acc.AccountLifetime.AddDays(days);
                            acc.AccountType     = (int)AccountType.VIP;
                            acc.FlushAsync();
                            acc.Reload();

                            player.UpdateCount++;

                            player.SendInfo("Reconnecting...");

                            var _reconnect = new RECONNECT
                            {
                                GameId = (int)WorldID.NEXUS_ID,     // change to Drasta Citadel in future versions!
                                Host   = string.Empty,
                                Key    = Empty <byte> .Array,
                                Name   = "Nexus",
                                Port   = Settings.GAMESERVER.GAME_PORT
                            };

                            _world.Timers.Add(new WorldTimer(2000, (w, t) => player.Client.Reconnect(_reconnect)));

                            callback = $"Success! You received {days} day{(days > 1 ? "s" : "")} as account lifetime to your VIP account type along event!";
                        }
                    }
                    break;

                    #endregion
                    #region "Blessings"
                case "check bless":
                case "check blessings":
                    callback = $"You have {player.CountBlessings()} of 5 blessings activated.";
                    break;

                case "bless":
                case "blessings":
                    player.SendHelp("[Blessings]:");
                    player.SendHelp("- Medusa's Bless.");
                    player.SendHelp("- Ghost's Bless.");
                    player.SendHelp("- Slime's Bless.");
                    player.SendHelp("- Beholder's Bless.");
                    player.SendHelp("- Ent's Bless.");

                    callback = "Oh, you know about blessings! I can sell 5 different blessings that can protect your against evil forces. Check your chat log.";
                    break;

                case "medusa's bless":
                case "ghost's bless":
                case "slime's bless":
                case "beholder's bless":
                case "ent's bless":
                    callback = $"That blessing is costing for your level {cost} Fame. Say \"buy {command}\" to confirm purchase.";
                    break;

                case "buy medusa's bless":
                    if (player.Bless1)
                    {
                        callback = "You already have this bless.";
                    }
                    else if (player.Client.Account.Fame >= player.GetBlessingPrice())
                    {
                        GameServer.Manager.Database.UpdateFame(acc, -cost);

                        player.Bless1      = true;
                        player.CurrentFame = acc.Fame;
                        player.SaveToCharacter();
                        player.UpdateCount++;

                        callback = "You received the blessings of Medusa God!";
                    }
                    else
                    {
                        callback = "You do not have enought Fame to purchase this blessing.";
                    }
                    break;

                case "buy ghost's bless":
                    if (player.Bless2)
                    {
                        callback = "You already have this bless.";
                    }
                    else if (player.Client.Account.Fame >= player.GetBlessingPrice())
                    {
                        GameServer.Manager.Database.UpdateFame(acc, -cost);

                        player.Bless2      = true;
                        player.CurrentFame = acc.Fame;
                        player.SaveToCharacter();
                        player.UpdateCount++;

                        callback = "You received the blessings of Ghost God!";
                    }
                    else
                    {
                        callback = "You do not have enought Fame to purchase this blessing.";
                    }
                    break;

                case "buy slime's bless":
                    if (player.Bless3)
                    {
                        callback = "You already have this bless.";
                    }
                    else if (player.Client.Account.Fame >= player.GetBlessingPrice())
                    {
                        GameServer.Manager.Database.UpdateFame(acc, -cost);

                        player.Bless3      = true;
                        player.CurrentFame = acc.Fame;
                        player.SaveToCharacter();
                        player.UpdateCount++;

                        callback = "You received the blessings of Slime God!";
                    }
                    else
                    {
                        callback = "You do not have enought Fame to purchase this blessing.";
                    }
                    break;

                case "buy beholder's bless":
                    if (player.Bless4)
                    {
                        callback = "You already have this bless.";
                    }
                    else if (player.Client.Account.Fame >= player.GetBlessingPrice())
                    {
                        GameServer.Manager.Database.UpdateFame(acc, -cost);

                        player.Bless4      = true;
                        player.CurrentFame = acc.Fame;
                        player.SaveToCharacter();
                        player.UpdateCount++;

                        callback = "You received the blessings of Beholder God!";
                    }
                    else
                    {
                        callback = "You do not have enought Fame to purchase this blessing.";
                    }
                    break;

                case "buy ent's bless":
                    if (player.Bless5)
                    {
                        callback = "You already have this bless.";
                    }
                    else if (player.Client.Account.Fame >= player.GetBlessingPrice())
                    {
                        GameServer.Manager.Database.UpdateFame(acc, -cost);

                        player.Bless5      = true;
                        player.CurrentFame = acc.Fame;
                        player.SaveToCharacter();
                        player.UpdateCount++;

                        callback = "You received the blessings of Ent God!";
                    }
                    else
                    {
                        callback = "You do not have enought Fame to purchase this blessing.";
                    }
                    break;

                    #endregion
                    #region "Wipe Fame"
                case "fame":
                    callback = "I can transfer your fame base to your account if you want, just say 'wipe fame'.";
                    break;

                case "wipe fame":
                    if (player.Fame == 0 || player.FakeExperience == 0)
                    {
                        callback = "You cannot use this feature yet, try again later.";
                    }
                    else if (player.Fame < 400)
                    {
                        callback = "You can only transfer fame to your account when you get 400 fame base.";
                    }
                    else
                    {
                        GameServer.Manager.Database.UpdateFame(acc, player.Fame);

                        player.CurrentFame    = acc.Fame;
                        player.Fame           = 0;
                        player.FakeExperience = 0;
                        player.CalculateFame(false);
                        player.SaveToCharacter();
                        player.UpdateCount++;

                        callback = "You wipe your fame base of your character and transfered to your account!";
                    }
                    break;

                    #endregion
                case "hi":
                case "hello":
                case "hey":
                case "good morning":
                case "good afternoon":
                case "good evening":
                    Callback(player, command, false);     // player only (self)
                    NoRepeat(player);
                    return;

                case "bye":
                case "good bye":
                case "good night":
                    RemovePlayer(player);
                    Callback(player, command, false);     // player only (self)
                    Leave(player, true);
                    return;

                default:
                    callback = "Sorry, I don't understand. Say 'help' for more details.";
                    break;
                }
            }
            else
            {
                if (!command.ToLower().Contains("start ")) // task details
                {
                    var starrequirement = GameTask.Tasks[task].StarsRequirement;

                    if (player.Stars >= starrequirement)
                    {
                        callback = $"You seems prepared to initialize this task, just say 'start {task}' to begin!";
                    }
                    else
                    {
                        callback = $"You are too young at this moment to do '{task}' task. Come back here later when you get {starrequirement} star{(starrequirement > 1 ? "s" : "")}...";
                    }
                }
                else // task start
                {
                    var getTask = GameTask.Tasks[task];

                    if (player.ActualTask == null)
                    {
                        if (player.Achievements.Contains(task) && !getTask.MultipleTimes)
                        {
                            callback = $"You cannot do '{task}' task again.";
                        }
                        else
                        {
                            if (player.Stars >= getTask.StarsRequirement)
                            {
                                var monsterCaches = new List <MonsterCache>();

                                foreach (var i in getTask.MonsterDatas)
                                {
                                    monsterCaches.Add(new MonsterCache()
                                    {
                                        ObjectId  = i.ObjectId,
                                        TaskCount = 0,
                                        TaskLimit = i.Total,
                                        Total     = 0
                                    });
                                }

                                foreach (var j in monsterCaches)
                                {
                                    var mob = player.MonsterCaches.FirstOrDefault(monster => monster.ObjectId == j.ObjectId);

                                    if (mob == null)
                                    {
                                        player.MonsterCaches.Add(j);
                                    }
                                    else
                                    {
                                        mob.TaskCount = j.TaskCount;
                                        mob.TaskLimit = j.TaskLimit;
                                    }
                                }

                                player.ActualTask = task;
                                player.Task       = getTask;
                                player.UpdateCount++;
                                player.SaveToCharacter();

                                callback = $"You have successfully initialized '{task}' task and all I want to say is good luck! Come back here and ask me for 'task reward' when you finish your task!";
                            }
                            else
                            {
                                callback = $"You are too young at this moment to do '{task}' task. Come back here later...";
                            }
                        }
                    }
                    else
                    {
                        if (player.ActualTask != null)
                        {
                            callback = $"You are already in '{player.ActualTask}' task and cannot begin another one until you finish yours. Also, you can ask me for 'task status' to show your progress.";
                        }
                        else
                        {
                            callback = $"I could give you permission to start this '{task}' task, but I'm gonna?";
                        }
                    }
                }
            }
            Callback(player, command, false);              // player only (self)
            Callback(player, callback);                    // to NPC
            ChatManager.ChatDataCache.Remove(player.Name); // Removing player from chat data cache.
        }