/// <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; } }
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); }
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); }
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); }
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. }