Пример #1
0
        /// <summary>
        /// Try to Send Tooltip to Client, return false if cache hit.
        /// Return true and register cache before you can send tooltip !
        /// </summary>
        /// <param name="type"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool CanSendTooltip(int type, int id)
        {
            m_tooltipRequestTimes.TryAdd(type, new ConcurrentDictionary <int, long>());

            // Queries cleanup
            foreach (Tuple <int, int> keys in m_tooltipRequestTimes.SelectMany(e => e.Value.Where(it => it.Value < GameTimer.GetTickCount()).Select(el => new Tuple <int, int>(e.Key, el.Key))))
            {
                long dummy;
                m_tooltipRequestTimes[keys.Item1].TryRemove(keys.Item2, out dummy);
            }

            // Query hit ?
            if (m_tooltipRequestTimes[type].ContainsKey(id))
            {
                return(false);
            }

            // Query register
            m_tooltipRequestTimes[type].TryAdd(id, GameTimer.GetTickCount() + 3600000);
            return(true);
        }
Пример #2
0
        /// <summary>
        /// This thread updates the NPCs and objects around the player at very short
        /// intervalls! But since the update is very quick the thread will
        /// sleep most of the time!
        /// </summary>
        public static void WorldUpdateThreadStart()
        {
            /// Tasks Collection of running Player updates, with starting time.
            Dictionary <GameClient, Tuple <long, Task, Region> > clientsUpdateTasks = new Dictionary <GameClient, Tuple <long, Task, Region> >();

            bool running = true;

            if (log.IsInfoEnabled)
            {
                log.InfoFormat("World Update Thread Starting - ThreadId = {0}", Thread.CurrentThread.ManagedThreadId);
            }

            while (running)
            {
                try
                {
                    // Start Time of the loop
                    long begin = GameTimer.GetTickCount();

                    // Get All Clients
                    IList <GameClient> clients = WorldMgr.GetAllClients();

                    // Clean Tasks Dict on Client Exiting.
                    foreach (GameClient cli in new List <GameClient>(clientsUpdateTasks.Keys))
                    {
                        if (cli == null)
                        {
                            continue;
                        }

                        if (!clients.Contains(cli))
                        {
                            clientsUpdateTasks.Remove(cli);
                            cli.GameObjectUpdateArray.Clear();
                            cli.HouseUpdateArray.Clear();
                        }
                    }

                    // Browse all clients to check if they can be updated.
                    for (int cl = 0; cl < clients.Count; cl++)
                    {
                        GameClient client = clients[cl];

                        // Check that client is healthy
                        if (client == null)
                        {
                            continue;
                        }

                        GamePlayer player = client.Player;

                        if (client.ClientState == GameClient.eClientState.Playing && player == null)
                        {
                            if (log.IsErrorEnabled)
                            {
                                log.Error("account has no active player but is playing, disconnecting! => " + client.Account.Name);
                            }

                            // Disconnect buggy Client
                            GameServer.Instance.Disconnect(client);
                            continue;
                        }

                        // Check that player is active.
                        if (client.ClientState != GameClient.eClientState.Playing || player == null || player.ObjectState != GameObject.eObjectState.Active)
                        {
                            continue;
                        }

                        // Check for existing Task
                        Tuple <long, Task, Region> clientEntry;

                        if (!clientsUpdateTasks.TryGetValue(client, out clientEntry))
                        {
                            // Client not in tasks, create it and run it !
                            clientEntry = new Tuple <long, Task, Region>(begin, Task.Factory.StartNew(() => UpdatePlayerWorld(player)), player.CurrentRegion);

                            // Register.
                            clientsUpdateTasks.Add(client, clientEntry);
                        }
                        else
                        {
                            // Get client entry data.
                            long   lastUpdate = clientEntry.Item1;
                            Task   taskEntry  = clientEntry.Item2;
                            Region lastRegion = clientEntry.Item3;

                            //Check if task finished
                            if (!taskEntry.IsCompleted)
                            {
                                // Check for how long
                                if ((begin - lastUpdate) > GetPlayerWorldUpdateInterval())
                                {
                                    if (log.IsWarnEnabled && (GameTimer.GetTickCount() - player.TempProperties.getProperty <long>("LAST_WORLD_UPDATE_THREAD_WARNING", 0) >= 1000))
                                    {
                                        log.WarnFormat("Player Update Task ({0}) Taking more than world update refresh rate : {1} ms (real {2} ms) - Task Status : {3}!", player.Name, GetPlayerWorldUpdateInterval(), begin - lastUpdate, taskEntry.Status);
                                        player.TempProperties.setProperty("LAST_WORLD_UPDATE_THREAD_WARNING", GameTimer.GetTickCount());
                                    }
                                }
                                // Continue loop
                                continue;
                            }

                            // Display Exception
                            if (taskEntry.IsFaulted)
                            {
                                if (log.IsErrorEnabled)
                                {
                                    log.ErrorFormat("Error in World Update Thread, Player Task ({0})! Exception : {1}", player.Name, taskEntry.Exception);
                                }
                            }

                            // Region Refresh
                            if (player.CurrentRegion != lastRegion)
                            {
                                if (client.GameObjectUpdateArray != null)
                                {
                                    client.GameObjectUpdateArray.Clear();
                                }

                                if (client.HouseUpdateArray != null)
                                {
                                    client.HouseUpdateArray.Clear();
                                }

                                lastUpdate = 0;
                                lastRegion = player.CurrentRegion;
                            }

                            // If this player need update.
                            if (PlayerNeedUpdate(lastUpdate))
                            {
                                // Update Time, Region and Create Task
                                Tuple <long, Task, Region> newClientEntry = new Tuple <long, Task, Region>(begin, Task.Factory.StartNew(() => UpdatePlayerWorld(player)), lastRegion);
                                // Register Tuple
                                clientsUpdateTasks[client] = newClientEntry;
                            }
                        }
                    }

                    long took = GameTimer.GetTickCount() - begin;

                    if (took >= 500)
                    {
                        if (log.IsWarnEnabled)
                        {
                            log.WarnFormat("World Update Thread (NPC/Object update) took {0} ms", took);
                        }
                    }

                    // relaunch update thread every 100 ms to check if any player need updates.
                    Thread.Sleep((int)Math.Max(1, 100 - took));
                }
                catch (ThreadAbortException)
                {
                    if (log.IsInfoEnabled)
                    {
                        log.Info("World Update Thread stopping...");
                    }

                    running = false;
                    break;
                }
                catch (Exception e)
                {
                    if (log.IsErrorEnabled)
                    {
                        log.Error("Error in World Update (NPC/Object Update) Thread!", e);
                    }
                }
            }
        }
