From a56f40470efd0b3ca6000cb4561efc59c6b3c25e Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Thu, 4 Apr 2019 18:55:40 +0100 Subject: [PATCH] control visible regions by avatar position and view range, first dirty code --- .../EntityTransfer/EntityTransferModule.cs | 360 ++++++++++++++---- .../Interfaces/IEntityTransferModule.cs | 2 + OpenSim/Region/Framework/Scenes/Scene.cs | 6 +- .../Region/Framework/Scenes/ScenePresence.cs | 146 ++++--- 4 files changed, 371 insertions(+), 143 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 6b3e8c48c3..b4ac968008 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -1932,12 +1932,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (seeds.ContainsKey(regionhandler)) seeds.Remove(regionhandler); -/* - List oldregions = new List(seeds.Keys); - if (oldregions.Contains(currentRegionHandler)) - oldregions.Remove(currentRegionHandler); -*/ if (!seeds.ContainsKey(currentRegionHandler)) seeds.Add(currentRegionHandler, sp.ControllingClient.RequestClientInfo().CapsPath); @@ -1975,24 +1970,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.Mac = currentAgentCircuit.Mac; agent.Id0 = currentAgentCircuit.Id0; } -/* - AgentPosition agentpos = null; - if (oldregions.Count > 0) - { - agentpos = new AgentPosition(); - agentpos.AgentID = new UUID(sp.UUID.Guid); - agentpos.SessionID = sp.ControllingClient.SessionId; - agentpos.Size = sp.Appearance.AvatarSize; - agentpos.Center = sp.CameraPosition; - agentpos.Far = sp.DrawDistance; - agentpos.Position = sp.AbsolutePosition; - agentpos.Velocity = sp.Velocity; - agentpos.RegionHandle = currentRegionHandler; - agentpos.Throttles = sp.ControllingClient.GetThrottlesPacked(1); - agentpos.ChildrenCapSeeds = seeds; - } -*/ IPEndPoint external = region.ExternalEndPoint; if (external != null) { @@ -2001,20 +1979,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer InformClientOfNeighbourCompleted, d); } -/* - if(oldregions.Count >0) - { - uint neighbourx; - uint neighboury; - UUID scope = sp.Scene.RegionInfo.ScopeID; - foreach (ulong handler in oldregions) - { - Utils.LongToUInts(handler, out neighbourx, out neighboury); - GridRegion neighbour = sp.Scene.GridService.GetRegionByPosition(scope, (int)neighbourx, (int)neighboury); - sp.Scene.SimulationService.UpdateAgent(neighbour, agentpos); - } - } - */ } #endregion @@ -2024,6 +1988,44 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private delegate void InformClientOfNeighbourDelegate( ScenePresence avatar, AgentCircuitData a, GridRegion reg, IPEndPoint endPoint, bool newAgent); + List RegionsInView(Vector3 pos, RegionInfo curregion, List fullneighbours, float viewrange) + { + List ret = new List(); + if(fullneighbours.Count == 0) + return ret; + + int curX = (int)Util.RegionToWorldLoc(curregion.RegionLocX) + (int)pos.X; + int minX = curX - (int)viewrange; + int maxX = curX + (int)viewrange; + int curY = (int)Util.RegionToWorldLoc(curregion.RegionLocY) + (int)pos.Y; + int minY = curY - (int)viewrange; + int maxY = curY + (int)viewrange; + int rtmp; + + foreach (GridRegion r in fullneighbours) + { + OpenSim.Framework.RegionFlags? regionFlags = r.RegionFlags; + if (regionFlags != null) + { + if ((regionFlags & OpenSim.Framework.RegionFlags.RegionOnline) == 0) + continue; + } + + rtmp = r.RegionLocX; + if (maxX < rtmp) + continue; + if (minX > rtmp + r.RegionSizeX) + continue; + rtmp = r.RegionLocY; + if (maxY < rtmp) + continue; + if (minY > rtmp + r.RegionSizeY) + continue; + ret.Add(r); + } + return ret; + } + /// /// This informs all neighbouring regions about agent "avatar". /// and as important informs the avatar about then @@ -2033,20 +2035,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // assumes that out of view range regions are disconnected by the previus region - List neighbours = new List(); Scene spScene = sp.Scene; - RegionInfo m_regionInfo = spScene.RegionInfo; + RegionInfo regionInfo = spScene.RegionInfo; - if (m_regionInfo != null) - { - neighbours = GetNeighbors(sp, m_regionInfo.RegionLocX, m_regionInfo.RegionLocY); - } - else - { - m_log.Debug("[ENTITY TRANSFER MODULE]: m_regionInfo was null in EnableChildAgents, is this a NPC?"); - } + if (regionInfo == null) + return; - ulong currentRegionHandler = m_regionInfo.RegionHandle; + ulong currentRegionHandler = regionInfo.RegionHandle; + + List fullneighbours = GetNeighbors(sp); + List neighbours = RegionsInView(sp.AbsolutePosition, regionInfo, fullneighbours, sp.RegionViewDistance); LinkedList previousRegionNeighbourHandles; Dictionary seeds; @@ -2082,13 +2080,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer List cagents = new List(); List newneighbours = new List(); - bool notHG = (sp.TeleportFlags & Constants.TeleportFlags.ViaHGLogin) == 0; - foreach (GridRegion neighbour in neighbours) { ulong handler = neighbour.RegionHandle; - if (notHG && previousRegionNeighbourHandles.Contains(handler)) + if (previousRegionNeighbourHandles.Contains(handler)) { // agent already knows this region previousRegionNeighbourHandles.Remove(handler); @@ -2135,13 +2131,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer foreach (ulong handler in previousRegionNeighbourHandles) seeds.Remove(handler); - if(notHG) // does not work on HG - { - toclose = new List(previousRegionNeighbourHandles); -// sp.CloseChildAgents(toclose); - } - else - toclose = new List(); + toclose = new List(previousRegionNeighbourHandles); } else toclose = new List(); @@ -2173,7 +2163,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Util.FireAndForget(delegate { - Thread.Sleep(500); // the original delay that was at InformClientOfNeighbourAsync start int count = 0; IPEndPoint ipe; @@ -2196,10 +2185,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } count++; } - else if (notHG && !previousRegionNeighbourHandles.Contains(handler)) + else if (!previousRegionNeighbourHandles.Contains(handler)) { spScene.SimulationService.UpdateAgent(neighbour, agentpos); } + if (sp.IsDeleted) + return; } catch (Exception e) { @@ -2216,6 +2207,202 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } + public void CheckChildAgents(ScenePresence sp) + { + // assumes that out of view range regions are disconnected by the previus region + + Scene spScene = sp.Scene; + RegionInfo regionInfo = spScene.RegionInfo; + + if (regionInfo == null) + return; + + ulong currentRegionHandler = regionInfo.RegionHandle; + + List fullneighbours = GetNeighbors(sp); + List neighbours = RegionsInView(sp.AbsolutePosition, regionInfo, fullneighbours, sp.RegionViewDistance); + + LinkedList previousRegionNeighbourHandles = new LinkedList(sp.KnownRegions.Keys); + + IClientAPI spClient = sp.ControllingClient; + + AgentCircuitData currentAgentCircuit = + spScene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); + + List cagents = new List(); + List newneighbours = new List(); + + foreach (GridRegion neighbour in neighbours) + { + ulong handler = neighbour.RegionHandle; + + if (previousRegionNeighbourHandles.Contains(handler)) + { + // agent already knows this region + previousRegionNeighbourHandles.Remove(handler); + continue; + } + + if (handler == currentRegionHandler) + continue; + + // a new region to add + AgentCircuitData agent = spClient.RequestClientInfo(); + agent.BaseFolder = UUID.Zero; + agent.InventoryFolder = UUID.Zero; + agent.startpos = sp.AbsolutePosition + CalculateOffset(sp, neighbour); + agent.child = true; + agent.Appearance = new AvatarAppearance(); + agent.Appearance.AvatarHeight = sp.Appearance.AvatarHeight; + agent.startfar = sp.DrawDistance; + if (currentAgentCircuit != null) + { + agent.ServiceURLs = currentAgentCircuit.ServiceURLs; + agent.IPAddress = currentAgentCircuit.IPAddress; + agent.Viewer = currentAgentCircuit.Viewer; + agent.Channel = currentAgentCircuit.Channel; + agent.Mac = currentAgentCircuit.Mac; + agent.Id0 = currentAgentCircuit.Id0; + } + + newneighbours.Add(neighbour); + agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); + sp.AddNeighbourRegion(neighbour, agent.CapsPath); + + agent.ChildrenCapSeeds = null; + cagents.Add(agent); + } + + List toclose; + // previousRegionNeighbourHandles now contains regions to forget + if (previousRegionNeighbourHandles.Count > 0) + { + if (previousRegionNeighbourHandles.Contains(currentRegionHandler)) + previousRegionNeighbourHandles.Remove(currentRegionHandler); + + foreach (ulong handler in previousRegionNeighbourHandles) + sp.KnownRegions.Remove(handler); + + toclose = new List(previousRegionNeighbourHandles); + } + else + toclose = new List(); + + ICapabilitiesModule capsModule = spScene.CapsModule; + if (capsModule != null) + capsModule.SetChildrenSeed(sp.UUID, sp.KnownRegions); + + if (toclose.Count > 0) + sp.CloseChildAgents(toclose); + + if (newneighbours.Count > 0) + { + int count = 0; + IPEndPoint ipe; + + foreach (GridRegion neighbour in newneighbours) + { + try + { + ipe = neighbour.ExternalEndPoint; + if (ipe != null) + InformClientOfNeighbourAsync(sp, cagents[count], neighbour, ipe, true); + else + { + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: lost DNS resolution for neighbour {0}", neighbour.ExternalHostName); + } + count++; + if (sp.IsDeleted) + return; + } + catch (Exception e) + { + m_log.ErrorFormat( + "[ENTITY TRANSFER MODULE]: Error creating child agent at {0} ({1} ({2}, {3}). {4}", + neighbour.ExternalHostName, + neighbour.RegionHandle, + neighbour.RegionLocX, + neighbour.RegionLocY, + e); + } + } + } + } + + public void CloseOldChildAgents(ScenePresence sp) + { + Scene spScene = sp.Scene; + RegionInfo regionInfo = spScene.RegionInfo; + + if (regionInfo == null) + return; + + ulong currentRegionHandler = regionInfo.RegionHandle; + + List fullneighbours = GetNeighbors(sp); + List neighbours = RegionsInView(sp.AbsolutePosition, regionInfo, fullneighbours, sp.RegionViewDistance); + + LinkedList previousRegionNeighbourHandles; + Dictionary seeds; + ICapabilitiesModule capsModule = spScene.CapsModule; + + if (capsModule != null) + { + seeds = new Dictionary(capsModule.GetChildrenSeeds(sp.UUID)); + previousRegionNeighbourHandles = new LinkedList(seeds.Keys); + } + else + { + seeds = new Dictionary(); + previousRegionNeighbourHandles = new LinkedList(); + } + + IClientAPI spClient = sp.ControllingClient; + + // This will fail if the user aborts login + try + { + if (!seeds.ContainsKey(currentRegionHandler)) + seeds.Add(currentRegionHandler, spClient.RequestClientInfo().CapsPath); + } + catch + { + return; + } + + foreach (GridRegion neighbour in neighbours) + { + ulong handler = neighbour.RegionHandle; + + if (previousRegionNeighbourHandles.Contains(handler)) + previousRegionNeighbourHandles.Remove(handler); + } + + List toclose; + // previousRegionNeighbourHandles now contains regions to forget + if (previousRegionNeighbourHandles.Count == 0) + return; + + if (previousRegionNeighbourHandles.Contains(currentRegionHandler)) + previousRegionNeighbourHandles.Remove(currentRegionHandler); + + foreach (ulong handler in previousRegionNeighbourHandles) + seeds.Remove(handler); + + toclose = new List(previousRegionNeighbourHandles); + + if (capsModule != null) + capsModule.SetChildrenSeed(sp.UUID, seeds); + + sp.KnownRegions = seeds; + sp.SetNeighbourRegionSizeInfo(neighbours); + + Util.FireAndForget(delegate + { + sp.CloseChildAgents(toclose); + }); + } + // Computes the difference between two region bases. // Returns a vector of world coordinates (meters) from base of first region to the second. // The first region is the home region of the passed scene presence. @@ -2416,6 +2603,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } + // all this code should be moved to scene replacing the now bad one there + // cache Neighbors + List Neighbors = null; + DateTime LastNeighborsTime = DateTime.MinValue; + /// /// Return the list of online regions that are considered to be neighbours to the given scene. /// @@ -2423,39 +2615,41 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// /// /// - protected List GetNeighbors(ScenePresence avatar, uint pRegionLocX, uint pRegionLocY) + protected List GetNeighbors(ScenePresence avatar) { Scene pScene = avatar.Scene; - RegionInfo m_regionInfo = pScene.RegionInfo; + + uint dd = (uint)pScene.MaxRegionViewDistance; + if(dd <= 1) + return new List(); + + if (Neighbors != null && (DateTime.UtcNow - LastNeighborsTime).TotalSeconds < 30) + { + return Neighbors; + } + + RegionInfo regionInfo = pScene.RegionInfo; List neighbours; - uint dd = (uint)avatar.RegionViewDistance; + dd--; - // until avatar movement updates client connections, we need to send at least this current region immediate neighbors - uint ddX = Math.Max(dd, Constants.RegionSize); - uint ddY = Math.Max(dd, Constants.RegionSize); + uint startX = Util.RegionToWorldLoc(regionInfo.RegionLocX); + uint endX = startX + regionInfo.RegionSizeX; + uint startY = Util.RegionToWorldLoc(regionInfo.RegionLocY); + uint endY = startY + regionInfo.RegionSizeY; - ddX--; - ddY--; + startX -= dd; + startY -= dd; + endX += dd; + endY += dd; - // reference to region edges. Should be avatar position - uint startX = Util.RegionToWorldLoc(pRegionLocX); - uint endX = startX + m_regionInfo.RegionSizeX; - uint startY = Util.RegionToWorldLoc(pRegionLocY); - uint endY = startY + m_regionInfo.RegionSizeY; - - startX -= ddX; - startY -= ddY; - endX += ddX; - endY += ddY; - - neighbours - = avatar.Scene.GridService.GetRegionRange( - m_regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); + neighbours = avatar.Scene.GridService.GetRegionRange( + regionInfo.ScopeID, (int)startX, (int)endX, (int)startY, (int)endY); // The r.RegionFlags == null check only needs to be made for simulators before 2015-01-14 (pre 0.8.1). - neighbours.RemoveAll( r => r.RegionID == m_regionInfo.RegionID ); - + neighbours.RemoveAll( r => r.RegionID == regionInfo.RegionID ); + Neighbors = neighbours; + LastNeighborsTime = DateTime.UtcNow; return neighbours; } #endregion diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 1b690bad3f..937756448b 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -90,6 +90,8 @@ namespace OpenSim.Region.Framework.Interfaces void AgentArrivedAtDestination(UUID agent); void EnableChildAgents(ScenePresence agent); + void CheckChildAgents(ScenePresence agent); + void CloseOldChildAgents(ScenePresence agent); void EnableChildAgent(ScenePresence agent, GridRegion region); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 7d312e90f0..e130bd7bc2 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1286,7 +1286,6 @@ namespace OpenSim.Region.Framework.Scenes { if (RegionInfo.RegionHandle != otherRegion.RegionHandle) { - if (isNeighborRegion(otherRegion)) { // Let the grid service module know, so this can be cached @@ -1296,9 +1295,6 @@ namespace OpenSim.Region.Framework.Scenes { ForEachRootScenePresence(delegate(ScenePresence agent) { - //agent.ControllingClient.new - //this.CommsManager.InterRegion.InformRegionOfChildAgent(otherRegion.RegionHandle, agent.ControllingClient.RequestClientInfo()); - List old = new List(); old.Add(otherRegion.RegionHandle); agent.DropOldNeighbours(old); @@ -1324,7 +1320,7 @@ namespace OpenSim.Region.Framework.Scenes public bool isNeighborRegion(GridRegion otherRegion) { - int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; ; + int tmp = otherRegion.RegionLocX - (int)RegionInfo.WorldLocX; if (tmp < -otherRegion.RegionSizeX && tmp > RegionInfo.RegionSizeX) return false; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index be593ad5a2..fbf9b4a783 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -165,6 +165,7 @@ namespace OpenSim.Region.Framework.Scenes public static readonly float MOVEMENT = .25f; public static readonly float SIGNIFICANT_MOVEMENT = 16.0f; public static readonly float CHILDUPDATES_MOVEMENT = 100.0f; + public static readonly float CHILDAGENTSCHECK_MOVEMENT = 1024f; // 32m public static readonly float CHILDUPDATES_TIME = 2000f; // min time between child updates (ms) private UUID m_previusParcelUUID = UUID.Zero; @@ -342,7 +343,8 @@ namespace OpenSim.Region.Framework.Scenes private int m_lastChildAgentUpdateGodLevel; private float m_lastChildAgentUpdateDrawDistance; private Vector3 m_lastChildAgentUpdatePosition; -// private Vector3 m_lastChildAgentUpdateCamPosition; + private Vector3 m_lastChildAgentCheckPosition; + // private Vector3 m_lastChildAgentUpdateCamPosition; private Vector3 m_lastCameraRayCastCam; private Vector3 m_lastCameraRayCastPos; @@ -627,7 +629,7 @@ namespace OpenSim.Region.Framework.Scenes { get { - return Util.Clamp(m_drawDistance, 32f, m_scene.MaxRegionViewDistance); + return Util.Clamp(m_drawDistance + 64f, 64f, m_scene.MaxRegionViewDistance); } } @@ -2321,6 +2323,7 @@ namespace OpenSim.Region.Framework.Scenes m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000; m_lastChildAgentUpdatePosition = AbsolutePosition; + m_lastChildAgentCheckPosition = m_lastChildAgentUpdatePosition; m_lastChildAgentUpdateDrawDistance = DrawDistance; m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; @@ -4049,20 +4052,11 @@ namespace OpenSim.Region.Framework.Scenes //NeedInitialData = 4; //return; } - - // Create child agents in neighbouring regions IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); if (m_agentTransfer != null) { - m_agentTransfer.EnableChildAgents(this); + m_agentTransfer.CloseOldChildAgents(this); } - - m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000; - m_lastChildAgentUpdatePosition = AbsolutePosition; - m_lastChildAgentUpdateDrawDistance = DrawDistance; - - m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; - m_childUpdatesBusy = false; // allow them } m_log.DebugFormat("[SCENE PRESENCE({0})]: SendInitialData for {1}", Scene.RegionInfo.RegionName, UUID); @@ -4126,6 +4120,24 @@ namespace OpenSim.Region.Framework.Scenes m_reprioritizationBusy = false; } + + if (!IsChildAgent) + { + // Create child agents in neighbouring regions + IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); + if (m_agentTransfer != null) + { + m_agentTransfer.EnableChildAgents(this); + } + + m_lastChildUpdatesTime = Util.EnvironmentTickCount() + 10000; + m_lastChildAgentUpdatePosition = AbsolutePosition; + m_lastChildAgentCheckPosition = m_lastChildAgentUpdatePosition; + m_lastChildAgentUpdateDrawDistance = DrawDistance; + + m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; + m_childUpdatesBusy = false; // allow them + } }); } @@ -4399,56 +4411,80 @@ namespace OpenSim.Region.Framework.Scenes if(m_childUpdatesBusy) return; - //possible KnownRegionHandles always contains current region and this check is not needed - int minhandles = KnownRegionHandles.Contains(RegionHandle) ? 1 : 0; - if(KnownRegionHandles.Count > minhandles) + int tdiff = Util.EnvironmentTickCountSubtract(m_lastChildUpdatesTime); + if (tdiff < CHILDUPDATES_TIME) + return; + + IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); + float dx = pos.X - m_lastChildAgentCheckPosition.Y; + float dy = pos.Y - m_lastChildAgentCheckPosition.Y; + if ((m_agentTransfer != null) && ((dx * dx + dy *dy) > CHILDAGENTSCHECK_MOVEMENT)) { - int tdiff = Util.EnvironmentTickCountSubtract(m_lastChildUpdatesTime); - if(tdiff < CHILDUPDATES_TIME) - return; + m_childUpdatesBusy = true; + m_lastChildAgentCheckPosition = pos; + m_lastChildAgentUpdatePosition = pos; + m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; + m_lastChildAgentUpdateDrawDistance = DrawDistance; + // m_lastChildAgentUpdateCamPosition = CameraPosition; - bool doUpdate = false; - if(m_lastChildAgentUpdateGodLevel != GodController.ViwerUIGodLevel) - doUpdate = true; - - if(!doUpdate && Math.Abs(DrawDistance - m_lastChildAgentUpdateDrawDistance) > 32.0f) - doUpdate = true; - - if(!doUpdate) + Util.FireAndForget( + o => + { + m_agentTransfer.EnableChildAgents(this); + m_lastChildUpdatesTime = Util.EnvironmentTickCount(); + m_childUpdatesBusy = false; + }, null, "ScenePresence.CheckChildAgents"); + } + else + { + //possible KnownRegionHandles always contains current region and this check is not needed + int minhandles = KnownRegionHandles.Contains(RegionHandle) ? 1 : 0; + if(KnownRegionHandles.Count > minhandles) { - diff = pos - m_lastChildAgentUpdatePosition; - if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT) + bool doUpdate = false; + if (m_lastChildAgentUpdateGodLevel != GodController.ViwerUIGodLevel) doUpdate = true; - } - if(doUpdate) - { - m_childUpdatesBusy = true; - m_lastChildAgentUpdatePosition = pos; - m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; - m_lastChildAgentUpdateDrawDistance = DrawDistance; -// m_lastChildAgentUpdateCamPosition = CameraPosition; + bool viewchanged = Math.Abs(DrawDistance - m_lastChildAgentUpdateDrawDistance) > 32.0f; + if (!viewchanged) + doUpdate = true; - AgentPosition agentpos = new AgentPosition(); - agentpos.AgentID = new UUID(UUID.Guid); - agentpos.SessionID = ControllingClient.SessionId; - agentpos.Size = Appearance.AvatarSize; - agentpos.Center = CameraPosition; - agentpos.Far = DrawDistance; - agentpos.Position = AbsolutePosition; - agentpos.Velocity = Velocity; - agentpos.RegionHandle = RegionHandle; - agentpos.GodData = GodController.State(); - agentpos.Throttles = ControllingClient.GetThrottlesPacked(1); + if(!doUpdate) + { + diff = pos - m_lastChildAgentUpdatePosition; + if (diff.LengthSquared() > CHILDUPDATES_MOVEMENT) + doUpdate = true; + } - // Let's get this out of the update loop - Util.FireAndForget( - o => - { - m_scene.SendOutChildAgentUpdates(agentpos, this); - m_lastChildUpdatesTime = Util.EnvironmentTickCount(); - m_childUpdatesBusy = false; - }, null, "ScenePresence.SendOutChildAgentUpdates"); + if (doUpdate) + { + m_childUpdatesBusy = true; + m_lastChildAgentUpdatePosition = pos; + m_lastChildAgentUpdateGodLevel = GodController.ViwerUIGodLevel; + m_lastChildAgentUpdateDrawDistance = DrawDistance; + // m_lastChildAgentUpdateCamPosition = CameraPosition; + + AgentPosition agentpos = new AgentPosition(); + agentpos.AgentID = new UUID(UUID.Guid); + agentpos.SessionID = ControllingClient.SessionId; + agentpos.Size = Appearance.AvatarSize; + agentpos.Center = CameraPosition; + agentpos.Far = DrawDistance; + agentpos.Position = AbsolutePosition; + agentpos.Velocity = Velocity; + agentpos.RegionHandle = RegionHandle; + agentpos.GodData = GodController.State(); + agentpos.Throttles = ControllingClient.GetThrottlesPacked(1); + + // Let's get this out of the update loop + Util.FireAndForget( + o => + { + m_scene.SendOutChildAgentUpdates(agentpos, this); + m_lastChildUpdatesTime = Util.EnvironmentTickCount(); + m_childUpdatesBusy = false; + }, null, "ScenePresence.SendOutChildAgentUpdates"); + } } } }