Пример #1
0
            /// <summary>
            ///     This is called by a timer and makes a SimStats class of the current stats that we have in this simulator.
            ///     It then sends the packet to the client and triggers the events to tell followers about the updated stats
            ///     and updates the LastSet* values for monitors.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void statsHeartBeat(object sender, EventArgs e)
            {
                if (m_currentScene.PhysicsScene == null)
                {
                    return;
                }
                m_report.Stop();
                if (rb == null)
                {
                    buildInitialRegionBlock();
                }

                // Know what's not thread safe in Mono... modifying timers.
                lock (m_report)
                {
                    ISimFrameMonitor           simFrameMonitor         = GetMonitor <ISimFrameMonitor>();
                    ITimeDilationMonitor       timeDilationMonitor     = GetMonitor <ITimeDilationMonitor>();
                    ITotalFrameTimeMonitor     totalFrameMonitor       = GetMonitor <ITotalFrameTimeMonitor>();
                    ISleepFrameMonitor         sleepFrameMonitor       = GetMonitor <ISleepFrameMonitor>();
                    IOtherFrameMonitor         otherFrameMonitor       = GetMonitor <IOtherFrameMonitor>();
                    IPhysicsFrameMonitor       physicsFrameMonitor     = GetMonitor <IPhysicsFrameMonitor>();
                    IPhysicsSyncFrameMonitor   physicsSyncFrameMonitor = GetMonitor <IPhysicsSyncFrameMonitor>();
                    IPhysicsUpdateFrameMonitor physicsTimeFrameMonitor = GetMonitor <IPhysicsUpdateFrameMonitor>();
                    IAgentUpdateMonitor        agentUpdateFrameMonitor = GetMonitor <IAgentUpdateMonitor>();
                    INetworkMonitor            networkMonitor          = GetMonitor <INetworkMonitor>();
                    IImageFrameTimeMonitor     imagesMonitor           = GetMonitor <IImageFrameTimeMonitor>();
                    IScriptFrameTimeMonitor    scriptMonitor           = GetMonitor <IScriptFrameTimeMonitor>();
                    IScriptCountMonitor        totalScriptMonitor      = GetMonitor <IScriptCountMonitor>();

                    #region various statistic googly moogly

                    float simfps = simFrameMonitor.SimFPS / statsUpdateFactor;
                    // save the reported value so there is something available for llGetRegionFPS
                    simFrameMonitor.LastReportedSimFPS = simfps;

                    float physfps = physicsFrameMonitor.PhysicsFPS / statsUpdateFactor;
                    physicsFrameMonitor.LastReportedPhysicsFPS = physfps;
                    //Update the time dilation with the newest physicsFPS
                    timeDilationMonitor.SetPhysicsFPS(physfps);

                    #endregion

                    #region Add the stats packets

                    //Some info on this packet http://wiki.secondlife.com/wiki/Statistics_Bar_Guide

                    sb[0].StatID    = (uint)Stats.TimeDilation;
                    sb[0].StatValue = (float)timeDilationMonitor.GetValue();

                    sb[1].StatID    = (uint)Stats.FPS;
                    sb[1].StatValue = simfps;

                    float realsimfps = simfps * 2;

                    sb[2].StatID    = (uint)Stats.PhysFPS;
                    sb[2].StatValue = physfps;

                    sb[3].StatID    = (uint)Stats.AgentUpdates;
                    sb[3].StatValue = (agentUpdateFrameMonitor.AgentUpdates / realsimfps);

                    sb[4].StatID = (uint)Stats.FrameMS;
                    float TotalFrames = (float)(totalFrameMonitor.GetValue() / realsimfps);
                    sb[4].StatValue = TotalFrames;

                    sb[5].StatID    = (uint)Stats.NetMS;
                    sb[5].StatValue = 0; //TODO: Implement this

                    sb[6].StatID = (uint)Stats.SimOtherMS;
                    float otherMS = (float)(otherFrameMonitor.GetValue() / realsimfps);
                    sb[6].StatValue = otherMS;

                    sb[7].StatID = (uint)Stats.SimPhysicsMS;
                    float PhysicsMS = (float)(physicsTimeFrameMonitor.GetValue() / realsimfps);
                    sb[7].StatValue = PhysicsMS;

                    sb[8].StatID    = (uint)Stats.AgentMS;
                    sb[8].StatValue = (agentUpdateFrameMonitor.AgentFrameTime / realsimfps);

                    sb[9].StatID = (uint)Stats.ImagesMS;
                    float imageMS = (float)(imagesMonitor.GetValue() / realsimfps);
                    sb[9].StatValue = imageMS;

                    sb[10].StatID = (uint)Stats.ScriptMS;
                    float ScriptMS = (float)(scriptMonitor.GetValue() / realsimfps);
                    sb[10].StatValue = ScriptMS;

                    sb[11].StatID = (uint)Stats.TotalObjects;
                    sb[12].StatID = (uint)Stats.ActiveObjects;
                    sb[13].StatID = (uint)Stats.NumAgentMain;
                    sb[14].StatID = (uint)Stats.NumAgentChild;

                    IEntityCountModule entityCountModule = m_currentScene.RequestModuleInterface <IEntityCountModule>();
                    if (entityCountModule != null)
                    {
                        sb[11].StatValue = entityCountModule.Objects;

                        sb[12].StatValue = entityCountModule.ActiveObjects;

                        sb[13].StatValue = entityCountModule.RootAgents;

                        sb[14].StatValue = entityCountModule.ChildAgents;
                    }

                    sb[15].StatID    = (uint)Stats.NumScriptActive;
                    sb[15].StatValue = totalScriptMonitor.ActiveScripts;

                    sb[16].StatID    = (uint)Stats.LSLIPS;
                    sb[16].StatValue = 0; //This isn't used anymore, and has been superseeded by LSLEPS

                    sb[17].StatID    = (uint)Stats.InPPS;
                    sb[17].StatValue = (networkMonitor.InPacketsPerSecond / statsUpdateFactor);

                    sb[18].StatID    = (uint)Stats.OutPPS;
                    sb[18].StatValue = (networkMonitor.OutPacketsPerSecond / statsUpdateFactor);

                    sb[19].StatID    = (uint)Stats.PendingDownloads;
                    sb[19].StatValue = (networkMonitor.PendingDownloads);

                    sb[20].StatID    = (uint)Stats.PendingUploads;
                    sb[20].StatValue = (networkMonitor.PendingUploads);

                    //21 and 22 are forced to the GC memory as they WILL make memory usage go up rapidly otherwise!
                    sb[21].StatID    = (uint)Stats.VirtualSizeKB;
                    sb[21].StatValue = GC.GetTotalMemory(false) / 1024;
                    // System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / (1024);

                    sb[22].StatID    = (uint)Stats.ResidentSizeKB;
                    sb[22].StatValue = GC.GetTotalMemory(false) / 1024;
                    //(float)System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / (1024);

                    sb[23].StatID    = (uint)Stats.PendingLocalUploads;
                    sb[23].StatValue = (networkMonitor.PendingUploads / statsUpdateFactor);

                    sb[24].StatID    = (uint)Stats.TotalUnackedBytes;
                    sb[24].StatValue = (networkMonitor.UnackedBytes);

                    sb[25].StatID    = (uint)Stats.PhysicsPinnedTasks;
                    sb[25].StatValue = 0;

                    sb[26].StatID    = (uint)Stats.PhysicsLODTasks;
                    sb[26].StatValue = 0;

                    sb[27].StatID    = (uint)Stats.SimPhysicsStepMS;
                    sb[27].StatValue = m_currentScene.PhysicsScene.StepTime;

                    sb[28].StatID    = (uint)Stats.SimPhysicsShape;
                    sb[28].StatValue = 0;

                    sb[29].StatID    = (uint)Stats.SimPhysicsOtherMS;
                    sb[29].StatValue = (float)(physicsSyncFrameMonitor.GetValue() / realsimfps);

                    sb[30].StatID    = (uint)Stats.SimPhysicsMemory;
                    sb[30].StatValue = 0;

                    sb[31].StatID    = (uint)Stats.ScriptEPS;
                    sb[31].StatValue = totalScriptMonitor.ScriptEPS / statsUpdateFactor;

                    sb[32].StatID = (uint)Stats.SimSpareTime;
                    //Spare time is the total time minus the stats that are in the same category in the client
                    // It is the sleep time, physics step, update physics shape, physics other, and pumpI0.
                    // Note: take out agent Update and script time for now, as they are not a part of the heartbeat right now and will mess this calc up
                    float SpareTime = TotalFrames - (
                        /*NetMS + */ PhysicsMS + otherMS + imageMS);
//                         + /*(agentUpdateFrameMonitor.AgentFrameTime / statsUpdateFactor) +*/
//                        (imagesMonitor.GetValue() / statsUpdateFactor) /* + ScriptMS*/));

                    sb[32].StatValue = SpareTime;

                    sb[33].StatID    = (uint)Stats.SimSleepTime;
                    sb[33].StatValue = (float)(sleepFrameMonitor.GetValue() / realsimfps);

                    sb[34].StatID    = (uint)Stats.IOPumpTime;
                    sb[34].StatValue = 0; //TODO: implement this

                    #endregion

                    for (int i = 0; i < sb.Length; i++)
                    {
                        if (float.IsInfinity(sb[i].StatValue) ||
                            float.IsNaN(sb[i].StatValue))
                        {
                            sb[i].StatValue = 0; //Don't send huge values
                        }
                        lastReportedSimStats[i] = sb[i].StatValue;
                    }

                    SimStats simStats
                        = new SimStats(rb, sb, m_currentScene.RegionInfo.RegionID);

                    //Fire the event and tell followers about the new stats
                    m_module.SendStatsResults(simStats);

                    //Tell all the scene presences about the new stats
                    foreach (IScenePresence agent in m_currentScene.GetScenePresences().Where(agent => !agent.IsChildAgent))
                    {
                        agent.ControllingClient.SendSimStats(simStats);
                    }

                    //Now fix any values that require reseting
                    ResetValues();
                }
                m_report.Start();
            }