Пример #3
0
 /// <summary>
 /// Check if this player can be updated
 /// </summary>
 /// <param name="player"></param>
 /// <returns></returns>
 private static bool PlayerNeedUpdate(long lastUpdate)
 {
     return((GameTimer.GetTickCount() - lastUpdate) >= GetPlayerWorldUpdateInterval());
 }
Пример #4
0
 /// <summary>
 /// Update all World Around Player
 /// </summary>
 /// <param name="player">The player needing update</param>
 private static void UpdatePlayerWorld(GamePlayer player)
 {
     UpdatePlayerWorld(player, GameTimer.GetTickCount());
 }
Пример #5
0
        /// <summary>
        /// This thread updates the NPCs and objects around the player at very short
        /// intervalls! But since the update is very quick the thread will
        /// sleep most of the time!
        /// </summary>
        public static void WorldUpdateThreadStart()
        {
            // Tasks Collection of running Player updates, with starting time.
            var clientsUpdateTasks = new Dictionary <GameClient, Tuple <long, Task, Region> >();

            bool running = true;

            if (log.IsInfoEnabled)
            {
                log.InfoFormat("World Update Thread Starting - ThreadId = {0}", Thread.CurrentThread.ManagedThreadId);
            }

            while (running)
            {
                try
                {
                    // Start Time of the loop
                    long begin = GameTimer.GetTickCount();

                    // Get All Clients
                    var clients = WorldMgr.GetAllClients();

                    // Clean Tasks Dict on Client Exiting.
                    foreach (GameClient cli in clientsUpdateTasks.Keys.ToArray())
                    {
                        if (cli == null)
                        {
                            continue;
                        }

                        GamePlayer player = cli.Player;

                        bool notActive    = cli.ClientState != GameClient.eClientState.Playing || player == null || player.ObjectState != GameObject.eObjectState.Active;
                        bool notConnected = !clients.Contains(cli);

                        if (notConnected || (notActive && IsTaskCompleted(cli, clientsUpdateTasks)))
                        {
                            clientsUpdateTasks.Remove(cli);
                            cli.GameObjectUpdateArray.Clear();
                            cli.HouseUpdateArray.Clear();
                        }
                    }

                    // Browse all clients to check if they can be updated.
                    for (int cl = 0; cl < clients.Count; cl++)
                    {
                        GameClient client = clients[cl];

                        // Check that client is healthy
                        if (client == null)
                        {
                            continue;
                        }

                        GamePlayer player = client.Player;

                        if (client.ClientState == GameClient.eClientState.Playing && player == null)
                        {
                            if (log.IsErrorEnabled)
                            {
                                log.Error("account has no active player but is playing, disconnecting! => " + client.Account.Name);
                            }

                            // Disconnect buggy Client
                            GameServer.Instance.Disconnect(client);
                            continue;
                        }

                        // Check that player is active.
                        if (client.ClientState != GameClient.eClientState.Playing || player == null || player.ObjectState != GameObject.eObjectState.Active)
                        {
                            continue;
                        }

                        // Start Update Task
                        StartPlayerUpdateTask(client, clientsUpdateTasks, begin);
                    }

                    long took = GameTimer.GetTickCount() - begin;

                    if (took >= 500)
                    {
                        if (log.IsWarnEnabled)
                        {
                            log.WarnFormat("World Update Thread (NPC/Object update) took {0} ms", took);
                        }
                    }

                    // relaunch update thread every 100 ms to check if any player need updates.
                    Thread.Sleep((int)Math.Max(1, 100 - took));
                }
                catch (ThreadInterruptedException)
                {
                    if (log.IsInfoEnabled)
                    {
                        log.Info("World Update Thread stopping...");
                    }

                    running = false;
                    break;
                }
                catch (Exception e)
                {
                    if (log.IsErrorEnabled)
                    {
                        log.Error("Error in World Update (NPC/Object Update) Thread!", e);
                    }
                }
            }
        }
