aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Capabilities/Caps.cs13
-rw-r--r--OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs2
-rw-r--r--OpenSim/Data/MySQL/MySQLSimulationData.cs4
-rw-r--r--OpenSim/Framework/AvatarAppearance.cs5
-rw-r--r--OpenSim/Framework/Util.cs108
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs5
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs27
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs21
-rw-r--r--OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs81
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs20
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs108
-rw-r--r--OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs16
-rw-r--r--OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs16
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs60
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs4
-rw-r--r--OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs271
-rw-r--r--OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs41
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs6
-rw-r--r--OpenSim/Region/Framework/Scenes/KeyframeMotion.cs513
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs66
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs26
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs170
-rw-r--r--OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs6
-rw-r--r--OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs2
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs22
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs1
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs5
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs2
-rw-r--r--OpenSim/Services/Interfaces/IAvatarService.cs21
40 files changed, 1198 insertions, 501 deletions
diff --git a/OpenSim/Capabilities/Caps.cs b/OpenSim/Capabilities/Caps.cs
index bc6f6f9..241fef3 100644
--- a/OpenSim/Capabilities/Caps.cs
+++ b/OpenSim/Capabilities/Caps.cs
@@ -30,6 +30,7 @@ using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.IO; 31using System.IO;
32using System.Reflection; 32using System.Reflection;
33using System.Threading;
33using log4net; 34using log4net;
34using Nini.Config; 35using Nini.Config;
35using OpenMetaverse; 36using OpenMetaverse;
@@ -68,6 +69,7 @@ namespace OpenSim.Framework.Capabilities
68 private IHttpServer m_httpListener; 69 private IHttpServer m_httpListener;
69 private UUID m_agentID; 70 private UUID m_agentID;
70 private string m_regionName; 71 private string m_regionName;
72 private ManualResetEvent m_capsActive = new ManualResetEvent(false);
71 73
72 public UUID AgentID 74 public UUID AgentID
73 { 75 {
@@ -171,5 +173,16 @@ namespace OpenSim.Framework.Capabilities
171 } 173 }
172 } 174 }
173 } 175 }
176
177 public void Activate()
178 {
179 m_capsActive.Set();
180 }
181
182 public bool WaitForActivation()
183 {
184 // Wait for 30s. If that elapses, return false and run without caps
185 return m_capsActive.WaitOne(30000);
186 }
174 } 187 }
175} 188}
diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
index 9a6ca86..11a2698 100644
--- a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
+++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs
@@ -435,4 +435,4 @@ namespace OpenSim.Capabilities.Handlers
435 return llsdItem; 435 return llsdItem;
436 } 436 }
437 } 437 }
438} \ No newline at end of file 438}
diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs
index 01b9299..d5a4f46 100644
--- a/OpenSim/Data/MySQL/MySQLSimulationData.cs
+++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs
@@ -1339,7 +1339,7 @@ namespace OpenSim.Data.MySQL
1339 prim.Density = (float)(double)row["Density"]; 1339 prim.Density = (float)(double)row["Density"];
1340 prim.GravityModifier = (float)(double)row["GravityModifier"]; 1340 prim.GravityModifier = (float)(double)row["GravityModifier"];
1341 prim.Friction = (float)(double)row["Friction"]; 1341 prim.Friction = (float)(double)row["Friction"];
1342 prim.Bounciness = (float)(double)row["Restitution"]; 1342 prim.Restitution = (float)(double)row["Restitution"];
1343 1343
1344 SOPVehicle vehicle = null; 1344 SOPVehicle vehicle = null;
1345 1345
@@ -1725,7 +1725,7 @@ namespace OpenSim.Data.MySQL
1725 cmd.Parameters.AddWithValue("Density", (double)prim.Density); 1725 cmd.Parameters.AddWithValue("Density", (double)prim.Density);
1726 cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier); 1726 cmd.Parameters.AddWithValue("GravityModifier", (double)prim.GravityModifier);
1727 cmd.Parameters.AddWithValue("Friction", (double)prim.Friction); 1727 cmd.Parameters.AddWithValue("Friction", (double)prim.Friction);
1728 cmd.Parameters.AddWithValue("Restitution", (double)prim.Bounciness); 1728 cmd.Parameters.AddWithValue("Restitution", (double)prim.Restitution);
1729 1729
1730 if (prim.VehicleParams != null) 1730 if (prim.VehicleParams != null)
1731 cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2()); 1731 cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2());
diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs
index 041fb94..ba6d87d 100644
--- a/OpenSim/Framework/AvatarAppearance.cs
+++ b/OpenSim/Framework/AvatarAppearance.cs
@@ -497,8 +497,6 @@ namespace OpenSim.Framework
497 /// </remarks> 497 /// </remarks>
498 public List<AvatarAttachment> GetAttachments() 498 public List<AvatarAttachment> GetAttachments()
499 { 499 {
500
501
502 lock (m_attachments) 500 lock (m_attachments)
503 { 501 {
504 List<AvatarAttachment> alist = new List<AvatarAttachment>(); 502 List<AvatarAttachment> alist = new List<AvatarAttachment>();
@@ -508,7 +506,8 @@ namespace OpenSim.Framework
508 alist.Add(new AvatarAttachment(attach)); 506 alist.Add(new AvatarAttachment(attach));
509 } 507 }
510 return alist; 508 return alist;
511 } } 509 }
510 }
512 511
513 internal void AppendAttachment(AvatarAttachment attach) 512 internal void AppendAttachment(AvatarAttachment attach)
514 { 513 {
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index e76a37b..48f3f8b 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -2097,4 +2097,112 @@ namespace OpenSim.Framework
2097 } 2097 }
2098 #endregion 2098 #endregion
2099 } 2099 }
2100
2101 public class DoubleQueue<T> where T:class
2102 {
2103 private Queue<T> m_lowQueue = new Queue<T>();
2104 private Queue<T> m_highQueue = new Queue<T>();
2105
2106 private object m_syncRoot = new object();
2107 private Semaphore m_s = new Semaphore(0, 1);
2108
2109 public DoubleQueue()
2110 {
2111 }
2112
2113 public virtual int Count
2114 {
2115 get { return m_highQueue.Count + m_lowQueue.Count; }
2116 }
2117
2118 public virtual void Enqueue(T data)
2119 {
2120 Enqueue(m_lowQueue, data);
2121 }
2122
2123 public virtual void EnqueueLow(T data)
2124 {
2125 Enqueue(m_lowQueue, data);
2126 }
2127
2128 public virtual void EnqueueHigh(T data)
2129 {
2130 Enqueue(m_highQueue, data);
2131 }
2132
2133 private void Enqueue(Queue<T> q, T data)
2134 {
2135 lock (m_syncRoot)
2136 {
2137 m_lowQueue.Enqueue(data);
2138 m_s.WaitOne(0);
2139 m_s.Release();
2140 }
2141 }
2142
2143 public virtual T Dequeue()
2144 {
2145 return Dequeue(Timeout.Infinite);
2146 }
2147
2148 public virtual T Dequeue(int tmo)
2149 {
2150 return Dequeue(TimeSpan.FromMilliseconds(tmo));
2151 }
2152
2153 public virtual T Dequeue(TimeSpan wait)
2154 {
2155 T res = null;
2156
2157 if (!Dequeue(wait, ref res))
2158 return null;
2159
2160 return res;
2161 }
2162
2163 public bool Dequeue(int timeout, ref T res)
2164 {
2165 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
2166 }
2167
2168 public bool Dequeue(TimeSpan wait, ref T res)
2169 {
2170 if (!m_s.WaitOne(wait))
2171 return false;
2172
2173 lock (m_syncRoot)
2174 {
2175 if (m_highQueue.Count > 0)
2176 res = m_highQueue.Dequeue();
2177 else
2178 res = m_lowQueue.Dequeue();
2179
2180 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
2181 return true;
2182
2183 try
2184 {
2185 m_s.Release();
2186 }
2187 catch
2188 {
2189 }
2190
2191 return true;
2192 }
2193 }
2194
2195 public virtual void Clear()
2196 {
2197
2198 lock (m_syncRoot)
2199 {
2200 // Make sure sem count is 0
2201 m_s.WaitOne(0);
2202
2203 m_lowQueue.Clear();
2204 m_highQueue.Clear();
2205 }
2206 }
2207 }
2100} 2208}
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
index b06788b..248eab6 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs
@@ -343,6 +343,9 @@ namespace OpenSim.Region.ClientStack.Linden
343 m_log.DebugFormat( 343 m_log.DebugFormat(
344 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); 344 "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID);
345 345
346 if (!m_HostCapsObj.WaitForActivation())
347 return string.Empty;
348
346 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) 349 if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint))
347 { 350 {
348 m_log.WarnFormat( 351 m_log.WarnFormat(
@@ -1317,7 +1320,7 @@ namespace OpenSim.Region.ClientStack.Linden
1317 object_data["PhysicsShapeType"] = obj.PhysicsShapeType; 1320 object_data["PhysicsShapeType"] = obj.PhysicsShapeType;
1318 object_data["Density"] = obj.Density; 1321 object_data["Density"] = obj.Density;
1319 object_data["Friction"] = obj.Friction; 1322 object_data["Friction"] = obj.Friction;
1320 object_data["Restitution"] = obj.Bounciness; 1323 object_data["Restitution"] = obj.Restitution;
1321 object_data["GravityMultiplier"] = obj.GravityModifier; 1324 object_data["GravityMultiplier"] = obj.GravityModifier;
1322 1325
1323 resp[uuid.ToString()] = object_data; 1326 resp[uuid.ToString()] = object_data;
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
index 986a665..f6e501d 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs
@@ -467,8 +467,8 @@ namespace OpenSim.Region.ClientStack.Linden
467 responsedata["content_type"] = "text/plain"; 467 responsedata["content_type"] = "text/plain";
468 responsedata["keepalive"] = false; 468 responsedata["keepalive"] = false;
469 responsedata["reusecontext"] = false; 469 responsedata["reusecontext"] = false;
470 responsedata["str_response_string"] = "Upstream error: "; 470 responsedata["str_response_string"] = "<llsd></llsd>";
471 responsedata["error_status_text"] = "Upstream error:"; 471 responsedata["error_status_text"] = "<llsd></llsd>";
472 responsedata["http_protocol_version"] = "HTTP/1.0"; 472 responsedata["http_protocol_version"] = "HTTP/1.0";
473 return responsedata; 473 return responsedata;
474 } 474 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 191bccf..6ef8815 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -59,6 +59,8 @@ namespace OpenSim.Region.ClientStack.Linden
59// private static readonly ILog m_log = 59// private static readonly ILog m_log =
60// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 60// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61 61
62 public event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
63
62 private Scene m_scene; 64 private Scene m_scene;
63 65
64 /// <summary> 66 /// <summary>
@@ -94,6 +96,8 @@ namespace OpenSim.Region.ClientStack.Linden
94 { 96 {
95 m_scene = s; 97 m_scene = s;
96 m_scene.EventManager.OnRegisterCaps += RegisterCaps; 98 m_scene.EventManager.OnRegisterCaps += RegisterCaps;
99
100 m_scene.RegisterModuleInterface<ISimulatorFeaturesModule>(this);
97 } 101 }
98 102
99 public void RemoveRegion(Scene s) 103 public void RemoveRegion(Scene s)
@@ -156,7 +160,7 @@ namespace OpenSim.Region.ClientStack.Linden
156 IRequestHandler reqHandler 160 IRequestHandler reqHandler
157 = new RestHTTPHandler( 161 = new RestHTTPHandler(
158 "GET", "/CAPS/" + UUID.Random(), 162 "GET", "/CAPS/" + UUID.Random(),
159 HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString()); 163 x => { return HandleSimulatorFeaturesRequest(x, agentID); }, "SimulatorFeatures", agentID.ToString());
160 164
161 caps.RegisterHandler("SimulatorFeatures", reqHandler); 165 caps.RegisterHandler("SimulatorFeatures", reqHandler);
162 } 166 }
@@ -185,18 +189,33 @@ namespace OpenSim.Region.ClientStack.Linden
185 return new OSDMap(m_features); 189 return new OSDMap(m_features);
186 } 190 }
187 191
188 private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod) 192 private OSDMap DeepCopy()
193 {
194 // This isn't the cheapest way of doing this but the rate
195 // of occurrence is low (on sim entry only) and it's a sure
196 // way to get a true deep copy.
197 OSD copy = OSDParser.DeserializeLLSDXml(OSDParser.SerializeLLSDXmlString(m_features));
198
199 return (OSDMap)copy;
200 }
201
202 private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod, UUID agentID)
189 { 203 {
190// m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request"); 204// m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");
191 205
206 OSDMap copy = DeepCopy();
207
208 SimulatorFeaturesRequestDelegate handlerOnSimulatorFeaturesRequest = OnSimulatorFeaturesRequest;
209 if (handlerOnSimulatorFeaturesRequest != null)
210 handlerOnSimulatorFeaturesRequest(agentID, ref copy);
211
192 //Send back data 212 //Send back data
193 Hashtable responsedata = new Hashtable(); 213 Hashtable responsedata = new Hashtable();
194 responsedata["int_response_code"] = 200; 214 responsedata["int_response_code"] = 200;
195 responsedata["content_type"] = "text/plain"; 215 responsedata["content_type"] = "text/plain";
196 responsedata["keepalive"] = false; 216 responsedata["keepalive"] = false;
197 217
198 lock (m_features) 218 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(copy);
199 responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(m_features);
200 219
201 return responsedata; 220 return responsedata;
202 } 221 }
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
index 6bed95f..eca576d 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs
@@ -190,8 +190,15 @@ namespace OpenSim.Region.ClientStack.Linden
190 { 190 {
191 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) 191 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
192 { 192 {
193 cacheItems[i].TextureID = 193 Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
194 textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID; 194 if (face == null)
195 {
196 textureEntry.CreateFace(cacheItems[i].TextureIndex);
197 textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
198 AppearanceManager.DEFAULT_AVATAR_TEXTURE;
199 continue;
200 }
201 cacheItems[i].TextureID =face.TextureID;
195 if (m_scene.AssetService != null) 202 if (m_scene.AssetService != null)
196 cacheItems[i].TextureAsset = 203 cacheItems[i].TextureAsset =
197 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); 204 m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString());
@@ -213,8 +220,16 @@ namespace OpenSim.Region.ClientStack.Linden
213 { 220 {
214 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) 221 if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex)
215 { 222 {
223 Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex];
224 if (face == null)
225 {
226 textureEntry.CreateFace(cacheItems[i].TextureIndex);
227 textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID =
228 AppearanceManager.DEFAULT_AVATAR_TEXTURE;
229 continue;
230 }
216 cacheItems[i].TextureID = 231 cacheItems[i].TextureID =
217 textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID; 232 face.TextureID;
218 } 233 }
219 else 234 else
220 { 235 {
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
index 04cd474..707cc93 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs
@@ -39,10 +39,13 @@ using OpenSim.Framework.Servers;
39using OpenSim.Framework.Servers.HttpServer; 39using OpenSim.Framework.Servers.HttpServer;
40using OpenSim.Region.Framework.Interfaces; 40using OpenSim.Region.Framework.Interfaces;
41using OpenSim.Region.Framework.Scenes; 41using OpenSim.Region.Framework.Scenes;
42using OpenSim.Framework.Capabilities;
42using OpenSim.Services.Interfaces; 43using OpenSim.Services.Interfaces;
43using Caps = OpenSim.Framework.Capabilities.Caps; 44using Caps = OpenSim.Framework.Capabilities.Caps;
44using OpenSim.Capabilities.Handlers; 45using OpenSim.Capabilities.Handlers;
45using OpenSim.Framework.Monitoring; 46using OpenSim.Framework.Monitoring;
47using OpenMetaverse;
48using OpenMetaverse.StructuredData;
46 49
47namespace OpenSim.Region.ClientStack.Linden 50namespace OpenSim.Region.ClientStack.Linden
48{ 51{
@@ -52,11 +55,13 @@ namespace OpenSim.Region.ClientStack.Linden
52 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebFetchInvDescModule")] 55 [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "WebFetchInvDescModule")]
53 public class WebFetchInvDescModule : INonSharedRegionModule 56 public class WebFetchInvDescModule : INonSharedRegionModule
54 { 57 {
55 struct aPollRequest 58 class aPollRequest
56 { 59 {
57 public PollServiceInventoryEventArgs thepoll; 60 public PollServiceInventoryEventArgs thepoll;
58 public UUID reqID; 61 public UUID reqID;
59 public Hashtable request; 62 public Hashtable request;
63 public ScenePresence presence;
64 public List<UUID> folders;
60 } 65 }
61 66
62 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 67 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -71,8 +76,8 @@ namespace OpenSim.Region.ClientStack.Linden
71 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>(); 76 private Dictionary<UUID, string> m_capsDict = new Dictionary<UUID, string>();
72 private static Thread[] m_workerThreads = null; 77 private static Thread[] m_workerThreads = null;
73 78
74 private static OpenMetaverse.BlockingQueue<aPollRequest> m_queue = 79 private static DoubleQueue<aPollRequest> m_queue =
75 new OpenMetaverse.BlockingQueue<aPollRequest>(); 80 new DoubleQueue<aPollRequest>();
76 81
77 #region ISharedRegionModule Members 82 #region ISharedRegionModule Members
78 83
@@ -143,12 +148,18 @@ namespace OpenSim.Region.ClientStack.Linden
143 148
144 private class PollServiceInventoryEventArgs : PollServiceEventArgs 149 private class PollServiceInventoryEventArgs : PollServiceEventArgs
145 { 150 {
151 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
152
146 private Dictionary<UUID, Hashtable> responses = 153 private Dictionary<UUID, Hashtable> responses =
147 new Dictionary<UUID, Hashtable>(); 154 new Dictionary<UUID, Hashtable>();
148 155
149 public PollServiceInventoryEventArgs(UUID pId) : 156 private Scene m_scene;
157
158 public PollServiceInventoryEventArgs(Scene scene, UUID pId) :
150 base(null, null, null, null, pId, int.MaxValue) 159 base(null, null, null, null, pId, int.MaxValue)
151 { 160 {
161 m_scene = scene;
162
152 HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); }; 163 HasEvents = (x, y) => { lock (responses) return responses.ContainsKey(x); };
153 GetEvents = (x, y) => 164 GetEvents = (x, y) =>
154 { 165 {
@@ -167,12 +178,68 @@ namespace OpenSim.Region.ClientStack.Linden
167 178
168 Request = (x, y) => 179 Request = (x, y) =>
169 { 180 {
181 ScenePresence sp = m_scene.GetScenePresence(Id);
182 if (sp == null)
183 {
184 m_log.ErrorFormat("[INVENTORY]: Unable to find ScenePresence for {0}", Id);
185 return;
186 }
187
170 aPollRequest reqinfo = new aPollRequest(); 188 aPollRequest reqinfo = new aPollRequest();
171 reqinfo.thepoll = this; 189 reqinfo.thepoll = this;
172 reqinfo.reqID = x; 190 reqinfo.reqID = x;
173 reqinfo.request = y; 191 reqinfo.request = y;
192 reqinfo.presence = sp;
193 reqinfo.folders = new List<UUID>();
194
195 // Decode the request here
196 string request = y["body"].ToString();
197
198 request = request.Replace("<string>00000000-0000-0000-0000-000000000000</string>", "<uuid>00000000-0000-0000-0000-000000000000</uuid>");
199
200 request = request.Replace("<key>fetch_folders</key><integer>0</integer>", "<key>fetch_folders</key><boolean>0</boolean>");
201 request = request.Replace("<key>fetch_folders</key><integer>1</integer>", "<key>fetch_folders</key><boolean>1</boolean>");
202
203 Hashtable hash = new Hashtable();
204 try
205 {
206 hash = (Hashtable)LLSD.LLSDDeserialize(Utils.StringToBytes(request));
207 }
208 catch (LLSD.LLSDParseException e)
209 {
210 m_log.ErrorFormat("[INVENTORY]: Fetch error: {0}{1}" + e.Message, e.StackTrace);
211 m_log.Error("Request: " + request);
212 return;
213 }
214 catch (System.Xml.XmlException)
215 {
216 m_log.ErrorFormat("[INVENTORY]: XML Format error");
217 }
218
219 ArrayList foldersrequested = (ArrayList)hash["folders"];
220
221 bool highPriority = false;
222
223 for (int i = 0; i < foldersrequested.Count; i++)
224 {
225 Hashtable inventoryhash = (Hashtable)foldersrequested[i];
226 string folder = inventoryhash["folder_id"].ToString();
227 UUID folderID;
228 if (UUID.TryParse(folder, out folderID))
229 {
230 if (!reqinfo.folders.Contains(folderID))
231 {
232 if (sp.COF != UUID.Zero && sp.COF == folderID)
233 highPriority = true;
234 reqinfo.folders.Add(folderID);
235 }
236 }
237 }
174 238
175 m_queue.Enqueue(reqinfo); 239 if (highPriority)
240 m_queue.EnqueueHigh(reqinfo);
241 else
242 m_queue.EnqueueLow(reqinfo);
176 }; 243 };
177 244
178 NoEvents = (x, y) => 245 NoEvents = (x, y) =>
@@ -208,7 +275,7 @@ namespace OpenSim.Region.ClientStack.Linden
208 response["reusecontext"] = false; 275 response["reusecontext"] = false;
209 276
210 response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest( 277 response["str_response_string"] = m_webFetchHandler.FetchInventoryDescendentsRequest(
211 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null); 278 requestinfo.request["body"].ToString(), String.Empty, String.Empty, null, null);
212 279
213 lock (responses) 280 lock (responses)
214 responses[requestID] = response; 281 responses[requestID] = response;
@@ -220,7 +287,7 @@ namespace OpenSim.Region.ClientStack.Linden
220 string capUrl = "/CAPS/" + UUID.Random() + "/"; 287 string capUrl = "/CAPS/" + UUID.Random() + "/";
221 288
222 // Register this as a poll service 289 // Register this as a poll service
223 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(agentID); 290 PollServiceInventoryEventArgs args = new PollServiceInventoryEventArgs(m_scene, agentID);
224 291
225 args.Type = PollServiceEventArgs.EventType.Inventory; 292 args.Type = PollServiceEventArgs.EventType.Inventory;
226 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args); 293 MainServer.Instance.AddPollServiceHTTPHandler(capUrl, args);
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index fd82db7..0388828 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -2654,7 +2654,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2654 byte physshapetype = part.PhysicsShapeType; 2654 byte physshapetype = part.PhysicsShapeType;
2655 float density = part.Density; 2655 float density = part.Density;
2656 float friction = part.Friction; 2656 float friction = part.Friction;
2657 float bounce = part.Bounciness; 2657 float bounce = part.Restitution;
2658 float gravmod = part.GravityModifier; 2658 float gravmod = part.GravityModifier;
2659 2659
2660 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId); 2660 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
@@ -3893,6 +3893,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3893 part.Shape.LightEntry = false; 3893 part.Shape.LightEntry = false;
3894 } 3894 }
3895 } 3895 }
3896
3897 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
3898 {
3899 // Ensure that mesh has at least 8 valid faces
3900 part.Shape.ProfileBegin = 12500;
3901 part.Shape.ProfileEnd = 0;
3902 part.Shape.ProfileHollow = 27500;
3903 }
3896 } 3904 }
3897 3905
3898 ++updatesThisCall; 3906 ++updatesThisCall;
@@ -4952,6 +4960,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4952 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset; 4960 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4953 rotation = part.RotationOffset * presence.Rotation; 4961 rotation = part.RotationOffset * presence.Rotation;
4954 } 4962 }
4963 angularVelocity = Vector3.Zero;
4964 }
4965 else
4966 {
4967 angularVelocity = presence.AngularVelocity;
4968 rotation = presence.Rotation;
4955 } 4969 }
4956 4970
4957 attachPoint = 0; 4971 attachPoint = 0;
@@ -4963,9 +4977,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4963 // in that direction, even though we don't model this on the server. Implementing this in the future 4977 // in that direction, even though we don't model this on the server. Implementing this in the future
4964 // may improve movement smoothness. 4978 // may improve movement smoothness.
4965// acceleration = new Vector3(1, 0, 0); 4979// acceleration = new Vector3(1, 0, 0);
4966 4980
4967 angularVelocity = Vector3.Zero;
4968
4969 if (sendTexture) 4981 if (sendTexture)
4970 textureEntry = presence.Appearance.Texture.GetBytes(); 4982 textureEntry = presence.Appearance.Texture.GetBytes();
4971 else 4983 else
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index da1ccb3..df76396 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -1903,112 +1903,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1903 } 1903 }
1904 } 1904 }
1905 } 1905 }
1906
1907 internal class DoubleQueue<T> where T:class
1908 {
1909 private Queue<T> m_lowQueue = new Queue<T>();
1910 private Queue<T> m_highQueue = new Queue<T>();
1911
1912 private object m_syncRoot = new object();
1913 private Semaphore m_s = new Semaphore(0, 1);
1914
1915 public DoubleQueue()
1916 {
1917 }
1918
1919 public virtual int Count
1920 {
1921 get { return m_highQueue.Count + m_lowQueue.Count; }
1922 }
1923
1924 public virtual void Enqueue(T data)
1925 {
1926 Enqueue(m_lowQueue, data);
1927 }
1928
1929 public virtual void EnqueueLow(T data)
1930 {
1931 Enqueue(m_lowQueue, data);
1932 }
1933
1934 public virtual void EnqueueHigh(T data)
1935 {
1936 Enqueue(m_highQueue, data);
1937 }
1938
1939 private void Enqueue(Queue<T> q, T data)
1940 {
1941 lock (m_syncRoot)
1942 {
1943 m_lowQueue.Enqueue(data);
1944 m_s.WaitOne(0);
1945 m_s.Release();
1946 }
1947 }
1948
1949 public virtual T Dequeue()
1950 {
1951 return Dequeue(Timeout.Infinite);
1952 }
1953
1954 public virtual T Dequeue(int tmo)
1955 {
1956 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1957 }
1958
1959 public virtual T Dequeue(TimeSpan wait)
1960 {
1961 T res = null;
1962
1963 if (!Dequeue(wait, ref res))
1964 return null;
1965
1966 return res;
1967 }
1968
1969 public bool Dequeue(int timeout, ref T res)
1970 {
1971 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1972 }
1973
1974 public bool Dequeue(TimeSpan wait, ref T res)
1975 {
1976 if (!m_s.WaitOne(wait))
1977 return false;
1978
1979 lock (m_syncRoot)
1980 {
1981 if (m_highQueue.Count > 0)
1982 res = m_highQueue.Dequeue();
1983 else
1984 res = m_lowQueue.Dequeue();
1985
1986 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1987 return true;
1988
1989 try
1990 {
1991 m_s.Release();
1992 }
1993 catch
1994 {
1995 }
1996
1997 return true;
1998 }
1999 }
2000
2001 public virtual void Clear()
2002 {
2003
2004 lock (m_syncRoot)
2005 {
2006 // Make sure sem count is 0
2007 m_s.WaitOne(0);
2008
2009 m_lowQueue.Clear();
2010 m_highQueue.Clear();
2011 }
2012 }
2013 }
2014} 1906}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
index 0aa4693..e13f479 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs
@@ -260,10 +260,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
260 { 260 {
261 CompleteTaskItemUpdate(m_updateTaskItemData); 261 CompleteTaskItemUpdate(m_updateTaskItemData);
262 } 262 }
263// else if (m_storeLocal) 263 else if (m_asset.Local)
264// { 264 {
265// m_Scene.AssetService.Store(m_asset); 265 m_Scene.AssetService.Store(m_asset);
266// } 266 }
267 } 267 }
268 268
269 m_log.DebugFormat( 269 m_log.DebugFormat(
@@ -339,7 +339,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
339 // to avoid a race condition when the appearance module retrieves the item to set the asset id in 339 // to avoid a race condition when the appearance module retrieves the item to set the asset id in
340 // the AvatarAppearance structure. 340 // the AvatarAppearance structure.
341 item.AssetID = m_asset.FullID; 341 item.AssetID = m_asset.FullID;
342 m_Scene.InventoryService.UpdateItem(item); 342 if (item.AssetID != UUID.Zero)
343 m_Scene.InventoryService.UpdateItem(item);
343 344
344 if (m_uploadState == UploadState.Complete) 345 if (m_uploadState == UploadState.Complete)
345 { 346 {
@@ -390,6 +391,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
390// m_asset.FullID, item.Name, ourClient.Name); 391// m_asset.FullID, item.Name, ourClient.Name);
391 392
392 m_Scene.AssetService.Store(m_asset); 393 m_Scene.AssetService.Store(m_asset);
394 if (m_asset.FullID != UUID.Zero)
395 {
396 item.AssetID = m_asset.FullID;
397 m_Scene.InventoryService.UpdateItem(item);
398 }
393 399
394 m_transactions.RemoveXferUploader(m_transactionID); 400 m_transactions.RemoveXferUploader(m_transactionID);
395 } 401 }
diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
index a0f1e8c..ec388f4 100644
--- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
+++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs
@@ -369,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Asset
369 AssetBase asset = null; 369 AssetBase asset = null;
370 370
371 string filename = GetFileName(id); 371 string filename = GetFileName(id);
372 if (File.Exists(filename)) 372 while (File.Exists(filename))
373 { 373 {
374 FileStream stream = null; 374 FileStream stream = null;
375 try 375 try
@@ -380,6 +380,8 @@ namespace OpenSim.Region.CoreModules.Asset
380 asset = (AssetBase)bformatter.Deserialize(stream); 380 asset = (AssetBase)bformatter.Deserialize(stream);
381 381
382 m_DiskHits++; 382 m_DiskHits++;
383
384 break;
383 } 385 }
384 catch (System.Runtime.Serialization.SerializationException e) 386 catch (System.Runtime.Serialization.SerializationException e)
385 { 387 {
@@ -392,12 +394,24 @@ namespace OpenSim.Region.CoreModules.Asset
392 // {different version of AssetBase} -- we should attempt to 394 // {different version of AssetBase} -- we should attempt to
393 // delete it and re-cache 395 // delete it and re-cache
394 File.Delete(filename); 396 File.Delete(filename);
397
398 break;
399 }
400 catch (IOException e)
401 {
402 // This is a sharing violation: File exists but can't be opened because it's
403 // being written
404 Thread.Sleep(100);
405
406 continue;
395 } 407 }
396 catch (Exception e) 408 catch (Exception e)
397 { 409 {
398 m_log.ErrorFormat( 410 m_log.ErrorFormat(
399 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", 411 "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
400 filename, id, e.Message, e.StackTrace); 412 filename, id, e.Message, e.StackTrace);
413
414 break;
401 } 415 }
402 finally 416 finally
403 { 417 {
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index acd156e..7cc5092 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -236,9 +236,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
236 // If we're an NPC then skip all the item checks and manipulations since we don't have an 236 // If we're an NPC then skip all the item checks and manipulations since we don't have an
237 // inventory right now. 237 // inventory right now.
238 if (sp.PresenceType == PresenceType.Npc) 238 if (sp.PresenceType == PresenceType.Npc)
239 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null); 239 RezSingleAttachmentFromInventoryInternal(sp, UUID.Zero, attach.AssetID, p, null, true);
240 else 240 else
241 RezSingleAttachmentFromInventory(sp, attach.ItemID, p, d); 241 RezSingleAttachmentFromInventory(sp, attach.ItemID, p | (uint)0x80, d);
242 } 242 }
243 catch (Exception e) 243 catch (Exception e)
244 { 244 {
@@ -284,12 +284,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
284 sp.ClearAttachments(); 284 sp.ClearAttachments();
285 } 285 }
286 286
287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) 287 public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append)
288 { 288 {
289 if (!Enabled) 289 if (!Enabled)
290 return false; 290 return false;
291 291
292 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp)) 292 if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp, append))
293 { 293 {
294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); 294 m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID);
295 return true; 295 return true;
@@ -298,7 +298,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
298 return false; 298 return false;
299 } 299 }
300 300
301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) 301 private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp, bool append)
302 { 302 {
303 lock (sp.AttachmentsSyncLock) 303 lock (sp.AttachmentsSyncLock)
304 { 304 {
@@ -326,10 +326,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
326 326
327 Vector3 attachPos = group.AbsolutePosition; 327 Vector3 attachPos = group.AbsolutePosition;
328 328
329 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
330 // be removed when that functionality is implemented in opensim
331 attachmentPt &= 0x7f;
332
333 // If the attachment point isn't the same as the one previously used 329 // If the attachment point isn't the same as the one previously used
334 // set it's offset position = 0 so that it appears on the attachment point 330 // set it's offset position = 0 so that it appears on the attachment point
335 // and not in a weird location somewhere unknown. 331 // and not in a weird location somewhere unknown.
@@ -375,7 +371,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
375 group.AbsolutePosition = attachPos; 371 group.AbsolutePosition = attachPos;
376 372
377 if (sp.PresenceType != PresenceType.Npc) 373 if (sp.PresenceType != PresenceType.Npc)
378 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp); 374 UpdateUserInventoryWithAttachment(sp, group, attachmentPt, temp, append);
379 375
380 AttachToAgent(sp, group, attachmentPt, attachPos, silent); 376 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
381 } 377 }
@@ -383,21 +379,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
383 return true; 379 return true;
384 } 380 }
385 381
386 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp) 382 private void UpdateUserInventoryWithAttachment(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool temp, bool append)
387 { 383 {
388 // Remove any previous attachments
389 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 384 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
390 385
391 // At the moment we can only deal with a single attachment 386 // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones
392 if (attachments.Count != 0) 387 while (attachments.Count >= 5)
393 { 388 {
394 if (attachments[0].FromItemID != UUID.Zero) 389 if (attachments[0].FromItemID != UUID.Zero)
395 DetachSingleAttachmentToInvInternal(sp, attachments[0]); 390 DetachSingleAttachmentToInvInternal(sp, attachments[0]);
396 // Error logging commented because UUID.Zero now means temp attachment 391 attachments.RemoveAt(0);
397// else 392 }
398// m_log.WarnFormat( 393
399// "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", 394 // If we're not appending, remove the rest as well
400// attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); 395 if (attachments.Count != 0 && !append)
396 {
397 foreach (SceneObjectGroup g in attachments)
398 {
399 if (g.FromItemID != UUID.Zero)
400 DetachSingleAttachmentToInvInternal(sp, g);
401 }
401 } 402 }
402 403
403 // Add the new attachment to inventory if we don't already have it. 404 // Add the new attachment to inventory if we don't already have it.
@@ -407,7 +408,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
407 if (newAttachmentItemID == UUID.Zero) 408 if (newAttachmentItemID == UUID.Zero)
408 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID; 409 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp, group).ID;
409 410
410 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); 411 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group, append);
411 } 412 }
412 } 413 }
413 414
@@ -425,8 +426,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
425// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", 426// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
426// (AttachmentPoint)AttachmentPt, itemID, sp.Name); 427// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
427 428
428 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 429 bool append = (AttachmentPt & 0x80) != 0;
429 // be removed when that functionality is implemented in opensim
430 AttachmentPt &= 0x7f; 430 AttachmentPt &= 0x7f;
431 431
432 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). 432 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
@@ -455,7 +455,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
455 return null; 455 return null;
456 } 456 }
457 457
458 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc); 458 return RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc, append);
459 } 459 }
460 460
461 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist) 461 public void RezMultipleAttachmentsFromInventory(IScenePresence sp, List<KeyValuePair<UUID, uint>> rezlist)
@@ -847,7 +847,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
847 } 847 }
848 848
849 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( 849 protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
850 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc) 850 IScenePresence sp, UUID itemID, UUID assetID, uint attachmentPt, XmlDocument doc, bool append)
851 { 851 {
852 if (m_invAccessModule == null) 852 if (m_invAccessModule == null)
853 return null; 853 return null;
@@ -885,7 +885,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
885 // This will throw if the attachment fails 885 // This will throw if the attachment fails
886 try 886 try
887 { 887 {
888 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false); 888 AttachObjectInternal(sp, objatt, attachmentPt, false, false, false, append);
889 } 889 }
890 catch (Exception e) 890 catch (Exception e)
891 { 891 {
@@ -936,7 +936,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
936 /// <param name="AttachmentPt"></param> 936 /// <param name="AttachmentPt"></param>
937 /// <param name="itemID"></param> 937 /// <param name="itemID"></param>
938 /// <param name="att"></param> 938 /// <param name="att"></param>
939 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) 939 private void ShowAttachInUserInventory(IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att, bool append)
940 { 940 {
941// m_log.DebugFormat( 941// m_log.DebugFormat(
942// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", 942// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
@@ -959,7 +959,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
959 if (item == null) 959 if (item == null)
960 return; 960 return;
961 961
962 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); 962 int attFlag = append ? 0x80 : 0;
963 bool changed = sp.Appearance.SetAttachment((int)AttachmentPt | attFlag, itemID, item.AssetID);
963 if (changed && m_scene.AvatarFactory != null) 964 if (changed && m_scene.AvatarFactory != null)
964 { 965 {
965// m_log.DebugFormat( 966// m_log.DebugFormat(
@@ -1043,12 +1044,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
1043 return; 1044 return;
1044 } 1045 }
1045 1046
1046 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 1047 bool append = (AttachmentPt & 0x80) != 0;
1047 // be removed when that functionality is implemented in opensim
1048 AttachmentPt &= 0x7f; 1048 AttachmentPt &= 0x7f;
1049 1049
1050 // Calls attach with a Zero position 1050 // Calls attach with a Zero position
1051 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false)) 1051 if (AttachObject(sp, part.ParentGroup, AttachmentPt, false, true, false, append))
1052 { 1052 {
1053// m_log.Debug( 1053// m_log.Debug(
1054// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 1054// "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
index 4e9d3f9..545aeda 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -197,7 +197,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); 197 SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID);
198 198
199 m_numberOfAttachEventsFired = 0; 199 m_numberOfAttachEventsFired = 0;
200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); 200 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false);
201 201
202 // Check status on scene presence 202 // Check status on scene presence
203 Assert.That(sp.HasAttachments(), Is.True); 203 Assert.That(sp.HasAttachments(), Is.True);
@@ -254,7 +254,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
254 sp2.AbsolutePosition = new Vector3(0, 0, 0); 254 sp2.AbsolutePosition = new Vector3(0, 0, 0);
255 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero); 255 sp2.HandleAgentRequestSit(sp2.ControllingClient, sp2.UUID, so.UUID, Vector3.Zero);
256 256
257 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); 257 scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false, false);
258 258
259 Assert.That(sp.HasAttachments(), Is.False); 259 Assert.That(sp.HasAttachments(), Is.False);
260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); 260 Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1));
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
index 7ec2860..1adff7e 100644
--- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs
@@ -674,26 +674,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
674 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) 674 private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance)
675 { 675 {
676 IInventoryService invService = m_scene.InventoryService; 676 IInventoryService invService = m_scene.InventoryService;
677 677 bool resetwearable = false;
678 if (invService.GetRootFolder(userID) != null) 678 if (invService.GetRootFolder(userID) != null)
679 { 679 {
680 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) 680 for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++)
681 { 681 {
682 for (int j = 0; j < appearance.Wearables[i].Count; j++) 682 for (int j = 0; j < appearance.Wearables[i].Count; j++)
683 { 683 {
684 // Check if the default wearables are not set
684 if (appearance.Wearables[i][j].ItemID == UUID.Zero) 685 if (appearance.Wearables[i][j].ItemID == UUID.Zero)
686 {
687 switch ((WearableType) i)
688 {
689 case WearableType.Eyes:
690 case WearableType.Hair:
691 case WearableType.Shape:
692 case WearableType.Skin:
693 //case WearableType.Underpants:
694 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
695 resetwearable = true;
696 m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values.");
697 resetwearable = true;
698 break;
699
700 }
685 continue; 701 continue;
702 }
686 703
687 // Ignore ruth's assets 704 // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1
688 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) 705 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID)
706 {
707 switch ((WearableType)i)
708 {
709 case WearableType.Eyes:
710 case WearableType.Hair:
711 case WearableType.Shape:
712 case WearableType.Skin:
713 //case WearableType.Underpants:
714 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
715
716 m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i);
717 resetwearable = true;
718 break;
719
720 }
689 continue; 721 continue;
690 722 }
723
691 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); 724 InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID);
692 baseItem = invService.GetItem(baseItem); 725 baseItem = invService.GetItem(baseItem);
693 726
694 if (baseItem != null) 727 if (baseItem != null)
695 { 728 {
696 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); 729 appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID);
730 int unmodifiedWearableIndexForClosure = i;
731 m_scene.AssetService.Get(baseItem.AssetID.ToString(), this,
732 delegate(string x, object y, AssetBase z)
733 {
734 if (z == null)
735 {
736 TryAndRepairBrokenWearable(
737 (WearableType)unmodifiedWearableIndexForClosure, invService,
738 userID, appearance);
739 }
740 });
697 } 741 }
698 else 742 else
699 { 743 {
@@ -701,17 +745,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
701 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", 745 "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default",
702 appearance.Wearables[i][j].ItemID, (WearableType)i); 746 appearance.Wearables[i][j].ItemID, (WearableType)i);
703 747
704 appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); 748 TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance);
749 resetwearable = true;
750
705 } 751 }
706 } 752 }
707 } 753 }
754
755 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
756 if (appearance.Wearables[(int) WearableType.Eyes] == null)
757 {
758 m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes));
759
760 TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
761 resetwearable = true;
762 }
763 else
764 {
765 if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero)
766 {
767 m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}",
768 appearance.Wearables[(int) WearableType.Eyes][0].ItemID,
769 appearance.Wearables[(int) WearableType.Eyes][0].AssetID);
770 TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance);
771 resetwearable = true;
772
773 }
774
775 }
776 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
777 if (appearance.Wearables[(int)WearableType.Shape] == null)
778 {
779 m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape));
780
781 TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
782 resetwearable = true;
783 }
784 else
785 {
786 if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero)
787 {
788 m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}",
789 appearance.Wearables[(int)WearableType.Shape][0].ItemID,
790 appearance.Wearables[(int)WearableType.Shape][0].AssetID);
791 TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance);
792 resetwearable = true;
793
794 }
795
796 }
797 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
798 if (appearance.Wearables[(int)WearableType.Hair] == null)
799 {
800 m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair));
801
802 TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
803 resetwearable = true;
804 }
805 else
806 {
807 if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero)
808 {
809 m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}",
810 appearance.Wearables[(int)WearableType.Hair][0].ItemID,
811 appearance.Wearables[(int)WearableType.Hair][0].AssetID);
812 TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance);
813 resetwearable = true;
814
815 }
816
817 }
818 // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason....
819 if (appearance.Wearables[(int)WearableType.Skin] == null)
820 {
821 m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin));
822
823 TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
824 resetwearable = true;
825 }
826 else
827 {
828 if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero)
829 {
830 m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}",
831 appearance.Wearables[(int)WearableType.Skin][0].ItemID,
832 appearance.Wearables[(int)WearableType.Skin][0].AssetID);
833 TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance);
834 resetwearable = true;
835
836 }
837
838 }
839 if (resetwearable)
840 {
841 ScenePresence presence = null;
842 if (m_scene.TryGetScenePresence(userID, out presence))
843 {
844 presence.ControllingClient.SendWearables(presence.Appearance.Wearables,
845 presence.Appearance.Serial++);
846 }
847 }
848
708 } 849 }
709 else 850 else
710 { 851 {
711 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); 852 m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID);
712 } 853 }
713 } 854 }
855 private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance)
856 {
857 UUID defaultwearable = GetDefaultItem(type);
858 if (defaultwearable != UUID.Zero)
859 {
860 UUID newInvItem = UUID.Random();
861 InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID)
862 {
863 AssetID =
864 defaultwearable,
865 AssetType
866 =
867 (int)
868 AssetType
869 .Bodypart,
870 CreatorId
871 =
872 userID
873 .ToString
874 (),
875 //InvType = (int)InventoryType.Wearable,
876
877 Description
878 =
879 "Failed Wearable Replacement",
880 Folder =
881 invService
882 .GetFolderForType
883 (userID,
884 AssetType
885 .Bodypart)
886 .ID,
887 Flags = (uint) type,
888 Name = Enum.GetName(typeof (WearableType), type),
889 BasePermissions = (uint) PermissionMask.Copy,
890 CurrentPermissions = (uint) PermissionMask.Copy,
891 EveryOnePermissions = (uint) PermissionMask.Copy,
892 GroupPermissions = (uint) PermissionMask.Copy,
893 NextPermissions = (uint) PermissionMask.Copy
894 };
895 invService.AddItem(itembase);
896 UUID LinkInvItem = UUID.Random();
897 itembase = new InventoryItemBase(LinkInvItem, userID)
898 {
899 AssetID =
900 newInvItem,
901 AssetType
902 =
903 (int)
904 AssetType
905 .Link,
906 CreatorId
907 =
908 userID
909 .ToString
910 (),
911 InvType = (int) InventoryType.Wearable,
912
913 Description
914 =
915 "Failed Wearable Replacement",
916 Folder =
917 invService
918 .GetFolderForType
919 (userID,
920 AssetType
921 .CurrentOutfitFolder)
922 .ID,
923 Flags = (uint) type,
924 Name = Enum.GetName(typeof (WearableType), type),
925 BasePermissions = (uint) PermissionMask.Copy,
926 CurrentPermissions = (uint) PermissionMask.Copy,
927 EveryOnePermissions = (uint) PermissionMask.Copy,
928 GroupPermissions = (uint) PermissionMask.Copy,
929 NextPermissions = (uint) PermissionMask.Copy
930 };
931 invService.AddItem(itembase);
932 appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type));
933 ScenePresence presence = null;
934 if (m_scene.TryGetScenePresence(userID, out presence))
935 {
936 m_scene.SendInventoryUpdate(presence.ControllingClient,
937 invService.GetFolderForType(userID,
938 AssetType
939 .CurrentOutfitFolder),
940 false, true);
941 }
942 }
943 }
944 private UUID GetDefaultItem(WearableType wearable)
945 {
946 // These are ruth
947 UUID ret = UUID.Zero;
948 switch (wearable)
949 {
950 case WearableType.Eyes:
951 ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7");
952 break;
953 case WearableType.Hair:
954 ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66");
955 break;
956 case WearableType.Pants:
957 ret = new UUID("00000000-38f9-1111-024e-222222111120");
958 break;
959 case WearableType.Shape:
960 ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73");
961 break;
962 case WearableType.Shirt:
963 ret = new UUID("00000000-38f9-1111-024e-222222111110");
964 break;
965 case WearableType.Skin:
966 ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb");
967 break;
968 case WearableType.Undershirt:
969 ret = new UUID("16499ebb-3208-ec27-2def-481881728f47");
970 break;
971 case WearableType.Underpants:
972 ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d");
973 break;
974 }
714 975
976 return ret;
977 }
715 #endregion 978 #endregion
716 979
717 #region Client Event Handlers 980 #region Client Event Handlers
diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
index 7f30e5a..2eb9bfb 100644
--- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs
@@ -55,7 +55,7 @@ namespace OpenSim.Region.CoreModules.Framework
55 /// <summary> 55 /// <summary>
56 /// Each agent has its own capabilities handler. 56 /// Each agent has its own capabilities handler.
57 /// </summary> 57 /// </summary>
58 protected Dictionary<UUID, Caps> m_capsObjects = new Dictionary<UUID, Caps>(); 58 protected Dictionary<uint, Caps> m_capsObjects = new Dictionary<uint, Caps>();
59 59
60 protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>(); 60 protected Dictionary<UUID, string> capsPaths = new Dictionary<UUID, string>();
61 protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds 61 protected Dictionary<UUID, Dictionary<ulong, string>> childrenSeeds
@@ -100,7 +100,7 @@ namespace OpenSim.Region.CoreModules.Framework
100 get { return null; } 100 get { return null; }
101 } 101 }
102 102
103 public void CreateCaps(UUID agentId) 103 public void CreateCaps(UUID agentId, uint circuitCode)
104 { 104 {
105 int flags = m_scene.GetUserFlags(agentId); 105 int flags = m_scene.GetUserFlags(agentId);
106 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags)) 106 if (m_scene.RegionInfo.EstateSettings.IsBanned(agentId, flags))
@@ -108,9 +108,9 @@ namespace OpenSim.Region.CoreModules.Framework
108 108
109 String capsObjectPath = GetCapsPath(agentId); 109 String capsObjectPath = GetCapsPath(agentId);
110 110
111 if (m_capsObjects.ContainsKey(agentId)) 111 if (m_capsObjects.ContainsKey(circuitCode))
112 { 112 {
113 Caps oldCaps = m_capsObjects[agentId]; 113 Caps oldCaps = m_capsObjects[circuitCode];
114 114
115 m_log.DebugFormat( 115 m_log.DebugFormat(
116 "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ", 116 "[CAPS]: Recreating caps for agent {0}. Old caps path {1}, new caps path {2}. ",
@@ -125,12 +125,12 @@ namespace OpenSim.Region.CoreModules.Framework
125 (MainServer.Instance == null) ? 0: MainServer.Instance.Port, 125 (MainServer.Instance == null) ? 0: MainServer.Instance.Port,
126 capsObjectPath, agentId, m_scene.RegionInfo.RegionName); 126 capsObjectPath, agentId, m_scene.RegionInfo.RegionName);
127 127
128 m_capsObjects[agentId] = caps; 128 m_capsObjects[circuitCode] = caps;
129 129
130 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps); 130 m_scene.EventManager.TriggerOnRegisterCaps(agentId, caps);
131 } 131 }
132 132
133 public void RemoveCaps(UUID agentId) 133 public void RemoveCaps(UUID agentId, uint circuitCode)
134 { 134 {
135 if (childrenSeeds.ContainsKey(agentId)) 135 if (childrenSeeds.ContainsKey(agentId))
136 { 136 {
@@ -139,11 +139,11 @@ namespace OpenSim.Region.CoreModules.Framework
139 139
140 lock (m_capsObjects) 140 lock (m_capsObjects)
141 { 141 {
142 if (m_capsObjects.ContainsKey(agentId)) 142 if (m_capsObjects.ContainsKey(circuitCode))
143 { 143 {
144 m_capsObjects[agentId].DeregisterHandlers(); 144 m_capsObjects[circuitCode].DeregisterHandlers();
145 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[agentId]); 145 m_scene.EventManager.TriggerOnDeregisterCaps(agentId, m_capsObjects[circuitCode]);
146 m_capsObjects.Remove(agentId); 146 m_capsObjects.Remove(circuitCode);
147 } 147 }
148 else 148 else
149 { 149 {
@@ -154,19 +154,30 @@ namespace OpenSim.Region.CoreModules.Framework
154 } 154 }
155 } 155 }
156 156
157 public Caps GetCapsForUser(UUID agentId) 157 public Caps GetCapsForUser(uint circuitCode)
158 { 158 {
159 lock (m_capsObjects) 159 lock (m_capsObjects)
160 { 160 {
161 if (m_capsObjects.ContainsKey(agentId)) 161 if (m_capsObjects.ContainsKey(circuitCode))
162 { 162 {
163 return m_capsObjects[agentId]; 163 return m_capsObjects[circuitCode];
164 } 164 }
165 } 165 }
166 166
167 return null; 167 return null;
168 } 168 }
169 169
170 public void ActivateCaps(uint circuitCode)
171 {
172 lock (m_capsObjects)
173 {
174 if (m_capsObjects.ContainsKey(circuitCode))
175 {
176 m_capsObjects[circuitCode].Activate();
177 }
178 }
179 }
180
170 public void SetAgentCapsSeeds(AgentCircuitData agent) 181 public void SetAgentCapsSeeds(AgentCircuitData agent)
171 { 182 {
172 capsPaths[agent.AgentID] = agent.CapsPath; 183 capsPaths[agent.AgentID] = agent.CapsPath;
@@ -237,9 +248,9 @@ namespace OpenSim.Region.CoreModules.Framework
237 StringBuilder caps = new StringBuilder(); 248 StringBuilder caps = new StringBuilder();
238 caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName); 249 caps.AppendFormat("Region {0}:\n", m_scene.RegionInfo.RegionName);
239 250
240 foreach (KeyValuePair<UUID, Caps> kvp in m_capsObjects) 251 foreach (KeyValuePair<uint, Caps> kvp in m_capsObjects)
241 { 252 {
242 caps.AppendFormat("** User {0}:\n", kvp.Key); 253 caps.AppendFormat("** Circuit {0}:\n", kvp.Key);
243 254
244 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); ) 255 for (IDictionaryEnumerator kvp2 = kvp.Value.CapsHandlers.GetCapsDetails(false).GetEnumerator(); kvp2.MoveNext(); )
245 { 256 {
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index cb09047..ac4d93d 100644
--- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
@@ -150,7 +150,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
150 { 150 {
151 client.OnTeleportHomeRequest += TriggerTeleportHome; 151 client.OnTeleportHomeRequest += TriggerTeleportHome;
152 client.OnTeleportLandmarkRequest += RequestTeleportLandmark; 152 client.OnTeleportLandmarkRequest += RequestTeleportLandmark;
153 client.OnTeleportCancel += TeleportCancel;
154 } 153 }
155 154
156 public virtual void Close() {} 155 public virtual void Close() {}
@@ -995,11 +994,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
995 return neighbourRegion; 994 return neighbourRegion;
996 } 995 }
997 996
998 private void TeleportCancel(IClientAPI remoteClient)
999 {
1000 m_entityTransferStateMachine.ResetFromTransit(remoteClient.AgentId);
1001 }
1002
1003 public bool Cross(ScenePresence agent, bool isFlying) 997 public bool Cross(ScenePresence agent, bool isFlying)
1004 { 998 {
1005 uint x; 999 uint x;
diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
index da59eab..24e925e 100644
--- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs
@@ -50,6 +50,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
50 public string url; 50 public string url;
51 public UUID urlcode; 51 public UUID urlcode;
52 public Dictionary<UUID, RequestData> requests; 52 public Dictionary<UUID, RequestData> requests;
53 public bool isSsl;
53 } 54 }
54 55
55 public class RequestData 56 public class RequestData
@@ -184,6 +185,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
184 urlData.engine = engine; 185 urlData.engine = engine;
185 urlData.url = url; 186 urlData.url = url;
186 urlData.urlcode = urlcode; 187 urlData.urlcode = urlcode;
188 urlData.isSsl = false;
187 urlData.requests = new Dictionary<UUID, RequestData>(); 189 urlData.requests = new Dictionary<UUID, RequestData>();
188 190
189 m_UrlMap[url] = urlData; 191 m_UrlMap[url] = urlData;
@@ -229,6 +231,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
229 urlData.engine = engine; 231 urlData.engine = engine;
230 urlData.url = url; 232 urlData.url = url;
231 urlData.urlcode = urlcode; 233 urlData.urlcode = urlcode;
234 urlData.isSsl = true;
232 urlData.requests = new Dictionary<UUID, RequestData>(); 235 urlData.requests = new Dictionary<UUID, RequestData>();
233 236
234 237
@@ -394,7 +397,10 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp
394 397
395 private void RemoveUrl(UrlData data) 398 private void RemoveUrl(UrlData data)
396 { 399 {
397 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); 400 if (data.isSsl)
401 m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/");
402 else
403 m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/");
398 } 404 }
399 405
400 private Hashtable NoEvents(UUID requestID, UUID sessionID) 406 private Hashtable NoEvents(UUID requestID, UUID sessionID)
diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
index f6e1d39..f697c24 100644
--- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs
@@ -262,6 +262,8 @@ namespace OpenSim.Region.CoreModules.Scripting.ScriptModuleComms
262 return "modInvokeR"; 262 return "modInvokeR";
263 else if (sid.ReturnType == typeof(object[])) 263 else if (sid.ReturnType == typeof(object[]))
264 return "modInvokeL"; 264 return "modInvokeL";
265 else if (sid.ReturnType == typeof(void))
266 return "modInvokeN";
265 267
266 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name); 268 m_log.WarnFormat("[MODULE COMMANDS] failed to find match for {0} with return type {1}",fname,sid.ReturnType.Name);
267 } 269 }
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index d781eae..eaaf7a3 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -84,7 +84,7 @@ namespace OpenSim.Region.Framework.Interfaces
84 /// <param name="AttachmentPt"></param> 84 /// <param name="AttachmentPt"></param>
85 /// <param name="silent"></param> 85 /// <param name="silent"></param>
86 /// <returns>true if the object was successfully attached, false otherwise</returns> 86 /// <returns>true if the object was successfully attached, false otherwise</returns>
87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp); 87 bool AttachObject(IScenePresence sp, SceneObjectGroup grp, uint AttachmentPt, bool silent, bool useAttachmentInfo, bool temp, bool append);
88 88
89 /// <summary> 89 /// <summary>
90 /// Rez an attachment from user inventory and change inventory status to match. 90 /// Rez an attachment from user inventory and change inventory status to match.
diff --git a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
index 522c82d..30d404e 100644
--- a/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ICapabilitiesModule.cs
@@ -40,19 +40,19 @@ namespace OpenSim.Region.Framework.Interfaces
40 /// </summary> 40 /// </summary>
41 /// <param name="agentId"></param> 41 /// <param name="agentId"></param>
42 /// <param name="capsObjectPath"></param> 42 /// <param name="capsObjectPath"></param>
43 void CreateCaps(UUID agentId); 43 void CreateCaps(UUID agentId, uint circuitCode);
44 44
45 /// <summary> 45 /// <summary>
46 /// Remove the caps handler for a given agent. 46 /// Remove the caps handler for a given agent.
47 /// </summary> 47 /// </summary>
48 /// <param name="agentId"></param> 48 /// <param name="agentId"></param>
49 void RemoveCaps(UUID agentId); 49 void RemoveCaps(UUID agentId, uint circuitCode);
50 50
51 /// <summary> 51 /// <summary>
52 /// Will return null if the agent doesn't have a caps handler registered 52 /// Will return null if the agent doesn't have a caps handler registered
53 /// </summary> 53 /// </summary>
54 /// <param name="agentId"></param> 54 /// <param name="agentId"></param>
55 Caps GetCapsForUser(UUID agentId); 55 Caps GetCapsForUser(uint circuitCode);
56 56
57 void SetAgentCapsSeeds(AgentCircuitData agent); 57 void SetAgentCapsSeeds(AgentCircuitData agent);
58 58
@@ -65,5 +65,7 @@ namespace OpenSim.Region.Framework.Interfaces
65 void DropChildSeed(UUID agentID, ulong handle); 65 void DropChildSeed(UUID agentID, ulong handle);
66 66
67 string GetCapsPath(UUID agentId); 67 string GetCapsPath(UUID agentId);
68
69 void ActivateCaps(uint circuitCode);
68 } 70 }
69} 71}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs b/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs
index 8cef14e..6effcc1 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs
@@ -26,18 +26,22 @@
26 */ 26 */
27 27
28using System; 28using System;
29using OpenMetaverse;
29using OpenMetaverse.StructuredData; 30using OpenMetaverse.StructuredData;
30 31
31namespace OpenSim.Region.Framework.Interfaces 32namespace OpenSim.Region.Framework.Interfaces
32{ 33{
34 public delegate void SimulatorFeaturesRequestDelegate(UUID agentID, ref OSDMap features);
35
33 /// <summary> 36 /// <summary>
34 /// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability. 37 /// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability.
35 /// </summary> 38 /// </summary>
36 public interface ISimulatorFeaturesModule 39 public interface ISimulatorFeaturesModule
37 { 40 {
41 event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
38 void AddFeature(string name, OSD value); 42 void AddFeature(string name, OSD value);
39 bool RemoveFeature(string name); 43 bool RemoveFeature(string name);
40 bool TryGetFeature(string name, out OSD value); 44 bool TryGetFeature(string name, out OSD value);
41 OSDMap GetFeatures(); 45 OSDMap GetFeatures();
42 } 46 }
43} \ No newline at end of file 47}
diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
index 5cfba39..b102e48 100644
--- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
+++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs
@@ -22,6 +22,115 @@ using log4net;
22 22
23namespace OpenSim.Region.Framework.Scenes 23namespace OpenSim.Region.Framework.Scenes
24{ 24{
25 public class KeyframeTimer
26 {
27 private static Dictionary<Scene, KeyframeTimer>m_timers =
28 new Dictionary<Scene, KeyframeTimer>();
29
30 private Timer m_timer;
31 private Dictionary<KeyframeMotion, object> m_motions = new Dictionary<KeyframeMotion, object>();
32 private object m_lockObject = new object();
33 private object m_timerLock = new object();
34 private const double m_tickDuration = 50.0;
35 private Scene m_scene;
36
37 public double TickDuration
38 {
39 get { return m_tickDuration; }
40 }
41
42 public KeyframeTimer(Scene scene)
43 {
44 m_timer = new Timer();
45 m_timer.Interval = TickDuration;
46 m_timer.AutoReset = true;
47 m_timer.Elapsed += OnTimer;
48
49 m_scene = scene;
50
51 m_timer.Start();
52 }
53
54 private void OnTimer(object sender, ElapsedEventArgs ea)
55 {
56 if (!Monitor.TryEnter(m_timerLock))
57 return;
58
59 try
60 {
61 List<KeyframeMotion> motions;
62
63 lock (m_lockObject)
64 {
65 motions = new List<KeyframeMotion>(m_motions.Keys);
66 }
67
68 foreach (KeyframeMotion m in motions)
69 {
70 try
71 {
72 m.OnTimer(TickDuration);
73 }
74 catch (Exception inner)
75 {
76 // Don't stop processing
77 }
78 }
79 }
80 catch (Exception e)
81 {
82 // Keep running no matter what
83 }
84 finally
85 {
86 Monitor.Exit(m_timerLock);
87 }
88 }
89
90 public static void Add(KeyframeMotion motion)
91 {
92 KeyframeTimer timer;
93
94 if (motion.Scene == null)
95 return;
96
97 lock (m_timers)
98 {
99 if (!m_timers.TryGetValue(motion.Scene, out timer))
100 {
101 timer = new KeyframeTimer(motion.Scene);
102 m_timers[motion.Scene] = timer;
103 }
104 }
105
106 lock (timer.m_lockObject)
107 {
108 timer.m_motions[motion] = null;
109 }
110 }
111
112 public static void Remove(KeyframeMotion motion)
113 {
114 KeyframeTimer timer;
115
116 if (motion.Scene == null)
117 return;
118
119 lock (m_timers)
120 {
121 if (!m_timers.TryGetValue(motion.Scene, out timer))
122 {
123 return;
124 }
125 }
126
127 lock (timer.m_lockObject)
128 {
129 timer.m_motions.Remove(motion);
130 }
131 }
132 }
133
25 [Serializable] 134 [Serializable]
26 public class KeyframeMotion 135 public class KeyframeMotion
27 { 136 {
@@ -63,18 +172,6 @@ namespace OpenSim.Region.Framework.Scenes
63 172
64 private Keyframe[] m_keyframes; 173 private Keyframe[] m_keyframes;
65 174
66 [NonSerialized()]
67 protected Timer m_timer = null;
68
69 // timer lock
70 [NonSerialized()]
71 private object m_onTimerLock;
72
73 // timer overrun detect
74 // prevents overlap or timer events threads frozen on the lock
75 [NonSerialized()]
76 private bool m_inOnTimer;
77
78 // skip timer events. 175 // skip timer events.
79 //timer.stop doesn't assure there aren't event threads still being fired 176 //timer.stop doesn't assure there aren't event threads still being fired
80 [NonSerialized()] 177 [NonSerialized()]
@@ -97,12 +194,21 @@ namespace OpenSim.Region.Framework.Scenes
97 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation; 194 private DataFormat m_data = DataFormat.Translation | DataFormat.Rotation;
98 195
99 private bool m_running = false; 196 private bool m_running = false;
197
100 [NonSerialized()] 198 [NonSerialized()]
101 private bool m_selected = false; 199 private bool m_selected = false;
102 200
103 private int m_iterations = 0; 201 private int m_iterations = 0;
104 202
105 private const double timerInterval = 50.0; 203 private int m_skipLoops = 0;
204
205 [NonSerialized()]
206 private Scene m_scene;
207
208 public Scene Scene
209 {
210 get { return m_scene; }
211 }
106 212
107 public DataFormat Data 213 public DataFormat Data
108 { 214 {
@@ -139,31 +245,16 @@ namespace OpenSim.Region.Framework.Scenes
139 245
140 private void StartTimer() 246 private void StartTimer()
141 { 247 {
142 if (m_timer == null) 248 KeyframeTimer.Add(this);
143 return;
144 m_timerStopped = false; 249 m_timerStopped = false;
145 m_timer.Start();
146 } 250 }
147 251
148 private void StopTimer() 252 private void StopTimer()
149 { 253 {
150 if (m_timer == null || m_timerStopped)
151 return;
152 m_timerStopped = true;
153 m_timer.Stop();
154 }
155
156 private void RemoveTimer()
157 {
158 if (m_timer == null)
159 return;
160 m_timerStopped = true; 254 m_timerStopped = true;
161 m_timer.Stop(); 255 KeyframeTimer.Remove(this);
162 m_timer.Elapsed -= OnTimer;
163 m_timer = null;
164 } 256 }
165 257
166
167 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data) 258 public static KeyframeMotion FromData(SceneObjectGroup grp, Byte[] data)
168 { 259 {
169 KeyframeMotion newMotion = null; 260 KeyframeMotion newMotion = null;
@@ -177,12 +268,15 @@ namespace OpenSim.Region.Framework.Scenes
177 268
178 newMotion.m_group = grp; 269 newMotion.m_group = grp;
179 270
180 if (grp != null && grp.IsSelected) 271 if (grp != null)
181 newMotion.m_selected = true; 272 {
273 newMotion.m_scene = grp.Scene;
274 if (grp.IsSelected)
275 newMotion.m_selected = true;
276 }
182 277
183 newMotion.m_onTimerLock = new object();
184 newMotion.m_timerStopped = false; 278 newMotion.m_timerStopped = false;
185 newMotion.m_inOnTimer = false; 279 newMotion.m_running = true;
186 newMotion.m_isCrossing = false; 280 newMotion.m_isCrossing = false;
187 newMotion.m_waitingCrossing = false; 281 newMotion.m_waitingCrossing = false;
188 } 282 }
@@ -196,37 +290,36 @@ namespace OpenSim.Region.Framework.Scenes
196 290
197 public void UpdateSceneObject(SceneObjectGroup grp) 291 public void UpdateSceneObject(SceneObjectGroup grp)
198 { 292 {
199// lock (m_onTimerLock) 293 m_isCrossing = false;
200 { 294 m_waitingCrossing = false;
201 m_isCrossing = false; 295 StopTimer();
202 m_waitingCrossing = false;
203 StopTimer();
204 296
205 if (grp == null) 297 if (grp == null)
206 return; 298 return;
207 299
208 m_group = grp; 300 m_group = grp;
209 Vector3 grppos = grp.AbsolutePosition; 301 m_scene = grp.Scene;
210 Vector3 offset = grppos - m_serializedPosition;
211 // avoid doing it more than once
212 // current this will happen draging a prim to other region
213 m_serializedPosition = grppos;
214 302
215 m_basePosition += offset; 303 Vector3 grppos = grp.AbsolutePosition;
216 m_currentFrame.Position += offset; 304 Vector3 offset = grppos - m_serializedPosition;
305 // avoid doing it more than once
306 // current this will happen draging a prim to other region
307 m_serializedPosition = grppos;
217 308
218 m_nextPosition += offset; 309 m_basePosition += offset;
310 m_currentFrame.Position += offset;
219 311
220 for (int i = 0; i < m_frames.Count; i++) 312 m_nextPosition += offset;
221 {
222 Keyframe k = m_frames[i];
223 k.Position += offset;
224 m_frames[i]=k;
225 }
226 313
227 if (m_running) 314 for (int i = 0; i < m_frames.Count; i++)
228 Start(); 315 {
316 Keyframe k = m_frames[i];
317 k.Position += offset;
318 m_frames[i]=k;
229 } 319 }
320
321 if (m_running)
322 Start();
230 } 323 }
231 324
232 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data) 325 public KeyframeMotion(SceneObjectGroup grp, PlayMode mode, DataFormat data)
@@ -239,11 +332,10 @@ namespace OpenSim.Region.Framework.Scenes
239 { 332 {
240 m_basePosition = grp.AbsolutePosition; 333 m_basePosition = grp.AbsolutePosition;
241 m_baseRotation = grp.GroupRotation; 334 m_baseRotation = grp.GroupRotation;
335 m_scene = grp.Scene;
242 } 336 }
243 337
244 m_onTimerLock = new object();
245 m_timerStopped = true; 338 m_timerStopped = true;
246 m_inOnTimer = false;
247 m_isCrossing = false; 339 m_isCrossing = false;
248 m_waitingCrossing = false; 340 m_waitingCrossing = false;
249 } 341 }
@@ -260,6 +352,7 @@ namespace OpenSim.Region.Framework.Scenes
260 KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data); 352 KeyframeMotion newmotion = new KeyframeMotion(null, m_mode, m_data);
261 353
262 newmotion.m_group = newgrp; 354 newmotion.m_group = newgrp;
355 newmotion.m_scene = newgrp.Scene;
263 356
264 if (m_keyframes != null) 357 if (m_keyframes != null)
265 { 358 {
@@ -296,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes
296 public void Delete() 389 public void Delete()
297 { 390 {
298 m_running = false; 391 m_running = false;
299 RemoveTimer(); 392 StopTimer();
300 m_isCrossing = false; 393 m_isCrossing = false;
301 m_waitingCrossing = false; 394 m_waitingCrossing = false;
302 m_frames.Clear(); 395 m_frames.Clear();
@@ -309,27 +402,13 @@ namespace OpenSim.Region.Framework.Scenes
309 m_waitingCrossing = false; 402 m_waitingCrossing = false;
310 if (m_keyframes != null && m_group != null && m_keyframes.Length > 0) 403 if (m_keyframes != null && m_group != null && m_keyframes.Length > 0)
311 { 404 {
312 if (m_timer == null)
313 {
314 m_timer = new Timer();
315 m_timer.Interval = timerInterval;
316 m_timer.AutoReset = true;
317 m_timer.Elapsed += OnTimer;
318 }
319 else
320 {
321 StopTimer();
322 m_timer.Interval = timerInterval;
323 }
324
325 m_inOnTimer = false;
326 StartTimer(); 405 StartTimer();
327 m_running = true; 406 m_running = true;
328 } 407 }
329 else 408 else
330 { 409 {
331 m_running = false; 410 m_running = false;
332 RemoveTimer(); 411 StopTimer();
333 } 412 }
334 } 413 }
335 414
@@ -339,7 +418,7 @@ namespace OpenSim.Region.Framework.Scenes
339 m_isCrossing = false; 418 m_isCrossing = false;
340 m_waitingCrossing = false; 419 m_waitingCrossing = false;
341 420
342 RemoveTimer(); 421 StopTimer();
343 422
344 m_basePosition = m_group.AbsolutePosition; 423 m_basePosition = m_group.AbsolutePosition;
345 m_baseRotation = m_group.GroupRotation; 424 m_baseRotation = m_group.GroupRotation;
@@ -354,7 +433,7 @@ namespace OpenSim.Region.Framework.Scenes
354 public void Pause() 433 public void Pause()
355 { 434 {
356 m_running = false; 435 m_running = false;
357 RemoveTimer(); 436 StopTimer();
358 437
359 m_group.RootPart.Velocity = Vector3.Zero; 438 m_group.RootPart.Velocity = Vector3.Zero;
360 m_group.RootPart.AngularVelocity = Vector3.Zero; 439 m_group.RootPart.AngularVelocity = Vector3.Zero;
@@ -377,15 +456,11 @@ namespace OpenSim.Region.Framework.Scenes
377 456
378 int start = 0; 457 int start = 0;
379 int end = m_keyframes.Length; 458 int end = m_keyframes.Length;
380// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
381// end = m_keyframes.Length - 1;
382 459
383 if (direction < 0) 460 if (direction < 0)
384 { 461 {
385 start = m_keyframes.Length - 1; 462 start = m_keyframes.Length - 1;
386 end = -1; 463 end = -1;
387// if (m_mode == PlayMode.PingPong && m_keyframes.Length > 1)
388// end = 0;
389 } 464 }
390 465
391 for (int i = start; i != end ; i += direction) 466 for (int i = start; i != end ; i += direction)
@@ -463,189 +538,172 @@ namespace OpenSim.Region.Framework.Scenes
463 } 538 }
464 } 539 }
465 540
466 protected void OnTimer(object sender, ElapsedEventArgs e) 541 public void OnTimer(double tickDuration)
467 { 542 {
468 if (m_timerStopped) // trap events still in air even after a timer.stop 543 if (m_skipLoops > 0)
469 return;
470
471 if (m_inOnTimer) // don't let overruns to happen
472 { 544 {
473 m_log.Warn("[KeyFrame]: timer overrun"); 545 m_skipLoops--;
474 return; 546 return;
475 } 547 }
476 548
549 if (m_timerStopped) // trap events still in air even after a timer.stop
550 return;
551
477 if (m_group == null) 552 if (m_group == null)
478 return; 553 return;
479 554
480 lock (m_onTimerLock) 555 bool update = false;
481 {
482 556
483 m_inOnTimer = true; 557 if (m_selected)
558 {
559 if (m_group.RootPart.Velocity != Vector3.Zero)
560 {
561 m_group.RootPart.Velocity = Vector3.Zero;
562 m_group.SendGroupRootTerseUpdate();
484 563
485 bool update = false; 564 }
565 return;
566 }
486 567
487 try 568 if (m_isCrossing)
569 {
570 // if crossing and timer running then cross failed
571 // wait some time then
572 // retry to set the position that evtually caused the outbound
573 // if still outside region this will call startCrossing below
574 m_isCrossing = false;
575 m_group.AbsolutePosition = m_nextPosition;
576 if (!m_isCrossing)
488 { 577 {
489 if (m_selected) 578 StopTimer();
490 { 579 StartTimer();
491 if (m_group.RootPart.Velocity != Vector3.Zero) 580 }
492 { 581 return;
493 m_group.RootPart.Velocity = Vector3.Zero; 582 }
494 m_group.SendGroupRootTerseUpdate();
495// m_group.RootPart.ScheduleTerseUpdate();
496 583
497 } 584 if (m_frames.Count == 0)
498 m_inOnTimer = false; 585 {
499 return; 586 GetNextList();
500 }
501 587
502 if (m_isCrossing) 588 if (m_frames.Count == 0)
503 { 589 {
504 // if crossing and timer running then cross failed 590 Stop();
505 // wait some time then 591 Scene scene = m_group.Scene;
506 // retry to set the position that evtually caused the outbound
507 // if still outside region this will call startCrossing below
508 m_isCrossing = false;
509 m_group.AbsolutePosition = m_nextPosition;
510 if (!m_isCrossing)
511 {
512 StopTimer();
513 m_timer.Interval = timerInterval;
514 StartTimer();
515 }
516 m_inOnTimer = false;
517 return;
518 }
519 592
520 if (m_frames.Count == 0) 593 IScriptModule[] scriptModules = scene.RequestModuleInterfaces<IScriptModule>();
594 foreach (IScriptModule m in scriptModules)
521 { 595 {
522 GetNextList(); 596 if (m == null)
597 continue;
598 m.PostObjectEvent(m_group.RootPart.UUID, "moving_end", new object[0]);
599 }
523 600
524 if (m_frames.Count == 0) 601 return;
525 { 602 }
526 Stop();
527 m_inOnTimer = false;
528 return;
529 }
530 603
531 m_currentFrame = m_frames[0]; 604 m_currentFrame = m_frames[0];
532 m_currentFrame.TimeMS += (int)timerInterval; 605 m_currentFrame.TimeMS += (int)tickDuration;
533 606
534 //force a update on a keyframe transition 607 //force a update on a keyframe transition
535 update = true; 608 update = true;
536 } 609 }
537 610
538 m_currentFrame.TimeMS -= (int)timerInterval; 611 m_currentFrame.TimeMS -= (int)tickDuration;
539 612
540 // Do the frame processing 613 // Do the frame processing
541 double steps = (double)m_currentFrame.TimeMS / timerInterval; 614 double steps = (double)m_currentFrame.TimeMS / tickDuration;
542 615
543 if (steps <= 0.0) 616 if (steps <= 0.0)
544 { 617 {
545 m_group.RootPart.Velocity = Vector3.Zero; 618 m_group.RootPart.Velocity = Vector3.Zero;
546 m_group.RootPart.AngularVelocity = Vector3.Zero; 619 m_group.RootPart.AngularVelocity = Vector3.Zero;
547 620
548 m_nextPosition = (Vector3)m_currentFrame.Position; 621 m_nextPosition = (Vector3)m_currentFrame.Position;
549 m_group.AbsolutePosition = m_nextPosition; 622 m_group.AbsolutePosition = m_nextPosition;
550 623
551 // we are sending imediate updates, no doing force a extra terseUpdate 624 // we are sending imediate updates, no doing force a extra terseUpdate
552// m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); 625 // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation);
553 626
554 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; 627 m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation;
555 m_frames.RemoveAt(0); 628 m_frames.RemoveAt(0);
556 if (m_frames.Count > 0) 629 if (m_frames.Count > 0)
557 m_currentFrame = m_frames[0]; 630 m_currentFrame = m_frames[0];
558 631
559 update = true; 632 update = true;
560 } 633 }
561 else 634 else
562 { 635 {
563 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; 636 float complete = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal;
564 637
565 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; 638 Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition;
566 Vector3 motionThisFrame = v / (float)steps; 639 Vector3 motionThisFrame = v / (float)steps;
567 v = v * 1000 / m_currentFrame.TimeMS; 640 v = v * 1000 / m_currentFrame.TimeMS;
568 641
569 if (Vector3.Mag(motionThisFrame) >= 0.05f) 642 if (Vector3.Mag(motionThisFrame) >= 0.05f)
570 { 643 {
571 // m_group.AbsolutePosition += motionThisFrame; 644 // m_group.AbsolutePosition += motionThisFrame;
572 m_nextPosition = m_group.AbsolutePosition + motionThisFrame; 645 m_nextPosition = m_group.AbsolutePosition + motionThisFrame;
573 m_group.AbsolutePosition = m_nextPosition; 646 m_group.AbsolutePosition = m_nextPosition;
574 647
575 m_group.RootPart.Velocity = v; 648 m_group.RootPart.Velocity = v;
576 update = true; 649 update = true;
577 } 650 }
578 651
579 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) 652 if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation)
580 { 653 {
581 Quaternion current = m_group.GroupRotation; 654 Quaternion current = m_group.GroupRotation;
582 655
583 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete); 656 Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, complete);
584 step.Normalize(); 657 step.Normalize();
585/* use simpler change detection 658/* use simpler change detection
586 * float angle = 0; 659* float angle = 0;
587
588 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
589 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
590 float aa_bb = aa * bb;
591
592 if (aa_bb == 0)
593 {
594 angle = 0;
595 }
596 else
597 {
598 float ab = current.X * step.X +
599 current.Y * step.Y +
600 current.Z * step.Z +
601 current.W * step.W;
602 float q = (ab * ab) / aa_bb;
603
604 if (q > 1.0f)
605 {
606 angle = 0;
607 }
608 else
609 {
610 angle = (float)Math.Acos(2 * q - 1);
611 }
612 }
613
614 if (angle > 0.01f)
615 */
616 if(Math.Abs(step.X - current.X) > 0.001f
617 || Math.Abs(step.Y - current.Y) > 0.001f
618 || Math.Abs(step.Z - current.Z) > 0.001f)
619 // assuming w is a dependente var
620 660
621 { 661 float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W;
622// m_group.UpdateGroupRotationR(step); 662 float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W;
623 m_group.RootPart.RotationOffset = step; 663 float aa_bb = aa * bb;
624 664
625 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); 665 if (aa_bb == 0)
626 update = true; 666 {
627 } 667 angle = 0;
668 }
669 else
670 {
671 float ab = current.X * step.X +
672 current.Y * step.Y +
673 current.Z * step.Z +
674 current.W * step.W;
675 float q = (ab * ab) / aa_bb;
676
677 if (q > 1.0f)
678 {
679 angle = 0;
680 }
681 else
682 {
683 angle = (float)Math.Acos(2 * q - 1);
628 } 684 }
629 } 685 }
630 686
631 if (update) 687 if (angle > 0.01f)
632 m_group.SendGroupRootTerseUpdate(); 688*/
633// m_group.RootPart.ScheduleTerseUpdate(); 689 if(Math.Abs(step.X - current.X) > 0.001f
690 || Math.Abs(step.Y - current.Y) > 0.001f
691 || Math.Abs(step.Z - current.Z) > 0.001f)
692 // assuming w is a dependente var
634 693
694 {
695// m_group.UpdateGroupRotationR(step);
696 m_group.RootPart.RotationOffset = step;
635 697
698 //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2);
699 update = true;
700 }
636 } 701 }
637 catch ( Exception ex) 702 }
638 {
639 // still happening sometimes
640 // lets try to see where
641 m_log.Warn("[KeyFrame]: timer overrun" + ex.Message);
642 }
643 703
644 finally 704 if (update)
645 { 705 {
646 // make sure we do not let this frozen 706 m_group.SendGroupRootTerseUpdate();
647 m_inOnTimer = false;
648 }
649 } 707 }
650 } 708 }
651 709
@@ -677,7 +735,7 @@ namespace OpenSim.Region.Framework.Scenes
677 m_isCrossing = true; 735 m_isCrossing = true;
678 m_waitingCrossing = true; 736 m_waitingCrossing = true;
679 737
680// to remove / retune to smoth crossings 738 // to remove / retune to smoth crossings
681 if (m_group.RootPart.Velocity != Vector3.Zero) 739 if (m_group.RootPart.Velocity != Vector3.Zero)
682 { 740 {
683 m_group.RootPart.Velocity = Vector3.Zero; 741 m_group.RootPart.Velocity = Vector3.Zero;
@@ -696,9 +754,10 @@ namespace OpenSim.Region.Framework.Scenes
696 m_group.SendGroupRootTerseUpdate(); 754 m_group.SendGroupRootTerseUpdate();
697// m_group.RootPart.ScheduleTerseUpdate(); 755// m_group.RootPart.ScheduleTerseUpdate();
698 756
699 if (m_running && m_timer != null) 757 if (m_running)
700 { 758 {
701 m_timer.Interval = 60000; 759 StopTimer();
760 m_skipLoops = 1200; // 60 seconds
702 StartTimer(); 761 StartTimer();
703 } 762 }
704 } 763 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index c9d1205..4130029 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -401,17 +401,17 @@ namespace OpenSim.Region.Framework.Scenes
401 if (item.Owner != remoteClient.AgentId) 401 if (item.Owner != remoteClient.AgentId)
402 return; 402 return;
403 403
404 if (UUID.Zero == transactionID) 404 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255);
405 { 405 item.Name = itemUpd.Name;
406 item.Flags = (item.Flags & ~(uint)255) | (itemUpd.Flags & (uint)255); 406 item.Description = itemUpd.Description;
407 item.Name = itemUpd.Name;
408 item.Description = itemUpd.Description;
409 407
410// m_log.DebugFormat( 408// m_log.DebugFormat(
411// "[USER INVENTORY]: itemUpd {0} {1} {2} {3}, item {4} {5} {6} {7}", 409// "[USER INVENTORY]: itemUpd {0} {1} {2} {3}, item {4} {5} {6} {7}",
412// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags, 410// itemUpd.NextPermissions, itemUpd.GroupPermissions, itemUpd.EveryOnePermissions, item.Flags,
413// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions); 411// item.NextPermissions, item.GroupPermissions, item.EveryOnePermissions, item.CurrentPermissions);
414 412
413 if (itemUpd.NextPermissions != 0) // Use this to determine validity. Can never be 0 if valid
414 {
415 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions)) 415 if (item.NextPermissions != (itemUpd.NextPermissions & item.BasePermissions))
416 item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner; 416 item.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner;
417 item.NextPermissions = itemUpd.NextPermissions & item.BasePermissions; 417 item.NextPermissions = itemUpd.NextPermissions & item.BasePermissions;
@@ -446,7 +446,8 @@ namespace OpenSim.Region.Framework.Scenes
446 446
447 InventoryService.UpdateItem(item); 447 InventoryService.UpdateItem(item);
448 } 448 }
449 else 449
450 if (UUID.Zero != transactionID)
450 { 451 {
451 if (AgentTransactionsModule != null) 452 if (AgentTransactionsModule != null)
452 { 453 {
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e3bc8c7..2e64819 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -2769,8 +2769,6 @@ namespace OpenSim.Region.Framework.Scenes
2769 2769
2770 if (newPosition != Vector3.Zero) 2770 if (newPosition != Vector3.Zero)
2771 newObject.RootPart.GroupPosition = newPosition; 2771 newObject.RootPart.GroupPosition = newPosition;
2772 if (newObject.RootPart.KeyframeMotion != null)
2773 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2774 2772
2775 if (!AddSceneObject(newObject)) 2773 if (!AddSceneObject(newObject))
2776 { 2774 {
@@ -2798,6 +2796,9 @@ namespace OpenSim.Region.Framework.Scenes
2798 // before we restart the scripts, or else some functions won't work. 2796 // before we restart the scripts, or else some functions won't work.
2799 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject)); 2797 newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, GetStateSource(newObject));
2800 newObject.ResumeScripts(); 2798 newObject.ResumeScripts();
2799
2800 if (newObject.RootPart.KeyframeMotion != null)
2801 newObject.RootPart.KeyframeMotion.UpdateSceneObject(newObject);
2801 } 2802 }
2802 2803
2803 // Do this as late as possible so that listeners have full access to the incoming object 2804 // Do this as late as possible so that listeners have full access to the incoming object
@@ -2865,7 +2866,7 @@ namespace OpenSim.Region.Framework.Scenes
2865 RootPrim.RemFlag(PrimFlags.TemporaryOnRez); 2866 RootPrim.RemFlag(PrimFlags.TemporaryOnRez);
2866 2867
2867 if (AttachmentsModule != null) 2868 if (AttachmentsModule != null)
2868 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false); 2869 AttachmentsModule.AttachObject(sp, grp, 0, false, false, false, true);
2869 } 2870 }
2870 else 2871 else
2871 { 2872 {
@@ -2970,6 +2971,13 @@ namespace OpenSim.Region.Framework.Scenes
2970 SubscribeToClientEvents(client); 2971 SubscribeToClientEvents(client);
2971 2972
2972 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); 2973 sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type);
2974 InventoryFolderBase cof = InventoryService.GetFolderForType(client.AgentId, (AssetType)46);
2975 if (cof == null)
2976 sp.COF = UUID.Zero;
2977 else
2978 sp.COF = cof.ID;
2979
2980 m_log.DebugFormat("[SCENE]: COF for {0} is {1}", client.AgentId, sp.COF);
2973 m_eventManager.TriggerOnNewPresence(sp); 2981 m_eventManager.TriggerOnNewPresence(sp);
2974 2982
2975 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; 2983 sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags;
@@ -3615,7 +3623,7 @@ namespace OpenSim.Region.Framework.Scenes
3615 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop 3623 // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop
3616 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI 3624 // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI
3617 if (closeChildAgents && CapsModule != null) 3625 if (closeChildAgents && CapsModule != null)
3618 CapsModule.RemoveCaps(agentID); 3626 CapsModule.RemoveCaps(agentID, avatar.ControllingClient.CircuitCode);
3619 3627
3620// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever 3628// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever
3621// // this method is doing is HORRIBLE!!! 3629// // this method is doing is HORRIBLE!!!
@@ -3846,20 +3854,36 @@ namespace OpenSim.Region.Framework.Scenes
3846 return false; 3854 return false;
3847 } 3855 }
3848 3856
3849
3850 ScenePresence sp = GetScenePresence(agent.AgentID); 3857 ScenePresence sp = GetScenePresence(agent.AgentID);
3851 3858
3852 if (sp != null && !sp.IsChildAgent) 3859 // If we have noo presence here or if that presence is a zombie root
3860 // presence that will be kicled, we need a new CAPS object.
3861 if (sp == null || (sp != null && !sp.IsChildAgent))
3853 { 3862 {
3854 // We have a zombie from a crashed session. 3863 if (CapsModule != null)
3855 // Or the same user is trying to be root twice here, won't work. 3864 {
3856 // Kill it. 3865 lock (agent)
3857 m_log.WarnFormat( 3866 {
3858 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", 3867 CapsModule.SetAgentCapsSeeds(agent);
3859 sp.Name, sp.UUID, RegionInfo.RegionName); 3868 CapsModule.CreateCaps(agent.AgentID, agent.circuitcode);
3869 }
3870 }
3871 }
3860 3872
3861 sp.ControllingClient.Close(true, true); 3873 if (sp != null)
3862 sp = null; 3874 {
3875 if (!sp.IsChildAgent)
3876 {
3877 // We have a zombie from a crashed session.
3878 // Or the same user is trying to be root twice here, won't work.
3879 // Kill it.
3880 m_log.WarnFormat(
3881 "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.",
3882 sp.Name, sp.UUID, RegionInfo.RegionName);
3883
3884 sp.ControllingClient.Close(true, true);
3885 sp = null;
3886 }
3863 } 3887 }
3864 3888
3865 lock (agent) 3889 lock (agent)
@@ -3900,7 +3924,9 @@ namespace OpenSim.Region.Framework.Scenes
3900 if (vialogin || (!m_seeIntoBannedRegion)) 3924 if (vialogin || (!m_seeIntoBannedRegion))
3901 { 3925 {
3902 if (!AuthorizeUser(agent, out reason)) 3926 if (!AuthorizeUser(agent, out reason))
3927 {
3903 return false; 3928 return false;
3929 }
3904 } 3930 }
3905 } 3931 }
3906 catch (Exception e) 3932 catch (Exception e)
@@ -3915,11 +3941,6 @@ namespace OpenSim.Region.Framework.Scenes
3915 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, 3941 RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname,
3916 agent.AgentID, agent.circuitcode); 3942 agent.AgentID, agent.circuitcode);
3917 3943
3918 if (CapsModule != null)
3919 {
3920 CapsModule.SetAgentCapsSeeds(agent);
3921 CapsModule.CreateCaps(agent.AgentID);
3922 }
3923 } 3944 }
3924 else 3945 else
3925 { 3946 {
@@ -3945,6 +3966,11 @@ namespace OpenSim.Region.Framework.Scenes
3945 agent.teleportFlags = teleportFlags; 3966 agent.teleportFlags = teleportFlags;
3946 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); 3967 m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent);
3947 3968
3969 if (CapsModule != null)
3970 {
3971 CapsModule.ActivateCaps(agent.circuitcode);
3972 }
3973
3948 if (vialogin) 3974 if (vialogin)
3949 { 3975 {
3950// CleanDroppedAttachments(); 3976// CleanDroppedAttachments();
@@ -5122,7 +5148,7 @@ namespace OpenSim.Region.Framework.Scenes
5122 { 5148 {
5123 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0) 5149 if ((grp.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)
5124 { 5150 {
5125 if (grp.RootPart.Expires <= DateTime.Now) 5151 if (grp.GetSittingAvatarsCount() == 0 && grp.RootPart.Expires <= DateTime.Now)
5126 DeleteSceneObject(grp, false); 5152 DeleteSceneObject(grp, false);
5127 } 5153 }
5128 } 5154 }
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 8528edc..20a6626 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -1689,6 +1689,10 @@ namespace OpenSim.Region.Framework.Scenes
1689 1689
1690 if (ParentGroup != null) 1690 if (ParentGroup != null)
1691 ParentGroup.HasGroupChanged = true; 1691 ParentGroup.HasGroupChanged = true;
1692
1693 PhysicsActor pa = PhysActor;
1694 if (pa != null)
1695 pa.Density = Density;
1692 } 1696 }
1693 } 1697 }
1694 1698
@@ -1708,6 +1712,9 @@ namespace OpenSim.Region.Framework.Scenes
1708 if (ParentGroup != null) 1712 if (ParentGroup != null)
1709 ParentGroup.HasGroupChanged = true; 1713 ParentGroup.HasGroupChanged = true;
1710 1714
1715 PhysicsActor pa = PhysActor;
1716 if (pa != null)
1717 pa.GravModifier = GravityModifier;
1711 } 1718 }
1712 } 1719 }
1713 1720
@@ -1726,10 +1733,14 @@ namespace OpenSim.Region.Framework.Scenes
1726 1733
1727 if (ParentGroup != null) 1734 if (ParentGroup != null)
1728 ParentGroup.HasGroupChanged = true; 1735 ParentGroup.HasGroupChanged = true;
1736
1737 PhysicsActor pa = PhysActor;
1738 if (pa != null)
1739 pa.Friction = Friction;
1729 } 1740 }
1730 } 1741 }
1731 1742
1732 public float Bounciness 1743 public float Restitution
1733 { 1744 {
1734 get { return m_bounce; } 1745 get { return m_bounce; }
1735 set 1746 set
@@ -1744,6 +1755,10 @@ namespace OpenSim.Region.Framework.Scenes
1744 1755
1745 if (ParentGroup != null) 1756 if (ParentGroup != null)
1746 ParentGroup.HasGroupChanged = true; 1757 ParentGroup.HasGroupChanged = true;
1758
1759 PhysicsActor pa = PhysActor;
1760 if (pa != null)
1761 pa.Restitution = Restitution;
1747 } 1762 }
1748 } 1763 }
1749 1764
@@ -4493,8 +4508,8 @@ namespace OpenSim.Region.Framework.Scenes
4493 GravityModifier = physdata.GravitationModifier; 4508 GravityModifier = physdata.GravitationModifier;
4494 if(Friction != physdata.Friction) 4509 if(Friction != physdata.Friction)
4495 Friction = physdata.Friction; 4510 Friction = physdata.Friction;
4496 if(Bounciness != physdata.Bounce) 4511 if(Restitution != physdata.Bounce)
4497 Bounciness = physdata.Bounce; 4512 Restitution = physdata.Bounce;
4498 } 4513 }
4499 /// <summary> 4514 /// <summary>
4500 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary. 4515 /// Update the flags on this prim. This covers properties such as phantom, physics and temporary.
@@ -4657,6 +4672,11 @@ namespace OpenSim.Region.Framework.Scenes
4657 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info 4672 pa.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
4658 pa.SetMaterial(Material); 4673 pa.SetMaterial(Material);
4659 4674
4675 pa.Density = Density;
4676 pa.GravModifier = GravityModifier;
4677 pa.Friction = Friction;
4678 pa.Restitution = Restitution;
4679
4660 if (VolumeDetectActive) // change if not the default only 4680 if (VolumeDetectActive) // change if not the default only
4661 pa.SetVolumeDetect(1); 4681 pa.SetVolumeDetect(1);
4662 4682
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a9195f7..230cb23 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -204,6 +204,11 @@ namespace OpenSim.Region.Framework.Scenes
204 204
205 private const int LAND_VELOCITYMAG_MAX = 12; 205 private const int LAND_VELOCITYMAG_MAX = 12;
206 206
207 private const float FLY_ROLL_MAX_RADIANS = 1.1f;
208
209 private const float FLY_ROLL_RADIANS_PER_UPDATE = 0.06f;
210 private const float FLY_ROLL_RESET_RADIANS_PER_UPDATE = 0.02f;
211
207 private float m_health = 100f; 212 private float m_health = 100f;
208 213
209 protected ulong crossingFromRegion; 214 protected ulong crossingFromRegion;
@@ -438,6 +443,8 @@ namespace OpenSim.Region.Framework.Scenes
438 get { return (IClientCore)ControllingClient; } 443 get { return (IClientCore)ControllingClient; }
439 } 444 }
440 445
446 public UUID COF { get; set; }
447
441// public Vector3 ParentPosition { get; set; } 448// public Vector3 ParentPosition { get; set; }
442 449
443 /// <summary> 450 /// <summary>
@@ -606,6 +613,14 @@ namespace OpenSim.Region.Framework.Scenes
606 } 613 }
607 } 614 }
608 615
616 // Used for limited viewer 'fake' user rotations.
617 private Vector3 m_AngularVelocity = Vector3.Zero;
618
619 public Vector3 AngularVelocity
620 {
621 get { return m_AngularVelocity; }
622 }
623
609 public bool IsChildAgent { get; set; } 624 public bool IsChildAgent { get; set; }
610 public bool IsLoggingIn { get; set; } 625 public bool IsLoggingIn { get; set; }
611 626
@@ -736,6 +751,8 @@ namespace OpenSim.Region.Framework.Scenes
736 751
737 #endregion 752 #endregion
738 753
754
755
739 #region Constructor(s) 756 #region Constructor(s)
740 757
741 public ScenePresence( 758 public ScenePresence(
@@ -1225,6 +1242,85 @@ namespace OpenSim.Region.Framework.Scenes
1225 ControllingClient.StopFlying(this); 1242 ControllingClient.StopFlying(this);
1226 } 1243 }
1227 1244
1245 /// <summary>
1246 /// Applies a roll accumulator to the avatar's angular velocity for the avatar fly roll effect.
1247 /// </summary>
1248 /// <param name="amount">Postive or negative roll amount in radians</param>
1249 private void ApplyFlyingRoll(float amount, bool PressingUp, bool PressingDown)
1250 {
1251
1252 float rollAmount = Util.Clamp(m_AngularVelocity.Z + amount, -FLY_ROLL_MAX_RADIANS, FLY_ROLL_MAX_RADIANS);
1253 m_AngularVelocity.Z = rollAmount;
1254
1255 // APPLY EXTRA consideration for flying up and flying down during this time.
1256 // if we're turning left
1257 if (amount > 0)
1258 {
1259
1260 // If we're at the max roll and pressing up, we want to swing BACK a bit
1261 // Automatically adds noise
1262 if (PressingUp)
1263 {
1264 if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS - 0.04f)
1265 m_AngularVelocity.Z -= 0.9f;
1266 }
1267 // If we're at the max roll and pressing down, we want to swing MORE a bit
1268 if (PressingDown)
1269 {
1270 if (m_AngularVelocity.Z >= FLY_ROLL_MAX_RADIANS && m_AngularVelocity.Z < FLY_ROLL_MAX_RADIANS + 0.6f)
1271 m_AngularVelocity.Z += 0.6f;
1272 }
1273 }
1274 else // we're turning right.
1275 {
1276 // If we're at the max roll and pressing up, we want to swing BACK a bit
1277 // Automatically adds noise
1278 if (PressingUp)
1279 {
1280 if (m_AngularVelocity.Z <= (-FLY_ROLL_MAX_RADIANS))
1281 m_AngularVelocity.Z += 0.6f;
1282 }
1283 // If we're at the max roll and pressing down, we want to swing MORE a bit
1284 if (PressingDown)
1285 {
1286 if (m_AngularVelocity.Z >= -FLY_ROLL_MAX_RADIANS - 0.6f)
1287 m_AngularVelocity.Z -= 0.6f;
1288 }
1289 }
1290 }
1291
1292 /// <summary>
1293 /// incrementally sets roll amount to zero
1294 /// </summary>
1295 /// <param name="amount">Positive roll amount in radians</param>
1296 /// <returns></returns>
1297 private float CalculateFlyingRollResetToZero(float amount)
1298 {
1299 const float rollMinRadians = 0f;
1300
1301 if (m_AngularVelocity.Z > 0)
1302 {
1303
1304 float leftOverToMin = m_AngularVelocity.Z - rollMinRadians;
1305 if (amount > leftOverToMin)
1306 return -leftOverToMin;
1307 else
1308 return -amount;
1309
1310 }
1311 else
1312 {
1313
1314 float leftOverToMin = -m_AngularVelocity.Z - rollMinRadians;
1315 if (amount > leftOverToMin)
1316 return leftOverToMin;
1317 else
1318 return amount;
1319 }
1320 }
1321
1322
1323
1228 // neighbouring regions we have enabled a child agent in 1324 // neighbouring regions we have enabled a child agent in
1229 // holds the seed cap for the child agent in that region 1325 // holds the seed cap for the child agent in that region
1230 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>(); 1326 private Dictionary<ulong, string> m_knownChildRegions = new Dictionary<ulong, string>();
@@ -1430,17 +1526,42 @@ namespace OpenSim.Region.Framework.Scenes
1430 m_doingCamRayCast = false; 1526 m_doingCamRayCast = false;
1431 if (hitYN && localid != LocalId) 1527 if (hitYN && localid != LocalId)
1432 { 1528 {
1433 CameraConstraintActive = true; 1529 SceneObjectGroup group = m_scene.GetGroupByPrim(localid);
1434 pNormal.X = (float)Math.Round(pNormal.X, 2); 1530 bool IsPrim = group != null;
1435 pNormal.Y = (float)Math.Round(pNormal.Y, 2); 1531 if (IsPrim)
1436 pNormal.Z = (float)Math.Round(pNormal.Z, 2); 1532 {
1437 pNormal.Normalize(); 1533 SceneObjectPart part = group.GetPart(localid);
1438 collisionPoint.X = (float)Math.Round(collisionPoint.X, 1); 1534 if (part != null && !part.VolumeDetectActive)
1439 collisionPoint.Y = (float)Math.Round(collisionPoint.Y, 1); 1535 {
1440 collisionPoint.Z = (float)Math.Round(collisionPoint.Z, 1); 1536 CameraConstraintActive = true;
1441 1537 pNormal.X = (float) Math.Round(pNormal.X, 2);
1442 Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z, Vector3.Dot(collisionPoint, pNormal)); 1538 pNormal.Y = (float) Math.Round(pNormal.Y, 2);
1443 UpdateCameraCollisionPlane(plane); 1539 pNormal.Z = (float) Math.Round(pNormal.Z, 2);
1540 pNormal.Normalize();
1541 collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
1542 collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
1543 collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
1544
1545 Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
1546 Vector3.Dot(collisionPoint, pNormal));
1547 UpdateCameraCollisionPlane(plane);
1548 }
1549 }
1550 else
1551 {
1552 CameraConstraintActive = true;
1553 pNormal.X = (float) Math.Round(pNormal.X, 2);
1554 pNormal.Y = (float) Math.Round(pNormal.Y, 2);
1555 pNormal.Z = (float) Math.Round(pNormal.Z, 2);
1556 pNormal.Normalize();
1557 collisionPoint.X = (float) Math.Round(collisionPoint.X, 1);
1558 collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1);
1559 collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1);
1560
1561 Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z,
1562 Vector3.Dot(collisionPoint, pNormal));
1563 UpdateCameraCollisionPlane(plane);
1564 }
1444 } 1565 }
1445 else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || 1566 else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
1446 !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) 1567 !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
@@ -1741,6 +1862,33 @@ namespace OpenSim.Region.Framework.Scenes
1741 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || 1862 bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
1742 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)); 1863 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
1743 1864
1865
1866 //m_log.Debug("[CONTROL]: " +flags);
1867 // Applies a satisfying roll effect to the avatar when flying.
1868 if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) != 0) && ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0))
1869 {
1870
1871 ApplyFlyingRoll(FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0));
1872
1873
1874 }
1875 else if (((flags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_RIGHT) != 0) &&
1876 ((flags & AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0))
1877 {
1878 ApplyFlyingRoll(-FLY_ROLL_RADIANS_PER_UPDATE, ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0), ((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0));
1879
1880
1881 }
1882 else
1883 {
1884 if (m_AngularVelocity.Z != 0)
1885 m_AngularVelocity.Z += CalculateFlyingRollResetToZero(FLY_ROLL_RESET_RADIANS_PER_UPDATE);
1886
1887 }
1888
1889
1890
1891
1744 if (Flying && IsColliding && controlland) 1892 if (Flying && IsColliding && controlland)
1745 { 1893 {
1746 // nesting this check because LengthSquared() is expensive and we don't 1894 // nesting this check because LengthSquared() is expensive and we don't
diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
index 123c158..2984782 100644
--- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
+++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs
@@ -633,7 +633,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
633 633
634 private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader) 634 private static void ProcessBounce(SceneObjectPart obj, XmlTextReader reader)
635 { 635 {
636 obj.Bounciness = reader.ReadElementContentAsFloat("Bounce", String.Empty); 636 obj.Restitution = reader.ReadElementContentAsFloat("Bounce", String.Empty);
637 } 637 }
638 638
639 private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader) 639 private static void ProcessGravityModifier(SceneObjectPart obj, XmlTextReader reader)
@@ -1363,8 +1363,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
1363 writer.WriteElementString("Density", sop.Density.ToString().ToLower()); 1363 writer.WriteElementString("Density", sop.Density.ToString().ToLower());
1364 if (sop.Friction != 0.6f) 1364 if (sop.Friction != 0.6f)
1365 writer.WriteElementString("Friction", sop.Friction.ToString().ToLower()); 1365 writer.WriteElementString("Friction", sop.Friction.ToString().ToLower());
1366 if (sop.Bounciness != 0.5f) 1366 if (sop.Restitution != 0.5f)
1367 writer.WriteElementString("Bounce", sop.Bounciness.ToString().ToLower()); 1367 writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower());
1368 if (sop.GravityModifier != 1.0f) 1368 if (sop.GravityModifier != 1.0f)
1369 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); 1369 writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower());
1370 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); 1370 WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset());
diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
index 17971e3..0b28edd 100644
--- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
+++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs
@@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); 183 hostPart.ParentGroup.RootPart.ScheduleFullUpdate();
184 } 184 }
185 185
186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0; 186 return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true, true) ? 1 : 0;
187 } 187 }
188 } 188 }
189} 189}
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 9338130..dcb2c91 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -274,7 +274,7 @@ namespace OpenSim.Region.Physics.Manager
274 public virtual float Density { get; set; } 274 public virtual float Density { get; set; }
275 public virtual float GravModifier { get; set; } 275 public virtual float GravModifier { get; set; }
276 public virtual float Friction { get; set; } 276 public virtual float Friction { get; set; }
277 public virtual float Bounce { get; set; } 277 public virtual float Restitution { get; set; }
278 278
279 /// <summary> 279 /// <summary>
280 /// Position of this actor. 280 /// Position of this actor.
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
index f7e4c1c..bea34d4 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODECharacter.cs
@@ -1014,8 +1014,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1014 offset.Y += contact.pos.Y; 1014 offset.Y += contact.pos.Y;
1015 offset.Z += contact.pos.Z; 1015 offset.Z += contact.pos.Z;
1016 1016
1017 _position = offset; 1017 //_position = offset;
1018 return false; 1018 //return false;
1019 } 1019 }
1020 1020
1021 offset.X = contact.pos.X - _position.X; 1021 offset.X = contact.pos.X - _position.X;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 53c6e5c..7be64eb 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -3332,7 +3332,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3332 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3332 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3333 3333
3334 if (attachmentsModule != null) 3334 if (attachmentsModule != null)
3335 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false); 3335 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, false, true);
3336 else 3336 else
3337 return false; 3337 return false;
3338 } 3338 }
@@ -4724,7 +4724,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4724 UUID av = new UUID(); 4724 UUID av = new UUID();
4725 if (!UUID.TryParse(agent,out av)) 4725 if (!UUID.TryParse(agent,out av))
4726 { 4726 {
4727 //LSLError("First parameter to llDialog needs to be a key");
4728 return; 4727 return;
4729 } 4728 }
4730 4729
@@ -7222,20 +7221,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7222 } 7221 }
7223 if (buttons.Length > 12) 7222 if (buttons.Length > 12)
7224 { 7223 {
7225 LSLError("No more than 12 buttons can be shown"); 7224 ShoutError("button list too long, must be 12 or fewer entries");
7226 return;
7227 } 7225 }
7228 string[] buts = new string[buttons.Length]; 7226 int length = buttons.Length;
7229 for (int i = 0; i < buttons.Length; i++) 7227 if (length > 12)
7228 length = 12;
7229
7230 string[] buts = new string[length];
7231 for (int i = 0; i < length; i++)
7230 { 7232 {
7231 if (buttons.Data[i].ToString() == String.Empty) 7233 if (buttons.Data[i].ToString() == String.Empty)
7232 { 7234 {
7233 LSLError("button label cannot be blank"); 7235 ShoutError("button label cannot be blank");
7234 return; 7236 return;
7235 } 7237 }
7236 if (buttons.Data[i].ToString().Length > 24) 7238 if (buttons.Data[i].ToString().Length > 24)
7237 { 7239 {
7238 llWhisper(ScriptBaseClass.DEBUG_CHANNEL, "button label cannot be longer than 24 characters"); 7240 ShoutError("button label cannot be longer than 24 characters");
7239 return; 7241 return;
7240 } 7242 }
7241 buts[i] = buttons.Data[i].ToString(); 7243 buts[i] = buttons.Data[i].ToString();
@@ -7843,7 +7845,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7843 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType; 7845 physdata.PhysShapeType = (PhysShapeType)part.PhysicsShapeType;
7844 physdata.Density = part.Density; 7846 physdata.Density = part.Density;
7845 physdata.Friction = part.Friction; 7847 physdata.Friction = part.Friction;
7846 physdata.Bounce = part.Bounciness; 7848 physdata.Bounce = part.Restitution;
7847 physdata.GravitationModifier = part.GravityModifier; 7849 physdata.GravitationModifier = part.GravityModifier;
7848 7850
7849 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0) 7851 if ((material_bits & (int)ScriptBaseClass.DENSITY) != 0)
@@ -8236,7 +8238,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8236 8238
8237 ExtraPhysicsData physdata = new ExtraPhysicsData(); 8239 ExtraPhysicsData physdata = new ExtraPhysicsData();
8238 physdata.Density = part.Density; 8240 physdata.Density = part.Density;
8239 physdata.Bounce = part.Bounciness; 8241 physdata.Bounce = part.Restitution;
8240 physdata.GravitationModifier = part.GravityModifier; 8242 physdata.GravitationModifier = part.GravityModifier;
8241 physdata.PhysShapeType = (PhysShapeType)shape_type; 8243 physdata.PhysShapeType = (PhysShapeType)shape_type;
8242 8244
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 8f34833..ee89f9d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -123,7 +123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
123 public void modInvokeN(string fname, params object[] parms) 123 public void modInvokeN(string fname, params object[] parms)
124 { 124 {
125 Type returntype = m_comms.LookupReturnType(fname); 125 Type returntype = m_comms.LookupReturnType(fname);
126 if (returntype != typeof(string)) 126 if (returntype != typeof(void))
127 MODError(String.Format("return type mismatch for {0}",fname)); 127 MODError(String.Format("return type mismatch for {0}",fname));
128 128
129 modInvoke(fname,parms); 129 modInvoke(fname,parms);
@@ -264,6 +264,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
264 if (result != null) 264 if (result != null)
265 return result; 265 return result;
266 266
267 Type returntype = m_comms.LookupReturnType(fname);
268 if (returntype == typeof(void))
269 return null;
270
267 MODError(String.Format("Invocation of {0} failed; null return value",fname)); 271 MODError(String.Format("Invocation of {0} failed; null return value",fname));
268 } 272 }
269 catch (Exception e) 273 catch (Exception e)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7c2f8ed..8aac33f 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1619,7 +1619,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1619 } 1619 }
1620 } 1620 }
1621 1621
1622 public Object osParseJSONNew(string JSON) 1622 private Object osParseJSONNew(string JSON)
1623 { 1623 {
1624 CheckThreatLevel(ThreatLevel.None, "osParseJSONNew"); 1624 CheckThreatLevel(ThreatLevel.None, "osParseJSONNew");
1625 1625
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index c447d1f..8aa1249 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -259,7 +259,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
259 259
260 string osGetScriptEngineName(); 260 string osGetScriptEngineName();
261 string osGetSimulatorVersion(); 261 string osGetSimulatorVersion();
262 Object osParseJSONNew(string JSON);
263 Hashtable osParseJSON(string JSON); 262 Hashtable osParseJSON(string JSON);
264 263
265 void osMessageObject(key objectUUID,string message); 264 void osMessageObject(key objectUUID,string message);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index afa9ae0..95dff18 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -430,11 +430,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
430 return m_OSSL_Functions.osParseJSON(JSON); 430 return m_OSSL_Functions.osParseJSON(JSON);
431 } 431 }
432 432
433 public Object osParseJSONNew(string JSON)
434 {
435 return m_OSSL_Functions.osParseJSONNew(JSON);
436 }
437
438 public void osMessageObject(key objectUUID,string message) 433 public void osMessageObject(key objectUUID,string message)
439 { 434 {
440 m_OSSL_Functions.osMessageObject(objectUUID,message); 435 m_OSSL_Functions.osMessageObject(objectUUID,message);
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index c9c4753..c6393ed 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -512,7 +512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared
512 else if (o is LSL_Types.LSLFloat) 512 else if (o is LSL_Types.LSLFloat)
513 size += 8; 513 size += 8;
514 else if (o is LSL_Types.LSLString) 514 else if (o is LSL_Types.LSLString)
515 size += ((LSL_Types.LSLString)o).m_string.Length; 515 size += ((LSL_Types.LSLString)o).m_string == null ? 0 : ((LSL_Types.LSLString)o).m_string.Length;
516 else if (o is LSL_Types.key) 516 else if (o is LSL_Types.key)
517 size += ((LSL_Types.key)o).value.Length; 517 size += ((LSL_Types.key)o).value.Length;
518 else if (o is LSL_Types.Vector3) 518 else if (o is LSL_Types.Vector3)
diff --git a/OpenSim/Services/Interfaces/IAvatarService.cs b/OpenSim/Services/Interfaces/IAvatarService.cs
index c0130f1..3663a7a 100644
--- a/OpenSim/Services/Interfaces/IAvatarService.cs
+++ b/OpenSim/Services/Interfaces/IAvatarService.cs
@@ -180,11 +180,18 @@ namespace OpenSim.Services.Interfaces
180 180
181 // Attachments 181 // Attachments
182 List<AvatarAttachment> attachments = appearance.GetAttachments(); 182 List<AvatarAttachment> attachments = appearance.GetAttachments();
183 Dictionary<int, List<string>> atts = new Dictionary<int, List<string>>();
183 foreach (AvatarAttachment attach in attachments) 184 foreach (AvatarAttachment attach in attachments)
184 { 185 {
185 if (attach.ItemID != UUID.Zero) 186 if (attach.ItemID != UUID.Zero)
186 Data["_ap_" + attach.AttachPoint] = attach.ItemID.ToString(); 187 {
188 if (!atts.ContainsKey(attach.AttachPoint))
189 atts[attach.AttachPoint] = new List<string>();
190 atts[attach.AttachPoint].Add(attach.ItemID.ToString());
191 }
187 } 192 }
193 foreach (KeyValuePair<int, List<string>> kvp in atts)
194 Data["_ap_" + kvp.Key] = string.Join(",", kvp.Value.ToArray());
188 } 195 }
189 196
190 public AvatarAppearance ToAvatarAppearance() 197 public AvatarAppearance ToAvatarAppearance()
@@ -320,10 +327,16 @@ namespace OpenSim.Services.Interfaces
320 if (!Int32.TryParse(pointStr, out point)) 327 if (!Int32.TryParse(pointStr, out point))
321 continue; 328 continue;
322 329
323 UUID uuid = UUID.Zero; 330 List<string> idList = new List<string>(_kvp.Value.Split(new char[] {','}));
324 UUID.TryParse(_kvp.Value, out uuid);
325 331
326 appearance.SetAttachment(point, uuid, UUID.Zero); 332 appearance.SetAttachment(point, UUID.Zero, UUID.Zero);
333 foreach (string id in idList)
334 {
335 UUID uuid = UUID.Zero;
336 UUID.TryParse(id, out uuid);
337
338 appearance.SetAttachment(point | 0x80, uuid, UUID.Zero);
339 }
327 } 340 }
328 341
329 if (appearance.Wearables[AvatarWearable.BODY].Count == 0) 342 if (appearance.Wearables[AvatarWearable.BODY].Count == 0)