Пример #2
0
        private bool OnAllowedIncomingAgent(IScene scene, AgentCircuitData agent, bool isRootAgent, out string reason)
        {
            #region Incoming Agent Checks

            UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.AllScopeIDs, agent.AgentID);
            if (account == null)
            {
                reason = "No account exists";
                return(false);
            }
            IScenePresence Sp = scene.GetScenePresence(agent.AgentID);

            if (LoginsDisabled)
            {
                reason = "Logins Disabled";
                return(false);
            }

            //Check how long its been since the last TP
            if (m_enabledBlockTeleportSeconds && Sp != null && !Sp.IsChildAgent)
            {
                if (TimeSinceLastTeleport.ContainsKey(Sp.Scene.RegionInfo.RegionID))
                {
                    if (TimeSinceLastTeleport[Sp.Scene.RegionInfo.RegionID] > Util.UnixTimeSinceEpoch())
                    {
                        reason = "Too many teleports. Please try again soon.";
                        return(false); // Too soon since the last TP
                    }
                }
                TimeSinceLastTeleport[Sp.Scene.RegionInfo.RegionID] = Util.UnixTimeSinceEpoch() +
                                                                      ((int)(SecondsBeforeNextTeleport));
            }

            //Gods tp freely
            if ((Sp != null && Sp.GodLevel != 0) || (account != null && account.UserLevel != 0))
            {
                reason = "";
                return(true);
            }

            //Check whether they fit any ban criteria
            if (Sp != null)
            {
                foreach (string banstr in BanCriteria)
                {
                    if (Sp.Name.Contains(banstr))
                    {
                        reason = "You have been banned from this region.";
                        return(false);
                    }
                    else if (((IPEndPoint)Sp.ControllingClient.GetClientEP()).Address.ToString().Contains(banstr))
                    {
                        reason = "You have been banned from this region.";
                        return(false);
                    }
                }
                //Make sure they exist in the grid right now
                IAgentInfoService presence = scene.RequestModuleInterface <IAgentInfoService>();
                if (presence == null)
                {
                    reason =
                        String.Format(
                            "Failed to verify user presence in the grid for {0} in region {1}. Presence service does not exist.",
                            account.Name, scene.RegionInfo.RegionName);
                    return(false);
                }

                UserInfo pinfo = presence.GetUserInfo(agent.AgentID.ToString());

                if (pinfo == null || (!pinfo.IsOnline && ((agent.TeleportFlags & (uint)TeleportFlags.ViaLogin) == 0)))
                {
                    reason =
                        String.Format(
                            "Failed to verify user presence in the grid for {0}, access denied to region {1}.",
                            account.Name, scene.RegionInfo.RegionName);
                    return(false);
                }
            }

            EstateSettings ES = scene.RegionInfo.EstateSettings;

            IEntityCountModule entityCountModule = scene.RequestModuleInterface <IEntityCountModule>();
            if (entityCountModule != null && scene.RegionInfo.RegionSettings.AgentLimit
                < entityCountModule.RootAgents + 1 &&
                scene.RegionInfo.RegionSettings.AgentLimit > 0)
            {
                reason = "Too many agents at this time. Please come back later.";
                return(false);
            }

            List <EstateBan> EstateBans = new List <EstateBan>(ES.EstateBans);
            int i = 0;
            //Check bans
            foreach (EstateBan ban in EstateBans)
            {
                if (ban.BannedUserID == agent.AgentID)
                {
                    if (Sp != null)
                    {
                        string banIP = ((IPEndPoint)Sp.ControllingClient.GetClientEP()).Address.ToString();

                        if (ban.BannedHostIPMask != banIP) //If it changed, ban them again
                        {
                            //Add the ban with the new hostname
                            ES.AddBan(new EstateBan
                            {
                                BannedHostIPMask   = banIP,
                                BannedUserID       = ban.BannedUserID,
                                EstateID           = ban.EstateID,
                                BannedHostAddress  = ban.BannedHostAddress,
                                BannedHostNameMask = ban.BannedHostNameMask
                            });
                            //Update the database
                            ES.Save();
                        }
                    }

                    reason = "Banned from this region.";
                    return(false);
                }
                if (Sp != null)
                {
                    IPAddress   end  = Sp.ControllingClient.EndPoint;
                    IPHostEntry rDNS = null;
                    try
                    {
                        rDNS = Dns.GetHostEntry(end);
                    }
                    catch (SocketException)
                    {
                        MainConsole.Instance.WarnFormat("[IPBAN] IP address \"{0}\" cannot be resolved via DNS", end);
                        rDNS = null;
                    }
                    if (ban.BannedHostIPMask == agent.IPAddress ||
                        (rDNS != null && rDNS.HostName.Contains(ban.BannedHostIPMask)) ||
                        end.ToString().StartsWith(ban.BannedHostIPMask))
                    {
                        //Ban the new user
                        ES.AddBan(new EstateBan
                        {
                            EstateID           = ES.EstateID,
                            BannedHostIPMask   = agent.IPAddress,
                            BannedUserID       = agent.AgentID,
                            BannedHostAddress  = agent.IPAddress,
                            BannedHostNameMask = agent.IPAddress
                        });
                        ES.Save();

                        reason = "Banned from this region.";
                        return(false);
                    }
                }
                i++;
            }

            //Estate owners/managers/access list people/access groups tp freely as well
            if (ES.EstateOwner == agent.AgentID ||
                new List <UUID>(ES.EstateManagers).Contains(agent.AgentID) ||
                new List <UUID>(ES.EstateAccess).Contains(agent.AgentID) ||
                CheckEstateGroups(ES, agent))
            {
                reason = "";
                return(true);
            }

            if (ES.DenyAnonymous &&
                ((account.UserFlags & (int)IUserProfileInfo.ProfileFlags.NoPaymentInfoOnFile) ==
                 (int)IUserProfileInfo.ProfileFlags.NoPaymentInfoOnFile))
            {
                reason = "You may not enter this region.";
                return(false);
            }

            if (ES.DenyIdentified &&
                ((account.UserFlags & (int)IUserProfileInfo.ProfileFlags.PaymentInfoOnFile) ==
                 (int)IUserProfileInfo.ProfileFlags.PaymentInfoOnFile))
            {
                reason = "You may not enter this region.";
                return(false);
            }

            if (ES.DenyTransacted &&
                ((account.UserFlags & (int)IUserProfileInfo.ProfileFlags.PaymentInfoInUse) ==
                 (int)IUserProfileInfo.ProfileFlags.PaymentInfoInUse))
            {
                reason = "You may not enter this region.";
                return(false);
            }

            const long m_Day = 25 * 60 * 60; //Find out day length in seconds
            if (scene.RegionInfo.RegionSettings.MinimumAge != 0 &&
                (account.Created - Util.UnixTimeSinceEpoch()) < (scene.RegionInfo.RegionSettings.MinimumAge * m_Day))
            {
                reason = "You may not enter this region.";
                return(false);
            }

            if (!ES.PublicAccess)
            {
                reason = "You may not enter this region, Public access has been turned off.";
                return(false);
            }

            IAgentConnector AgentConnector = Framework.Utilities.DataManager.RequestPlugin <IAgentConnector>();
            IAgentInfo      agentInfo      = null;
            if (AgentConnector != null)
            {
                agentInfo = AgentConnector.GetAgent(agent.AgentID);
                if (agentInfo == null)
                {
                    AgentConnector.CreateNewAgent(agent.AgentID);
                    agentInfo = AgentConnector.GetAgent(agent.AgentID);
                }
            }

            if (m_checkMaturityLevel)
            {
                if (agentInfo != null &&
                    scene.RegionInfo.AccessLevel > Util.ConvertMaturityToAccessLevel((uint)agentInfo.MaturityRating))
                {
                    reason = "The region has too high of a maturity level. Blocking teleport.";
                    return(false);
                }

                if (agentInfo != null && ES.DenyMinors && (agentInfo.Flags & IAgentFlags.Minor) == IAgentFlags.Minor)
                {
                    reason = "The region has too high of a maturity level. Blocking teleport.";
                    return(false);
                }
            }

            #endregion

            reason = "";
            return(true);
        }