Пример #6
0
        private static bool StartPlayerUpdateTask(GameClient client, IDictionary <GameClient, Tuple <long, Task, Region> > clientsUpdateTasks, long begin)
        {
            var player = client.Player;
            // Check for existing Task
            Tuple <long, Task, Region> clientEntry;

            if (!clientsUpdateTasks.TryGetValue(client, out clientEntry))
            {
                // Client not in tasks, create it and run it !
                clientEntry = new Tuple <long, Task, Region>(begin, Task.Factory.StartNew(() => UpdatePlayerWorld(player)), player.CurrentRegion);

                // Register.
                clientsUpdateTasks.Add(client, clientEntry);
                return(true);
            }
            else
            {
                // Get client entry data.
                long   lastUpdate = clientEntry.Item1;
                Task   taskEntry  = clientEntry.Item2;
                Region lastRegion = clientEntry.Item3;

                //Check if task finished
                if (!taskEntry.IsCompleted)
                {
                    // Check for how long
                    if ((begin - lastUpdate) > GetPlayerWorldUpdateInterval)
                    {
                        if (log.IsWarnEnabled && (GameTimer.GetTickCount() - player.TempProperties.getProperty <long>("LAST_WORLD_UPDATE_THREAD_WARNING", 0) >= 1000))
                        {
                            log.WarnFormat("Player Update Task ({0}) Taking more than world update refresh rate : {1} ms (real {2} ms) - Task Status : {3}!", player.Name, GetPlayerWorldUpdateInterval, begin - lastUpdate, taskEntry.Status);
                            player.TempProperties.setProperty("LAST_WORLD_UPDATE_THREAD_WARNING", GameTimer.GetTickCount());
                        }
                    }
                    // Don't init this client.
                    return(false);
                }

                // Display Exception
                if (taskEntry.IsFaulted)
                {
                    if (log.IsErrorEnabled)
                    {
                        log.ErrorFormat("Error in World Update Thread, Player Task ({0})! Exception : {1}", player.Name, taskEntry.Exception);
                    }
                }

                // Region Refresh
                if (player.CurrentRegion != lastRegion)
                {
                    lastUpdate = 0;
                    lastRegion = player.CurrentRegion;
                    client.GameObjectUpdateArray.Clear();
                    client.HouseUpdateArray.Clear();
                }

                // If this player need update.
                if (PlayerNeedUpdate(lastUpdate))
                {
                    // Update Time, Region and Create Task
                    var newClientEntry = new Tuple <long, Task, Region>(begin, Task.Factory.StartNew(() => UpdatePlayerWorld(player)), lastRegion);
                    // Register Tuple
                    clientsUpdateTasks[client] = newClientEntry;
                    return(true);
                }
            }

            return(false);
        }