diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 31c80c1238..29bd6b634a 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -176,7 +176,8 @@ namespace OpenSim.Data.MySQL "PassCollisions, " + "LinkNumber, MediaURL, KeyframeMotion, " + "PhysicsShapeType, Density, GravityModifier, " + - "Friction, Restitution) values (" + "?UUID, " + + "Friction, Restitution, Vehicle " + + ") values (" + "?UUID, " + "?CreationDate, ?Name, ?Text, " + "?Description, ?SitName, ?TouchName, " + "?ObjectFlags, ?OwnerMask, ?NextOwnerMask, " + @@ -210,7 +211,7 @@ namespace OpenSim.Data.MySQL "?CollisionSoundVolume, ?PassTouches, ?PassCollisions, " + "?LinkNumber, ?MediaURL, ?KeyframeMotion, " + "?PhysicsShapeType, ?Density, ?GravityModifier, " + - "?Friction, ?Restitution)"; + "?Friction, ?Restitution, ?Vehicle)"; FillPrimCommand(cmd, prim, obj.UUID, regionUUID); @@ -1320,6 +1321,15 @@ namespace OpenSim.Data.MySQL prim.GravityModifier = (float)(double)row["GravityModifier"]; prim.Friction = (float)(double)row["Friction"]; prim.Bounciness = (float)(double)row["Restitution"]; + + SOPVehicle vehicle = null; + + if (row["Vehicle"].ToString() != String.Empty) + { + vehicle = SOPVehicle.FromXml2(row["Vehicle"].ToString()); + if (vehicle != null) + prim.VehicleParams = vehicle; + } return prim; } @@ -1697,6 +1707,11 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier); cmd.Parameters.AddWithValue("Friction", (double)prim.Friction); cmd.Parameters.AddWithValue("Restitution", (double)prim.Bounciness); + + if (prim.VehicleParams != null) + cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2()); + else + cmd.Parameters.AddWithValue("Vehicle", String.Empty); } /// diff --git a/OpenSim/Framework/LocklessQueue.cs b/OpenSim/Framework/LocklessQueue.cs index dd3d2016d1..84f887cc4d 100644 --- a/OpenSim/Framework/LocklessQueue.cs +++ b/OpenSim/Framework/LocklessQueue.cs @@ -99,8 +99,13 @@ namespace OpenSim.Framework } else { - item = oldHeadNext.Item; + item = oldHeadNext.Item; haveAdvancedHead = CAS(ref head, oldHead, oldHeadNext); + if (haveAdvancedHead) + { + oldHeadNext.Item = default(T); + oldHead.Next = null; + } } } } @@ -111,6 +116,10 @@ namespace OpenSim.Framework public void Clear() { + // ugly + T item; + while(count > 0) + Dequeue(out item); Init(); } diff --git a/OpenSim/Framework/MinHeap.cs b/OpenSim/Framework/MinHeap.cs index 33d0364b6e..99ac25d09d 100644 --- a/OpenSim/Framework/MinHeap.cs +++ b/OpenSim/Framework/MinHeap.cs @@ -63,12 +63,15 @@ namespace OpenSim.Framework internal void Clear() { - this.value = default(T); if (this.handle != null) - { this.handle.Clear(); - this.handle = null; - } + ClearRef(); + } + + internal void ClearRef() + { + this.value = default(T); + this.handle = null; } } @@ -285,6 +288,7 @@ namespace OpenSim.Framework if (--this.size > 0 && index != this.size) { Set(this.items[this.size], index); + this.items[this.size].ClearRef(); if (!BubbleUp(index)) BubbleDown(index); } diff --git a/OpenSim/Framework/Statistics/BaseStatsCollector.cs b/OpenSim/Framework/Statistics/BaseStatsCollector.cs index c9e57ce7b3..3f918f3bd9 100644 --- a/OpenSim/Framework/Statistics/BaseStatsCollector.cs +++ b/OpenSim/Framework/Statistics/BaseStatsCollector.cs @@ -48,10 +48,26 @@ namespace OpenSim.Framework.Statistics string.Format( "Allocated to OpenSim objects: {0} MB\n", Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); - sb.Append( - string.Format( - "Process memory : {0} MB\n", - Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0))); + + Process myprocess = Process.GetCurrentProcess(); + if (!myprocess.HasExited) + { + myprocess.Refresh(); + sb.Append( + string.Format( + "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", + Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0), + Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0), + Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0))); + sb.Append( + string.Format( + "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", + Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0), + Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0), + Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0))); + } + else + sb.Append("Process reported as Exited \n"); return sb.ToString(); } diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index 0c60391fe2..4f18b53311 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -90,9 +90,9 @@ namespace OpenSim.Region.CoreModules.Hypergrid } } - protected override List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + protected override List GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { - List mapBlocks = base.GetAndSendBlocks(remoteClient, minX, minY, maxX, maxY, flag); + List mapBlocks = base.GetAndSendBlocksInternal(remoteClient, minX, minY, maxX, maxY, flag); lock (m_SeenMapBlocks) { if (!m_SeenMapBlocks.ContainsKey(remoteClient.AgentId)) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs index 4e6bfb88a1..2417b1ad75 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapSearchModule.cs @@ -86,90 +86,93 @@ namespace OpenSim.Region.CoreModules.World.WorldMap private void OnMapNameRequest(IClientAPI remoteClient, string mapName, uint flags) { - if (mapName.Length < 2) + Util.FireAndForget(x => { - remoteClient.SendAlertMessage("Use a search string with at least 2 characters"); - return; - } - - //m_log.DebugFormat("MAP NAME=({0})", mapName); - - // Hack to get around the fact that ll V3 now drops the port from the - // map name. See https://jira.secondlife.com/browse/VWR-28570 - // - // Caller, use this magic form instead: - // secondlife://http|!!mygrid.com|8002|Region+Name/128/128 - // or url encode if possible. - // the hacks we do with this viewer... - // - string mapNameOrig = mapName; - if (mapName.Contains("|")) - mapName = mapName.Replace('|', ':'); - if (mapName.Contains("+")) - mapName = mapName.Replace('+', ' '); - if (mapName.Contains("!")) - mapName = mapName.Replace('!', '/'); - - // try to fetch from GridServer - List regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); -// if (regionInfos.Count == 0) -// remoteClient.SendAlertMessage("Hyperlink could not be established."); - - //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count); - List blocks = new List(); - - MapBlockData data; - if (regionInfos.Count > 0) - { - foreach (GridRegion info in regionInfos) + if (mapName.Length < 2) { - data = new MapBlockData(); - data.Agents = 0; - data.Access = info.Access; - if (flags == 2) // V2 sends this - data.MapImageId = UUID.Zero; - else - data.MapImageId = info.TerrainImage; - // ugh! V2-3 is very sensitive about the result being - // exactly the same as the requested name - if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+")) - data.Name = mapNameOrig; - else - data.Name = info.RegionName; - data.RegionFlags = 0; // TODO not used? - data.WaterHeight = 0; // not used - data.X = (ushort)(info.RegionLocX / Constants.RegionSize); - data.Y = (ushort)(info.RegionLocY / Constants.RegionSize); - blocks.Add(data); + remoteClient.SendAlertMessage("Use a search string with at least 2 characters"); + return; } - } - // final block, closing the search result - data = new MapBlockData(); - data.Agents = 0; - data.Access = 255; - data.MapImageId = UUID.Zero; - data.Name = mapName; - data.RegionFlags = 0; - data.WaterHeight = 0; // not used - data.X = 0; - data.Y = 0; - blocks.Add(data); + //m_log.DebugFormat("MAP NAME=({0})", mapName); - // flags are agent flags sent from the viewer. - // they have different values depending on different viewers, apparently - remoteClient.SendMapBlock(blocks, flags); + // Hack to get around the fact that ll V3 now drops the port from the + // map name. See https://jira.secondlife.com/browse/VWR-28570 + // + // Caller, use this magic form instead: + // secondlife://http|!!mygrid.com|8002|Region+Name/128/128 + // or url encode if possible. + // the hacks we do with this viewer... + // + string mapNameOrig = mapName; + if (mapName.Contains("|")) + mapName = mapName.Replace('|', ':'); + if (mapName.Contains("+")) + mapName = mapName.Replace('+', ' '); + if (mapName.Contains("!")) + mapName = mapName.Replace('!', '/'); + + // try to fetch from GridServer + List regionInfos = m_scene.GridService.GetRegionsByName(m_scene.RegionInfo.ScopeID, mapName, 20); + // if (regionInfos.Count == 0) + // remoteClient.SendAlertMessage("Hyperlink could not be established."); - // send extra user messages for V3 - // because the UI is very confusing - // while we don't fix the hard-coded urls - if (flags == 2) - { - if (regionInfos.Count == 0) - remoteClient.SendAgentAlertMessage("No regions found with that name.", true); - else if (regionInfos.Count == 1) - remoteClient.SendAgentAlertMessage("Region found!", false); - } + //m_log.DebugFormat("[MAPSEARCHMODULE]: search {0} returned {1} regions", mapName, regionInfos.Count); + List blocks = new List(); + + MapBlockData data; + if (regionInfos.Count > 0) + { + foreach (GridRegion info in regionInfos) + { + data = new MapBlockData(); + data.Agents = 0; + data.Access = info.Access; + if (flags == 2) // V2 sends this + data.MapImageId = UUID.Zero; + else + data.MapImageId = info.TerrainImage; + // ugh! V2-3 is very sensitive about the result being + // exactly the same as the requested name + if (regionInfos.Count == 1 && mapNameOrig.Contains("|") || mapNameOrig.Contains("+")) + data.Name = mapNameOrig; + else + data.Name = info.RegionName; + data.RegionFlags = 0; // TODO not used? + data.WaterHeight = 0; // not used + data.X = (ushort)(info.RegionLocX / Constants.RegionSize); + data.Y = (ushort)(info.RegionLocY / Constants.RegionSize); + blocks.Add(data); + } + } + + // final block, closing the search result + data = new MapBlockData(); + data.Agents = 0; + data.Access = 255; + data.MapImageId = UUID.Zero; + data.Name = mapName; + data.RegionFlags = 0; + data.WaterHeight = 0; // not used + data.X = 0; + data.Y = 0; + blocks.Add(data); + + // flags are agent flags sent from the viewer. + // they have different values depending on different viewers, apparently + remoteClient.SendMapBlock(blocks, flags); + + // send extra user messages for V3 + // because the UI is very confusing + // while we don't fix the hard-coded urls + if (flags == 2) + { + if (regionInfos.Count == 0) + remoteClient.SendAgentAlertMessage("No regions found with that name.", true); + else if (regionInfos.Count == 1) + remoteClient.SendAgentAlertMessage("Region found!", false); + } + }); } // private Scene GetClientScene(IClientAPI client) diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 00be5df0d5..309856f542 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -63,7 +63,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap private static readonly UUID STOP_UUID = UUID.Random(); private static readonly string m_mapLayerPath = "0001/"; - private OpenSim.Framework.BlockingQueue requests = new OpenSim.Framework.BlockingQueue(); + private ManualResetEvent queueEvent = new ManualResetEvent(false); + private Queue requests = new Queue(); + + private ManualResetEvent m_mapBlockRequestEvent = new ManualResetEvent(false); + private Dictionary> m_mapBlockRequests = new Dictionary>(); protected Scene m_scene; private List cachedMapBlocks = new List(); @@ -71,7 +75,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap private int blacklistTimeout = 10*60*1000; // 10 minutes private byte[] myMapImageJPEG; protected volatile bool m_Enabled = false; - private Dictionary m_openRequests = new Dictionary(); private Dictionary m_blacklistedurls = new Dictionary(); private Dictionary m_blacklistedregions = new Dictionary(); private Dictionary m_cachedRegionMapItemsAddress = new Dictionary(); @@ -228,54 +231,54 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // 6/8/2011 -- I'm adding an explicit 2048 check, so that we never forget that there is // a hack here, and so that regions below 4096 don't get spammed with unnecessary map blocks. - if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) - { - ScenePresence avatarPresence = null; + //if (m_scene.RegionInfo.RegionLocX >= 2048 || m_scene.RegionInfo.RegionLocY >= 2048) + //{ + // ScenePresence avatarPresence = null; - m_scene.TryGetScenePresence(agentID, out avatarPresence); + // m_scene.TryGetScenePresence(agentID, out avatarPresence); - if (avatarPresence != null) - { - bool lookup = false; + // if (avatarPresence != null) + // { + // bool lookup = false; - lock (cachedMapBlocks) - { - if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) - { - List mapBlocks; + // lock (cachedMapBlocks) + // { + // if (cachedMapBlocks.Count > 0 && ((cachedTime + 1800) > Util.UnixTimeSinceEpoch())) + // { + // List mapBlocks; - mapBlocks = cachedMapBlocks; - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); - } - else - { - lookup = true; - } - } - if (lookup) - { - List mapBlocks = new List(); ; + // mapBlocks = cachedMapBlocks; + // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + // } + // else + // { + // lookup = true; + // } + // } + // if (lookup) + // { + // List mapBlocks = new List(); ; - List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, - (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); - foreach (GridRegion r in regions) - { - MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r, 0); - mapBlocks.Add(block); - } - avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); + // List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, + // (int)(m_scene.RegionInfo.RegionLocX - 8) * (int)Constants.RegionSize, + // (int)(m_scene.RegionInfo.RegionLocX + 8) * (int)Constants.RegionSize, + // (int)(m_scene.RegionInfo.RegionLocY - 8) * (int)Constants.RegionSize, + // (int)(m_scene.RegionInfo.RegionLocY + 8) * (int)Constants.RegionSize); + // foreach (GridRegion r in regions) + // { + // MapBlockData block = new MapBlockData(); + // MapBlockFromGridRegion(block, r, 0); + // mapBlocks.Add(block); + // } + // avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); - lock (cachedMapBlocks) - cachedMapBlocks = mapBlocks; + // lock (cachedMapBlocks) + // cachedMapBlocks = mapBlocks; - cachedTime = Util.UnixTimeSinceEpoch(); - } - } - } + // cachedTime = Util.UnixTimeSinceEpoch(); + // } + // } + //} LLSDMapLayerResponse mapResponse = new LLSDMapLayerResponse(); mapResponse.LayerData.Array.Add(GetOSDMapLayerResponse()); @@ -302,8 +305,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap protected static OSDMapLayer GetOSDMapLayerResponse() { OSDMapLayer mapLayer = new OSDMapLayer(); - mapLayer.Right = 5000; - mapLayer.Top = 5000; + mapLayer.Right = 2048; + mapLayer.Top = 2048; mapLayer.ImageID = new UUID("00000000-0000-1111-9999-000000000006"); return mapLayer; @@ -332,6 +335,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { m_rootAgents.Remove(AgentId); } + lock (m_mapBlockRequestEvent) + { + if (m_mapBlockRequests.ContainsKey(AgentId)) + m_mapBlockRequests.Remove(AgentId); + } } #endregion @@ -354,6 +362,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap ThreadPriority.BelowNormal, true, true); + Watchdog.StartThread( + MapBlockSendThread, + string.Format("MapBlockSendThread ({0})", m_scene.RegionInfo.RegionName), + ThreadPriority.BelowNormal, + true, + true); } /// @@ -369,7 +383,27 @@ namespace OpenSim.Region.CoreModules.World.WorldMap st.itemtype=0; st.regionhandle=0; - requests.Enqueue(st); + lock (requests) + { + queueEvent.Set(); + requests.Enqueue(st); + } + + MapBlockRequestData req = new MapBlockRequestData(); + + req.client = null; + req.minX = 0; + req.maxX = 0; + req.minY = 0; + req.maxY = 0; + req.flags = 0; + + lock (m_mapBlockRequestEvent) + { + m_mapBlockRequests[UUID.Zero] = new Queue(); + m_mapBlockRequests[UUID.Zero].Enqueue(req); + m_mapBlockRequestEvent.Set(); + } } public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, @@ -525,7 +559,21 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { while (true) { - MapRequestState st = requests.Dequeue(1000); + MapRequestState st = new MapRequestState(); + bool valid = false; + queueEvent.WaitOne(); + lock (requests) + { + if (requests.Count > 0) + { + st = requests.Dequeue(); + valid = true; + } + if (requests.Count == 0) + queueEvent.Reset(); + } + if (!valid) + continue; // end gracefully if (st.agentID == STOP_UUID) @@ -543,13 +591,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (dorequest && !m_blacklistedregions.ContainsKey(st.regionhandle)) { while (nAsyncRequests >= MAX_ASYNC_REQUESTS) // hit the break - Thread.Sleep(80); + Thread.Sleep(100); - RequestMapItemsDelegate d = RequestMapItemsAsync; - d.BeginInvoke(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle, RequestMapItemsCompleted, null); - //OSDMap response = RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); - //RequestMapItemsCompleted(response); Interlocked.Increment(ref nAsyncRequests); + Util.FireAndForget(x => + { + RequestMapItemsAsync(st.agentID, st.flags, st.EstateID, st.godlike, st.itemtype, st.regionhandle); + }); } } @@ -571,110 +619,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// public void EnqueueMapItemRequest(MapRequestState state) { - requests.Enqueue(state); - } - - /// - /// Sends the mapitem response to the IClientAPI - /// - /// The OSDMap Response for the mapitem - private void RequestMapItemsCompleted(IAsyncResult iar) - { - AsyncResult result = (AsyncResult)iar; - RequestMapItemsDelegate icon = (RequestMapItemsDelegate)result.AsyncDelegate; - - OSDMap response = (OSDMap)icon.EndInvoke(iar); - - Interlocked.Decrement(ref nAsyncRequests); - - if (!response.ContainsKey("requestID")) - return; - - UUID requestID = response["requestID"].AsUUID(); - - if (requestID != UUID.Zero) + lock (requests) { - MapRequestState mrs = new MapRequestState(); - mrs.agentID = UUID.Zero; - lock (m_openRequests) - { - if (m_openRequests.ContainsKey(requestID)) - { - mrs = m_openRequests[requestID]; - m_openRequests.Remove(requestID); - } - } - - if (mrs.agentID != UUID.Zero) - { - ScenePresence av = null; - m_scene.TryGetScenePresence(mrs.agentID, out av); - if (av != null) - { - if (response.ContainsKey(mrs.itemtype.ToString())) - { - List returnitems = new List(); - OSDArray itemarray = (OSDArray)response[mrs.itemtype.ToString()]; - for (int i = 0; i < itemarray.Count; i++) - { - OSDMap mapitem = (OSDMap)itemarray[i]; - mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); - returnitems.Add(mi); - } - av.ControllingClient.SendMapItemReply(returnitems.ToArray(), mrs.itemtype, mrs.flags); - } - - // Service 7 (MAP_ITEM_LAND_FOR_SALE) - uint itemtype = 7; - - if (response.ContainsKey(itemtype.ToString())) - { - List returnitems = new List(); - OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; - for (int i = 0; i < itemarray.Count; i++) - { - OSDMap mapitem = (OSDMap)itemarray[i]; - mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); - returnitems.Add(mi); - } - av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); - } - - // Service 1 (MAP_ITEM_TELEHUB) - itemtype = 1; - - if (response.ContainsKey(itemtype.ToString())) - { - List returnitems = new List(); - OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; - for (int i = 0; i < itemarray.Count; i++) - { - OSDMap mapitem = (OSDMap)itemarray[i]; - mapItemReply mi = new mapItemReply(); - mi.x = (uint)mapitem["X"].AsInteger(); - mi.y = (uint)mapitem["Y"].AsInteger(); - mi.id = mapitem["ID"].AsUUID(); - mi.Extra = mapitem["Extra"].AsInteger(); - mi.Extra2 = mapitem["Extra2"].AsInteger(); - mi.name = mapitem["Name"].AsString(); - returnitems.Add(mi); - } - av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); - } - } - } + queueEvent.Set(); + requests.Enqueue(state); } } @@ -701,8 +649,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap EnqueueMapItemRequest(st); } - private delegate OSDMap RequestMapItemsDelegate(UUID id, uint flags, - uint EstateID, bool godlike, uint itemtype, ulong regionhandle); /// /// Does the actual remote mapitem request /// This should be called from an asynchronous thread @@ -717,7 +663,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// passed in from packet /// Region we're looking up /// - private OSDMap RequestMapItemsAsync(UUID id, uint flags, + private void RequestMapItemsAsync(UUID id, uint flags, uint EstateID, bool godlike, uint itemtype, ulong regionhandle) { // m_log.DebugFormat("[WORLDMAP]: RequestMapItemsAsync; region handle: {0} {1}", regionhandle, itemtype); @@ -740,7 +686,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } if (blacklisted) - return new OSDMap(); + { + Interlocked.Decrement(ref nAsyncRequests); + return; + } UUID requestID = UUID.Random(); lock (m_cachedRegionMapItemsAddress) @@ -748,6 +697,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (m_cachedRegionMapItemsAddress.ContainsKey(regionhandle)) httpserver = m_cachedRegionMapItemsAddress[regionhandle]; } + if (httpserver.Length == 0) { uint x = 0, y = 0; @@ -792,18 +742,10 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // Can't find the http server if (httpserver.Length == 0 || blacklisted) - return new OSDMap(); - - MapRequestState mrs = new MapRequestState(); - mrs.agentID = id; - mrs.EstateID = EstateID; - mrs.flags = flags; - mrs.godlike = godlike; - mrs.itemtype=itemtype; - mrs.regionhandle = regionhandle; - - lock (m_openRequests) - m_openRequests.Add(requestID, mrs); + { + Interlocked.Decrement(ref nAsyncRequests); + return; + } WebRequest mapitemsrequest = null; try @@ -813,7 +755,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap catch (Exception e) { m_log.DebugFormat("[WORLD MAP]: Access to {0} failed with {1}", httpserver, e); - return new OSDMap(); + Interlocked.Decrement(ref nAsyncRequests); + return; } mapitemsrequest.Method = "POST"; @@ -838,7 +781,6 @@ namespace OpenSim.Region.CoreModules.World.WorldMap catch (WebException ex) { m_log.WarnFormat("[WORLD MAP]: Bad send on GetMapItems {0}", ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedurls) { if (!m_blacklistedurls.ContainsKey(httpserver)) @@ -847,13 +789,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } catch { m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); - responseMap["connect"] = OSD.FromBoolean(false); - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } finally { @@ -874,12 +817,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } else { - return new OSDMap(); + Interlocked.Decrement(ref nAsyncRequests); + return; } } catch (WebException) { - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedurls) { if (!m_blacklistedurls.ContainsKey(httpserver)) @@ -888,19 +831,20 @@ namespace OpenSim.Region.CoreModules.World.WorldMap m_log.WarnFormat("[WORLD MAP]: Blacklisted {0}", httpserver); - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } catch { m_log.DebugFormat("[WORLD MAP]: RequestMapItems failed for {0}", httpserver); - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedregions) { if (!m_blacklistedregions.ContainsKey(regionhandle)) m_blacklistedregions.Add(regionhandle, Environment.TickCount); } - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } finally { @@ -919,14 +863,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap catch (Exception ex) { m_log.InfoFormat("[WORLD MAP]: exception on parse of RequestMapItems reply from {0}: {1}", httpserver, ex.Message); - responseMap["connect"] = OSD.FromBoolean(false); lock (m_blacklistedregions) { if (!m_blacklistedregions.ContainsKey(regionhandle)) m_blacklistedregions.Add(regionhandle, Environment.TickCount); } - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + return; } } @@ -940,7 +884,78 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } - return responseMap; + Interlocked.Decrement(ref nAsyncRequests); + + if (id != UUID.Zero) + { + ScenePresence av = null; + m_scene.TryGetScenePresence(id, out av); + if (av != null) + { + if (responseMap.ContainsKey(itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags); + } + + // Service 7 (MAP_ITEM_LAND_FOR_SALE) + itemtype = 7; + + if (responseMap.ContainsKey(itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags); + } + + // Service 1 (MAP_ITEM_TELEHUB) + itemtype = 1; + + if (responseMap.ContainsKey(itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)responseMap[itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, flags); + } + } + } } /// @@ -950,7 +965,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap /// /// /// - public virtual void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + public void RequestMapBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { //m_log.ErrorFormat("[YYY] RequestMapBlocks {0}={1}={2}={3} {4}", minX, minY, maxX, maxY, flag); if ((flag & 0x10000) != 0) // user clicked on qthe map a tile that isn't visible @@ -1003,21 +1018,91 @@ namespace OpenSim.Region.CoreModules.World.WorldMap protected virtual List GetAndSendBlocks(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) { + MapBlockRequestData req = new MapBlockRequestData(); + + req.client = remoteClient; + req.minX = minX; + req.maxX = maxX; + req.minY = minY; + req.maxY = maxY; + req.flags = flag; + + lock (m_mapBlockRequestEvent) + { + if (!m_mapBlockRequests.ContainsKey(remoteClient.AgentId)) + m_mapBlockRequests[remoteClient.AgentId] = new Queue(); + m_mapBlockRequests[remoteClient.AgentId].Enqueue(req); + m_mapBlockRequestEvent.Set(); + } + + return new List(); + } + + protected void MapBlockSendThread() + { + while (true) + { + List thisRunData = new List(); + + m_mapBlockRequestEvent.WaitOne(); + lock (m_mapBlockRequestEvent) + { + int total = 0; + foreach (Queue q in m_mapBlockRequests.Values) + { + if (q.Count > 0) + thisRunData.Add(q.Dequeue()); + + total += q.Count; + } + + if (total == 0) + m_mapBlockRequestEvent.Reset(); + } + + foreach (MapBlockRequestData req in thisRunData) + { + // Null client stops thread + if (req.client == null) + return; + + GetAndSendBlocksInternal(req.client, req.minX, req.minY, req.maxX, req.maxY, req.flags); + } + + Thread.Sleep(50); + } + } + + protected virtual List GetAndSendBlocksInternal(IClientAPI remoteClient, int minX, int minY, int maxX, int maxY, uint flag) + { + List allBlocks = new List(); List mapBlocks = new List(); List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, - (minX - 4) * (int)Constants.RegionSize, - (maxX + 4) * (int)Constants.RegionSize, - (minY - 4) * (int)Constants.RegionSize, - (maxY + 4) * (int)Constants.RegionSize); + minX * (int)Constants.RegionSize, + maxX * (int)Constants.RegionSize, + minY * (int)Constants.RegionSize, + maxY * (int)Constants.RegionSize); +// (minX - 4) * (int)Constants.RegionSize, +// (maxX + 4) * (int)Constants.RegionSize, +// (minY - 4) * (int)Constants.RegionSize, +// (maxY + 4) * (int)Constants.RegionSize); foreach (GridRegion r in regions) { MapBlockData block = new MapBlockData(); MapBlockFromGridRegion(block, r, flag); mapBlocks.Add(block); + allBlocks.Add(block); + if (mapBlocks.Count >= 10) + { + remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); + mapBlocks.Clear(); + Thread.Sleep(50); + } } - remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); + if (mapBlocks.Count > 0) + remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); - return mapBlocks; + return allBlocks; } protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) @@ -1417,6 +1502,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { m_rootAgents.Remove(avatar.UUID); } + + lock (m_mapBlockRequestEvent) + { + if (m_mapBlockRequests.ContainsKey(avatar.UUID)) + m_mapBlockRequests.Remove(avatar.UUID); + } } public void OnRegionUp(GridRegion otherRegion) @@ -1540,4 +1631,14 @@ namespace OpenSim.Region.CoreModules.World.WorldMap public uint itemtype; public ulong regionhandle; } + + public struct MapBlockRequestData + { + public IClientAPI client; + public int minX; + public int minY; + public int maxX; + public int maxY; + public uint flags; + } } diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs index d3c2d27d79..41e894419e 100644 --- a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs +++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs @@ -30,6 +30,8 @@ using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; +using System.Text; +using System.IO; using System.Xml; using OpenSim.Framework.Serialization; using OpenSim.Framework.Serialization.External; @@ -561,8 +563,56 @@ namespace OpenSim.Region.Framework.Scenes } + public string ToXml2() + { + MemoryStream ms = new MemoryStream(512); + UTF8Encoding enc = new UTF8Encoding(); + XmlTextWriter xwriter = new XmlTextWriter(ms, enc); + ToXml2(xwriter); + xwriter.Flush(); + string s = ms.GetStreamString(); + xwriter.Close(); + return s; + } - public void FromXml2(XmlTextReader _reader, out bool errors) + public static SOPVehicle FromXml2(string text) + { + if (text == String.Empty) + return null; + + UTF8Encoding enc = new UTF8Encoding(); + MemoryStream ms = new MemoryStream(enc.GetBytes(text)); + XmlTextReader xreader = new XmlTextReader(ms); + + SOPVehicle v = new SOPVehicle(); + bool error; + + v.FromXml2(xreader, out error); + + xreader.Close(); + + if (error) + { + v = null; + return null; + } + return v; + } + + public static SOPVehicle FromXml2(XmlTextReader reader) + { + SOPVehicle vehicle = new SOPVehicle(); + + bool errors = false; + + vehicle.FromXml2(reader, out errors); + if (errors) + return null; + + return vehicle; + } + + private void FromXml2(XmlTextReader _reader, out bool errors) { errors = false; reader = _reader; @@ -739,4 +789,4 @@ namespace OpenSim.Region.Framework.Scenes vd.m_referenceFrame = XRquat(); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index b23d2e59b1..c3d66eb466 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -1824,6 +1824,8 @@ namespace OpenSim.Region.Framework.Scenes { parentGroup.LinkToGroup(child); + child.DetachFromBackup(); + // this is here so physics gets updated! // Don't remove! Bad juju! Stay away! or fix physics! child.AbsolutePosition = child.AbsolutePosition; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 1f1cacaba7..241097018c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -353,7 +353,7 @@ namespace OpenSim.Region.Framework.Scenes private int LastColSoundSentTime; - private SOPVehicle m_vehicle = null; + private SOPVehicle m_vehicleParams = null; private KeyframeMotion m_keyframeMotion = null; @@ -973,7 +973,15 @@ namespace OpenSim.Region.Framework.Scenes } return m_angularVelocity; } - set { m_angularVelocity = value; } + set + { + m_angularVelocity = value; + PhysicsActor actor = PhysActor; + if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE) + { + actor.RotationalVelocity = m_angularVelocity; + } + } } /// @@ -1877,7 +1885,7 @@ namespace OpenSim.Region.Framework.Scenes } } -// SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future + // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future public void SetVelocity(Vector3 pVel, bool localGlobalTF) { if (ParentGroup == null || ParentGroup.IsDeleted) @@ -1903,6 +1911,33 @@ namespace OpenSim.Region.Framework.Scenes ParentGroup.Velocity = pVel; } + + // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future + public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF) + { + if (ParentGroup == null || ParentGroup.IsDeleted) + return; + + if (ParentGroup.IsAttachment) + return; // don't work on attachments (for now ??) + + SceneObjectPart root = ParentGroup.RootPart; + + if (root.VehicleType != (int)Vehicle.TYPE_NONE) // don't mess with vehicles + return; + + PhysicsActor pa = root.PhysActor; + + if (pa == null || !pa.IsPhysical) + return; + + if (localGlobalTF) + { + pAngVel = pAngVel * GetWorldRotation(); + } + + root.AngularVelocity = pAngVel; + } /// @@ -3415,15 +3450,15 @@ namespace OpenSim.Region.Framework.Scenes Force = force; } - public SOPVehicle sopVehicle + public SOPVehicle VehicleParams { get { - return m_vehicle; + return m_vehicleParams; } set { - m_vehicle = value; + m_vehicleParams = value; } } @@ -3432,10 +3467,10 @@ namespace OpenSim.Region.Framework.Scenes { get { - if (m_vehicle == null) + if (m_vehicleParams == null) return (int)Vehicle.TYPE_NONE; else - return (int)m_vehicle.Type; + return (int)m_vehicleParams.Type; } set { @@ -3445,7 +3480,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetVehicleType(int type) { - m_vehicle = null; + m_vehicleParams = null; if (type == (int)Vehicle.TYPE_NONE) { @@ -3453,8 +3488,8 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.VehicleType = (int)Vehicle.TYPE_NONE; return; } - m_vehicle = new SOPVehicle(); - m_vehicle.ProcessTypeChange((Vehicle)type); + m_vehicleParams = new SOPVehicle(); + m_vehicleParams.ProcessTypeChange((Vehicle)type); { if (_parentID ==0 && PhysActor != null) PhysActor.VehicleType = type; @@ -3464,10 +3499,10 @@ namespace OpenSim.Region.Framework.Scenes public void SetVehicleFlags(int param, bool remove) { - if (m_vehicle == null) + if (m_vehicleParams == null) return; - m_vehicle.ProcessVehicleFlags(param, remove); + m_vehicleParams.ProcessVehicleFlags(param, remove); if (_parentID ==0 && PhysActor != null) { @@ -3477,10 +3512,10 @@ namespace OpenSim.Region.Framework.Scenes public void SetVehicleFloatParam(int param, float value) { - if (m_vehicle == null) + if (m_vehicleParams == null) return; - m_vehicle.ProcessFloatVehicleParam((Vehicle)param, value); + m_vehicleParams.ProcessFloatVehicleParam((Vehicle)param, value); if (_parentID == 0 && PhysActor != null) { @@ -3490,10 +3525,10 @@ namespace OpenSim.Region.Framework.Scenes public void SetVehicleVectorParam(int param, Vector3 value) { - if (m_vehicle == null) + if (m_vehicleParams == null) return; - m_vehicle.ProcessVectorVehicleParam((Vehicle)param, value); + m_vehicleParams.ProcessVectorVehicleParam((Vehicle)param, value); if (_parentID == 0 && PhysActor != null) { @@ -3503,10 +3538,10 @@ namespace OpenSim.Region.Framework.Scenes public void SetVehicleRotationParam(int param, Quaternion rotation) { - if (m_vehicle == null) + if (m_vehicleParams == null) return; - m_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); + m_vehicleParams.ProcessRotationVehicleParam((Vehicle)param, rotation); if (_parentID == 0 && PhysActor != null) { @@ -4673,8 +4708,8 @@ namespace OpenSim.Region.Framework.Scenes if (VolumeDetectActive) // change if not the default only pa.SetVolumeDetect(1); - if (m_vehicle != null && LocalId == ParentGroup.RootPart.LocalId) - m_vehicle.SetVehicle(pa); + if (m_vehicleParams != null && LocalId == ParentGroup.RootPart.LocalId) + m_vehicleParams.SetVehicle(pa); // we are going to tell rest of code about physics so better have this here PhysActor = pa; @@ -4712,7 +4747,7 @@ namespace OpenSim.Region.Framework.Scenes pa.RotationalVelocity = rotationalVelocity; // if not vehicle and root part apply force and torque - if ((m_vehicle == null || m_vehicle.Type == Vehicle.TYPE_NONE) + if ((m_vehicleParams == null || m_vehicleParams.Type == Vehicle.TYPE_NONE) && LocalId == ParentGroup.RootPart.LocalId) { pa.Force = Force; diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index e223f4716f..2372d6ba93 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -623,20 +623,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessVehicle(SceneObjectPart obj, XmlTextReader reader) { - bool errors = false; - SOPVehicle _vehicle = new SOPVehicle(); + SOPVehicle vehicle = SOPVehicle.FromXml2(reader); - _vehicle.FromXml2(reader, out errors); - - if (errors) + if (vehicle == null) { - obj.sopVehicle = null; + obj.VehicleParams = null; m_log.DebugFormat( "[SceneObjectSerializer]: Parsing Vehicle for object part {0} {1} encountered errors. Please see earlier log entries.", obj.Name, obj.UUID); } else - obj.sopVehicle = _vehicle; + { + obj.VehicleParams = vehicle; + } } private static void ProcessShape(SceneObjectPart obj, XmlTextReader reader) @@ -1325,8 +1324,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("VolumeDetectActive", sop.VolumeDetectActive.ToString().ToLower()); - if (sop.sopVehicle != null) - sop.sopVehicle.ToXml2(writer); + if (sop.VehicleParams != null) + sop.VehicleParams.ToXml2(writer); if(sop.PhysicsShapeType != sop.DefaultPhysicsShapeType()) writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs index 6e4e41feb0..865180f534 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs @@ -740,6 +740,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (Shell != IntPtr.Zero) { _parent_scene.geom_name_map.Remove(Shell); + _parent_scene.actor_name_map.Remove(Shell); _parent_scene.waitForSpaceUnlock(_parent_scene.ActiveSpace); d.GeomDestroy(Shell); Shell = IntPtr.Zero; @@ -1188,6 +1189,7 @@ namespace OpenSim.Region.Physics.OdePlugin } else { + _parent_scene.RemoveCollisionEventReporting(this); _parent_scene.RemoveCharacter(this); // destroy avatar capsule and related ODE data AvatarGeomAndBodyDestroy(); diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs index e27be1eab7..e900c02a6c 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEDynamics.cs @@ -137,6 +137,7 @@ namespace OpenSim.Region.Physics.OdePlugin float m_amdampY; float m_amdampZ; + public float FrictionFactor { get @@ -145,6 +146,7 @@ namespace OpenSim.Region.Physics.OdePlugin } } + public ODEDynamics(OdePrim rootp) { rootPrim = rootp; @@ -345,7 +347,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale; m_lmEfect = 1.0f; // turn it on - m_ffactor = 0.01f; + m_ffactor = 0.0f; if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body) && !rootPrim.m_isSelected && !rootPrim.m_disabled) d.BodyEnable(rootPrim.Body); @@ -401,7 +403,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_lmEfect = 1.0f; // turn it on m_lmDecay = 1.0f - 1.0f / m_linearMotorDecayTimescale; - m_ffactor = 0.01f; + m_ffactor = 0.0f; if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body) && !rootPrim.m_isSelected && !rootPrim.m_disabled) d.BodyEnable(rootPrim.Body); @@ -805,7 +807,8 @@ namespace OpenSim.Region.Physics.OdePlugin } m_lmEfect *= m_lmDecay; - m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared(); +// m_ffactor = 0.01f + 1e-4f * curVel.LengthSquared(); + m_ffactor = 0.0f; } else { diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs index 9b3b51b8ba..ff17a6e46b 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs @@ -275,6 +275,7 @@ namespace OpenSim.Region.Physics.OdePlugin if (veh != null && veh.Type != Vehicle.TYPE_NONE) cdata.mu *= veh.FrictionFactor; +// cdata.mu *= 0; } } @@ -582,8 +583,6 @@ namespace OpenSim.Region.Physics.OdePlugin if (value.IsFinite()) { AddChange(changes.Velocity, value); -// _velocity = value; - } else { @@ -675,9 +674,7 @@ namespace OpenSim.Region.Physics.OdePlugin { if (value.IsFinite()) { - m_rotationalVelocity = value; - if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) - d.BodyEnable(Body); + AddChange(changes.AngVelocity, value); } else { @@ -686,7 +683,6 @@ namespace OpenSim.Region.Physics.OdePlugin } } - public override float Buoyancy { get { return m_buoyancy; } @@ -947,6 +943,8 @@ namespace OpenSim.Region.Physics.OdePlugin CollisionEventsThisFrame = null; } m_eventsubscription = 0; + // for now still done on odescene +// _parent_scene.RemoveCollisionEventReporting(this); } public void AddCollisionEvent(uint CollidedWith, ContactPoint contact) @@ -1736,17 +1734,14 @@ namespace OpenSim.Region.Physics.OdePlugin d.BodySetAutoDisableFlag(Body, true); d.BodySetAutoDisableSteps(Body, body_autodisable_frames); -// d.BodySetLinearDampingThreshold(Body, 0.01f); -// d.BodySetAngularDampingThreshold(Body, 0.001f); - d.BodySetDamping(Body, .002f, .002f); - - if (m_targetSpace != IntPtr.Zero) - { - _parent_scene.waitForSpaceUnlock(m_targetSpace); - if (d.SpaceQuery(m_targetSpace, prim_geom)) - d.SpaceRemove(m_targetSpace, prim_geom); - } + d.BodySetDamping(Body, .005f, .005f); + if (m_targetSpace != IntPtr.Zero) + { + _parent_scene.waitForSpaceUnlock(m_targetSpace); + if (d.SpaceQuery(m_targetSpace, prim_geom)) + d.SpaceRemove(m_targetSpace, prim_geom); + } if (childrenPrim.Count == 0) { @@ -3295,6 +3290,13 @@ namespace OpenSim.Region.Physics.OdePlugin private void changevelocity(Vector3 newVel) { + float len = newVel.LengthSquared(); + if (len > 100000.0f) // limit to 100m/s + { + len = 100.0f / (float)Math.Sqrt(len); + newVel *= len; + } + if (!m_isSelected) { if (Body != IntPtr.Zero) @@ -3311,6 +3313,33 @@ namespace OpenSim.Region.Physics.OdePlugin _velocity = newVel; } + + private void changeangvelocity(Vector3 newAngVel) + { + float len = newAngVel.LengthSquared(); + if (len > 144.0f) // limit to 12rad/s + { + len = 12.0f / (float)Math.Sqrt(len); + newAngVel *= len; + } + + if (!m_isSelected) + { + if (Body != IntPtr.Zero) + { + if (m_disabled) + enableBodySoft(); + else if (!d.BodyIsEnabled(Body)) + d.BodyEnable(Body); + + + d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z); + } + //resetCollisionAccounting(); + } + m_rotationalVelocity = newAngVel; + } + private void changeVolumedetetion(bool newVolDtc) { m_isVolumeDetect = newVolDtc; @@ -3947,9 +3976,10 @@ namespace OpenSim.Region.Physics.OdePlugin // case changes.Acceleration: // changeacceleration((Vector3)arg); // break; -// case changes.AngVelocity: -// changeangvelocity((Vector3)arg); -// break; + + case changes.AngVelocity: + changeangvelocity((Vector3)arg); + break; case changes.Force: changeForce((Vector3)arg); diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs index 0e4961b85a..23411868c7 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeApi.cs @@ -1312,7 +1312,14 @@ namespace OdeAPI public static extern void GeomTriMeshSetRayCallback(IntPtr g, TriRayCallback callback); [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dGetConfiguration"), SuppressUnmanagedCodeSecurity] - public static extern string GetConfiguration(string str); + public static extern IntPtr iGetConfiguration(); + + public static string GetConfiguration() + { + IntPtr ptr = iGetConfiguration(); + string s = Marshal.PtrToStringAnsi(ptr); + return s; + } [DllImport("ode", CallingConvention = CallingConvention.Cdecl, EntryPoint = "dHashSpaceCreate"), SuppressUnmanagedCodeSecurity] public static extern IntPtr HashSpaceCreate(IntPtr space); diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs index 6c72324ba4..7848b35edf 100644 --- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs @@ -237,20 +237,20 @@ namespace OpenSim.Region.Physics.OdePlugin private d.NearCallback nearCallback; - private readonly HashSet _characters = new HashSet(); - private readonly HashSet _prims = new HashSet(); - private readonly HashSet _activeprims = new HashSet(); - private readonly HashSet _activegroups = new HashSet(); + private HashSet _characters = new HashSet(); + private HashSet _prims = new HashSet(); + private HashSet _activeprims = new HashSet(); + private HashSet _activegroups = new HashSet(); public OpenSim.Framework.LocklessQueue ChangesQueue = new OpenSim.Framework.LocklessQueue(); /// /// A list of actors that should receive collision events. /// - private readonly List _collisionEventPrim = new List(); - private readonly List _collisionEventPrimRemove = new List(); + private List _collisionEventPrim = new List(); + private List _collisionEventPrimRemove = new List(); - private readonly HashSet _badCharacter = new HashSet(); + private HashSet _badCharacter = new HashSet(); public Dictionary geom_name_map = new Dictionary(); public Dictionary actor_name_map = new Dictionary(); @@ -264,26 +264,21 @@ namespace OpenSim.Region.Physics.OdePlugin private volatile int m_global_contactcount = 0; - private readonly IntPtr contactgroup; + private IntPtr contactgroup; public ContactData[] m_materialContactsData = new ContactData[8]; - private readonly DoubleDictionary RegionTerrain = new DoubleDictionary(); - private readonly Dictionary TerrainHeightFieldHeights = new Dictionary(); - private readonly Dictionary TerrainHeightFieldHeightsHandlers = new Dictionary(); + private Dictionary RegionTerrain = new Dictionary(); + private Dictionary TerrainHeightFieldHeights = new Dictionary(); + private Dictionary TerrainHeightFieldHeightsHandlers = new Dictionary(); private int m_physicsiterations = 10; private const float m_SkipFramesAtms = 0.40f; // Drop frames gracefully at a 400 ms lag - private readonly PhysicsActor PANull = new NullPhysicsActor(); + private PhysicsActor PANull = new NullPhysicsActor(); private float step_time = 0.0f; public IntPtr world; - private uint obj2LocalID = 0; - private OdeCharacter cc1; - private OdePrim cp1; - private OdeCharacter cc2; - private OdePrim cp2; // split the spaces acording to contents type // ActiveSpace contains characters and active prims @@ -408,8 +403,8 @@ namespace OpenSim.Region.Physics.OdePlugin // checkThread(); mesher = meshmerizer; m_config = config; -/* - string ode_config = d.GetConfiguration("ODE"); + + string ode_config = d.GetConfiguration(); if (ode_config != null && ode_config != "") { m_log.WarnFormat("ODE configuration: {0}", ode_config); @@ -419,7 +414,7 @@ namespace OpenSim.Region.Physics.OdePlugin OdeUbitLib = true; } } -*/ + /* if (region != null) { @@ -526,8 +521,8 @@ namespace OpenSim.Region.Physics.OdePlugin d.WorldSetGravity(world, gravityx, gravityy, gravityz); d.WorldSetContactSurfaceLayer(world, contactsurfacelayer); - d.WorldSetLinearDamping(world, 0.001f); - d.WorldSetAngularDamping(world, 0.001f); + d.WorldSetLinearDamping(world, 0.002f); + d.WorldSetAngularDamping(world, 0.002f); d.WorldSetAngularDampingThreshold(world, 0f); d.WorldSetLinearDampingThreshold(world, 0f); d.WorldSetMaxAngularSpeed(world, 100f); @@ -921,6 +916,8 @@ namespace OpenSim.Region.Physics.OdePlugin cfm = 0.0001f / cfm; if (cfm > 0.01f) cfm = 0.01f; + else if (cfm < 0.00001f) + cfm = 0.00001f; if ((Math.Abs(p2.Velocity.X - p1.Velocity.X) > 0.1f || Math.Abs(p2.Velocity.Y - p1.Velocity.Y) > 0.1f)) mu *= frictionMovementMult; @@ -947,6 +944,8 @@ namespace OpenSim.Region.Physics.OdePlugin cfm = 0.0001f / cfm; if (cfm > 0.01f) cfm = 0.01f; + else if (cfm < 0.00001f) + cfm = 0.00001f; if (d.GeomGetClass(g1) == d.GeomClassID.TriMeshClass) { @@ -989,6 +988,8 @@ namespace OpenSim.Region.Physics.OdePlugin cfm = 0.0001f / cfm; if (cfm > 0.01f) cfm = 0.01f; + else if (cfm < 0.00001f) + cfm = 0.00001f; if (curContact.side1 > 0) // should be 2 ? IgnoreNegSides = true; @@ -1155,7 +1156,13 @@ namespace OpenSim.Region.Physics.OdePlugin private void collision_accounting_events(PhysicsActor p1, PhysicsActor p2, ContactPoint contact) { - obj2LocalID = 0; + + OdeCharacter cc1; + OdePrim cp1; + OdeCharacter cc2; + OdePrim cp2; + + uint obj2LocalID = 0; bool p1events = p1.SubscribedEvents(); bool p2events = p2.SubscribedEvents(); @@ -1892,18 +1899,22 @@ namespace OpenSim.Region.Physics.OdePlugin lock (SimulationLock) lock(OdeLock) { + if (world == IntPtr.Zero) + return 0; + // adjust number of iterations per step - try - { + +// try +// { d.WorldSetQuickStepNumIterations(world, curphysiteractions); - } +/* } catch (StackOverflowException) { m_log.Error("[PHYSICS]: The operating system wasn't able to allocate enough memory for the simulation. Restarting the sim."); // ode.drelease(world); base.TriggerPhysicsBasedRestart(); } - +*/ while (step_time > HalfOdeStep && nodeframes < 10) //limit number of steps so we don't say here for ever { try @@ -1955,6 +1966,7 @@ namespace OpenSim.Region.Physics.OdePlugin { RemoveCharacter(defect); } + defects.Clear(); } } @@ -2060,13 +2072,13 @@ namespace OpenSim.Region.Physics.OdePlugin _badCharacter.Clear(); } } - +/* int nactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); int nstaticgeoms = d.SpaceGetNumGeoms(StaticSpace); int ntopgeoms = d.SpaceGetNumGeoms(TopSpace); int nbodies = d.NTotalBodies; int ngeoms = d.NTotalGeoms; - +*/ // Finished with all sim stepping. If requested, dump world state to file for debugging. // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? // TODO: This overwrites all dump files in-place. Should this be a growing logfile, or separate snapshots? @@ -2383,11 +2395,9 @@ namespace OpenSim.Region.Physics.OdePlugin d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); d.GeomSetRotation(GroundGeom, ref R); d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f, 0); - RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); -// TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap); + RegionTerrain.Add(pOffset, GroundGeom); TerrainHeightFieldHeights.Add(GroundGeom, _heightmap); - TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler); - + TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler); } } @@ -2486,8 +2496,7 @@ namespace OpenSim.Region.Physics.OdePlugin geom_name_map[GroundGeom] = "Terrain"; d.GeomSetPosition(GroundGeom, pOffset.X + (float)Constants.RegionSize * 0.5f, pOffset.Y + (float)Constants.RegionSize * 0.5f, 0); - RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); - // TerrainHeightFieldHeights.Add(GroundGeom, ODElandMap); + RegionTerrain.Add(pOffset, GroundGeom); TerrainHeightFieldHeights.Add(GroundGeom, _heightmap); TerrainHeightFieldHeightsHandlers.Add(GroundGeom, _heightmaphandler); } @@ -2649,19 +2658,42 @@ namespace OpenSim.Region.Physics.OdePlugin public override void Dispose() { - m_rayCastManager.Dispose(); - m_rayCastManager = null; - lock (OdeLock) { + m_rayCastManager.Dispose(); + m_rayCastManager = null; + lock (_prims) { + ChangesQueue.Clear(); foreach (OdePrim prm in _prims) { - RemovePrim(prm); + prm.DoAChange(changes.Remove, null); + _collisionEventPrim.Remove(prm); } + _prims.Clear(); } + OdeCharacter[] chtorem; + lock (_characters) + { + chtorem = new OdeCharacter[_characters.Count]; + _characters.CopyTo(chtorem); + } + + ChangesQueue.Clear(); + foreach (OdeCharacter ch in chtorem) + ch.DoAChange(changes.Remove, null); + + + foreach (IntPtr GroundGeom in RegionTerrain.Values) + { + if (GroundGeom != IntPtr.Zero) + d.GeomDestroy(GroundGeom); + } + + RegionTerrain.Clear(); + if (TerrainHeightFieldHeightsHandlers.Count > 0) { foreach (GCHandle gch in TerrainHeightFieldHeightsHandlers.Values) @@ -2671,6 +2703,9 @@ namespace OpenSim.Region.Physics.OdePlugin } } + TerrainHeightFieldHeightsHandlers.Clear(); + TerrainHeightFieldHeights.Clear(); + if (WaterGeom != IntPtr.Zero) { d.GeomDestroy(WaterGeom); @@ -2691,6 +2726,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.WorldDestroy(world); + world = IntPtr.Zero; //d.CloseODE(); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index b257cd4f16..e9db5d5880 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -113,8 +113,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api new Dictionary(); protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. - protected Timer m_ShoutSayTimer; +// protected Timer m_ShoutSayTimer; protected int m_SayShoutCount = 0; + DateTime m_lastSayShoutCheck; private Dictionary MovementAnimationsForLSL = new Dictionary { @@ -140,10 +141,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) { +/* m_ShoutSayTimer = new Timer(1000); m_ShoutSayTimer.Elapsed += SayShoutTimerElapsed; m_ShoutSayTimer.AutoReset = true; m_ShoutSayTimer.Start(); +*/ + m_lastSayShoutCheck = DateTime.UtcNow; m_ScriptEngine = ScriptEngine; m_host = host; @@ -858,12 +862,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); } + private void CheckSayShoutTime() + { + DateTime now = DateTime.UtcNow; + if ((now - m_lastSayShoutCheck).Ticks > 10000000) // 1sec + { + m_lastSayShoutCheck = now; + m_SayShoutCount = 0; + } + else + m_SayShoutCount++; + } + public void llSay(int channelID, string text) { m_host.AddScriptLPS(1); if (channelID == 0) - m_SayShoutCount++; +// m_SayShoutCount++; + CheckSayShoutTime(); if (m_SayShoutCount >= 11) ScriptSleep(2000); @@ -891,7 +908,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); if (channelID == 0) - m_SayShoutCount++; +// m_SayShoutCount++; + CheckSayShoutTime(); if (m_SayShoutCount >= 11) ScriptSleep(2000); @@ -2556,12 +2574,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); } - public void llSetAngularVelocity(LSL_Vector avel, int local) { m_host.AddScriptLPS(1); - // Still not done !!!! -// m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0); + m_host.SetAngularVelocity(new Vector3((float)avel.x, (float)avel.y, (float)avel.z), local != 0); } public LSL_Vector llGetOmega() @@ -3671,6 +3687,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) { + spinrate *= gain; part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); } @@ -12044,12 +12061,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return rq.ToString(); } - +/* private void SayShoutTimerElapsed(Object sender, ElapsedEventArgs args) { m_SayShoutCount = 0; } - +*/ private struct Tri { public Vector3 p1; diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 2886344e0a..cc783aa84d 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -636,7 +636,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (!m_Enabled) return; lockScriptsForRead(true); - foreach (IScriptInstance instance in m_Scripts.Values) + + List instancesToDel = new List(m_Scripts.Values); + +// foreach (IScriptInstance instance in m_Scripts.Values) + foreach (IScriptInstance instance in instancesToDel) { // Force a final state save // @@ -659,7 +663,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine // Must be done explicitly because they have infinite // lifetime // - if (!m_SimulatorShuttingDown) +// if (!m_SimulatorShuttingDown) { m_DomainScripts[instance.AppDomain].Remove(instance.ItemID); if (m_DomainScripts[instance.AppDomain].Count == 0) @@ -669,10 +673,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine } } - m_Scripts.Clear(); - m_PrimObjects.Clear(); - m_Assemblies.Clear(); - m_DomainScripts.Clear(); +// m_Scripts.Clear(); +// m_PrimObjects.Clear(); +// m_Assemblies.Clear(); +// m_DomainScripts.Clear(); } lockScriptsForRead(false); lockScriptsForWrite(true); diff --git a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs index fb85d1ce1c..4502b7d9f7 100644 --- a/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapGetServerConnector.cs @@ -29,6 +29,7 @@ using System; using System.IO; using System.Net; using System.Reflection; +using System.Threading; using Nini.Config; using log4net; @@ -70,6 +71,8 @@ namespace OpenSim.Server.Handlers.MapImage class MapServerGetHandler : BaseStreamHandler { + public static ManualResetEvent ev = new ManualResetEvent(true); + // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IMapImageService m_MapService; @@ -82,8 +85,13 @@ namespace OpenSim.Server.Handlers.MapImage public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - byte[] result = new byte[0]; + ev.WaitOne(); + lock (ev) + { + ev.Reset(); + } + byte[] result = new byte[0]; string format = string.Empty; result = m_MapService.GetMapTile(path.Trim('/'), out format); if (result.Length > 0) @@ -100,6 +108,11 @@ namespace OpenSim.Server.Handlers.MapImage httpResponse.ContentType = "text/plain"; } + lock (ev) + { + ev.Set(); + } + return result; } diff --git a/bin/lib32/libode.so b/bin/lib32/libode.so old mode 100644 new mode 100755 index 6bb85fb72a..5b110ae54c Binary files a/bin/lib32/libode.so and b/bin/lib32/libode.so differ diff --git a/bin/lib32/ode.dll b/bin/lib32/ode.dll index f310358693..90106cad75 100755 Binary files a/bin/lib32/ode.dll and b/bin/lib32/ode.dll differ