Пример #3
0
        private List <SensedEntity> doAgentSensor(SenseRepeatClass ts)
        {
            List <SensedEntity> sensedEntities = new List <SensedEntity>();

            // If nobody about quit fast
            IEntityCountModule entityCountModule =
                ts.host.ParentEntity.Scene.RequestModuleInterface <IEntityCountModule>();

            if (entityCountModule != null && entityCountModule.RootAgents == 0)
            {
                return(sensedEntities);
            }

            ISceneChildEntity SensePoint    = ts.host;
            Vector3           fromRegionPos = SensePoint.AbsolutePosition;
            Quaternion        q             = SensePoint.GetRotationOffset();

            LSL_Types.Quaternion r           = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
            LSL_Types.Vector3    forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
            double  mag_fwd  = LSL_Types.Vector3.Mag(forward_dir);
            bool    attached = (SensePoint.AttachmentPoint != 0);
            Vector3 toRegionPos;
            double  dis;

            Action <IScenePresence> senseEntity = delegate(IScenePresence presence)
            {
                if (presence.IsDeleted || presence.IsChildAgent ||
                    presence.GodLevel > 0.0)
                {
                    return;
                }

                // if the object the script is in is attached and the avatar is the owner
                // then this one is not wanted
                if (attached && presence.UUID == SensePoint.OwnerID)
                {
                    return;
                }

                toRegionPos = presence.AbsolutePosition;
                dis         = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos));

                // are they in range
                if (dis <= ts.range)
                {
                    // Are they in the required angle of view
                    if (ts.arc < Math.PI)
                    {
                        // not omni-directional. Can you see it ?
                        // vec forward_dir = llRot2Fwd(llGetRot())
                        // vec obj_dir = toRegionPos-fromRegionPos
                        // dot=dot(forward_dir,obj_dir)
                        // mag_fwd = mag(forward_dir)
                        // mag_obj = mag(obj_dir)
                        // ang = acos(dot /(mag_fwd*mag_obj))
                        double ang_obj = 0;
                        try
                        {
                            Vector3           diff    = toRegionPos - fromRegionPos;
                            LSL_Types.Vector3 obj_dir =
                                new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
                            double dot = LSL_Types.Vector3.Dot(forward_dir,
                                                               obj_dir);
                            double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
                            ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
                        }
                        catch
                        {
                        }
                        if (ang_obj <= ts.arc)
                        {
                            sensedEntities.Add(new SensedEntity(dis,
                                                                presence.UUID));
                        }
                    }
                    else
                    {
                        sensedEntities.Add(new SensedEntity(dis, presence.UUID));
                    }
                }
            };

            // If this is an avatar sense by key try to get them directly
            // rather than getting a list to scan through
            if (ts.keyID != UUID.Zero)
            {
                IScenePresence sp;
                // Try direct lookup by UUID
                if (!ts.host.ParentEntity.Scene.TryGetScenePresence(ts.keyID, out sp))
                {
                    return(sensedEntities);
                }
                senseEntity(sp);
            }
            else if (!string.IsNullOrEmpty(ts.name))
            {
                IScenePresence sp;
                // Try lookup by name will return if/when found
                if (!ts.host.ParentEntity.Scene.TryGetAvatarByName(ts.name, out sp))
                {
                    return(sensedEntities);
                }
                if (((ts.type & AGENT) != 0) && ts.host.ParentEntity.Scene.TryGetAvatarByName(ts.name, out sp))
                {
                    senseEntity(sp);
                }
                if ((ts.type & AGENT_BY_USERNAME) != 0)
                {
                    ts.host.ParentEntity.Scene.ForEachScenePresence(
                        delegate(IScenePresence ssp)
                    {
                        if (ssp.Name.Replace(" ", ".").ToLower() == ts.name)
                        {
                            senseEntity(ssp);
                        }
                    }
                        );
                }
            }
            else
            {
                ts.host.ParentEntity.Scene.ForEachScenePresence(senseEntity);
            }
            return(sensedEntities);
        }
Пример #4
0
        public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags,
                                                 uint EstateID, bool godlike, uint itemtype, ulong regionhandle)
        {
            lock (m_rootAgents)
            {
                if (!m_rootAgents.Contains(remoteClient.AgentId))
                {
                    return;
                }
            }

            uint xstart = 0;
            uint ystart = 0;

            OpenMetaverse.Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out xstart, out ystart);

            List <mapItemReply> mapitems = new List <mapItemReply>();
            int tc = Environment.TickCount;

            if (itemtype == (int)OpenMetaverse.GridItemType.AgentLocations)
            {
                //If its local, just let it do it on its own.
                if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle)
                {
                    //Only one person here, send a zero person response
                    mapItemReply       mapitem           = new mapItemReply();
                    IEntityCountModule entityCountModule = m_scene.RequestModuleInterface <IEntityCountModule>();
                    if (entityCountModule != null && entityCountModule.RootAgents <= 1)
                    {
                        mapitem        = new mapItemReply();
                        mapitem.x      = (uint)(xstart + 1);
                        mapitem.y      = (uint)(ystart + 1);
                        mapitem.id     = UUID.Zero;
                        mapitem.name   = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString());
                        mapitem.Extra  = 0;
                        mapitem.Extra2 = 0;
                        mapitems.Add(mapitem);
                        remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
                        return;
                    }
                    m_scene.ForEachScenePresence(delegate(IScenePresence sp)
                    {
                        // Don't send a green dot for yourself
                        if (!sp.IsChildAgent && sp.UUID != remoteClient.AgentId)
                        {
                            mapitem        = new mapItemReply();
                            mapitem.x      = (uint)(xstart + sp.AbsolutePosition.X);
                            mapitem.y      = (uint)(ystart + sp.AbsolutePosition.Y);
                            mapitem.id     = UUID.Zero;
                            mapitem.name   = Util.Md5Hash(m_scene.RegionInfo.RegionName + tc.ToString());
                            mapitem.Extra  = 1;
                            mapitem.Extra2 = 0;
                            mapitems.Add(mapitem);
                        }
                    });
                    remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags);
                }
                else
                {
                    List <mapItemReply> reply;
                    if (!m_mapItemCache.TryGetValue(regionhandle, out reply))
                    {
                        m_itemsToRequest.Add(new MapItemRequester()
                        {
                            flags        = flags,
                            itemtype     = itemtype,
                            regionhandle = regionhandle,
                            remoteClient = remoteClient
                        });

                        if (!itemRequesterIsRunning)
                        {
                            threadpool.QueueEvent(GetMapItems, 3);
                        }
                    }
                    else
                    {
                        remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, 0);
                    }
                }
            }
        }