aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/Shared/Api/Implementation
diff options
context:
space:
mode:
authorDavid Walter Seikel2016-11-03 21:44:39 +1000
committerDavid Walter Seikel2016-11-03 21:44:39 +1000
commit134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch)
tree216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/ScriptEngine/Shared/Api/Implementation
parentMore changing to production grid. Double oops. (diff)
downloadopensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2
opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation')
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs329
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs5807
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs431
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs79
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs488
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs18
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs4
7 files changed, 5758 insertions, 1398 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
index 47a9cdc..036cb5d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs
@@ -28,7 +28,9 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Reflection;
31using System.Threading; 32using System.Threading;
33using log4net;
32using OpenMetaverse; 34using OpenMetaverse;
33using OpenSim.Framework; 35using OpenSim.Framework;
34using OpenSim.Framework.Monitoring; 36using OpenSim.Framework.Monitoring;
@@ -45,15 +47,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
45 /// </summary> 47 /// </summary>
46 public class AsyncCommandManager 48 public class AsyncCommandManager
47 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51
48 private static Thread cmdHandlerThread; 52 private static Thread cmdHandlerThread;
49 private static int cmdHandlerThreadCycleSleepms; 53 private static int cmdHandlerThreadCycleSleepms;
50 54
51 private static List<IScene> m_Scenes = new List<IScene>(); 55 /// <summary>
56 /// Lock for reading/writing static components of AsyncCommandManager.
57 /// </summary>
58 /// <remarks>
59 /// This lock exists so that multiple threads from different engines and/or different copies of the same engine
60 /// are prevented from running non-thread safe code (e.g. read/write of lists) concurrently.
61 /// </remarks>
62 private static object staticLock = new object();
63
52 private static List<IScriptEngine> m_ScriptEngines = 64 private static List<IScriptEngine> m_ScriptEngines =
53 new List<IScriptEngine>(); 65 new List<IScriptEngine>();
54 66
55 public IScriptEngine m_ScriptEngine; 67 public IScriptEngine m_ScriptEngine;
56 private IScene m_Scene;
57 68
58 private static Dictionary<IScriptEngine, Dataserver> m_Dataserver = 69 private static Dictionary<IScriptEngine, Dataserver> m_Dataserver =
59 new Dictionary<IScriptEngine, Dataserver>(); 70 new Dictionary<IScriptEngine, Dataserver>();
@@ -70,67 +81,99 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
70 81
71 public Dataserver DataserverPlugin 82 public Dataserver DataserverPlugin
72 { 83 {
73 get { return m_Dataserver[m_ScriptEngine]; } 84 get
85 {
86 lock (staticLock)
87 return m_Dataserver[m_ScriptEngine];
88 }
74 } 89 }
75 90
76 public Timer TimerPlugin 91 public Timer TimerPlugin
77 { 92 {
78 get { return m_Timer[m_ScriptEngine]; } 93 get
94 {
95 lock (staticLock)
96 return m_Timer[m_ScriptEngine];
97 }
79 } 98 }
80 99
81 public HttpRequest HttpRequestPlugin 100 public HttpRequest HttpRequestPlugin
82 { 101 {
83 get { return m_HttpRequest[m_ScriptEngine]; } 102 get
103 {
104 lock (staticLock)
105 return m_HttpRequest[m_ScriptEngine];
106 }
84 } 107 }
85 108
86 public Listener ListenerPlugin 109 public Listener ListenerPlugin
87 { 110 {
88 get { return m_Listener[m_ScriptEngine]; } 111 get
112 {
113 lock (staticLock)
114 return m_Listener[m_ScriptEngine];
115 }
89 } 116 }
90 117
91 public SensorRepeat SensorRepeatPlugin 118 public SensorRepeat SensorRepeatPlugin
92 { 119 {
93 get { return m_SensorRepeat[m_ScriptEngine]; } 120 get
121 {
122 lock (staticLock)
123 return m_SensorRepeat[m_ScriptEngine];
124 }
94 } 125 }
95 126
96 public XmlRequest XmlRequestPlugin 127 public XmlRequest XmlRequestPlugin
97 { 128 {
98 get { return m_XmlRequest[m_ScriptEngine]; } 129 get
130 {
131 lock (staticLock)
132 return m_XmlRequest[m_ScriptEngine];
133 }
99 } 134 }
100 135
101 public IScriptEngine[] ScriptEngines 136 public IScriptEngine[] ScriptEngines
102 { 137 {
103 get { return m_ScriptEngines.ToArray(); } 138 get
139 {
140 lock (staticLock)
141 return m_ScriptEngines.ToArray();
142 }
104 } 143 }
105 144
106 public AsyncCommandManager(IScriptEngine _ScriptEngine) 145 public AsyncCommandManager(IScriptEngine _ScriptEngine)
107 { 146 {
108 m_ScriptEngine = _ScriptEngine; 147 m_ScriptEngine = _ScriptEngine;
109 m_Scene = m_ScriptEngine.World; 148
110 149 // If there is more than one scene in the simulator or multiple script engines are used on the same region
111 if (m_Scenes.Count == 0) 150 // then more than one thread could arrive at this block of code simultaneously. However, it cannot be
112 ReadConfig(); 151 // executed concurrently both because concurrent list operations are not thread-safe and because of other
113 152 // race conditions such as the later check of cmdHandlerThread == null.
114 if (!m_Scenes.Contains(m_Scene)) 153 lock (staticLock)
115 m_Scenes.Add(m_Scene); 154 {
116 if (!m_ScriptEngines.Contains(m_ScriptEngine)) 155 if (m_ScriptEngines.Count == 0)
117 m_ScriptEngines.Add(m_ScriptEngine); 156 ReadConfig();
118 157
119 // Create instances of all plugins 158 if (!m_ScriptEngines.Contains(m_ScriptEngine))
120 if (!m_Dataserver.ContainsKey(m_ScriptEngine)) 159 m_ScriptEngines.Add(m_ScriptEngine);
121 m_Dataserver[m_ScriptEngine] = new Dataserver(this); 160
122 if (!m_Timer.ContainsKey(m_ScriptEngine)) 161 // Create instances of all plugins
123 m_Timer[m_ScriptEngine] = new Timer(this); 162 if (!m_Dataserver.ContainsKey(m_ScriptEngine))
124 if (!m_HttpRequest.ContainsKey(m_ScriptEngine)) 163 m_Dataserver[m_ScriptEngine] = new Dataserver(this);
125 m_HttpRequest[m_ScriptEngine] = new HttpRequest(this); 164 if (!m_Timer.ContainsKey(m_ScriptEngine))
126 if (!m_Listener.ContainsKey(m_ScriptEngine)) 165 m_Timer[m_ScriptEngine] = new Timer(this);
127 m_Listener[m_ScriptEngine] = new Listener(this); 166 if (!m_HttpRequest.ContainsKey(m_ScriptEngine))
128 if (!m_SensorRepeat.ContainsKey(m_ScriptEngine)) 167 m_HttpRequest[m_ScriptEngine] = new HttpRequest(this);
129 m_SensorRepeat[m_ScriptEngine] = new SensorRepeat(this); 168 if (!m_Listener.ContainsKey(m_ScriptEngine))
130 if (!m_XmlRequest.ContainsKey(m_ScriptEngine)) 169 m_Listener[m_ScriptEngine] = new Listener(this);
131 m_XmlRequest[m_ScriptEngine] = new XmlRequest(this); 170 if (!m_SensorRepeat.ContainsKey(m_ScriptEngine))
132 171 m_SensorRepeat[m_ScriptEngine] = new SensorRepeat(this);
133 StartThread(); 172 if (!m_XmlRequest.ContainsKey(m_ScriptEngine))
173 m_XmlRequest[m_ScriptEngine] = new XmlRequest(this);
174
175 StartThread();
176 }
134 } 177 }
135 178
136 private static void StartThread() 179 private static void StartThread()
@@ -139,7 +182,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
139 { 182 {
140 // Start the thread that will be doing the work 183 // Start the thread that will be doing the work
141 cmdHandlerThread 184 cmdHandlerThread
142 = Watchdog.StartThread( 185 = WorkManager.StartThread(
143 CmdHandlerThreadLoop, "AsyncLSLCmdHandlerThread", ThreadPriority.Normal, true, true); 186 CmdHandlerThreadLoop, "AsyncLSLCmdHandlerThread", ThreadPriority.Normal, true, true);
144 } 187 }
145 } 188 }
@@ -179,42 +222,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
179 { 222 {
180 try 223 try
181 { 224 {
182 while (true) 225 Thread.Sleep(cmdHandlerThreadCycleSleepms);
183 {
184 Thread.Sleep(cmdHandlerThreadCycleSleepms);
185 226
186 DoOneCmdHandlerPass(); 227 DoOneCmdHandlerPass();
187 228
188 Watchdog.UpdateThread(); 229 Watchdog.UpdateThread();
189 }
190 } 230 }
191 catch 231 catch (Exception e)
192 { 232 {
233 m_log.Error("[ASYNC COMMAND MANAGER]: Exception in command handler pass: ", e);
193 } 234 }
194 } 235 }
195 } 236 }
196 237
197 private static void DoOneCmdHandlerPass() 238 private static void DoOneCmdHandlerPass()
198 { 239 {
199 // Check HttpRequests 240 lock (staticLock)
200 m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests(); 241 {
242 // Check HttpRequests
243 m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests();
201 244
202 // Check XMLRPCRequests 245 // Check XMLRPCRequests
203 m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests(); 246 m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests();
204 247
205 foreach (IScriptEngine s in m_ScriptEngines) 248 foreach (IScriptEngine s in m_ScriptEngines)
206 { 249 {
207 // Check Listeners 250 // Check Listeners
208 m_Listener[s].CheckListeners(); 251 m_Listener[s].CheckListeners();
209 252
210 // Check timers 253 // Check timers
211 m_Timer[s].CheckTimerEvents(); 254 m_Timer[s].CheckTimerEvents();
212 255
213 // Check Sensors 256 // Check Sensors
214 m_SensorRepeat[s].CheckSenseRepeaterEvents(); 257 m_SensorRepeat[s].CheckSenseRepeaterEvents();
215 258
216 // Check dataserver 259 // Check dataserver
217 m_Dataserver[s].ExpireRequests(); 260 m_Dataserver[s].ExpireRequests();
261 }
218 } 262 }
219 } 263 }
220 264
@@ -225,19 +269,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
225 /// <param name="itemID"></param> 269 /// <param name="itemID"></param>
226 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID) 270 public static void RemoveScript(IScriptEngine engine, uint localID, UUID itemID)
227 { 271 {
272// m_log.DebugFormat("[ASYNC COMMAND MANAGER]: Removing facilities for script {0}", itemID);
273
274 lock (staticLock)
275 {
276 // Remove dataserver events
277 m_Dataserver[engine].RemoveEvents(localID, itemID);
278
279 // Remove from: Timers
280 m_Timer[engine].UnSetTimerEvents(localID, itemID);
281
282 // Remove from: HttpRequest
283 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>();
284 if (iHttpReq != null)
285 iHttpReq.StopHttpRequestsForScript(itemID);
286
287 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
288 if (comms != null)
289 comms.DeleteListener(itemID);
290
291 IXMLRPC xmlrpc = engine.World.RequestModuleInterface<IXMLRPC>();
292 if (xmlrpc != null)
293 {
294 xmlrpc.DeleteChannels(itemID);
295 xmlrpc.CancelSRDRequests(itemID);
296 }
297
298 // Remove Sensors
299 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
300 }
301 }
302
303 public static void StateChange(IScriptEngine engine, uint localID, UUID itemID)
304 {
228 // Remove a specific script 305 // Remove a specific script
229 306
230 // Remove dataserver events 307 // Remove dataserver events
231 m_Dataserver[engine].RemoveEvents(localID, itemID); 308 m_Dataserver[engine].RemoveEvents(localID, itemID);
232 309
233 // Remove from: Timers
234 m_Timer[engine].UnSetTimerEvents(localID, itemID);
235
236 // Remove from: HttpRequest
237 IHttpRequestModule iHttpReq = engine.World.RequestModuleInterface<IHttpRequestModule>();
238 if (iHttpReq != null)
239 iHttpReq.StopHttpRequest(localID, itemID);
240
241 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>(); 310 IWorldComm comms = engine.World.RequestModuleInterface<IWorldComm>();
242 if (comms != null) 311 if (comms != null)
243 comms.DeleteListener(itemID); 312 comms.DeleteListener(itemID);
@@ -248,9 +317,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
248 xmlrpc.DeleteChannels(itemID); 317 xmlrpc.DeleteChannels(itemID);
249 xmlrpc.CancelSRDRequests(itemID); 318 xmlrpc.CancelSRDRequests(itemID);
250 } 319 }
251
252 // Remove Sensors 320 // Remove Sensors
253 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID); 321 m_SensorRepeat[engine].UnSetSenseRepeaterEvents(localID, itemID);
322
254 } 323 }
255 324
256 /// <summary> 325 /// <summary>
@@ -260,10 +329,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
260 /// <returns></returns> 329 /// <returns></returns>
261 public static SensorRepeat GetSensorRepeatPlugin(IScriptEngine engine) 330 public static SensorRepeat GetSensorRepeatPlugin(IScriptEngine engine)
262 { 331 {
263 if (m_SensorRepeat.ContainsKey(engine)) 332 lock (staticLock)
264 return m_SensorRepeat[engine]; 333 {
265 else 334 if (m_SensorRepeat.ContainsKey(engine))
266 return null; 335 return m_SensorRepeat[engine];
336 else
337 return null;
338 }
267 } 339 }
268 340
269 /// <summary> 341 /// <summary>
@@ -273,10 +345,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
273 /// <returns></returns> 345 /// <returns></returns>
274 public static Dataserver GetDataserverPlugin(IScriptEngine engine) 346 public static Dataserver GetDataserverPlugin(IScriptEngine engine)
275 { 347 {
276 if (m_Dataserver.ContainsKey(engine)) 348 lock (staticLock)
277 return m_Dataserver[engine]; 349 {
278 else 350 if (m_Dataserver.ContainsKey(engine))
279 return null; 351 return m_Dataserver[engine];
352 else
353 return null;
354 }
280 } 355 }
281 356
282 /// <summary> 357 /// <summary>
@@ -286,10 +361,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
286 /// <returns></returns> 361 /// <returns></returns>
287 public static Timer GetTimerPlugin(IScriptEngine engine) 362 public static Timer GetTimerPlugin(IScriptEngine engine)
288 { 363 {
289 if (m_Timer.ContainsKey(engine)) 364 lock (staticLock)
290 return m_Timer[engine]; 365 {
291 else 366 if (m_Timer.ContainsKey(engine))
292 return null; 367 return m_Timer[engine];
368 else
369 return null;
370 }
293 } 371 }
294 372
295 /// <summary> 373 /// <summary>
@@ -299,38 +377,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
299 /// <returns></returns> 377 /// <returns></returns>
300 public static Listener GetListenerPlugin(IScriptEngine engine) 378 public static Listener GetListenerPlugin(IScriptEngine engine)
301 { 379 {
302 if (m_Listener.ContainsKey(engine)) 380 lock (staticLock)
303 return m_Listener[engine]; 381 {
304 else 382 if (m_Listener.ContainsKey(engine))
305 return null; 383 return m_Listener[engine];
384 else
385 return null;
386 }
306 } 387 }
307 388
308 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) 389 public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID)
309 { 390 {
310 List<Object> data = new List<Object>(); 391 List<Object> data = new List<Object>();
311 392
312 Object[] listeners = m_Listener[engine].GetSerializationData(itemID); 393 lock (staticLock)
313 if (listeners.Length > 0)
314 { 394 {
315 data.Add("listener"); 395 Object[] listeners = m_Listener[engine].GetSerializationData(itemID);
316 data.Add(listeners.Length); 396 if (listeners.Length > 0)
317 data.AddRange(listeners); 397 {
318 } 398 data.Add("listener");
399 data.Add(listeners.Length);
400 data.AddRange(listeners);
401 }
319 402
320 Object[] timers=m_Timer[engine].GetSerializationData(itemID); 403 Object[] timers=m_Timer[engine].GetSerializationData(itemID);
321 if (timers.Length > 0) 404 if (timers.Length > 0)
322 { 405 {
323 data.Add("timer"); 406 data.Add("timer");
324 data.Add(timers.Length); 407 data.Add(timers.Length);
325 data.AddRange(timers); 408 data.AddRange(timers);
326 } 409 }
327 410
328 Object[] sensors = m_SensorRepeat[engine].GetSerializationData(itemID); 411 Object[] sensors = m_SensorRepeat[engine].GetSerializationData(itemID);
329 if (sensors.Length > 0) 412 if (sensors.Length > 0)
330 { 413 {
331 data.Add("sensor"); 414 data.Add("sensor");
332 data.Add(sensors.Length); 415 data.Add(sensors.Length);
333 data.AddRange(sensors); 416 data.AddRange(sensors);
417 }
334 } 418 }
335 419
336 return data.ToArray(); 420 return data.ToArray();
@@ -355,41 +439,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
355 439
356 idx+=len; 440 idx+=len;
357 441
442 lock (staticLock)
443 {
358 switch (type) 444 switch (type)
359 { 445 {
360 case "listener": 446 case "listener":
361 m_Listener[engine].CreateFromData(localID, itemID, 447 m_Listener[engine].CreateFromData(localID, itemID,
362 hostID, item); 448 hostID, item);
363 break; 449 break;
364 case "timer": 450 case "timer":
365 m_Timer[engine].CreateFromData(localID, itemID, 451 m_Timer[engine].CreateFromData(localID, itemID,
366 hostID, item); 452 hostID, item);
367 break; 453 break;
368 case "sensor": 454 case "sensor":
369 m_SensorRepeat[engine].CreateFromData(localID, 455 m_SensorRepeat[engine].CreateFromData(localID,
370 itemID, hostID, item); 456 itemID, hostID, item);
371 break; 457 break;
458 }
372 } 459 }
373 } 460 }
374 } 461 }
375 } 462 }
376
377 #region Check llRemoteData channels
378
379 #endregion
380
381 #region Check llListeners
382
383 #endregion
384
385 /// <summary>
386 /// If set to true then threads and stuff should try to make a graceful exit
387 /// </summary>
388 public bool PleaseShutdown
389 {
390 get { return _PleaseShutdown; }
391 set { _PleaseShutdown = value; }
392 }
393 private bool _PleaseShutdown = false;
394 } 463 }
395} 464}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 1ab107a..4eda443 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -28,6 +28,9 @@
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics;
32using System.Drawing;
33using System.Drawing.Imaging;
31using System.Runtime.Remoting.Lifetime; 34using System.Runtime.Remoting.Lifetime;
32using System.Text; 35using System.Text;
33using System.Threading; 36using System.Threading;
@@ -35,7 +38,9 @@ using System.Text.RegularExpressions;
35using Nini.Config; 38using Nini.Config;
36using log4net; 39using log4net;
37using OpenMetaverse; 40using OpenMetaverse;
41using OpenMetaverse.Assets;
38using OpenMetaverse.Packets; 42using OpenMetaverse.Packets;
43using OpenMetaverse.Rendering;
39using OpenSim; 44using OpenSim;
40using OpenSim.Framework; 45using OpenSim.Framework;
41 46
@@ -45,7 +50,8 @@ using OpenSim.Region.CoreModules.World.Terrain;
45using OpenSim.Region.Framework.Interfaces; 50using OpenSim.Region.Framework.Interfaces;
46using OpenSim.Region.Framework.Scenes; 51using OpenSim.Region.Framework.Scenes;
47using OpenSim.Region.Framework.Scenes.Animation; 52using OpenSim.Region.Framework.Scenes.Animation;
48using OpenSim.Region.Physics.Manager; 53using OpenSim.Region.Framework.Scenes.Scripting;
54using OpenSim.Region.PhysicsModules.SharedBase;
49using OpenSim.Region.ScriptEngine.Shared; 55using OpenSim.Region.ScriptEngine.Shared;
50using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 56using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
51using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 57using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
@@ -66,6 +72,8 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
66using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 72using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
67using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 73using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
68using System.Reflection; 74using System.Reflection;
75using System.Linq;
76using PermissionMask = OpenSim.Framework.PermissionMask;
69 77
70namespace OpenSim.Region.ScriptEngine.Shared.Api 78namespace OpenSim.Region.ScriptEngine.Shared.Api
71{ 79{
@@ -83,15 +91,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
83 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 91 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
84 { 92 {
85 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 93 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
94
95 public int LlRequestAgentDataCacheTimeoutMs { get; set; }
96
86 protected IScriptEngine m_ScriptEngine; 97 protected IScriptEngine m_ScriptEngine;
87 protected SceneObjectPart m_host; 98 protected SceneObjectPart m_host;
88 99
89 /// <summary> 100 /// <summary>
101 /// Used for script sleeps when we are using co-operative script termination.
102 /// </summary>
103 /// <remarks>null if co-operative script termination is not active</remarks>
104 /// <summary>
90 /// The item that hosts this script 105 /// The item that hosts this script
91 /// </summary> 106 /// </summary>
92 protected TaskInventoryItem m_item; 107 protected TaskInventoryItem m_item;
93 108
94 protected bool throwErrorOnNotImplemented = true; 109 protected bool throwErrorOnNotImplemented = false;
95 protected AsyncCommandManager AsyncCommands = null; 110 protected AsyncCommandManager AsyncCommands = null;
96 protected float m_ScriptDelayFactor = 1.0f; 111 protected float m_ScriptDelayFactor = 1.0f;
97 protected float m_ScriptDistanceFactor = 1.0f; 112 protected float m_ScriptDistanceFactor = 1.0f;
@@ -108,49 +123,260 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
108 protected IUrlModule m_UrlModule = null; 123 protected IUrlModule m_UrlModule = null;
109 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 124 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
110 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 125 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
126 protected int m_sleepMsOnSetTexture = 200;
127 protected int m_sleepMsOnSetLinkTexture = 200;
128 protected int m_sleepMsOnScaleTexture = 200;
129 protected int m_sleepMsOnOffsetTexture = 200;
130 protected int m_sleepMsOnRotateTexture = 200;
131 protected int m_sleepMsOnSetPos = 200;
132 protected int m_sleepMsOnSetRot = 200;
133 protected int m_sleepMsOnSetLocalRot = 200;
134 protected int m_sleepMsOnPreloadSound = 1000;
135 protected int m_sleepMsOnMakeExplosion = 100;
136 protected int m_sleepMsOnMakeFountain = 100;
137 protected int m_sleepMsOnMakeSmoke = 100;
138 protected int m_sleepMsOnMakeFire = 100;
139 protected int m_sleepMsOnRezAtRoot = 100;
140 protected int m_sleepMsOnInstantMessage = 2000;
141 protected int m_sleepMsOnEmail = 20000;
142 protected int m_sleepMsOnCreateLink = 1000;
143 protected int m_sleepMsOnGiveInventory = 3000;
144 protected int m_sleepMsOnRequestAgentData = 100;
145 protected int m_sleepMsOnRequestInventoryData = 1000;
146 protected int m_sleepMsOnSetDamage = 5000;
147 protected int m_sleepMsOnTextBox = 1000;
148 protected int m_sleepMsOnAdjustSoundVolume = 100;
149 protected int m_sleepMsOnEjectFromLand = 5000;
150 protected int m_sleepMsOnAddToLandPassList = 100;
151 protected int m_sleepMsOnDialog = 1000;
152 protected int m_sleepMsOnRemoteLoadScript = 3000;
153 protected int m_sleepMsOnRemoteLoadScriptPin = 3000;
154 protected int m_sleepMsOnOpenRemoteDataChannel = 1000;
155 protected int m_sleepMsOnSendRemoteData = 3000;
156 protected int m_sleepMsOnRemoteDataReply = 3000;
157 protected int m_sleepMsOnCloseRemoteDataChannel = 1000;
158 protected int m_sleepMsOnSetPrimitiveParams = 200;
159 protected int m_sleepMsOnSetLinkPrimitiveParams = 200;
160 protected int m_sleepMsOnXorBase64Strings = 300;
161 protected int m_sleepMsOnSetParcelMusicURL = 2000;
162 protected int m_sleepMsOnGetPrimMediaParams = 1000;
163 protected int m_sleepMsOnGetLinkMedia = 1000;
164 protected int m_sleepMsOnSetPrimMediaParams = 1000;
165 protected int m_sleepMsOnSetLinkMedia = 1000;
166 protected int m_sleepMsOnClearPrimMedia = 1000;
167 protected int m_sleepMsOnClearLinkMedia = 1000;
168 protected int m_sleepMsOnRequestSimulatorData = 1000;
169 protected int m_sleepMsOnLoadURL = 10000;
170 protected int m_sleepMsOnParcelMediaCommandList = 2000;
171 protected int m_sleepMsOnParcelMediaQuery = 2000;
172 protected int m_sleepMsOnModPow = 1000;
173 protected int m_sleepMsOnSetPrimURL = 2000;
174 protected int m_sleepMsOnRefreshPrimURL = 20000;
175 protected int m_sleepMsOnMapDestination = 1000;
176 protected int m_sleepMsOnAddToLandBanList = 100;
177 protected int m_sleepMsOnRemoveFromLandPassList = 100;
178 protected int m_sleepMsOnRemoveFromLandBanList = 100;
179 protected int m_sleepMsOnResetLandBanList = 100;
180 protected int m_sleepMsOnResetLandPassList = 100;
181 protected int m_sleepMsOnGetParcelPrimOwners = 2000;
182 protected int m_sleepMsOnGetNumberOfNotecardLines = 100;
183 protected int m_sleepMsOnGetNotecardLine = 100;
184 protected string m_internalObjectHost = "lsl.opensim.local";
185 protected bool m_restrictEmail = false;
111 protected ISoundModule m_SoundModule = null; 186 protected ISoundModule m_SoundModule = null;
112 187
113 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 188 protected float m_avatarHeightCorrection = 0.2f;
189 protected bool m_useSimpleBoxesInGetBoundingBox = false;
190 protected bool m_addStatsInGetBoundingBox = false;
191
192 //LSL Avatar Bounding Box (lABB), lower (1) and upper (2),
193 //standing (Std), Groundsitting (Grs), Sitting (Sit),
194 //along X, Y and Z axes, constants (0) and coefficients (1)
195 protected float m_lABB1StdX0 = -0.275f;
196 protected float m_lABB2StdX0 = 0.275f;
197 protected float m_lABB1StdY0 = -0.35f;
198 protected float m_lABB2StdY0 = 0.35f;
199 protected float m_lABB1StdZ0 = -0.1f;
200 protected float m_lABB1StdZ1 = -0.5f;
201 protected float m_lABB2StdZ0 = 0.1f;
202 protected float m_lABB2StdZ1 = 0.5f;
203 protected float m_lABB1GrsX0 = -0.3875f;
204 protected float m_lABB2GrsX0 = 0.3875f;
205 protected float m_lABB1GrsY0 = -0.5f;
206 protected float m_lABB2GrsY0 = 0.5f;
207 protected float m_lABB1GrsZ0 = -0.05f;
208 protected float m_lABB1GrsZ1 = -0.375f;
209 protected float m_lABB2GrsZ0 = 0.5f;
210 protected float m_lABB2GrsZ1 = 0.0f;
211 protected float m_lABB1SitX0 = -0.5875f;
212 protected float m_lABB2SitX0 = 0.1875f;
213 protected float m_lABB1SitY0 = -0.35f;
214 protected float m_lABB2SitY0 = 0.35f;
215 protected float m_lABB1SitZ0 = -0.35f;
216 protected float m_lABB1SitZ1 = -0.375f;
217 protected float m_lABB2SitZ0 = -0.25f;
218 protected float m_lABB2SitZ1 = 0.25f;
219
220 protected float m_primSafetyCoeffX = 2.414214f;
221 protected float m_primSafetyCoeffY = 2.414214f;
222 protected float m_primSafetyCoeffZ = 1.618034f;
223 protected bool m_useCastRayV3 = false;
224 protected float m_floatToleranceInCastRay = 0.00001f;
225 protected float m_floatTolerance2InCastRay = 0.001f;
226 protected DetailLevel m_primLodInCastRay = DetailLevel.Medium;
227 protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium;
228 protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest;
229 protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium;
230 protected int m_maxHitsInCastRay = 16;
231 protected int m_maxHitsPerPrimInCastRay = 16;
232 protected int m_maxHitsPerObjectInCastRay = 16;
233 protected bool m_detectExitsInCastRay = false;
234 protected bool m_filterPartsInCastRay = false;
235 protected bool m_doAttachmentsInCastRay = false;
236 protected int m_msThrottleInCastRay = 200;
237 protected int m_msPerRegionInCastRay = 40;
238 protected int m_msPerAvatarInCastRay = 10;
239 protected int m_msMinInCastRay = 2;
240 protected int m_msMaxInCastRay = 40;
241 protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>();
242 protected bool m_useMeshCacheInCastRay = true;
243 protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>();
244
245 //An array of HTTP/1.1 headers that are not allowed to be used
246 //as custom headers by llHTTPRequest.
247 private string[] HttpStandardHeaders =
248 {
249 "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language",
250 "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control",
251 "Connection", "Content-Encoding", "Content-Language",
252 "Content-Length", "Content-Location", "Content-MD5",
253 "Content-Range", "Content-Type", "Date", "ETag", "Expect",
254 "Expires", "From", "Host", "If-Match", "If-Modified-Since",
255 "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified",
256 "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
257 "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
258 "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent",
259 "Vary", "Via", "Warning", "WWW-Authenticate"
260 };
261
262 public void Initialize(
263 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
114 { 264 {
115 m_ScriptEngine = ScriptEngine; 265 m_ScriptEngine = scriptEngine;
116 m_host = host; 266 m_host = host;
117 m_item = item; 267 m_item = item;
118 268
119 LoadLimits(); // read script limits from config. 269 LoadConfig();
120 270
121 m_TransferModule = 271 m_TransferModule =
122 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 272 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
123 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 273 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
124 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); 274 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
125 275
126 AsyncCommands = new AsyncCommandManager(ScriptEngine); 276 AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
127 } 277 }
128 278
129 /* load configuration items that affect script, object and run-time behavior. */ 279 /// <summary>
130 private void LoadLimits() 280 /// Load configuration items that affect script, object and run-time behavior. */
281 /// </summary>
282 private void LoadConfig()
131 { 283 {
132 m_ScriptDelayFactor = 284 LlRequestAgentDataCacheTimeoutMs = 20000;
133 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 285
134 m_ScriptDistanceFactor = 286 IConfig seConfig = m_ScriptEngine.Config;
135 m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f); 287
136 m_MinTimerInterval = 288 if (seConfig != null)
137 m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f); 289 {
138 m_automaticLinkPermission = 290 m_ScriptDelayFactor =
139 m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false); 291 seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor);
140 m_notecardLineReadCharsMax = 292 m_ScriptDistanceFactor =
141 m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255); 293 seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor);
294 m_MinTimerInterval =
295 seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval);
296 m_automaticLinkPermission =
297 seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission);
298 m_notecardLineReadCharsMax =
299 seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax);
300
301 // Rezzing an object with a velocity can create recoil. This feature seems to have been
302 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
303 // it by this factor. May be zero to turn off recoil all together.
304 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
305 }
306
142 if (m_notecardLineReadCharsMax > 65535) 307 if (m_notecardLineReadCharsMax > 65535)
143 m_notecardLineReadCharsMax = 65535; 308 m_notecardLineReadCharsMax = 65535;
309
144 // load limits for particular subsystems. 310 // load limits for particular subsystems.
145 IConfig SMTPConfig; 311 IConfigSource seConfigSource = m_ScriptEngine.ConfigSource;
146 if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) { 312
147 // there's an smtp config, so load in the snooze time. 313 if (seConfigSource != null)
148 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); 314 {
149 } 315 IConfig lslConfig = seConfigSource.Configs["LL-Functions"];
150 // Rezzing an object with a velocity can create recoil. This feature seems to have been 316 if (lslConfig != null)
151 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales 317 {
152 // it by this factor. May be zero to turn off recoil all together. 318 m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail);
153 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor); 319 m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection);
320 m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox);
321 m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox);
322 m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0);
323 m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0);
324 m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0);
325 m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0);
326 m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0);
327 m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1);
328 m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0);
329 m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1);
330 m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0);
331 m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0);
332 m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0);
333 m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0);
334 m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0);
335 m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1);
336 m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0);
337 m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1);
338 m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0);
339 m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0);
340 m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0);
341 m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0);
342 m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0);
343 m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1);
344 m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0);
345 m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1);
346 m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX);
347 m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY);
348 m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ);
349 m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3);
350 m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay);
351 m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay);
352 m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay);
353 m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay);
354 m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay);
355 m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay);
356 m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay);
357 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
358 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
359 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
360 m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
361 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
362 m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay);
363 m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay);
364 m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay);
365 m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay);
366 m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay);
367 m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay);
368 }
369
370 IConfig smtpConfig = seConfigSource.Configs["SMTP"];
371 if (smtpConfig != null)
372 {
373 // there's an smtp config, so load in the snooze time.
374 EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
375
376 m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
377 }
378 }
379 m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000;
154 } 380 }
155 381
156 public override Object InitializeLifetimeService() 382 public override Object InitializeLifetimeService()
@@ -171,9 +397,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 delay = (int)((float)delay * m_ScriptDelayFactor); 397 delay = (int)((float)delay * m_ScriptDelayFactor);
172 if (delay == 0) 398 if (delay == 0)
173 return; 399 return;
174 System.Threading.Thread.Sleep(delay); 400
401 Sleep(delay);
175 } 402 }
176 403
404 protected virtual void Sleep(int delay)
405 {
406 if (m_item == null) // Some unit tests don't set this
407 {
408 Thread.Sleep(delay);
409 return;
410 }
411
412 m_ScriptEngine.SleepScript(m_item.ItemID, delay);
413 }
414
415 /// <summary>
416 /// Check for co-operative termination.
417 /// </summary>
418 /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param>
419
177 public Scene World 420 public Scene World
178 { 421 {
179 get { return m_ScriptEngine.World; } 422 get { return m_ScriptEngine.World; }
@@ -209,7 +452,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
209 if ((item = GetScriptByName(name)) != UUID.Zero) 452 if ((item = GetScriptByName(name)) != UUID.Zero)
210 m_ScriptEngine.ResetScript(item); 453 m_ScriptEngine.ResetScript(item);
211 else 454 else
212 ShoutError("llResetOtherScript: script "+name+" not found"); 455 Error("llResetOtherScript", "Can't find script '" + name + "'");
213 } 456 }
214 457
215 public LSL_Integer llGetScriptState(string name) 458 public LSL_Integer llGetScriptState(string name)
@@ -223,7 +466,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
223 return m_ScriptEngine.GetScriptState(item) ?1:0; 466 return m_ScriptEngine.GetScriptState(item) ?1:0;
224 } 467 }
225 468
226 ShoutError("llGetScriptState: script "+name+" not found"); 469 Error("llGetScriptState", "Can't find script '" + name + "'");
227 470
228 // If we didn't find it, then it's safe to 471 // If we didn't find it, then it's safe to
229 // assume it is not running. 472 // assume it is not running.
@@ -246,7 +489,78 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
246 } 489 }
247 else 490 else
248 { 491 {
249 ShoutError("llSetScriptState: script "+name+" not found"); 492 Error("llSetScriptState", "Can't find script '" + name + "'");
493 }
494 }
495
496 /// <summary>
497 /// Get a given link entity from a linkset (linked objects and any sitting avatars).
498 /// </summary>
499 /// <remarks>
500 /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then
501 /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset.
502 /// The ScenePresences receive linknums in the order in which they sat.
503 /// </remarks>
504 /// <returns>
505 /// The link entity. null if not found.
506 /// </returns>
507 /// <param name='part'></param>
508 /// <param name='linknum'>
509 /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4).
510 /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned.
511 /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned. If any
512 /// positive integer is given in this case then null is returned.
513 /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number
514 /// of entities, then the entity which corresponds to that linknum is returned.
515 /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then
516 /// null is returned.
517 /// </param>
518 public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum)
519 {
520 if (linknum < 0)
521 {
522 if (linknum == ScriptBaseClass.LINK_THIS)
523 return part;
524 else
525 return null;
526 }
527
528 int actualPrimCount = part.ParentGroup.PrimCount;
529 List<ScenePresence> sittingAvatars = part.ParentGroup.GetSittingAvatars();
530 int adjustedPrimCount = actualPrimCount + sittingAvatars.Count;
531
532 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
533 // prim that has any avatars sat upon it (in which case the root prim is link 1).
534 if (linknum == 0)
535 {
536 if (actualPrimCount == 1 && sittingAvatars.Count == 0)
537 return part;
538
539 return null;
540 }
541 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
542 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
543 else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1)
544 {
545 if (sittingAvatars.Count > 0)
546 return part.ParentGroup.RootPart;
547 else
548 return null;
549 }
550 else if (linknum <= adjustedPrimCount)
551 {
552 if (linknum <= actualPrimCount)
553 {
554 return part.ParentGroup.GetLinkNumPart(linknum);
555 }
556 else
557 {
558 return sittingAvatars[linknum - actualPrimCount - 1];
559 }
560 }
561 else
562 {
563 return null;
250 } 564 }
251 } 565 }
252 566
@@ -301,77 +615,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
301 } 615 }
302 } 616 }
303 617
304 protected UUID InventoryKey(string name, int type) 618 public List<ISceneEntity> GetLinkEntities(int linkType)
305 { 619 {
306 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 620 return GetLinkEntities(m_host, linkType);
307
308 if (item != null && item.Type == type)
309 return item.AssetID;
310 else
311 return UUID.Zero;
312 } 621 }
313 622
314 /// <summary> 623 public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType)
315 /// accepts a valid UUID, -or- a name of an inventory item.
316 /// Returns a valid UUID or UUID.Zero if key invalid and item not found
317 /// in prim inventory.
318 /// </summary>
319 /// <param name="k"></param>
320 /// <returns></returns>
321 protected UUID KeyOrName(string k)
322 { 624 {
323 UUID key; 625 List<ISceneEntity> ret;
324 626
325 // if we can parse the string as a key, use it. 627 switch (linkType)
326 // else try to locate the name in inventory of object. found returns key,
327 // not found returns UUID.Zero
328 if (!UUID.TryParse(k, out key))
329 { 628 {
330 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); 629 case ScriptBaseClass.LINK_SET:
630 return new List<ISceneEntity>(part.ParentGroup.Parts);
331 631
332 if (item != null) 632 case ScriptBaseClass.LINK_ROOT:
333 key = item.AssetID; 633 return new List<ISceneEntity>() { part.ParentGroup.RootPart };
334 else
335 key = UUID.Zero;
336 }
337 634
338 return key; 635 case ScriptBaseClass.LINK_ALL_OTHERS:
339 } 636 ret = new List<ISceneEntity>(part.ParentGroup.Parts);
340 637
341 /// <summary> 638 if (ret.Contains(part))
342 /// Return the UUID of the asset matching the specified key or name 639 ret.Remove(part);
343 /// and asset type.
344 /// </summary>
345 /// <param name="k"></param>
346 /// <param name="type"></param>
347 /// <returns></returns>
348 protected UUID KeyOrName(string k, AssetType type)
349 {
350 UUID key;
351 640
352 if (!UUID.TryParse(k, out key)) 641 return ret;
353 { 642
354 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); 643 case ScriptBaseClass.LINK_ALL_CHILDREN:
355 if (item != null && item.Type == (int)type) 644 ret = new List<ISceneEntity>(part.ParentGroup.Parts);
356 key = item.AssetID;
357 }
358 else
359 {
360 lock (m_host.TaskInventory)
361 {
362 foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory)
363 {
364 if (item.Value.Type == (int)type && item.Value.Name == k)
365 {
366 key = item.Value.ItemID;
367 break;
368 }
369 }
370 }
371 }
372 645
646 if (ret.Contains(part.ParentGroup.RootPart))
647 ret.Remove(part.ParentGroup.RootPart);
373 648
374 return key; 649 return ret;
650
651 case ScriptBaseClass.LINK_THIS:
652 return new List<ISceneEntity>() { part };
653
654 default:
655 if (linkType < 0)
656 return new List<ISceneEntity>();
657
658 ISceneEntity target = GetLinkEntity(part, linkType);
659 if (target == null)
660 return new List<ISceneEntity>();
661
662 return new List<ISceneEntity>() { target };
663 }
375 } 664 }
376 665
377 //These are the implementations of the various ll-functions used by the LSL scripts. 666 //These are the implementations of the various ll-functions used by the LSL scripts.
@@ -430,10 +719,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
430 public LSL_Float llFrand(double mag) 719 public LSL_Float llFrand(double mag)
431 { 720 {
432 m_host.AddScriptLPS(1); 721 m_host.AddScriptLPS(1);
433 lock (Util.RandomClass) 722
434 { 723 return Util.RandomClass.NextDouble() * mag;
435 return Util.RandomClass.NextDouble() * mag;
436 }
437 } 724 }
438 725
439 public LSL_Integer llFloor(double f) 726 public LSL_Integer llFloor(double f)
@@ -837,7 +1124,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
837 { 1124 {
838 if (channelID == 0) 1125 if (channelID == 0)
839 { 1126 {
840 LSLError("Cannot use llRegionSay() on channel 0"); 1127 Error("llRegionSay", "Cannot use on channel 0");
841 return; 1128 return;
842 } 1129 }
843 1130
@@ -846,6 +1133,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
846 1133
847 m_host.AddScriptLPS(1); 1134 m_host.AddScriptLPS(1);
848 1135
1136 World.SimChat(Utils.StringToBytes(text),
1137 ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
1138
849 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1139 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
850 if (wComm != null) 1140 if (wComm != null)
851 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); 1141 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
@@ -866,6 +1156,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
866 UUID TargetID; 1156 UUID TargetID;
867 UUID.TryParse(target, out TargetID); 1157 UUID.TryParse(target, out TargetID);
868 1158
1159 World.SimChatToAgent(TargetID, Utils.StringToBytes(msg),
1160 channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
1161
869 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1162 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
870 if (wComm != null) 1163 if (wComm != null)
871 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); 1164 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
@@ -1255,12 +1548,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1255 } 1548 }
1256 1549
1257 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) 1550 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
1258 { 1551 m_host.BlockGrab = value != 0;
1259 if (value != 0) 1552
1260 m_host.SetBlockGrab(true); 1553 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
1261 else 1554 m_host.ParentGroup.BlockGrabOverride = value != 0;
1262 m_host.SetBlockGrab(false);
1263 }
1264 1555
1265 if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) 1556 if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
1266 { 1557 {
@@ -1321,10 +1612,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1321 return 0; 1612 return 0;
1322 1613
1323 case ScriptBaseClass.STATUS_BLOCK_GRAB: 1614 case ScriptBaseClass.STATUS_BLOCK_GRAB:
1324 if (m_host.GetBlockGrab()) 1615 return m_host.BlockGrab ? 1 : 0;
1325 return 1; 1616
1326 else 1617 case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT:
1327 return 0; 1618 return m_host.ParentGroup.BlockGrabOverride ? 1 : 0;
1328 1619
1329 case ScriptBaseClass.STATUS_DIE_AT_EDGE: 1620 case ScriptBaseClass.STATUS_DIE_AT_EDGE:
1330 if (m_host.GetDieAtEdge()) 1621 if (m_host.GetDieAtEdge())
@@ -1427,6 +1718,73 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1427 m_host.SetFaceColorAlpha(face, color, null); 1718 m_host.SetFaceColorAlpha(face, color, null);
1428 } 1719 }
1429 1720
1721 public void llSetContentType(LSL_Key id, LSL_Integer type)
1722 {
1723 m_host.AddScriptLPS(1);
1724
1725 if (m_UrlModule == null)
1726 return;
1727
1728 // Make sure the content type is text/plain to start with
1729 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1730
1731 // Is the object owner online and in the region
1732 ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID);
1733 if (agent == null || agent.IsChildAgent)
1734 return; // Fail if the owner is not in the same region
1735
1736 // Is it the embeded browser?
1737 string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
1738 if (userAgent.IndexOf("SecondLife") < 0)
1739 return; // Not the embedded browser. Is this check good enough?
1740
1741 // Use the IP address of the client and check against the request
1742 // seperate logins from the same IP will allow all of them to get non-text/plain as long
1743 // as the owner is in the region. Same as SL!
1744 string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString();
1745 string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr");
1746 //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'");
1747 if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "")
1748 return;
1749 if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "")
1750 return;
1751
1752 // If the request isnt from the same IP address then the request cannot be from the owner
1753 if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim()))
1754 return;
1755
1756 switch (type)
1757 {
1758 case ScriptBaseClass.CONTENT_TYPE_HTML:
1759 m_UrlModule.HttpContentType(new UUID(id), "text/html");
1760 break;
1761 case ScriptBaseClass.CONTENT_TYPE_XML:
1762 m_UrlModule.HttpContentType(new UUID(id), "application/xml");
1763 break;
1764 case ScriptBaseClass.CONTENT_TYPE_XHTML:
1765 m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml");
1766 break;
1767 case ScriptBaseClass.CONTENT_TYPE_ATOM:
1768 m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml");
1769 break;
1770 case ScriptBaseClass.CONTENT_TYPE_JSON:
1771 m_UrlModule.HttpContentType(new UUID(id), "application/json");
1772 break;
1773 case ScriptBaseClass.CONTENT_TYPE_LLSD:
1774 m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml");
1775 break;
1776 case ScriptBaseClass.CONTENT_TYPE_FORM:
1777 m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded");
1778 break;
1779 case ScriptBaseClass.CONTENT_TYPE_RSS:
1780 m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml");
1781 break;
1782 default:
1783 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1784 break;
1785 }
1786 }
1787
1430 public void SetTexGen(SceneObjectPart part, int face,int style) 1788 public void SetTexGen(SceneObjectPart part, int face,int style)
1431 { 1789 {
1432 Primitive.TextureEntry tex = part.Shape.Textures; 1790 Primitive.TextureEntry tex = part.Shape.Textures;
@@ -1522,7 +1880,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1522 if (tex.FaceTextures[i] != null) 1880 if (tex.FaceTextures[i] != null)
1523 { 1881 {
1524 tex.FaceTextures[i].Shiny = sval; 1882 tex.FaceTextures[i].Shiny = sval;
1525 tex.FaceTextures[i].Bump = bump;; 1883 tex.FaceTextures[i].Bump = bump;
1526 } 1884 }
1527 tex.DefaultTexture.Shiny = sval; 1885 tex.DefaultTexture.Shiny = sval;
1528 tex.DefaultTexture.Bump = bump; 1886 tex.DefaultTexture.Bump = bump;
@@ -1631,7 +1989,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1631 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); 1989 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1632 tex.DefaultTexture.RGBA = texcolor; 1990 tex.DefaultTexture.RGBA = texcolor;
1633 } 1991 }
1634 1992
1635 part.UpdateTextureEntry(tex.GetBytes()); 1993 part.UpdateTextureEntry(tex.GetBytes());
1636 return; 1994 return;
1637 } 1995 }
@@ -1703,9 +2061,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1703 part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); 2061 part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
1704 part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); 2062 part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
1705 part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); 2063 part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
1706 part.Shape.LightIntensity = intensity; 2064 part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f);
1707 part.Shape.LightRadius = radius; 2065 part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f);
1708 part.Shape.LightFalloff = falloff; 2066 part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f);
1709 } 2067 }
1710 else 2068 else
1711 { 2069 {
@@ -1752,7 +2110,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1752 rgb.x = texcolor.R; 2110 rgb.x = texcolor.R;
1753 rgb.y = texcolor.G; 2111 rgb.y = texcolor.G;
1754 rgb.z = texcolor.B; 2112 rgb.z = texcolor.B;
1755 2113
1756 return rgb; 2114 return rgb;
1757 } 2115 }
1758 else 2116 else
@@ -1765,7 +2123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1765 { 2123 {
1766 m_host.AddScriptLPS(1); 2124 m_host.AddScriptLPS(1);
1767 SetTexture(m_host, texture, face); 2125 SetTexture(m_host, texture, face);
1768 ScriptSleep(200); 2126 ScriptSleep(m_sleepMsOnSetTexture);
1769 } 2127 }
1770 2128
1771 public void llSetLinkTexture(int linknumber, string texture, int face) 2129 public void llSetLinkTexture(int linknumber, string texture, int face)
@@ -1777,19 +2135,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1777 foreach (SceneObjectPart part in parts) 2135 foreach (SceneObjectPart part in parts)
1778 SetTexture(part, texture, face); 2136 SetTexture(part, texture, face);
1779 2137
1780 ScriptSleep(200); 2138 ScriptSleep(m_sleepMsOnSetLinkTexture);
1781 } 2139 }
1782 2140
1783 protected void SetTexture(SceneObjectPart part, string texture, int face) 2141 protected void SetTexture(SceneObjectPart part, string texture, int face)
1784 { 2142 {
1785 UUID textureID = new UUID(); 2143 UUID textureID = new UUID();
1786 2144
1787 textureID = InventoryKey(texture, (int)AssetType.Texture); 2145 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
1788 if (textureID == UUID.Zero) 2146 if (textureID == UUID.Zero)
1789 { 2147 {
1790 if (!UUID.TryParse(texture, out textureID)) 2148 if (!UUID.TryParse(texture, out textureID))
1791 return; 2149 return;
1792 } 2150 }
1793 2151
1794 Primitive.TextureEntry tex = part.Shape.Textures; 2152 Primitive.TextureEntry tex = part.Shape.Textures;
1795 2153
@@ -1821,7 +2179,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1821 m_host.AddScriptLPS(1); 2179 m_host.AddScriptLPS(1);
1822 2180
1823 ScaleTexture(m_host, u, v, face); 2181 ScaleTexture(m_host, u, v, face);
1824 ScriptSleep(200); 2182 ScriptSleep(m_sleepMsOnScaleTexture);
1825 } 2183 }
1826 2184
1827 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2185 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
@@ -1857,7 +2215,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1857 { 2215 {
1858 m_host.AddScriptLPS(1); 2216 m_host.AddScriptLPS(1);
1859 OffsetTexture(m_host, u, v, face); 2217 OffsetTexture(m_host, u, v, face);
1860 ScriptSleep(200); 2218 ScriptSleep(m_sleepMsOnOffsetTexture);
1861 } 2219 }
1862 2220
1863 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2221 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
@@ -1893,7 +2251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1893 { 2251 {
1894 m_host.AddScriptLPS(1); 2252 m_host.AddScriptLPS(1);
1895 RotateTexture(m_host, rotation, face); 2253 RotateTexture(m_host, rotation, face);
1896 ScriptSleep(200); 2254 ScriptSleep(m_sleepMsOnRotateTexture);
1897 } 2255 }
1898 2256
1899 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2257 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
@@ -1968,7 +2326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1968 2326
1969 SetPos(m_host, pos, true); 2327 SetPos(m_host, pos, true);
1970 2328
1971 ScriptSleep(200); 2329 ScriptSleep(m_sleepMsOnSetPos);
1972 } 2330 }
1973 2331
1974 /// <summary> 2332 /// <summary>
@@ -1986,8 +2344,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1986 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. 2344 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
1987 // 2345 //
1988 // This workaround is to prevent silent failure of this function. 2346 // This workaround is to prevent silent failure of this function.
1989 // According to the specification on the SL Wiki, providing a position outside of the 2347 // According to the specification on the SL Wiki, providing a position outside of the
1990 if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize) 2348 if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
1991 { 2349 {
1992 return 0; 2350 return 0;
1993 } 2351 }
@@ -1997,9 +2355,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1997 m_host.ParentGroup.IsAttachment || // return FALSE if attachment 2355 m_host.ParentGroup.IsAttachment || // return FALSE if attachment
1998 ( 2356 (
1999 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. 2357 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
2000 pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2358 pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2001 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2359 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2002 pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. 2360 pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2003 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m 2361 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2004 ) 2362 )
2005 ) 2363 )
@@ -2151,14 +2509,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2151 } 2509 }
2152 } 2510 }
2153 2511
2154 ScriptSleep(200); 2512 ScriptSleep(m_sleepMsOnSetRot);
2155 } 2513 }
2156 2514
2157 public void llSetLocalRot(LSL_Rotation rot) 2515 public void llSetLocalRot(LSL_Rotation rot)
2158 { 2516 {
2159 m_host.AddScriptLPS(1); 2517 m_host.AddScriptLPS(1);
2160 SetRot(m_host, rot); 2518 SetRot(m_host, rot);
2161 ScriptSleep(200); 2519 ScriptSleep(m_sleepMsOnSetLocalRot);
2162 } 2520 }
2163 2521
2164 protected void SetRot(SceneObjectPart part, Quaternion rot) 2522 protected void SetRot(SceneObjectPart part, Quaternion rot)
@@ -2195,7 +2553,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2195 { 2553 {
2196 return llGetRootRotation(); 2554 return llGetRootRotation();
2197 } 2555 }
2198 2556
2199 m_host.AddScriptLPS(1); 2557 m_host.AddScriptLPS(1);
2200 Quaternion q = m_host.GetWorldRotation(); 2558 Quaternion q = m_host.GetWorldRotation();
2201 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2559 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
@@ -2214,23 +2572,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2214 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 2572 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2215 q = avatar.CameraRotation; // Mouselook 2573 q = avatar.CameraRotation; // Mouselook
2216 else 2574 else
2217 q = avatar.Rotation; // Currently infrequently updated so may be inaccurate 2575 q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
2218 } 2576 }
2219 else 2577 else
2220 q = part.ParentGroup.GroupRotation; // Likely never get here but just in case 2578 q = part.ParentGroup.GroupRotation; // Likely never get here but just in case
2221 } 2579 }
2222 else 2580 else
2223 q = part.ParentGroup.GroupRotation; // just the group rotation 2581 q = part.ParentGroup.GroupRotation; // just the group rotation
2224 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2582
2583 return new LSL_Rotation(q);
2225 } 2584 }
2226 q = part.GetWorldRotation(); 2585
2227 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2586 return new LSL_Rotation(part.GetWorldRotation());
2228 } 2587 }
2229 2588
2230 public LSL_Rotation llGetLocalRot() 2589 public LSL_Rotation llGetLocalRot()
2231 { 2590 {
2232 m_host.AddScriptLPS(1); 2591 m_host.AddScriptLPS(1);
2233 return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); 2592
2593 return new LSL_Rotation(m_host.RotationOffset);
2234 } 2594 }
2235 2595
2236 public void llSetForce(LSL_Vector force, int local) 2596 public void llSetForce(LSL_Vector force, int local)
@@ -2260,6 +2620,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2260 return force; 2620 return force;
2261 } 2621 }
2262 2622
2623 public void llSetVelocity(LSL_Vector velocity, int local)
2624 {
2625 m_host.AddScriptLPS(1);
2626
2627 if (!m_host.ParentGroup.IsDeleted)
2628 {
2629 if (local != 0)
2630 velocity *= llGetRot();
2631
2632 m_host.ParentGroup.RootPart.Velocity = velocity;
2633 }
2634 }
2635
2636 public void llSetAngularVelocity(LSL_Vector angularVelocity, int local)
2637 {
2638 m_host.AddScriptLPS(1);
2639
2640 if (!m_host.ParentGroup.IsDeleted)
2641 {
2642 if (local != 0)
2643 angularVelocity *= llGetRot();
2644
2645 m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity;
2646 }
2647 }
2648
2263 public LSL_Integer llTarget(LSL_Vector position, double range) 2649 public LSL_Integer llTarget(LSL_Vector position, double range)
2264 { 2650 {
2265 m_host.AddScriptLPS(1); 2651 m_host.AddScriptLPS(1);
@@ -2325,8 +2711,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2325 public LSL_Vector llGetTorque() 2711 public LSL_Vector llGetTorque()
2326 { 2712 {
2327 m_host.AddScriptLPS(1); 2713 m_host.AddScriptLPS(1);
2328 Vector3 torque = m_host.ParentGroup.GetTorque(); 2714
2329 return new LSL_Vector(torque.X,torque.Y,torque.Z); 2715 return new LSL_Vector(m_host.ParentGroup.GetTorque());
2330 } 2716 }
2331 2717
2332 public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) 2718 public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
@@ -2345,26 +2731,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2345 if (m_host.ParentGroup.IsAttachment) 2731 if (m_host.ParentGroup.IsAttachment)
2346 { 2732 {
2347 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 2733 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2348 vel = avatar.Velocity; 2734 vel = avatar.GetWorldVelocity();
2349 } 2735 }
2350 else 2736 else
2351 { 2737 {
2352 vel = m_host.Velocity; 2738 vel = m_host.Velocity;
2353 } 2739 }
2354 2740
2355 return new LSL_Vector(vel.X, vel.Y, vel.Z); 2741 return new LSL_Vector(vel);
2356 } 2742 }
2357 2743
2358 public LSL_Vector llGetAccel() 2744 public LSL_Vector llGetAccel()
2359 { 2745 {
2360 m_host.AddScriptLPS(1); 2746 m_host.AddScriptLPS(1);
2361 return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); 2747
2748 return new LSL_Vector(m_host.Acceleration);
2362 } 2749 }
2363 2750
2364 public LSL_Vector llGetOmega() 2751 public LSL_Vector llGetOmega()
2365 { 2752 {
2366 m_host.AddScriptLPS(1); 2753 m_host.AddScriptLPS(1);
2367 return new LSL_Vector(m_host.AngularVelocity.X, m_host.AngularVelocity.Y, m_host.AngularVelocity.Z); 2754
2755 return new LSL_Vector(m_host.AngularVelocity);
2368 } 2756 }
2369 2757
2370 public LSL_Float llGetTimeOfDay() 2758 public LSL_Float llGetTimeOfDay()
@@ -2403,9 +2791,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2403 public void llSound(string sound, double volume, int queue, int loop) 2791 public void llSound(string sound, double volume, int queue, int loop)
2404 { 2792 {
2405 m_host.AddScriptLPS(1); 2793 m_host.AddScriptLPS(1);
2406 // This function has been deprecated 2794 Deprecated("llSound", "Use llPlaySound instead");
2407 // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
2408 Deprecated("llSound");
2409 } 2795 }
2410 2796
2411 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound 2797 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
@@ -2417,9 +2803,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2417 // send the sound, once, to all clients in range 2803 // send the sound, once, to all clients in range
2418 if (m_SoundModule != null) 2804 if (m_SoundModule != null)
2419 { 2805 {
2420 m_SoundModule.SendSound(m_host.UUID, 2806 m_SoundModule.SendSound(
2421 KeyOrName(sound, AssetType.Sound), volume, false, 0, 2807 m_host.UUID,
2422 0, false, false); 2808 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
2809 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
2810 0, false, false);
2423 } 2811 }
2424 } 2812 }
2425 2813
@@ -2428,7 +2816,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2428 m_host.AddScriptLPS(1); 2816 m_host.AddScriptLPS(1);
2429 if (m_SoundModule != null) 2817 if (m_SoundModule != null)
2430 { 2818 {
2431 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2819 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2432 volume, 20, false); 2820 volume, 20, false);
2433 } 2821 }
2434 } 2822 }
@@ -2438,7 +2826,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2438 m_host.AddScriptLPS(1); 2826 m_host.AddScriptLPS(1);
2439 if (m_SoundModule != null) 2827 if (m_SoundModule != null)
2440 { 2828 {
2441 m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), 2829 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2442 volume, 20, true); 2830 volume, 20, true);
2443 } 2831 }
2444 } 2832 }
@@ -2460,7 +2848,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2460 if (m_SoundModule != null) 2848 if (m_SoundModule != null)
2461 { 2849 {
2462 m_SoundModule.SendSound(m_host.UUID, 2850 m_SoundModule.SendSound(m_host.UUID,
2463 KeyOrName(sound, AssetType.Sound), volume, false, 0, 2851 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
2464 0, true, false); 2852 0, true, false);
2465 } 2853 }
2466 } 2854 }
@@ -2472,7 +2860,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2472 if (m_SoundModule != null) 2860 if (m_SoundModule != null)
2473 { 2861 {
2474 m_SoundModule.SendSound(m_host.UUID, 2862 m_SoundModule.SendSound(m_host.UUID,
2475 KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, 2863 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0,
2476 false, false); 2864 false, false);
2477 } 2865 }
2478 } 2866 }
@@ -2489,8 +2877,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2489 { 2877 {
2490 m_host.AddScriptLPS(1); 2878 m_host.AddScriptLPS(1);
2491 if (m_SoundModule != null) 2879 if (m_SoundModule != null)
2492 m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); 2880 m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
2493 ScriptSleep(1000); 2881 ScriptSleep(m_sleepMsOnPreloadSound);
2494 } 2882 }
2495 2883
2496 /// <summary> 2884 /// <summary>
@@ -2723,70 +3111,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2723 return src.ToLower(); 3111 return src.ToLower();
2724 } 3112 }
2725 3113
2726 public LSL_Integer llGiveMoney(string destination, int amount) 3114 public void llGiveMoney(string destination, int amount)
2727 { 3115 {
2728 m_host.AddScriptLPS(1); 3116 Util.FireAndForget(x =>
2729
2730 if (m_item.PermsGranter == UUID.Zero)
2731 return 0;
2732
2733 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
2734 { 3117 {
2735 LSLError("No permissions to give money"); 3118 m_host.AddScriptLPS(1);
2736 return 0;
2737 }
2738 3119
2739 UUID toID = new UUID(); 3120 if (m_item.PermsGranter == UUID.Zero)
3121 return;
2740 3122
2741 if (!UUID.TryParse(destination, out toID)) 3123 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
2742 { 3124 {
2743 LSLError("Bad key in llGiveMoney"); 3125 Error("llGiveMoney", "No permissions to give money");
2744 return 0; 3126 return;
2745 } 3127 }
2746 3128
2747 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); 3129 UUID toID = new UUID();
2748 3130
2749 if (money == null) 3131 if (!UUID.TryParse(destination, out toID))
2750 { 3132 {
2751 NotImplemented("llGiveMoney"); 3133 Error("llGiveMoney", "Bad key in llGiveMoney");
2752 return 0; 3134 return;
2753 } 3135 }
2754 3136
2755 bool result = money.ObjectGiveMoney( 3137 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
2756 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
2757 3138
2758 if (result) 3139 if (money == null)
2759 return 1; 3140 {
3141 NotImplemented("llGiveMoney");
3142 return;
3143 }
2760 3144
2761 return 0; 3145 money.ObjectGiveMoney(
3146 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
3147 }, null, "LSL_Api.llGiveMoney");
2762 } 3148 }
2763 3149
2764 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3150 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
2765 { 3151 {
2766 m_host.AddScriptLPS(1); 3152 m_host.AddScriptLPS(1);
2767 Deprecated("llMakeExplosion"); 3153 Deprecated("llMakeExplosion", "Use llParticleSystem instead");
2768 ScriptSleep(100); 3154 ScriptSleep(m_sleepMsOnMakeExplosion);
2769 } 3155 }
2770 3156
2771 public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset) 3157 public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
2772 { 3158 {
2773 m_host.AddScriptLPS(1); 3159 m_host.AddScriptLPS(1);
2774 Deprecated("llMakeFountain"); 3160 Deprecated("llMakeFountain", "Use llParticleSystem instead");
2775 ScriptSleep(100); 3161 ScriptSleep(m_sleepMsOnMakeFountain);
2776 } 3162 }
2777 3163
2778 public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3164 public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
2779 { 3165 {
2780 m_host.AddScriptLPS(1); 3166 m_host.AddScriptLPS(1);
2781 Deprecated("llMakeSmoke"); 3167 Deprecated("llMakeSmoke", "Use llParticleSystem instead");
2782 ScriptSleep(100); 3168 ScriptSleep(m_sleepMsOnMakeSmoke);
2783 } 3169 }
2784 3170
2785 public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3171 public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
2786 { 3172 {
2787 m_host.AddScriptLPS(1); 3173 m_host.AddScriptLPS(1);
2788 Deprecated("llMakeFire"); 3174 Deprecated("llMakeFire", "Use llParticleSystem instead");
2789 ScriptSleep(100); 3175 ScriptSleep(m_sleepMsOnMakeFire);
2790 } 3176 }
2791 3177
2792 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3178 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
@@ -2807,54 +3193,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2807 3193
2808 if (item == null) 3194 if (item == null)
2809 { 3195 {
2810 llSay(0, "Could not find object " + inventory); 3196 Error("llRezAtRoot", "Can't find object '" + inventory + "'");
2811 return; 3197 return;
2812 } 3198 }
2813 3199
2814 if (item.InvType != (int)InventoryType.Object) 3200 if (item.InvType != (int)InventoryType.Object)
2815 { 3201 {
2816 llSay(0, "Unable to create requested object. Object is missing from database."); 3202 Error("llRezAtRoot", "Can't create requested object; object is missing from database");
2817 return; 3203 return;
2818 } 3204 }
2819 3205
2820 // need the magnitude later 3206 // need the magnitude later
2821 // float velmag = (float)Util.GetMagnitude(llvel); 3207 // float velmag = (float)Util.GetMagnitude(llvel);
2822 3208
2823 SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); 3209 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
2824 3210
2825 // If either of these are null, then there was an unknown error. 3211 // If either of these are null, then there was an unknown error.
2826 if (new_group == null) 3212 if (new_groups == null)
2827 return; 3213 return;
2828 3214
2829 // objects rezzed with this method are die_at_edge by default. 3215 foreach (SceneObjectGroup group in new_groups)
2830 new_group.RootPart.SetDieAtEdge(true); 3216 {
3217 // objects rezzed with this method are die_at_edge by default.
3218 group.RootPart.SetDieAtEdge(true);
2831 3219
2832 new_group.ResumeScripts(); 3220 group.ResumeScripts();
2833 3221
2834 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3222 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
2835 "object_rez", new Object[] { 3223 "object_rez", new Object[] {
2836 new LSL_String( 3224 new LSL_String(
2837 new_group.RootPart.UUID.ToString()) }, 3225 group.RootPart.UUID.ToString()) },
2838 new DetectParams[0])); 3226 new DetectParams[0]));
2839 3227
2840 float groupmass = new_group.GetMass(); 3228 float groupmass = group.GetMass();
2841 3229
2842 PhysicsActor pa = new_group.RootPart.PhysActor; 3230 PhysicsActor pa = group.RootPart.PhysActor;
2843 3231
2844 //Recoil. 3232 //Recoil.
2845 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3233 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
2846 {
2847 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
2848 if (recoil != Vector3.Zero)
2849 { 3234 {
2850 llApplyImpulse(recoil, 0); 3235 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3236 if (recoil != Vector3.Zero)
3237 {
3238 llApplyImpulse(recoil, 0);
3239 }
2851 } 3240 }
3241 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
2852 } 3242 }
2853 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3243 }, null, "LSL_Api.llRezAtRoot");
2854 });
2855 3244
2856 //ScriptSleep((int)((groupmass * velmag) / 10)); 3245 //ScriptSleep((int)((groupmass * velmag) / 10));
2857 ScriptSleep(100); 3246 ScriptSleep(m_sleepMsOnRezAtRoot);
2858 } 3247 }
2859 3248
2860 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3249 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
@@ -2868,26 +3257,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2868 // Determine where we are looking from 3257 // Determine where we are looking from
2869 LSL_Vector from = llGetPos(); 3258 LSL_Vector from = llGetPos();
2870 3259
2871 // Work out the normalised vector from the source to the target 3260 // normalized direction to target
2872 LSL_Vector delta = llVecNorm(target - from); 3261 LSL_Vector dir = llVecNorm(target - from);
2873 LSL_Vector angle = new LSL_Vector(0,0,0); 3262 // use vertical to help compute left axis
3263 LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
3264 // find normalized left axis parallel to horizon
3265 LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
3266 // make up orthogonal to left and dir
3267 up = LSL_Vector.Cross(dir, left);
2874 3268
2875 // Calculate the yaw 3269 // compute rotation based on orthogonal axes
2876 // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system 3270 LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up);
2877 angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO;
2878 3271
2879 // Calculate pitch
2880 angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z)));
2881
2882 // we need to convert from a vector describing
2883 // the angles of rotation in radians into rotation value
2884 LSL_Rotation rot = llEuler2Rot(angle);
2885
2886 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3272 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
2887 // set the rotation of the object, copy that behavior 3273 // set the rotation of the object, copy that behavior
2888 PhysicsActor pa = m_host.PhysActor; 3274 PhysicsActor pa = m_host.PhysActor;
2889 3275
2890 if (strength == 0 || pa == null || !pa.IsPhysical) 3276 if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical)
2891 { 3277 {
2892 llSetRot(rot); 3278 llSetRot(rot);
2893 } 3279 }
@@ -2900,7 +3286,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2900 public void llStopLookAt() 3286 public void llStopLookAt()
2901 { 3287 {
2902 m_host.AddScriptLPS(1); 3288 m_host.AddScriptLPS(1);
2903// NotImplemented("llStopLookAt");
2904 m_host.StopLookAt(); 3289 m_host.StopLookAt();
2905 } 3290 }
2906 3291
@@ -2917,7 +3302,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2917 { 3302 {
2918// m_log.Info("llSleep snoozing " + sec + "s."); 3303// m_log.Info("llSleep snoozing " + sec + "s.");
2919 m_host.AddScriptLPS(1); 3304 m_host.AddScriptLPS(1);
2920 Thread.Sleep((int)(sec * 1000)); 3305
3306 Sleep((int)(sec * 1000));
2921 } 3307 }
2922 3308
2923 public LSL_Float llGetMass() 3309 public LSL_Float llGetMass()
@@ -2950,6 +3336,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2950 } 3336 }
2951 } 3337 }
2952 3338
3339 public LSL_Float llGetMassMKS()
3340 {
3341 // this is what the wiki says it does!
3342 // http://wiki.secondlife.com/wiki/LlGetMassMKS
3343 return llGetMass() * 100.0;
3344 }
3345
2953 public void llCollisionFilter(string name, string id, int accept) 3346 public void llCollisionFilter(string name, string id, int accept)
2954 { 3347 {
2955 m_host.AddScriptLPS(1); 3348 m_host.AddScriptLPS(1);
@@ -2958,7 +3351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2958 3351
2959 if (!UUID.TryParse(id, out objectID)) 3352 if (!UUID.TryParse(id, out objectID))
2960 objectID = UUID.Zero; 3353 objectID = UUID.Zero;
2961 3354
2962 if (objectID == UUID.Zero && name == "") 3355 if (objectID == UUID.Zero && name == "")
2963 return; 3356 return;
2964 3357
@@ -3026,7 +3419,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3026 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3419 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3027 3420
3028 if (attachmentsModule != null) 3421 if (attachmentsModule != null)
3029 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, false); 3422 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true);
3030 else 3423 else
3031 return false; 3424 return false;
3032 } 3425 }
@@ -3039,7 +3432,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3039 /// </remarks> 3432 /// </remarks>
3040 public void DetachFromAvatar() 3433 public void DetachFromAvatar()
3041 { 3434 {
3042 Util.FireAndForget(DetachWrapper, m_host); 3435 Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar");
3043 } 3436 }
3044 3437
3045 private void DetachWrapper(object o) 3438 private void DetachWrapper(object o)
@@ -3083,13 +3476,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3083 public void llTakeCamera(string avatar) 3476 public void llTakeCamera(string avatar)
3084 { 3477 {
3085 m_host.AddScriptLPS(1); 3478 m_host.AddScriptLPS(1);
3086 Deprecated("llTakeCamera"); 3479 Deprecated("llTakeCamera", "Use llSetCameraParams instead");
3087 } 3480 }
3088 3481
3089 public void llReleaseCamera(string avatar) 3482 public void llReleaseCamera(string avatar)
3090 { 3483 {
3091 m_host.AddScriptLPS(1); 3484 m_host.AddScriptLPS(1);
3092 Deprecated("llReleaseCamera"); 3485 Deprecated("llReleaseCamera", "Use llClearCameraParams instead");
3093 } 3486 }
3094 3487
3095 public LSL_String llGetOwner() 3488 public LSL_String llGetOwner()
@@ -3112,14 +3505,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3112 3505
3113 // TODO: figure out values for client, fromSession, and imSessionID 3506 // TODO: figure out values for client, fromSession, and imSessionID
3114 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); 3507 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
3115 UUID friendTransactionID = UUID.Random();
3116
3117 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
3118 3508
3119 GridInstantMessage msg = new GridInstantMessage(); 3509 GridInstantMessage msg = new GridInstantMessage();
3120 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; 3510 msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid;
3121 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3511 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3122 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here 3512 msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here
3123// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3513// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3124// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3514// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3125 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3515 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
@@ -3142,20 +3532,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3142 msg.ParentEstateID = 0; //ParentEstateID; 3532 msg.ParentEstateID = 0; //ParentEstateID;
3143 msg.Position = new Vector3(m_host.AbsolutePosition); 3533 msg.Position = new Vector3(m_host.AbsolutePosition);
3144 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3534 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
3145 msg.binaryBucket 3535
3536 Vector3 pos = m_host.AbsolutePosition;
3537 msg.binaryBucket
3146 = Util.StringToBytes256( 3538 = Util.StringToBytes256(
3147 "{0}/{1}/{2}/{3}", 3539 "{0}/{1}/{2}/{3}",
3148 World.RegionInfo.RegionName, 3540 World.RegionInfo.RegionName,
3149 (int)Math.Floor(m_host.AbsolutePosition.X), 3541 (int)Math.Floor(pos.X),
3150 (int)Math.Floor(m_host.AbsolutePosition.Y), 3542 (int)Math.Floor(pos.Y),
3151 (int)Math.Floor(m_host.AbsolutePosition.Z)); 3543 (int)Math.Floor(pos.Z));
3152 3544
3153 if (m_TransferModule != null) 3545 if (m_TransferModule != null)
3154 { 3546 {
3155 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 3547 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
3156 } 3548 }
3157 3549
3158 ScriptSleep(2000); 3550 ScriptSleep(m_sleepMsOnInstantMessage);
3159 } 3551 }
3160 3552
3161 public void llEmail(string address, string subject, string message) 3553 public void llEmail(string address, string subject, string message)
@@ -3164,12 +3556,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3164 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); 3556 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
3165 if (emailModule == null) 3557 if (emailModule == null)
3166 { 3558 {
3167 ShoutError("llEmail: email module not configured"); 3559 Error("llEmail", "Email module not configured");
3168 return; 3560 return;
3169 } 3561 }
3170 3562
3563 //Restrict email destination to the avatars registered email address?
3564 //The restriction only applies if the destination address is not local.
3565 if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false)
3566 {
3567 UserAccount account =
3568 World.UserAccountService.GetUserAccount(
3569 World.RegionInfo.ScopeID,
3570 m_host.OwnerID);
3571
3572 if (account == null)
3573 {
3574 Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'");
3575 return;
3576 }
3577
3578 if (String.IsNullOrEmpty(account.Email))
3579 {
3580 Error("llEmail", "User account has not registered an email address.");
3581 return;
3582 }
3583
3584 address = account.Email;
3585 }
3586
3171 emailModule.SendEmail(m_host.UUID, address, subject, message); 3587 emailModule.SendEmail(m_host.UUID, address, subject, message);
3172 llSleep(EMAIL_PAUSE_TIME); 3588 ScriptSleep(m_sleepMsOnEmail);
3173 } 3589 }
3174 3590
3175 public void llGetNextEmail(string address, string subject) 3591 public void llGetNextEmail(string address, string subject)
@@ -3178,7 +3594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3178 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); 3594 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
3179 if (emailModule == null) 3595 if (emailModule == null)
3180 { 3596 {
3181 ShoutError("llGetNextEmail: email module not configured"); 3597 Error("llGetNextEmail", "Email module not configured");
3182 return; 3598 return;
3183 } 3599 }
3184 Email email; 3600 Email email;
@@ -3263,23 +3679,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3263 catch (NotImplementedException) 3679 catch (NotImplementedException)
3264 { 3680 {
3265 // Currently not implemented in DotNetEngine only XEngine 3681 // Currently not implemented in DotNetEngine only XEngine
3266 NotImplemented("llMinEventDelay in DotNetEngine"); 3682 NotImplemented("llMinEventDelay", "In DotNetEngine");
3267 } 3683 }
3268 } 3684 }
3269 3685
3270 /// <summary>
3271 /// llSoundPreload is deprecated. In SL this appears to do absolutely nothing
3272 /// and is documented to have no delay.
3273 /// </summary>
3274 public void llSoundPreload(string sound) 3686 public void llSoundPreload(string sound)
3275 { 3687 {
3276 m_host.AddScriptLPS(1); 3688 m_host.AddScriptLPS(1);
3689 Deprecated("llSoundPreload", "Use llPreloadSound instead");
3277 } 3690 }
3278 3691
3279 public void llRotLookAt(LSL_Rotation target, double strength, double damping) 3692 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3280 { 3693 {
3281 m_host.AddScriptLPS(1); 3694 m_host.AddScriptLPS(1);
3282 3695
3283 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3696 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
3284 // set the rotation of the object, copy that behavior 3697 // set the rotation of the object, copy that behavior
3285 PhysicsActor pa = m_host.PhysActor; 3698 PhysicsActor pa = m_host.PhysActor;
@@ -3321,7 +3734,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3321 if (presence != null) 3734 if (presence != null)
3322 { 3735 {
3323 // Do NOT try to parse UUID, animations cannot be triggered by ID 3736 // Do NOT try to parse UUID, animations cannot be triggered by ID
3324 UUID animID = InventoryKey(anim, (int)AssetType.Animation); 3737 UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
3325 if (animID == UUID.Zero) 3738 if (animID == UUID.Zero)
3326 presence.Animator.AddAnimation(anim, m_host.UUID); 3739 presence.Animator.AddAnimation(anim, m_host.UUID);
3327 else 3740 else
@@ -3343,7 +3756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3343 3756
3344 if (presence != null) 3757 if (presence != null)
3345 { 3758 {
3346 UUID animID = KeyOrName(anim); 3759 UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim);
3347 3760
3348 if (animID == UUID.Zero) 3761 if (animID == UUID.Zero)
3349 presence.Animator.RemoveAnimation(anim); 3762 presence.Animator.RemoveAnimation(anim);
@@ -3371,6 +3784,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3371 3784
3372 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) 3785 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
3373 { 3786 {
3787 PhysicsActor pa = part.PhysActor;
3788 if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d )
3789 spinrate = 0.0d;
3374 part.UpdateAngularVelocity(axis * spinrate); 3790 part.UpdateAngularVelocity(axis * spinrate);
3375 } 3791 }
3376 3792
@@ -3415,11 +3831,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3415 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3831 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3416 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3832 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3417 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3833 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3834 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3418 ScriptBaseClass.PERMISSION_ATTACH; 3835 ScriptBaseClass.PERMISSION_ATTACH;
3419 } 3836 }
3420 else 3837 else
3421 { 3838 {
3422 if (m_host.ParentGroup.GetSittingAvatars().Contains(agentID)) 3839 if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null)
3423 { 3840 {
3424 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3841 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3425 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3842 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
@@ -3451,10 +3868,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3451 } 3868 }
3452 3869
3453 ScenePresence presence = World.GetScenePresence(agentID); 3870 ScenePresence presence = World.GetScenePresence(agentID);
3871
3454 if (presence != null) 3872 if (presence != null)
3455 { 3873 {
3456 // If permissions are being requested from an NPC and were not implicitly granted above then 3874 // If permissions are being requested from an NPC and were not implicitly granted above then
3457 // auto grant all reuqested permissions if the script is owned by the NPC or the NPCs owner 3875 // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner
3458 INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); 3876 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
3459 if (npcModule != null && npcModule.IsNPC(agentID, World)) 3877 if (npcModule != null && npcModule.IsNPC(agentID, World))
3460 { 3878 {
@@ -3570,22 +3988,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3570 public void llCreateLink(string target, int parent) 3988 public void llCreateLink(string target, int parent)
3571 { 3989 {
3572 m_host.AddScriptLPS(1); 3990 m_host.AddScriptLPS(1);
3573 UUID targetID;
3574
3575 if (!UUID.TryParse(target, out targetID))
3576 return;
3577 3991
3578 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 3992 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3579 && !m_automaticLinkPermission) 3993 && !m_automaticLinkPermission)
3580 { 3994 {
3581 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 3995 Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set");
3582 return; 3996 return;
3583 } 3997 }
3584 3998
3585 IClientAPI client = null; 3999 CreateLink(target, parent);
3586 ScenePresence sp = World.GetScenePresence(m_item.PermsGranter); 4000 }
3587 if (sp != null) 4001
3588 client = sp.ControllingClient; 4002 public void CreateLink(string target, int parent)
4003 {
4004 UUID targetID;
4005
4006 if (!UUID.TryParse(target, out targetID))
4007 return;
3589 4008
3590 SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); 4009 SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID);
3591 4010
@@ -3620,10 +4039,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3620 parentPrim.HasGroupChanged = true; 4039 parentPrim.HasGroupChanged = true;
3621 parentPrim.ScheduleGroupForFullUpdate(); 4040 parentPrim.ScheduleGroupForFullUpdate();
3622 4041
4042 IClientAPI client = null;
4043 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
4044 if (sp != null)
4045 client = sp.ControllingClient;
4046
3623 if (client != null) 4047 if (client != null)
3624 parentPrim.SendPropertiesToClient(client); 4048 parentPrim.SendPropertiesToClient(client);
3625 4049
3626 ScriptSleep(1000); 4050 ScriptSleep(m_sleepMsOnCreateLink);
3627 } 4051 }
3628 4052
3629 public void llBreakLink(int linknum) 4053 public void llBreakLink(int linknum)
@@ -3633,10 +4057,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3633 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4057 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
3634 && !m_automaticLinkPermission) 4058 && !m_automaticLinkPermission)
3635 { 4059 {
3636 ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); 4060 Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set");
3637 return; 4061 return;
3638 } 4062 }
3639 4063
4064 BreakLink(linknum);
4065 }
4066
4067 public void BreakLink(int linknum)
4068 {
3640 if (linknum < ScriptBaseClass.LINK_THIS) 4069 if (linknum < ScriptBaseClass.LINK_THIS)
3641 return; 4070 return;
3642 4071
@@ -3712,6 +4141,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3712 public void llBreakAllLinks() 4141 public void llBreakAllLinks()
3713 { 4142 {
3714 m_host.AddScriptLPS(1); 4143 m_host.AddScriptLPS(1);
4144
4145 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4146 && !m_automaticLinkPermission)
4147 {
4148 Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set");
4149 return;
4150 }
4151
4152 BreakAllLinks();
4153 }
4154
4155 public void BreakAllLinks()
4156 {
3715 SceneObjectGroup parentPrim = m_host.ParentGroup; 4157 SceneObjectGroup parentPrim = m_host.ParentGroup;
3716 if (parentPrim.AttachmentPoint != 0) 4158 if (parentPrim.AttachmentPoint != 0)
3717 return; // Fail silently if attached 4159 return; // Fail silently if attached
@@ -3732,47 +4174,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3732 { 4174 {
3733 m_host.AddScriptLPS(1); 4175 m_host.AddScriptLPS(1);
3734 4176
3735 if (linknum < 0) 4177 ISceneEntity entity = GetLinkEntity(m_host, linknum);
3736 {
3737 if (linknum == ScriptBaseClass.LINK_THIS)
3738 return m_host.UUID.ToString();
3739 else
3740 return ScriptBaseClass.NULL_KEY;
3741 }
3742
3743 int actualPrimCount = m_host.ParentGroup.PrimCount;
3744 List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars();
3745 int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count;
3746
3747 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
3748 // prim that has any avatars sat upon it (in which case the root prim is link 1).
3749 if (linknum == 0)
3750 {
3751 if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
3752 return m_host.UUID.ToString();
3753 4178
3754 return ScriptBaseClass.NULL_KEY; 4179 if (entity != null)
3755 } 4180 return entity.UUID.ToString();
3756 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
3757 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
3758 else if (linknum == 1 && actualPrimCount == 1)
3759 {
3760 if (sittingAvatarIds.Count > 0)
3761 return m_host.ParentGroup.RootPart.UUID.ToString();
3762 else
3763 return ScriptBaseClass.NULL_KEY;
3764 }
3765 else if (linknum <= adjustedPrimCount)
3766 {
3767 if (linknum <= actualPrimCount)
3768 return m_host.ParentGroup.GetLinkNumPart(linknum).UUID.ToString();
3769 else
3770 return sittingAvatarIds[linknum - actualPrimCount - 1].ToString();
3771 }
3772 else 4181 else
3773 {
3774 return ScriptBaseClass.NULL_KEY; 4182 return ScriptBaseClass.NULL_KEY;
3775 }
3776 } 4183 }
3777 4184
3778 /// <summary> 4185 /// <summary>
@@ -3818,55 +4225,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3818 { 4225 {
3819 m_host.AddScriptLPS(1); 4226 m_host.AddScriptLPS(1);
3820 4227
3821 if (linknum < 0) 4228 ISceneEntity entity = GetLinkEntity(m_host, linknum);
3822 {
3823 if (linknum == ScriptBaseClass.LINK_THIS)
3824 return m_host.Name;
3825 else
3826 return ScriptBaseClass.NULL_KEY;
3827 }
3828 4229
3829 int actualPrimCount = m_host.ParentGroup.PrimCount; 4230 if (entity != null)
3830 List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); 4231 return entity.Name;
3831 int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count;
3832
3833 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
3834 // prim that has any avatars sat upon it (in which case the root prim is link 1).
3835 if (linknum == 0)
3836 {
3837 if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
3838 return m_host.Name;
3839
3840 return ScriptBaseClass.NULL_KEY;
3841 }
3842 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
3843 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
3844 else if (linknum == 1 && actualPrimCount == 1)
3845 {
3846 if (sittingAvatarIds.Count > 0)
3847 return m_host.ParentGroup.RootPart.Name;
3848 else
3849 return ScriptBaseClass.NULL_KEY;
3850 }
3851 else if (linknum <= adjustedPrimCount)
3852 {
3853 if (linknum <= actualPrimCount)
3854 {
3855 return m_host.ParentGroup.GetLinkNumPart(linknum).Name;
3856 }
3857 else
3858 {
3859 ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]);
3860 if (sp != null)
3861 return sp.Name;
3862 else
3863 return ScriptBaseClass.NULL_KEY;
3864 }
3865 }
3866 else 4232 else
3867 {
3868 return ScriptBaseClass.NULL_KEY; 4233 return ScriptBaseClass.NULL_KEY;
3869 }
3870 } 4234 }
3871 4235
3872 public LSL_Integer llGetInventoryNumber(int type) 4236 public LSL_Integer llGetInventoryNumber(int type)
@@ -3931,7 +4295,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3931 4295
3932 if (!UUID.TryParse(destination, out destId)) 4296 if (!UUID.TryParse(destination, out destId))
3933 { 4297 {
3934 llSay(0, "Could not parse key " + destination); 4298 Error("llGiveInventory", "Can't parse destination key '" + destination + "'");
3935 return; 4299 return;
3936 } 4300 }
3937 4301
@@ -3939,8 +4303,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3939 4303
3940 if (item == null) 4304 if (item == null)
3941 { 4305 {
3942 llSay(0, String.Format("Could not find object '{0}'", inventory)); 4306 Error("llGiveInventory", "Can't find inventory object '" + inventory + "'");
3943 throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); 4307 return;
3944 } 4308 }
3945 4309
3946 UUID objId = item.ItemID; 4310 UUID objId = item.ItemID;
@@ -3964,15 +4328,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3964 4328
3965 if (account == null) 4329 if (account == null)
3966 { 4330 {
3967 llSay(0, "Can't find destination "+destId.ToString()); 4331 GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString());
3968 return; 4332 if(info == null || info.Online == false)
4333 {
4334 Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'");
4335 return;
4336 }
3969 } 4337 }
3970 } 4338 }
3971 // destination is an avatar 4339 // destination is an avatar
3972 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); 4340 string message;
4341 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message);
3973 4342
3974 if (agentItem == null) 4343 if (agentItem == null)
4344 {
4345 llSay(0, message);
3975 return; 4346 return;
4347 }
3976 4348
3977 if (m_TransferModule != null) 4349 if (m_TransferModule != null)
3978 { 4350 {
@@ -3991,7 +4363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3991 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4363 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
3992 } 4364 }
3993 4365
3994 ScriptSleep(3000); 4366 ScriptSleep(m_sleepMsOnGiveInventory);
3995 } 4367 }
3996 } 4368 }
3997 4369
@@ -4054,87 +4426,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4054 UserAccount account; 4426 UserAccount account;
4055 4427
4056 UserInfoCacheEntry ce; 4428 UserInfoCacheEntry ce;
4057 if (!m_userInfoCache.TryGetValue(uuid, out ce)) 4429
4430 lock (m_userInfoCache)
4058 { 4431 {
4059 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4432 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4060 if (account == null)
4061 { 4433 {
4062 m_userInfoCache[uuid] = null; // Cache negative 4434 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4063 return UUID.Zero.ToString(); 4435 if (account == null)
4064 } 4436 {
4065 4437 m_userInfoCache[uuid] = null; // Cache negative
4438 return UUID.Zero.ToString();
4439 }
4066 4440
4067 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4441 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4068 if (pinfos != null && pinfos.Length > 0) 4442 if (pinfos != null && pinfos.Length > 0)
4069 {
4070 foreach (PresenceInfo p in pinfos)
4071 { 4443 {
4072 if (p.RegionID != UUID.Zero) 4444 foreach (PresenceInfo p in pinfos)
4073 { 4445 {
4074 pinfo = p; 4446 if (p.RegionID != UUID.Zero)
4447 {
4448 pinfo = p;
4449 }
4075 } 4450 }
4076 } 4451 }
4077 }
4078 4452
4079 ce = new UserInfoCacheEntry(); 4453 ce = new UserInfoCacheEntry();
4080 ce.time = Util.EnvironmentTickCount(); 4454 ce.time = Util.EnvironmentTickCount();
4081 ce.account = account; 4455 ce.account = account;
4082 ce.pinfo = pinfo; 4456 ce.pinfo = pinfo;
4083 }
4084 else
4085 {
4086 if (ce == null)
4087 return UUID.Zero.ToString();
4088
4089 account = ce.account;
4090 pinfo = ce.pinfo;
4091 }
4092 4457
4093 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) 4458 m_userInfoCache[uuid] = ce;
4094 { 4459 }
4095 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4460 else
4096 if (pinfos != null && pinfos.Length > 0)
4097 { 4461 {
4098 foreach (PresenceInfo p in pinfos) 4462 if (ce == null)
4463 return UUID.Zero.ToString();
4464
4465 account = ce.account;
4466
4467 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time)
4468 >= LlRequestAgentDataCacheTimeoutMs)
4099 { 4469 {
4100 if (p.RegionID != UUID.Zero) 4470 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4471 if (pinfos != null && pinfos.Length > 0)
4101 { 4472 {
4102 pinfo = p; 4473 foreach (PresenceInfo p in pinfos)
4474 {
4475 if (p.RegionID != UUID.Zero)
4476 {
4477 pinfo = p;
4478 }
4479 }
4103 } 4480 }
4481 else
4482 {
4483 pinfo = null;
4484 }
4485
4486 ce.time = Util.EnvironmentTickCount();
4487 ce.pinfo = pinfo;
4488 }
4489 else
4490 {
4491 pinfo = ce.pinfo;
4104 } 4492 }
4105 } 4493 }
4106 else
4107 pinfo = null;
4108
4109 ce.time = Util.EnvironmentTickCount();
4110 ce.pinfo = pinfo;
4111 } 4494 }
4112 4495
4113 string reply = String.Empty; 4496 string reply = String.Empty;
4114 4497
4115 switch (data) 4498 switch (data)
4116 { 4499 {
4117 case 1: // DATA_ONLINE (0|1) 4500 case ScriptBaseClass.DATA_ONLINE:
4118 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4501 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4119 reply = "1"; 4502 reply = "1";
4120 else 4503 else
4121 reply = "0"; 4504 reply = "0";
4122 break; 4505 break;
4123 case 2: // DATA_NAME (First Last) 4506 case ScriptBaseClass.DATA_NAME: // (First Last)
4124 reply = account.FirstName + " " + account.LastName; 4507 reply = account.FirstName + " " + account.LastName;
4125 break; 4508 break;
4126 case 3: // DATA_BORN (YYYY-MM-DD) 4509 case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD)
4127 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4510 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4128 born = born.AddSeconds(account.Created); 4511 born = born.AddSeconds(account.Created);
4129 reply = born.ToString("yyyy-MM-dd"); 4512 reply = born.ToString("yyyy-MM-dd");
4130 break; 4513 break;
4131 case 4: // DATA_RATING (0,0,0,0,0,0) 4514 case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0)
4132 reply = "0,0,0,0,0,0"; 4515 reply = "0,0,0,0,0,0";
4133 break; 4516 break;
4134 case 7: // DATA_USERLEVEL (integer) 4517 case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant.
4135 reply = account.UserLevel.ToString(); 4518 reply = account.UserLevel.ToString();
4136 break; 4519 break;
4137 case 8: // DATA_PAYINFO (0|1|2|3) 4520 case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3)
4138 reply = "0"; 4521 reply = "0";
4139 break; 4522 break;
4140 default: 4523 default:
@@ -4150,7 +4533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4150 AsyncCommands. 4533 AsyncCommands.
4151 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4534 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4152 4535
4153 ScriptSleep(100); 4536 ScriptSleep(m_sleepMsOnRequestAgentData);
4154 return tid.ToString(); 4537 return tid.ToString();
4155 } 4538 }
4156 4539
@@ -4166,10 +4549,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4166 DataserverPlugin.RegisterRequest(m_host.LocalId, 4549 DataserverPlugin.RegisterRequest(m_host.LocalId,
4167 m_item.ItemID, item.AssetID.ToString()); 4550 m_item.ItemID, item.AssetID.ToString());
4168 4551
4169 Vector3 region = new Vector3( 4552 Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
4170 World.RegionInfo.RegionLocX * Constants.RegionSize,
4171 World.RegionInfo.RegionLocY * Constants.RegionSize,
4172 0);
4173 4553
4174 World.AssetService.Get(item.AssetID.ToString(), this, 4554 World.AssetService.Get(item.AssetID.ToString(), this,
4175 delegate(string i, object sender, AssetBase a) 4555 delegate(string i, object sender, AssetBase a)
@@ -4186,12 +4566,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4186 reply); 4566 reply);
4187 }); 4567 });
4188 4568
4189 ScriptSleep(1000); 4569 ScriptSleep(m_sleepMsOnRequestInventoryData);
4190 return tid.ToString(); 4570 return tid.ToString();
4191 } 4571 }
4192 } 4572 }
4193 4573
4194 ScriptSleep(1000); 4574 ScriptSleep(m_sleepMsOnRequestInventoryData);
4195 return String.Empty; 4575 return String.Empty;
4196 } 4576 }
4197 4577
@@ -4211,14 +4591,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4211 if (presence != null) 4591 if (presence != null)
4212 { 4592 {
4213 // agent must be over the owners land 4593 // agent must be over the owners land
4214 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4594 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4215 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4216 { 4595 {
4217 World.TeleportClientHome(agentId, presence.ControllingClient); 4596 World.TeleportClientHome(agentId, presence.ControllingClient);
4218 } 4597 }
4219 } 4598 }
4220 } 4599 }
4221 ScriptSleep(5000); 4600
4601 ScriptSleep(m_sleepMsOnSetDamage);
4222 } 4602 }
4223 4603
4224 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) 4604 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
@@ -4238,8 +4618,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4238 destination = World.RegionInfo.RegionName; 4618 destination = World.RegionInfo.RegionName;
4239 4619
4240 // agent must be over the owners land 4620 // agent must be over the owners land
4241 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4621 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4242 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4243 { 4622 {
4244 DoLLTeleport(presence, destination, targetPos, targetLookAt); 4623 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4245 } 4624 }
@@ -4259,7 +4638,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4259 m_host.AddScriptLPS(1); 4638 m_host.AddScriptLPS(1);
4260 UUID agentId = new UUID(); 4639 UUID agentId = new UUID();
4261 4640
4262 ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); 4641 ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y);
4263 4642
4264 if (UUID.TryParse(agent, out agentId)) 4643 if (UUID.TryParse(agent, out agentId))
4265 { 4644 {
@@ -4270,8 +4649,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4270 if (presence.GodLevel >= 200) return; 4649 if (presence.GodLevel >= 200) return;
4271 4650
4272 // agent must be over the owners land 4651 // agent must be over the owners land
4273 if (m_host.OwnerID == World.LandChannel.GetLandObject( 4652 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4274 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
4275 { 4653 {
4276 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); 4654 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4277 } 4655 }
@@ -4288,7 +4666,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4288 4666
4289 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) 4667 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt)
4290 { 4668 {
4291 UUID assetID = KeyOrName(destination); 4669 UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination);
4292 4670
4293 // The destinaion is not an asset ID and also doesn't name a landmark. 4671 // The destinaion is not an asset ID and also doesn't name a landmark.
4294 // Use it as a sim name 4672 // Use it as a sim name
@@ -4321,22 +4699,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4321 UUID av = new UUID(); 4699 UUID av = new UUID();
4322 if (!UUID.TryParse(agent,out av)) 4700 if (!UUID.TryParse(agent,out av))
4323 { 4701 {
4324 LSLError("First parameter to llDialog needs to be a key"); 4702 Error("llTextBox", "First parameter must be a key");
4325 return; 4703 return;
4326 } 4704 }
4327 4705
4328 if (message == string.Empty) 4706 if (message == string.Empty)
4329 { 4707 {
4330 ShoutError("Trying to use llTextBox with empty message."); 4708 Error("llTextBox", "Empty message");
4331 } 4709 }
4332 else if (message.Length > 512) 4710 else if (message.Length > 512)
4333 { 4711 {
4334 ShoutError("Trying to use llTextBox with message over 512 characters."); 4712 Error("llTextBox", "Message more than 512 characters");
4335 } 4713 }
4336 else 4714 else
4337 { 4715 {
4338 dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID); 4716 dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
4339 ScriptSleep(1000); 4717 ScriptSleep(m_sleepMsOnTextBox);
4340 } 4718 }
4341 } 4719 }
4342 4720
@@ -4353,9 +4731,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4353 public void llCollisionSound(string impact_sound, double impact_volume) 4731 public void llCollisionSound(string impact_sound, double impact_volume)
4354 { 4732 {
4355 m_host.AddScriptLPS(1); 4733 m_host.AddScriptLPS(1);
4356 4734
4357 // TODO: Parameter check logic required. 4735 // TODO: Parameter check logic required.
4358 m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); 4736 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4359 m_host.CollisionSoundVolume = (float)impact_volume; 4737 m_host.CollisionSoundVolume = (float)impact_volume;
4360 } 4738 }
4361 4739
@@ -4475,7 +4853,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4475 { 4853 {
4476 if (pushrestricted) 4854 if (pushrestricted)
4477 { 4855 {
4478 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y); 4856 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
4479 4857
4480 // We didn't find the parcel but region is push restricted so assume it is NOT ok 4858 // We didn't find the parcel but region is push restricted so assume it is NOT ok
4481 if (targetlandObj == null) 4859 if (targetlandObj == null)
@@ -4490,7 +4868,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4490 } 4868 }
4491 else 4869 else
4492 { 4870 {
4493 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y); 4871 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
4494 if (targetlandObj == null) 4872 if (targetlandObj == null)
4495 { 4873 {
4496 // We didn't find the parcel but region isn't push restricted so assume it's ok 4874 // We didn't find the parcel but region isn't push restricted so assume it's ok
@@ -4520,6 +4898,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4520 } 4898 }
4521 } 4899 }
4522 } 4900 }
4901
4523 if (pushAllowed) 4902 if (pushAllowed)
4524 { 4903 {
4525 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4904 float distance = (PusheePos - m_host.AbsolutePosition).Length();
@@ -4548,17 +4927,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4548 applied_linear_impulse *= scaling_factor; 4927 applied_linear_impulse *= scaling_factor;
4549 4928
4550 } 4929 }
4930
4551 if (pusheeIsAvatar) 4931 if (pusheeIsAvatar)
4552 { 4932 {
4553 if (pusheeav != null) 4933 if (pusheeav != null)
4554 { 4934 {
4555 if (pusheeav.PhysicsActor != null) 4935 PhysicsActor pa = pusheeav.PhysicsActor;
4936
4937 if (pa != null)
4556 { 4938 {
4557 if (local != 0) 4939 if (local != 0)
4558 { 4940 {
4559 applied_linear_impulse *= m_host.GetWorldRotation(); 4941 applied_linear_impulse *= m_host.GetWorldRotation();
4560 } 4942 }
4561 pusheeav.PhysicsActor.AddForce(applied_linear_impulse, true); 4943
4944 pa.AddForce(applied_linear_impulse, true);
4562 } 4945 }
4563 } 4946 }
4564 } 4947 }
@@ -4666,6 +5049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4666 5049
4667 s = Math.Cos(angle * 0.5); 5050 s = Math.Cos(angle * 0.5);
4668 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs 5051 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs
5052 axis = LSL_Vector.Norm(axis);
4669 x = axis.x * t; 5053 x = axis.x * t;
4670 y = axis.y * t; 5054 y = axis.y * t;
4671 z = axis.z * t; 5055 z = axis.z * t;
@@ -4673,41 +5057,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4673 return new LSL_Rotation(x,y,z,s); 5057 return new LSL_Rotation(x,y,z,s);
4674 } 5058 }
4675 5059
4676 5060 /// <summary>
4677 // Xantor 29/apr/2008 5061 /// Returns the axis of rotation for a quaternion
4678 // converts a Quaternion to X,Y,Z axis rotations 5062 /// </summary>
5063 /// <returns></returns>
5064 /// <param name='rot'></param>
4679 public LSL_Vector llRot2Axis(LSL_Rotation rot) 5065 public LSL_Vector llRot2Axis(LSL_Rotation rot)
4680 { 5066 {
4681 m_host.AddScriptLPS(1); 5067 m_host.AddScriptLPS(1);
4682 double x,y,z;
4683
4684 if (rot.s > 1) // normalization needed
4685 {
4686 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
4687 rot.z * rot.z + rot.s * rot.s);
4688 5068
4689 rot.x /= length; 5069 if (Math.Abs(rot.s) > 1) // normalization needed
4690 rot.y /= length; 5070 rot.Normalize();
4691 rot.z /= length;
4692 rot.s /= length;
4693 5071
4694 }
4695
4696 // double angle = 2 * Math.Acos(rot.s);
4697 double s = Math.Sqrt(1 - rot.s * rot.s); 5072 double s = Math.Sqrt(1 - rot.s * rot.s);
4698 if (s < 0.001) 5073 if (s < 0.001)
4699 { 5074 {
4700 x = 1; 5075 return new LSL_Vector(1, 0, 0);
4701 y = z = 0;
4702 } 5076 }
4703 else 5077 else
4704 { 5078 {
4705 x = rot.x / s; // normalise axis 5079 double invS = 1.0 / s;
4706 y = rot.y / s; 5080 if (rot.s < 0) invS = -invS;
4707 z = rot.z / s; 5081 return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
4708 } 5082 }
4709
4710 return new LSL_Vector(x,y,z);
4711 } 5083 }
4712 5084
4713 5085
@@ -4716,18 +5088,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4716 { 5088 {
4717 m_host.AddScriptLPS(1); 5089 m_host.AddScriptLPS(1);
4718 5090
4719 if (rot.s > 1) // normalization needed 5091 if (Math.Abs(rot.s) > 1) // normalization needed
4720 { 5092 rot.Normalize();
4721 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
4722 rot.z * rot.z + rot.s * rot.s);
4723
4724 rot.x /= length;
4725 rot.y /= length;
4726 rot.z /= length;
4727 rot.s /= length;
4728 }
4729 5093
4730 double angle = 2 * Math.Acos(rot.s); 5094 double angle = 2 * Math.Acos(rot.s);
5095 if (angle > Math.PI)
5096 angle = 2 * Math.PI - angle;
4731 5097
4732 return angle; 5098 return angle;
4733 } 5099 }
@@ -4907,8 +5273,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4907 public LSL_Vector llGetCenterOfMass() 5273 public LSL_Vector llGetCenterOfMass()
4908 { 5274 {
4909 m_host.AddScriptLPS(1); 5275 m_host.AddScriptLPS(1);
4910 Vector3 center = m_host.GetGeometricCenter(); 5276
4911 return new LSL_Vector(center.X,center.Y,center.Z); 5277 return new LSL_Vector(m_host.GetCenterOfMass());
4912 } 5278 }
4913 5279
4914 public LSL_List llListSort(LSL_List src, int stride, int ascending) 5280 public LSL_List llListSort(LSL_List src, int stride, int ascending)
@@ -5043,10 +5409,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5043 // SL spits out an empty string for types other than key & string 5409 // SL spits out an empty string for types other than key & string
5044 // At the time of patching, LSL_Key is currently LSL_String, 5410 // At the time of patching, LSL_Key is currently LSL_String,
5045 // so the OR check may be a little redundant, but it's being done 5411 // so the OR check may be a little redundant, but it's being done
5046 // for completion and should LSL_Key ever be implemented 5412 // for completion and should LSL_Key ever be implemented
5047 // as it's own struct 5413 // as it's own struct
5414 // NOTE: 3rd case is needed because a NULL_KEY comes through as
5415 // type 'obj' and wrongly returns ""
5048 else if (!(src.Data[index] is LSL_String || 5416 else if (!(src.Data[index] is LSL_String ||
5049 src.Data[index] is LSL_Key)) 5417 src.Data[index] is LSL_Key ||
5418 src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000"))
5050 { 5419 {
5051 return ""; 5420 return "";
5052 } 5421 }
@@ -5179,8 +5548,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5179 { 5548 {
5180 m_host.AddScriptLPS(1); 5549 m_host.AddScriptLPS(1);
5181 5550
5182 return string.Join(", ", 5551 return string.Join(", ",
5183 (new List<object>(src.Data)).ConvertAll<string>(o => 5552 (new List<object>(src.Data)).ConvertAll<string>(o =>
5184 { 5553 {
5185 return o.ToString(); 5554 return o.ToString();
5186 }).ToArray()); 5555 }).ToArray());
@@ -5254,7 +5623,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5254 public LSL_List llListRandomize(LSL_List src, int stride) 5623 public LSL_List llListRandomize(LSL_List src, int stride)
5255 { 5624 {
5256 LSL_List result; 5625 LSL_List result;
5257 Random rand = new Random(); 5626 BetterRandom rand = new BetterRandom();
5258 5627
5259 int chunkk; 5628 int chunkk;
5260 int[] chunks; 5629 int[] chunks;
@@ -5270,24 +5639,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5270 // If not, then return the src list. This also 5639 // If not, then return the src list. This also
5271 // traps those cases where stride > length. 5640 // traps those cases where stride > length.
5272 5641
5273 if (src.Length != stride && src.Length%stride == 0) 5642 if (src.Length != stride && src.Length % stride == 0)
5274 { 5643 {
5275 chunkk = src.Length/stride; 5644 chunkk = src.Length/stride;
5276 5645
5277 chunks = new int[chunkk]; 5646 chunks = new int[chunkk];
5278 5647
5279 for (int i = 0; i < chunkk; i++) 5648 for (int i = 0; i < chunkk; i++)
5649 {
5280 chunks[i] = i; 5650 chunks[i] = i;
5651 }
5281 5652
5282 // Knuth shuffle the chunkk index 5653 // Knuth shuffle the chunkk index
5283 for (int i = chunkk - 1; i >= 1; i--) 5654 for (int i = chunkk - 1; i > 0; i--)
5284 { 5655 {
5285 // Elect an unrandomized chunk to swap 5656 // Elect an unrandomized chunk to swap
5286 int index = rand.Next(i + 1); 5657 int index = rand.Next(i + 1);
5287 int tmp;
5288 5658
5289 // and swap position with first unrandomized chunk 5659 // and swap position with first unrandomized chunk
5290 tmp = chunks[i]; 5660 int tmp = chunks[i];
5291 chunks[i] = chunks[index]; 5661 chunks[i] = chunks[index];
5292 chunks[index] = tmp; 5662 chunks[index] = tmp;
5293 } 5663 }
@@ -5300,7 +5670,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5300 { 5670 {
5301 for (int j = 0; j < stride; j++) 5671 for (int j = 0; j < stride; j++)
5302 { 5672 {
5303 result.Add(src.Data[chunks[i]*stride+j]); 5673 result.Add(src.Data[chunks[i] * stride + j]);
5304 } 5674 }
5305 } 5675 }
5306 } 5676 }
@@ -5417,7 +5787,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5417 public LSL_Vector llGetRegionCorner() 5787 public LSL_Vector llGetRegionCorner()
5418 { 5788 {
5419 m_host.AddScriptLPS(1); 5789 m_host.AddScriptLPS(1);
5420 return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); 5790 return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
5791 }
5792
5793 public LSL_String llGetEnv(LSL_String name)
5794 {
5795 m_host.AddScriptLPS(1);
5796 if (name == "agent_limit")
5797 {
5798 return World.RegionInfo.RegionSettings.AgentLimit.ToString();
5799 }
5800 else if (name == "dynamic_pathfinding")
5801 {
5802 return "0";
5803 }
5804 else if (name == "estate_id")
5805 {
5806 return World.RegionInfo.EstateSettings.EstateID.ToString();
5807 }
5808 else if (name == "estate_name")
5809 {
5810 return World.RegionInfo.EstateSettings.EstateName;
5811 }
5812 else if (name == "frame_number")
5813 {
5814 return World.Frame.ToString();
5815 }
5816 else if (name == "region_cpu_ratio")
5817 {
5818 return "1";
5819 }
5820 else if (name == "region_idle")
5821 {
5822 return "0";
5823 }
5824 else if (name == "region_product_name")
5825 {
5826 if (World.RegionInfo.RegionType != String.Empty)
5827 return World.RegionInfo.RegionType;
5828 else
5829 return "";
5830 }
5831 else if (name == "region_product_sku")
5832 {
5833 return "OpenSim";
5834 }
5835 else if (name == "region_start_time")
5836 {
5837 return World.UnixStartTime.ToString();
5838 }
5839 else if (name == "sim_channel")
5840 {
5841 return "OpenSim";
5842 }
5843 else if (name == "sim_version")
5844 {
5845 return World.GetSimulatorVersion();
5846 }
5847 else if (name == "simulator_hostname")
5848 {
5849 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
5850 return UrlModule.ExternalHostNameForLSL;
5851 }
5852 else
5853 {
5854 return "";
5855 }
5421 } 5856 }
5422 5857
5423 /// <summary> 5858 /// <summary>
@@ -5429,8 +5864,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5429 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) 5864 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
5430 { 5865 {
5431 5866
5432 LSL_List pref = null; 5867 LSL_List pref;
5433 LSL_List suff = null; 5868 LSL_List suff;
5434 5869
5435 m_host.AddScriptLPS(1); 5870 m_host.AddScriptLPS(1);
5436 5871
@@ -5564,7 +5999,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5564 LSL_Float mag; 5999 LSL_Float mag;
5565 if (dir.x > 0) 6000 if (dir.x > 0)
5566 { 6001 {
5567 mag = (Constants.RegionSize - pos.x) / dir.x; 6002 mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
5568 } 6003 }
5569 else 6004 else
5570 { 6005 {
@@ -5575,7 +6010,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5575 6010
5576 edge.y = pos.y + (dir.y * mag); 6011 edge.y = pos.y + (dir.y * mag);
5577 6012
5578 if (edge.y > Constants.RegionSize || edge.y < 0) 6013 if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
5579 { 6014 {
5580 // Y goes out of bounds first 6015 // Y goes out of bounds first
5581 edge.y = dir.y / Math.Abs(dir.y); 6016 edge.y = dir.y / Math.Abs(dir.y);
@@ -5704,12 +6139,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5704 6139
5705 public LSL_String llGetAgentLanguage(string id) 6140 public LSL_String llGetAgentLanguage(string id)
5706 { 6141 {
5707 // This should only return a value if the avatar is in the same region 6142 // This should only return a value if the avatar is in the same region, but eh. idc.
5708 //ckrinke 1-30-09 : This needs to parse the XMLRPC language field supplied
5709 //by the client at login. Currently returning only en-us until our I18N
5710 //effort gains momentum
5711 m_host.AddScriptLPS(1); 6143 m_host.AddScriptLPS(1);
5712 return "en-us"; 6144 if (World.AgentPreferencesService == null)
6145 {
6146 Error("llGetAgentLanguage", "No AgentPreferencesService present");
6147 }
6148 else
6149 {
6150 UUID key = new UUID();
6151 if (UUID.TryParse(id, out key))
6152 {
6153 return new LSL_String(World.AgentPreferencesService.GetLang(key));
6154 }
6155 }
6156 return new LSL_String("en-us");
5713 } 6157 }
5714 /// <summary> 6158 /// <summary>
5715 /// http://wiki.secondlife.com/wiki/LlGetAgentList 6159 /// http://wiki.secondlife.com/wiki/LlGetAgentList
@@ -5739,12 +6183,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5739 } 6183 }
5740 6184
5741 ILandObject land; 6185 ILandObject land;
5742 Vector3 pos;
5743 UUID id = UUID.Zero; 6186 UUID id = UUID.Zero;
6187
5744 if (parcel || parcelOwned) 6188 if (parcel || parcelOwned)
5745 { 6189 {
5746 pos = m_host.ParentGroup.RootPart.GetWorldPosition(); 6190 land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition());
5747 land = World.LandChannel.GetLandObject(pos.X, pos.Y);
5748 if (land == null) 6191 if (land == null)
5749 { 6192 {
5750 id = UUID.Zero; 6193 id = UUID.Zero;
@@ -5770,8 +6213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5770 { 6213 {
5771 if (!regionWide) 6214 if (!regionWide)
5772 { 6215 {
5773 pos = ssp.AbsolutePosition; 6216 land = World.LandChannel.GetLandObject(ssp.AbsolutePosition);
5774 land = World.LandChannel.GetLandObject(pos.X, pos.Y);
5775 if (land != null) 6217 if (land != null)
5776 { 6218 {
5777 if (parcelOwned && land.LandData.OwnerID == id || 6219 if (parcelOwned && land.LandData.OwnerID == id ||
@@ -5800,7 +6242,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5800 { 6242 {
5801 m_host.AddScriptLPS(1); 6243 m_host.AddScriptLPS(1);
5802 m_host.AdjustSoundGain(volume); 6244 m_host.AdjustSoundGain(volume);
5803 ScriptSleep(100); 6245 ScriptSleep(m_sleepMsOnAdjustSoundVolume);
5804 } 6246 }
5805 6247
5806 public void llSetSoundRadius(double radius) 6248 public void llSetSoundRadius(double radius)
@@ -5881,7 +6323,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5881 if (m_SoundModule != null) 6323 if (m_SoundModule != null)
5882 { 6324 {
5883 m_SoundModule.TriggerSoundLimited(m_host.UUID, 6325 m_SoundModule.TriggerSoundLimited(m_host.UUID,
5884 KeyOrName(sound, AssetType.Sound), volume, 6326 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume,
5885 bottom_south_west, top_north_east); 6327 bottom_south_west, top_north_east);
5886 } 6328 }
5887 } 6329 }
@@ -5896,7 +6338,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5896 if (presence != null) 6338 if (presence != null)
5897 { 6339 {
5898 // agent must be over the owners land 6340 // agent must be over the owners land
5899 ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); 6341 ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition);
5900 if (land == null) 6342 if (land == null)
5901 return; 6343 return;
5902 6344
@@ -5906,7 +6348,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5906 } 6348 }
5907 } 6349 }
5908 } 6350 }
5909 ScriptSleep(5000); 6351 ScriptSleep(m_sleepMsOnEjectFromLand);
5910 } 6352 }
5911 6353
5912 public LSL_Integer llOverMyLand(string id) 6354 public LSL_Integer llOverMyLand(string id)
@@ -5918,19 +6360,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5918 ScenePresence presence = World.GetScenePresence(key); 6360 ScenePresence presence = World.GetScenePresence(key);
5919 if (presence != null) // object is an avatar 6361 if (presence != null) // object is an avatar
5920 { 6362 {
5921 if (m_host.OwnerID 6363 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
5922 == World.LandChannel.GetLandObject(
5923 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
5924 return 1; 6364 return 1;
5925 } 6365 }
5926 else // object is not an avatar 6366 else // object is not an avatar
5927 { 6367 {
5928 SceneObjectPart obj = World.GetSceneObjectPart(key); 6368 SceneObjectPart obj = World.GetSceneObjectPart(key);
6369
5929 if (obj != null) 6370 if (obj != null)
5930 if (m_host.OwnerID 6371 {
5931 == World.LandChannel.GetLandObject( 6372 if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID)
5932 obj.AbsolutePosition.X, obj.AbsolutePosition.Y).LandData.OwnerID)
5933 return 1; 6373 return 1;
6374 }
5934 } 6375 }
5935 } 6376 }
5936 6377
@@ -5962,8 +6403,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5962 } 6403 }
5963 else 6404 else
5964 { 6405 {
5965 agentSize = new LSL_Vector(0.45, 0.6, avatar.Appearance.AvatarHeight); 6406 agentSize = GetAgentSize(avatar);
5966 } 6407 }
6408
5967 return agentSize; 6409 return agentSize;
5968 } 6410 }
5969 6411
@@ -5991,10 +6433,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5991 if (UUID.TryParse(id, out key)) 6433 if (UUID.TryParse(id, out key))
5992 { 6434 {
5993 ScenePresence av = World.GetScenePresence(key); 6435 ScenePresence av = World.GetScenePresence(key);
6436 List<ScenePresence> sittingAvatars = m_host.ParentGroup.GetSittingAvatars();
5994 6437
5995 if (av != null) 6438 if (av != null)
5996 { 6439 {
5997 if (llAvatarOnSitTarget() == id) 6440 if (sittingAvatars.Contains(av))
5998 { 6441 {
5999 // if the avatar is sitting on this object, then 6442 // if the avatar is sitting on this object, then
6000 // we can unsit them. We don't want random scripts unsitting random people 6443 // we can unsit them. We don't want random scripts unsitting random people
@@ -6008,8 +6451,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6008 // if the land is group owned and the object is group owned by the same group 6451 // if the land is group owned and the object is group owned by the same group
6009 // or 6452 // or
6010 // if the object is owned by a person with estate access. 6453 // if the object is owned by a person with estate access.
6011 6454 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition);
6012 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
6013 if (parcel != null) 6455 if (parcel != null)
6014 { 6456 {
6015 if (m_host.OwnerID == parcel.LandData.OwnerID || 6457 if (m_host.OwnerID == parcel.LandData.OwnerID ||
@@ -6021,14 +6463,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6021 } 6463 }
6022 } 6464 }
6023 } 6465 }
6024
6025 } 6466 }
6026
6027 } 6467 }
6028 6468
6029 public LSL_Vector llGroundSlope(LSL_Vector offset) 6469 public LSL_Vector llGroundSlope(LSL_Vector offset)
6030 { 6470 {
6031 m_host.AddScriptLPS(1); 6471 m_host.AddScriptLPS(1);
6472
6032 //Get the slope normal. This gives us the equation of the plane tangent to the slope. 6473 //Get the slope normal. This gives us the equation of the plane tangent to the slope.
6033 LSL_Vector vsn = llGroundNormal(offset); 6474 LSL_Vector vsn = llGroundNormal(offset);
6034 6475
@@ -6039,7 +6480,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6039 vsl.Normalize(); 6480 vsl.Normalize();
6040 //Normalization might be overkill here 6481 //Normalization might be overkill here
6041 6482
6042 return new LSL_Vector(vsl.X, vsl.Y, vsl.Z); 6483 vsn.x = vsl.X;
6484 vsn.y = vsl.Y;
6485 vsn.z = vsl.Z;
6486
6487 return vsn;
6043 } 6488 }
6044 6489
6045 public LSL_Vector llGroundNormal(LSL_Vector offset) 6490 public LSL_Vector llGroundNormal(LSL_Vector offset)
@@ -6089,7 +6534,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6089 //I believe the crossproduct of two normalized vectors is a normalized vector so 6534 //I believe the crossproduct of two normalized vectors is a normalized vector so
6090 //this normalization may be overkill 6535 //this normalization may be overkill
6091 6536
6092 return new LSL_Vector(vsn.X, vsn.Y, vsn.Z); 6537 return new LSL_Vector(vsn);
6093 } 6538 }
6094 6539
6095 public LSL_Vector llGroundContour(LSL_Vector offset) 6540 public LSL_Vector llGroundContour(LSL_Vector offset)
@@ -6105,11 +6550,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6105 return m_host.ParentGroup.AttachmentPoint; 6550 return m_host.ParentGroup.AttachmentPoint;
6106 } 6551 }
6107 6552
6108 public LSL_Integer llGetFreeMemory() 6553 public virtual LSL_Integer llGetFreeMemory()
6109 { 6554 {
6110 m_host.AddScriptLPS(1); 6555 m_host.AddScriptLPS(1);
6111 // Make scripts designed for LSO happy 6556 // Make scripts designed for Mono happy
6112 return 16384; 6557 return 65536;
6113 } 6558 }
6114 6559
6115 public LSL_Integer llGetFreeURLs() 6560 public LSL_Integer llGetFreeURLs()
@@ -6176,7 +6621,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6176 PSYS_SRC_TARGET_KEY = 20, 6621 PSYS_SRC_TARGET_KEY = 20,
6177 PSYS_SRC_OMEGA = 21, 6622 PSYS_SRC_OMEGA = 21,
6178 PSYS_SRC_ANGLE_BEGIN = 22, 6623 PSYS_SRC_ANGLE_BEGIN = 22,
6179 PSYS_SRC_ANGLE_END = 23 6624 PSYS_SRC_ANGLE_END = 23,
6625 PSYS_PART_BLEND_FUNC_SOURCE = 24,
6626 PSYS_PART_BLEND_FUNC_DEST = 25,
6627 PSYS_PART_START_GLOW = 26,
6628 PSYS_PART_END_GLOW = 27
6180 } 6629 }
6181 6630
6182 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) 6631 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
@@ -6202,6 +6651,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6202 ps.BurstRate = 0.1f; 6651 ps.BurstRate = 0.1f;
6203 ps.PartMaxAge = 10.0f; 6652 ps.PartMaxAge = 10.0f;
6204 ps.BurstPartCount = 1; 6653 ps.BurstPartCount = 1;
6654 ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA;
6655 ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA;
6656 ps.PartStartGlow = 0.0f;
6657 ps.PartEndGlow = 0.0f;
6658
6205 return ps; 6659 return ps;
6206 } 6660 }
6207 6661
@@ -6213,17 +6667,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6213 6667
6214 foreach (SceneObjectPart part in parts) 6668 foreach (SceneObjectPart part in parts)
6215 { 6669 {
6216 SetParticleSystem(part, rules); 6670 SetParticleSystem(part, rules, "llLinkParticleSystem");
6217 } 6671 }
6218 } 6672 }
6219 6673
6220 public void llParticleSystem(LSL_List rules) 6674 public void llParticleSystem(LSL_List rules)
6221 { 6675 {
6222 m_host.AddScriptLPS(1); 6676 m_host.AddScriptLPS(1);
6223 SetParticleSystem(m_host, rules); 6677 SetParticleSystem(m_host, rules, "llParticleSystem");
6224 } 6678 }
6225 6679
6226 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) 6680 private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc)
6227 { 6681 {
6228 if (rules.Length == 0) 6682 if (rules.Length == 0)
6229 { 6683 {
@@ -6236,65 +6690,156 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6236 LSL_Vector tempv = new LSL_Vector(); 6690 LSL_Vector tempv = new LSL_Vector();
6237 6691
6238 float tempf = 0; 6692 float tempf = 0;
6693 int tmpi = 0;
6239 6694
6240 for (int i = 0; i < rules.Length; i += 2) 6695 for (int i = 0; i < rules.Length; i += 2)
6241 { 6696 {
6242 switch (rules.GetLSLIntegerItem(i)) 6697 int psystype;
6698 try
6699 {
6700 psystype = rules.GetLSLIntegerItem(i);
6701 }
6702 catch (InvalidCastException)
6703 {
6704 Error(originFunc, string.Format("Error running particle system params index #{0}: particle system parameter type must be integer", i));
6705 return;
6706 }
6707 switch (psystype)
6243 { 6708 {
6244 case (int)ScriptBaseClass.PSYS_PART_FLAGS: 6709 case (int)ScriptBaseClass.PSYS_PART_FLAGS:
6245 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); 6710 try
6711 {
6712 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
6713 }
6714 catch(InvalidCastException)
6715 {
6716 Error(originFunc, string.Format("Error running rule PSYS_PART_FLAGS: arg #{0} - parameter 1 must be integer", i + 1));
6717 return;
6718 }
6246 break; 6719 break;
6247 6720
6248 case (int)ScriptBaseClass.PSYS_PART_START_COLOR: 6721 case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
6249 tempv = rules.GetVector3Item(i + 1); 6722 try
6723 {
6724 tempv = rules.GetVector3Item(i + 1);
6725 }
6726 catch(InvalidCastException)
6727 {
6728 Error(originFunc, string.Format("Error running rule PSYS_PART_START_COLOR: arg #{0} - parameter 1 must be vector", i + 1));
6729 return;
6730 }
6250 prules.PartStartColor.R = (float)tempv.x; 6731 prules.PartStartColor.R = (float)tempv.x;
6251 prules.PartStartColor.G = (float)tempv.y; 6732 prules.PartStartColor.G = (float)tempv.y;
6252 prules.PartStartColor.B = (float)tempv.z; 6733 prules.PartStartColor.B = (float)tempv.z;
6253 break; 6734 break;
6254 6735
6255 case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: 6736 case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
6256 tempf = (float)rules.GetLSLFloatItem(i + 1); 6737 try
6738 {
6739 tempf = (float)rules.GetLSLFloatItem(i + 1);
6740 }
6741 catch(InvalidCastException)
6742 {
6743 Error(originFunc, string.Format("Error running rule PSYS_PART_START_ALPHA: arg #{0} - parameter 1 must be float", i + 1));
6744 return;
6745 }
6257 prules.PartStartColor.A = tempf; 6746 prules.PartStartColor.A = tempf;
6258 break; 6747 break;
6259 6748
6260 case (int)ScriptBaseClass.PSYS_PART_END_COLOR: 6749 case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
6261 tempv = rules.GetVector3Item(i + 1); 6750 try
6751 {
6752 tempv = rules.GetVector3Item(i + 1);
6753 }
6754 catch(InvalidCastException)
6755 {
6756 Error(originFunc, string.Format("Error running rule PSYS_PART_END_COLOR: arg #{0} - parameter 1 must be vector", i + 1));
6757 return;
6758 }
6262 prules.PartEndColor.R = (float)tempv.x; 6759 prules.PartEndColor.R = (float)tempv.x;
6263 prules.PartEndColor.G = (float)tempv.y; 6760 prules.PartEndColor.G = (float)tempv.y;
6264 prules.PartEndColor.B = (float)tempv.z; 6761 prules.PartEndColor.B = (float)tempv.z;
6265 break; 6762 break;
6266 6763
6267 case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: 6764 case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
6268 tempf = (float)rules.GetLSLFloatItem(i + 1); 6765 try
6766 {
6767 tempf = (float)rules.GetLSLFloatItem(i + 1);
6768 }
6769 catch(InvalidCastException)
6770 {
6771 Error(originFunc, string.Format("Error running rule PSYS_PART_END_ALPHA: arg #{0} - parameter 1 must be float", i + 1));
6772 return;
6773 }
6269 prules.PartEndColor.A = tempf; 6774 prules.PartEndColor.A = tempf;
6270 break; 6775 break;
6271 6776
6272 case (int)ScriptBaseClass.PSYS_PART_START_SCALE: 6777 case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
6273 tempv = rules.GetVector3Item(i + 1); 6778 try
6274 prules.PartStartScaleX = (float)tempv.x; 6779 {
6275 prules.PartStartScaleY = (float)tempv.y; 6780 tempv = rules.GetVector3Item(i + 1);
6781 }
6782 catch(InvalidCastException)
6783 {
6784 Error(originFunc, string.Format("Error running rule PSYS_PART_START_SCALE: arg #{0} - parameter 1 must be vector", i + 1));
6785 return;
6786 }
6787 prules.PartStartScaleX = validParticleScale((float)tempv.x);
6788 prules.PartStartScaleY = validParticleScale((float)tempv.y);
6276 break; 6789 break;
6277 6790
6278 case (int)ScriptBaseClass.PSYS_PART_END_SCALE: 6791 case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
6279 tempv = rules.GetVector3Item(i + 1); 6792 try
6280 prules.PartEndScaleX = (float)tempv.x; 6793 {
6281 prules.PartEndScaleY = (float)tempv.y; 6794 tempv = rules.GetVector3Item(i + 1);
6795 }
6796 catch(InvalidCastException)
6797 {
6798 Error(originFunc, string.Format("Error running rule PSYS_PART_END_SCALE: arg #{0} - parameter 1 must be vector", i + 1));
6799 return;
6800 }
6801 prules.PartEndScaleX = validParticleScale((float)tempv.x);
6802 prules.PartEndScaleY = validParticleScale((float)tempv.y);
6282 break; 6803 break;
6283 6804
6284 case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: 6805 case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
6285 tempf = (float)rules.GetLSLFloatItem(i + 1); 6806 try
6807 {
6808 tempf = (float)rules.GetLSLFloatItem(i + 1);
6809 }
6810 catch(InvalidCastException)
6811 {
6812 Error(originFunc, string.Format("Error running rule PSYS_PART_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1));
6813 return;
6814 }
6286 prules.PartMaxAge = tempf; 6815 prules.PartMaxAge = tempf;
6287 break; 6816 break;
6288 6817
6289 case (int)ScriptBaseClass.PSYS_SRC_ACCEL: 6818 case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
6290 tempv = rules.GetVector3Item(i + 1); 6819 try
6820 {
6821 tempv = rules.GetVector3Item(i + 1);
6822 }
6823 catch(InvalidCastException)
6824 {
6825 Error(originFunc, string.Format("Error running rule PSYS_SRC_ACCEL: arg #{0} - parameter 1 must be vector", i + 1));
6826 return;
6827 }
6291 prules.PartAcceleration.X = (float)tempv.x; 6828 prules.PartAcceleration.X = (float)tempv.x;
6292 prules.PartAcceleration.Y = (float)tempv.y; 6829 prules.PartAcceleration.Y = (float)tempv.y;
6293 prules.PartAcceleration.Z = (float)tempv.z; 6830 prules.PartAcceleration.Z = (float)tempv.z;
6294 break; 6831 break;
6295 6832
6296 case (int)ScriptBaseClass.PSYS_SRC_PATTERN: 6833 case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
6297 int tmpi = (int)rules.GetLSLIntegerItem(i + 1); 6834 try
6835 {
6836 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6837 }
6838 catch(InvalidCastException)
6839 {
6840 Error(originFunc, string.Format("Error running rule PSYS_SRC_PATTERN: arg #{0} - parameter 1 must be integer", i + 1));
6841 return;
6842 }
6298 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; 6843 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
6299 break; 6844 break;
6300 6845
@@ -6303,47 +6848,171 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6303 // client tells the difference between the two by looking at the 0x02 bit in 6848 // client tells the difference between the two by looking at the 0x02 bit in
6304 // the PartFlags variable. 6849 // the PartFlags variable.
6305 case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: 6850 case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE:
6306 tempf = (float)rules.GetLSLFloatItem(i + 1); 6851 try
6852 {
6853 tempf = (float)rules.GetLSLFloatItem(i + 1);
6854 }
6855 catch(InvalidCastException)
6856 {
6857 Error(originFunc, string.Format("Error running rule PSYS_SRC_INNERANGLE: arg #{0} - parameter 1 must be float", i + 1));
6858 return;
6859 }
6307 prules.InnerAngle = (float)tempf; 6860 prules.InnerAngle = (float)tempf;
6308 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. 6861 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
6309 break; 6862 break;
6310 6863
6311 case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: 6864 case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE:
6312 tempf = (float)rules.GetLSLFloatItem(i + 1); 6865 try
6866 {
6867 tempf = (float)rules.GetLSLFloatItem(i + 1);
6868 }
6869 catch(InvalidCastException)
6870 {
6871 Error(originFunc, string.Format("Error running rule PSYS_SRC_OUTERANGLE: arg #{0} - parameter 1 must be float", i + 1));
6872 return;
6873 }
6313 prules.OuterAngle = (float)tempf; 6874 prules.OuterAngle = (float)tempf;
6314 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. 6875 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
6315 break; 6876 break;
6316 6877
6878 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE:
6879 try
6880 {
6881 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6882 }
6883 catch(InvalidCastException)
6884 {
6885 Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_SOURCE: arg #{0} - parameter 1 must be integer", i + 1));
6886 return;
6887 }
6888 prules.BlendFuncSource = (byte)tmpi;
6889 break;
6890
6891 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST:
6892 try
6893 {
6894 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6895 }
6896 catch(InvalidCastException)
6897 {
6898 Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_DEST: arg #{0} - parameter 1 must be integer", i + 1));
6899 return;
6900 }
6901 prules.BlendFuncDest = (byte)tmpi;
6902 break;
6903
6904 case (int)ScriptBaseClass.PSYS_PART_START_GLOW:
6905 try
6906 {
6907 tempf = (float)rules.GetLSLFloatItem(i + 1);
6908 }
6909 catch(InvalidCastException)
6910 {
6911 Error(originFunc, string.Format("Error running rule PSYS_PART_START_GLOW: arg #{0} - parameter 1 must be float", i + 1));
6912 return;
6913 }
6914 prules.PartStartGlow = (float)tempf;
6915 break;
6916
6917 case (int)ScriptBaseClass.PSYS_PART_END_GLOW:
6918 try
6919 {
6920 tempf = (float)rules.GetLSLFloatItem(i + 1);
6921 }
6922 catch(InvalidCastException)
6923 {
6924 Error(originFunc, string.Format("Error running rule PSYS_PART_END_GLOW: arg #{0} - parameter 1 must be float", i + 1));
6925 return;
6926 }
6927 prules.PartEndGlow = (float)tempf;
6928 break;
6929
6317 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: 6930 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
6318 prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1)); 6931 try
6932 {
6933 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
6934 }
6935 catch(InvalidCastException)
6936 {
6937 Error(originFunc, string.Format("Error running rule PSYS_SRC_TEXTURE: arg #{0} - parameter 1 must be string or key", i + 1));
6938 return;
6939 }
6319 break; 6940 break;
6320 6941
6321 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: 6942 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
6322 tempf = (float)rules.GetLSLFloatItem(i + 1); 6943 try
6944 {
6945 tempf = (float)rules.GetLSLFloatItem(i + 1);
6946 }
6947 catch(InvalidCastException)
6948 {
6949 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RATE: arg #{0} - parameter 1 must be float", i + 1));
6950 return;
6951 }
6323 prules.BurstRate = (float)tempf; 6952 prules.BurstRate = (float)tempf;
6324 break; 6953 break;
6325 6954
6326 case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: 6955 case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
6327 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); 6956 try
6957 {
6958 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
6959 }
6960 catch(InvalidCastException)
6961 {
6962 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_PART_COUNT: arg #{0} - parameter 1 must be integer", i + 1));
6963 return;
6964 }
6328 break; 6965 break;
6329 6966
6330 case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: 6967 case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
6331 tempf = (float)rules.GetLSLFloatItem(i + 1); 6968 try
6969 {
6970 tempf = (float)rules.GetLSLFloatItem(i + 1);
6971 }
6972 catch(InvalidCastException)
6973 {
6974 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RADIUS: arg #{0} - parameter 1 must be float", i + 1));
6975 return;
6976 }
6332 prules.BurstRadius = (float)tempf; 6977 prules.BurstRadius = (float)tempf;
6333 break; 6978 break;
6334 6979
6335 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: 6980 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
6336 tempf = (float)rules.GetLSLFloatItem(i + 1); 6981 try
6982 {
6983 tempf = (float)rules.GetLSLFloatItem(i + 1);
6984 }
6985 catch(InvalidCastException)
6986 {
6987 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MIN: arg #{0} - parameter 1 must be float", i + 1));
6988 return;
6989 }
6337 prules.BurstSpeedMin = (float)tempf; 6990 prules.BurstSpeedMin = (float)tempf;
6338 break; 6991 break;
6339 6992
6340 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: 6993 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
6341 tempf = (float)rules.GetLSLFloatItem(i + 1); 6994 try
6995 {
6996 tempf = (float)rules.GetLSLFloatItem(i + 1);
6997 }
6998 catch(InvalidCastException)
6999 {
7000 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MAX: arg #{0} - parameter 1 must be float", i + 1));
7001 return;
7002 }
6342 prules.BurstSpeedMax = (float)tempf; 7003 prules.BurstSpeedMax = (float)tempf;
6343 break; 7004 break;
6344 7005
6345 case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: 7006 case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
6346 tempf = (float)rules.GetLSLFloatItem(i + 1); 7007 try
7008 {
7009 tempf = (float)rules.GetLSLFloatItem(i + 1);
7010 }
7011 catch(InvalidCastException)
7012 {
7013 Error(originFunc, string.Format("Error running rule PSYS_SRC_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1));
7014 return;
7015 }
6347 prules.MaxAge = (float)tempf; 7016 prules.MaxAge = (float)tempf;
6348 break; 7017 break;
6349 7018
@@ -6361,20 +7030,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6361 7030
6362 case (int)ScriptBaseClass.PSYS_SRC_OMEGA: 7031 case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
6363 // AL: This is an assumption, since it is the only thing that would match. 7032 // AL: This is an assumption, since it is the only thing that would match.
6364 tempv = rules.GetVector3Item(i + 1); 7033 try
7034 {
7035 tempv = rules.GetVector3Item(i + 1);
7036 }
7037 catch(InvalidCastException)
7038 {
7039 Error(originFunc, string.Format("Error running rule PSYS_SRC_OMEGA: arg #{0} - parameter 1 must be vector", i + 1));
7040 return;
7041 }
6365 prules.AngularVelocity.X = (float)tempv.x; 7042 prules.AngularVelocity.X = (float)tempv.x;
6366 prules.AngularVelocity.Y = (float)tempv.y; 7043 prules.AngularVelocity.Y = (float)tempv.y;
6367 prules.AngularVelocity.Z = (float)tempv.z; 7044 prules.AngularVelocity.Z = (float)tempv.z;
6368 break; 7045 break;
6369 7046
6370 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: 7047 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
6371 tempf = (float)rules.GetLSLFloatItem(i + 1); 7048 try
7049 {
7050 tempf = (float)rules.GetLSLFloatItem(i + 1);
7051 }
7052 catch(InvalidCastException)
7053 {
7054 Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_BEGIN: arg #{0} - parameter 1 must be float", i + 1));
7055 return;
7056 }
6372 prules.InnerAngle = (float)tempf; 7057 prules.InnerAngle = (float)tempf;
6373 prules.PartFlags |= 0x02; // Set new angle format. 7058 prules.PartFlags |= 0x02; // Set new angle format.
6374 break; 7059 break;
6375 7060
6376 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: 7061 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
6377 tempf = (float)rules.GetLSLFloatItem(i + 1); 7062 try
7063 {
7064 tempf = (float)rules.GetLSLFloatItem(i + 1);
7065 }
7066 catch (InvalidCastException)
7067 {
7068 Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_END: arg #{0} - parameter 1 must be float", i + 1));
7069 return;
7070 }
6378 prules.OuterAngle = (float)tempf; 7071 prules.OuterAngle = (float)tempf;
6379 prules.PartFlags |= 0x02; // Set new angle format. 7072 prules.PartFlags |= 0x02; // Set new angle format.
6380 break; 7073 break;
@@ -6389,6 +7082,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6389 part.SendFullUpdateToAllClients(); 7082 part.SendFullUpdateToAllClients();
6390 } 7083 }
6391 7084
7085 private float validParticleScale(float value)
7086 {
7087 if (value > 4.0f) return 4.0f;
7088 return value;
7089 }
7090
6392 public void llGroundRepel(double height, int water, double tau) 7091 public void llGroundRepel(double height, int water, double tau)
6393 { 7092 {
6394 m_host.AddScriptLPS(1); 7093 m_host.AddScriptLPS(1);
@@ -6460,7 +7159,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6460 m_host.OwnerID, m_host.Name, destID, 7159 m_host.OwnerID, m_host.Name, destID,
6461 (byte)InstantMessageDialog.TaskInventoryOffered, 7160 (byte)InstantMessageDialog.TaskInventoryOffered,
6462 false, string.Format("'{0}'", category), 7161 false, string.Format("'{0}'", category),
6463// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 7162// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06
6464// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), 7163// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
6465 folderID, false, pos, 7164 folderID, false, pos,
6466 bucket, false); 7165 bucket, false);
@@ -6575,12 +7274,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6575 public LSL_String llAvatarOnLinkSitTarget(int linknum) 7274 public LSL_String llAvatarOnLinkSitTarget(int linknum)
6576 { 7275 {
6577 m_host.AddScriptLPS(1); 7276 m_host.AddScriptLPS(1);
6578 if(linknum == ScriptBaseClass.LINK_SET || 7277 if(linknum == ScriptBaseClass.LINK_SET ||
6579 linknum == ScriptBaseClass.LINK_ALL_CHILDREN || 7278 linknum == ScriptBaseClass.LINK_ALL_CHILDREN ||
6580 linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); 7279 linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString();
6581 7280
6582 List<SceneObjectPart> parts = GetLinkParts(linknum); 7281 List<SceneObjectPart> parts = GetLinkParts(linknum);
6583 if (parts.Count == 0) return UUID.Zero.ToString(); 7282 if (parts.Count == 0) return UUID.Zero.ToString();
6584 return parts[0].SitTargetAvatar.ToString(); 7283 return parts[0].SitTargetAvatar.ToString();
6585 } 7284 }
6586 7285
@@ -6589,7 +7288,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6589 { 7288 {
6590 m_host.AddScriptLPS(1); 7289 m_host.AddScriptLPS(1);
6591 UUID key; 7290 UUID key;
6592 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 7291 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
7292
6593 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 7293 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
6594 { 7294 {
6595 int expires = 0; 7295 int expires = 0;
@@ -6623,7 +7323,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6623 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 7323 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
6624 } 7324 }
6625 } 7325 }
6626 ScriptSleep(100); 7326 ScriptSleep(m_sleepMsOnAddToLandPassList);
6627 } 7327 }
6628 7328
6629 public void llSetTouchText(string text) 7329 public void llSetTouchText(string text)
@@ -6642,12 +7342,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6642 { 7342 {
6643 m_host.AddScriptLPS(1); 7343 m_host.AddScriptLPS(1);
6644 m_host.SetCameraEyeOffset(offset); 7344 m_host.SetCameraEyeOffset(offset);
7345
7346 if (m_host.ParentGroup.RootPart.GetCameraEyeOffset() == Vector3.Zero)
7347 m_host.ParentGroup.RootPart.SetCameraEyeOffset(offset);
6645 } 7348 }
6646 7349
6647 public void llSetCameraAtOffset(LSL_Vector offset) 7350 public void llSetCameraAtOffset(LSL_Vector offset)
6648 { 7351 {
6649 m_host.AddScriptLPS(1); 7352 m_host.AddScriptLPS(1);
6650 m_host.SetCameraAtOffset(offset); 7353 m_host.SetCameraAtOffset(offset);
7354
7355 if (m_host.ParentGroup.RootPart.GetCameraAtOffset() == Vector3.Zero)
7356 m_host.ParentGroup.RootPart.SetCameraAtOffset(offset);
6651 } 7357 }
6652 7358
6653 public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at) 7359 public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at)
@@ -6722,17 +7428,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6722 UUID av = new UUID(); 7428 UUID av = new UUID();
6723 if (!UUID.TryParse(avatar,out av)) 7429 if (!UUID.TryParse(avatar,out av))
6724 { 7430 {
6725 LSLError("First parameter to llDialog needs to be a key"); 7431 Error("llDialog", "First parameter must be a key");
6726 return; 7432 return;
6727 } 7433 }
6728 if (buttons.Length < 1) 7434 if (buttons.Length < 1)
6729 { 7435 {
6730 LSLError("No less than 1 button can be shown"); 7436 Error("llDialog", "At least 1 button must be shown");
6731 return; 7437 return;
6732 } 7438 }
6733 if (buttons.Length > 12) 7439 if (buttons.Length > 12)
6734 { 7440 {
6735 LSLError("No more than 12 buttons can be shown"); 7441 Error("llDialog", "No more than 12 buttons can be shown");
6736 return; 7442 return;
6737 } 7443 }
6738 string[] buts = new string[buttons.Length]; 7444 string[] buts = new string[buttons.Length];
@@ -6740,12 +7446,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6740 { 7446 {
6741 if (buttons.Data[i].ToString() == String.Empty) 7447 if (buttons.Data[i].ToString() == String.Empty)
6742 { 7448 {
6743 LSLError("button label cannot be blank"); 7449 Error("llDialog", "Button label cannot be blank");
6744 return; 7450 return;
6745 } 7451 }
6746 if (buttons.Data[i].ToString().Length > 24) 7452 if (buttons.Data[i].ToString().Length > 24)
6747 { 7453 {
6748 LSLError("button label cannot be longer than 24 characters"); 7454 Error("llDialog", "Button label cannot be longer than 24 characters");
6749 return; 7455 return;
6750 } 7456 }
6751 buts[i] = buttons.Data[i].ToString(); 7457 buts[i] = buttons.Data[i].ToString();
@@ -6755,7 +7461,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6755 av, m_host.Name, m_host.UUID, m_host.OwnerID, 7461 av, m_host.Name, m_host.UUID, m_host.OwnerID,
6756 message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); 7462 message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
6757 7463
6758 ScriptSleep(1000); 7464 ScriptSleep(m_sleepMsOnDialog);
6759 } 7465 }
6760 7466
6761 public void llVolumeDetect(int detect) 7467 public void llVolumeDetect(int detect)
@@ -6766,16 +7472,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6766 m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0); 7472 m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0);
6767 } 7473 }
6768 7474
6769 /// <summary>
6770 /// This is a depecated function so this just replicates the result of
6771 /// invoking it in SL
6772 /// </summary>
6773 public void llRemoteLoadScript(string target, string name, int running, int start_param) 7475 public void llRemoteLoadScript(string target, string name, int running, int start_param)
6774 { 7476 {
6775 m_host.AddScriptLPS(1); 7477 m_host.AddScriptLPS(1);
6776 // Report an error as it does in SL 7478 Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead");
6777 ShoutError("Deprecated. Please use llRemoteLoadScriptPin instead."); 7479 ScriptSleep(m_sleepMsOnRemoteLoadScript);
6778 ScriptSleep(3000);
6779 } 7480 }
6780 7481
6781 public void llSetRemoteScriptAccessPin(int pin) 7482 public void llSetRemoteScriptAccessPin(int pin)
@@ -6792,7 +7493,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6792 7493
6793 if (!UUID.TryParse(target, out destId)) 7494 if (!UUID.TryParse(target, out destId))
6794 { 7495 {
6795 llSay(0, "Could not parse key " + target); 7496 Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'");
6796 return; 7497 return;
6797 } 7498 }
6798 7499
@@ -6808,7 +7509,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6808 // make sure the object is a script 7509 // make sure the object is a script
6809 if (item == null || item.Type != 10) 7510 if (item == null || item.Type != 10)
6810 { 7511 {
6811 llSay(0, "Could not find script " + name); 7512 Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'");
6812 return; 7513 return;
6813 } 7514 }
6814 7515
@@ -6816,14 +7517,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6816 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7517 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
6817 7518
6818 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7519 // this will cause the delay even if the script pin or permissions were wrong - seems ok
6819 ScriptSleep(3000); 7520 ScriptSleep(m_sleepMsOnRemoteLoadScriptPin);
6820 } 7521 }
6821 7522
6822 public void llOpenRemoteDataChannel() 7523 public void llOpenRemoteDataChannel()
6823 { 7524 {
6824 m_host.AddScriptLPS(1); 7525 m_host.AddScriptLPS(1);
6825 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7526 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
6826 if (xmlrpcMod.IsEnabled()) 7527 if (xmlrpcMod != null && xmlrpcMod.IsEnabled())
6827 { 7528 {
6828 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); 7529 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero);
6829 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); 7530 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
@@ -6847,14 +7548,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6847 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj, 7548 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj,
6848 new DetectParams[0])); 7549 new DetectParams[0]));
6849 } 7550 }
6850 ScriptSleep(1000); 7551 ScriptSleep(m_sleepMsOnOpenRemoteDataChannel);
6851 } 7552 }
6852 7553
6853 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) 7554 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
6854 { 7555 {
6855 m_host.AddScriptLPS(1); 7556 m_host.AddScriptLPS(1);
6856 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7557 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
6857 ScriptSleep(3000); 7558 ScriptSleep(m_sleepMsOnSendRemoteData);
7559 if (xmlrpcMod == null)
7560 return "";
6858 return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); 7561 return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString();
6859 } 7562 }
6860 7563
@@ -6862,8 +7565,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6862 { 7565 {
6863 m_host.AddScriptLPS(1); 7566 m_host.AddScriptLPS(1);
6864 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7567 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
6865 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); 7568 if (xmlrpcMod != null)
6866 ScriptSleep(3000); 7569 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
7570 ScriptSleep(m_sleepMsOnRemoteDataReply);
6867 } 7571 }
6868 7572
6869 public void llCloseRemoteDataChannel(string channel) 7573 public void llCloseRemoteDataChannel(string channel)
@@ -6877,8 +7581,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6877 } 7581 }
6878 7582
6879 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7583 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
6880 xmlrpcMod.CloseXMLRPCChannel((UUID)channel); 7584 if (xmlrpcMod != null)
6881 ScriptSleep(1000); 7585 xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
7586 ScriptSleep(m_sleepMsOnCloseRemoteDataChannel);
6882 } 7587 }
6883 7588
6884 public LSL_String llMD5String(string src, int nonce) 7589 public LSL_String llMD5String(string src, int nonce)
@@ -6924,13 +7629,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6924 { 7629 {
6925 cut.y = 1f; 7630 cut.y = 1f;
6926 } 7631 }
6927 if (cut.y - cut.x < 0.05f) 7632 if (cut.y - cut.x < 0.02f)
6928 { 7633 {
6929 cut.x = cut.y - 0.05f; 7634 cut.x = cut.y - 0.02f;
6930 if (cut.x < 0.0f) 7635 if (cut.x < 0.0f)
6931 { 7636 {
6932 cut.x = 0.0f; 7637 cut.x = 0.0f;
6933 cut.y = 0.05f; 7638 cut.y = 0.02f;
6934 } 7639 }
6935 } 7640 }
6936 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); 7641 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
@@ -6952,12 +7657,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6952 hollow = 0.70f; 7657 hollow = 0.70f;
6953 } 7658 }
6954 } 7659 }
6955 // Otherwise, hollow is limited to 95%. 7660 // Otherwise, hollow is limited to 99%.
6956 else 7661 else
6957 { 7662 {
6958 if (hollow > 0.95f) 7663 if (hollow > 0.99f)
6959 { 7664 {
6960 hollow = 0.95f; 7665 hollow = 0.99f;
6961 } 7666 }
6962 } 7667 }
6963 shapeBlock.ProfileHollow = (ushort)(50000 * hollow); 7668 shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
@@ -7081,9 +7786,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7081 { 7786 {
7082 dimple.y = 1f; 7787 dimple.y = 1f;
7083 } 7788 }
7084 if (dimple.y - cut.x < 0.05f) 7789 if (dimple.y - dimple.x < 0.02f)
7085 { 7790 {
7086 dimple.x = cut.y - 0.05f; 7791 dimple.x = dimple.y - 0.02f;
7792 if (dimple.x < 0.0f)
7793 {
7794 dimple.x = 0.0f;
7795 dimple.y = 0.02f;
7796 }
7087 } 7797 }
7088 shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); 7798 shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
7089 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); 7799 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
@@ -7104,17 +7814,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7104 shapeBlock.PathBegin = shapeBlock.ProfileBegin; 7814 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
7105 shapeBlock.PathEnd = shapeBlock.ProfileEnd; 7815 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
7106 7816
7107 if (holesize.x < 0.05f) 7817 if (holesize.x < 0.01f)
7108 { 7818 {
7109 holesize.x = 0.05f; 7819 holesize.x = 0.01f;
7110 } 7820 }
7111 if (holesize.x > 1f) 7821 if (holesize.x > 1f)
7112 { 7822 {
7113 holesize.x = 1f; 7823 holesize.x = 1f;
7114 } 7824 }
7115 if (holesize.y < 0.05f) 7825 if (holesize.y < 0.01f)
7116 { 7826 {
7117 holesize.y = 0.05f; 7827 holesize.y = 0.01f;
7118 } 7828 }
7119 if (holesize.y > 0.5f) 7829 if (holesize.y > 0.5f)
7120 { 7830 {
@@ -7160,13 +7870,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7160 { 7870 {
7161 profilecut.y = 1f; 7871 profilecut.y = 1f;
7162 } 7872 }
7163 if (profilecut.y - profilecut.x < 0.05f) 7873 if (profilecut.y - profilecut.x < 0.02f)
7164 { 7874 {
7165 profilecut.x = profilecut.y - 0.05f; 7875 profilecut.x = profilecut.y - 0.02f;
7166 if (profilecut.x < 0.0f) 7876 if (profilecut.x < 0.0f)
7167 { 7877 {
7168 profilecut.x = 0.0f; 7878 profilecut.x = 0.0f;
7169 profilecut.y = 0.05f; 7879 profilecut.y = 0.02f;
7170 } 7880 }
7171 } 7881 }
7172 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); 7882 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
@@ -7234,9 +7944,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7234 UUID sculptId; 7944 UUID sculptId;
7235 7945
7236 if (!UUID.TryParse(map, out sculptId)) 7946 if (!UUID.TryParse(map, out sculptId))
7237 { 7947 sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture);
7238 sculptId = InventoryKey(map, (int)AssetType.Texture);
7239 }
7240 7948
7241 if (sculptId == UUID.Zero) 7949 if (sculptId == UUID.Zero)
7242 return; 7950 return;
@@ -7266,45 +7974,205 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7266 { 7974 {
7267 m_host.AddScriptLPS(1); 7975 m_host.AddScriptLPS(1);
7268 7976
7269 setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); 7977 SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
7270 7978
7271 ScriptSleep(200); 7979 ScriptSleep(m_sleepMsOnSetPrimitiveParams);
7272 } 7980 }
7273 7981
7274 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 7982 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
7275 { 7983 {
7276 m_host.AddScriptLPS(1); 7984 m_host.AddScriptLPS(1);
7277 7985
7278 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); 7986 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
7279 7987
7280 ScriptSleep(200); 7988 ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams);
7281 } 7989 }
7282 7990
7283 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 7991 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
7284 { 7992 {
7285 m_host.AddScriptLPS(1); 7993 m_host.AddScriptLPS(1);
7286 7994
7287 setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 7995 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
7288 } 7996 }
7289 7997
7290 protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 7998 protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
7291 { 7999 {
7292 List<SceneObjectPart> parts = GetLinkParts(linknumber); 8000 SetEntityParams(GetLinkEntities(linknumber), rules, originFunc);
8001 }
7293 8002
7294 LSL_List remaining = null; 8003 protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc)
8004 {
8005 LSL_List remaining = new LSL_List();
7295 uint rulesParsed = 0; 8006 uint rulesParsed = 0;
7296 8007
7297 foreach (SceneObjectPart part in parts) 8008 foreach (ISceneEntity entity in entities)
7298 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); 8009 {
8010 if (entity is SceneObjectPart)
8011 remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed);
8012 else
8013 remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed);
8014 }
7299 8015
7300 while (remaining != null && remaining.Length > 2) 8016 while (remaining.Length > 2)
7301 { 8017 {
7302 linknumber = remaining.GetLSLIntegerItem(0); 8018 int linknumber;
8019 try
8020 {
8021 linknumber = remaining.GetLSLIntegerItem(0);
8022 }
8023 catch(InvalidCastException)
8024 {
8025 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_LINK_TARGET: parameter 2 must be integer", rulesParsed));
8026 return;
8027 }
8028
7303 rules = remaining.GetSublist(1, -1); 8029 rules = remaining.GetSublist(1, -1);
7304 parts = GetLinkParts(linknumber); 8030 entities = GetLinkEntities(linknumber);
7305 8031
7306 foreach (SceneObjectPart part in parts) 8032 foreach (ISceneEntity entity in entities)
7307 remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); 8033 {
8034 if (entity is SceneObjectPart)
8035 remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed);
8036 else
8037 remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed);
8038 }
8039 }
8040 }
8041
8042 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
8043 {
8044 SceneObjectGroup group = m_host.ParentGroup;
8045
8046 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
8047 return;
8048 if (group.IsAttachment)
8049 return;
8050
8051 if (frames.Data.Length > 0) // We are getting a new motion
8052 {
8053 if (group.RootPart.KeyframeMotion != null)
8054 group.RootPart.KeyframeMotion.Delete();
8055 group.RootPart.KeyframeMotion = null;
8056
8057 int idx = 0;
8058
8059 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
8060 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
8061
8062 while (idx < options.Data.Length)
8063 {
8064 int option = (int)options.GetLSLIntegerItem(idx++);
8065 int remain = options.Data.Length - idx;
8066
8067 switch (option)
8068 {
8069 case ScriptBaseClass.KFM_MODE:
8070 if (remain < 1)
8071 break;
8072 int modeval = (int)options.GetLSLIntegerItem(idx++);
8073 switch(modeval)
8074 {
8075 case ScriptBaseClass.KFM_FORWARD:
8076 mode = KeyframeMotion.PlayMode.Forward;
8077 break;
8078 case ScriptBaseClass.KFM_REVERSE:
8079 mode = KeyframeMotion.PlayMode.Reverse;
8080 break;
8081 case ScriptBaseClass.KFM_LOOP:
8082 mode = KeyframeMotion.PlayMode.Loop;
8083 break;
8084 case ScriptBaseClass.KFM_PING_PONG:
8085 mode = KeyframeMotion.PlayMode.PingPong;
8086 break;
8087 }
8088 break;
8089 case ScriptBaseClass.KFM_DATA:
8090 if (remain < 1)
8091 break;
8092 int dataval = (int)options.GetLSLIntegerItem(idx++);
8093 data = (KeyframeMotion.DataFormat)dataval;
8094 break;
8095 }
8096 }
8097
8098 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
8099
8100 idx = 0;
8101
8102 int elemLength = 2;
8103 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
8104 elemLength = 3;
8105
8106 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
8107 while (idx < frames.Data.Length)
8108 {
8109 int remain = frames.Data.Length - idx;
8110
8111 if (remain < elemLength)
8112 break;
8113
8114 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
8115 frame.Position = null;
8116 frame.Rotation = null;
8117
8118 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
8119 {
8120 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
8121 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
8122 }
8123 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
8124 {
8125 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
8126 Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
8127 q.Normalize();
8128 frame.Rotation = q;
8129 }
8130
8131 float tempf = (float)frames.GetLSLFloatItem(idx++);
8132 frame.TimeMS = (int)(tempf * 1000.0f);
8133
8134 keyframes.Add(frame);
8135 }
8136
8137 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
8138 group.RootPart.KeyframeMotion.Start();
8139 }
8140 else
8141 {
8142 if (group.RootPart.KeyframeMotion == null)
8143 return;
8144
8145 if (options.Data.Length == 0)
8146 {
8147 group.RootPart.KeyframeMotion.Stop();
8148 return;
8149 }
8150
8151 int idx = 0;
8152
8153 while (idx < options.Data.Length)
8154 {
8155 int option = (int)options.GetLSLIntegerItem(idx++);
8156
8157 switch (option)
8158 {
8159 case ScriptBaseClass.KFM_COMMAND:
8160 int cmd = (int)options.GetLSLIntegerItem(idx++);
8161 switch (cmd)
8162 {
8163 case ScriptBaseClass.KFM_CMD_PLAY:
8164 group.RootPart.KeyframeMotion.Start();
8165 break;
8166 case ScriptBaseClass.KFM_CMD_STOP:
8167 group.RootPart.KeyframeMotion.Stop();
8168 break;
8169 case ScriptBaseClass.KFM_CMD_PAUSE:
8170 group.RootPart.KeyframeMotion.Pause();
8171 break;
8172 }
8173 break;
8174 }
8175 }
7308 } 8176 }
7309 } 8177 }
7310 8178
@@ -7331,29 +8199,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7331 8199
7332 switch (code) 8200 switch (code)
7333 { 8201 {
7334 case (int)ScriptBaseClass.PRIM_POSITION: 8202 case ScriptBaseClass.PRIM_POSITION:
7335 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 8203 case ScriptBaseClass.PRIM_POS_LOCAL:
7336 if (remain < 1) 8204 if (remain < 1)
7337 return null; 8205 return new LSL_List();
7338 8206
7339 v=rules.GetVector3Item(idx++); 8207 try
8208 {
8209 v = rules.GetVector3Item(idx++);
8210 }
8211 catch(InvalidCastException)
8212 {
8213 if(code == ScriptBaseClass.PRIM_POSITION)
8214 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8215 else
8216 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8217 return new LSL_List();
8218 }
7340 positionChanged = true; 8219 positionChanged = true;
7341 currentPosition = GetSetPosTarget(part, v, currentPosition); 8220 currentPosition = GetSetPosTarget(part, v, currentPosition);
7342 8221
7343 break; 8222 break;
7344 case (int)ScriptBaseClass.PRIM_SIZE: 8223 case ScriptBaseClass.PRIM_SIZE:
7345 if (remain < 1) 8224 if (remain < 1)
7346 return null; 8225 return new LSL_List();
7347 8226
7348 v=rules.GetVector3Item(idx++); 8227 v=rules.GetVector3Item(idx++);
7349 SetScale(part, v); 8228 SetScale(part, v);
7350 8229
7351 break; 8230 break;
7352 case (int)ScriptBaseClass.PRIM_ROTATION: 8231 case ScriptBaseClass.PRIM_ROTATION:
7353 if (remain < 1) 8232 if (remain < 1)
7354 return null; 8233 return new LSL_List();
7355 8234 LSL_Rotation q;
7356 LSL_Rotation q = rules.GetQuaternionItem(idx++); 8235 try
8236 {
8237 q = rules.GetQuaternionItem(idx++);
8238 }
8239 catch(InvalidCastException)
8240 {
8241 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 1 must be rotation", rulesParsed, idx - idxStart - 1));
8242 return new LSL_List();
8243 }
7357 // try to let this work as in SL... 8244 // try to let this work as in SL...
7358 if (part.ParentID == 0) 8245 if (part.ParentID == 0)
7359 { 8246 {
@@ -7369,11 +8256,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7369 8256
7370 break; 8257 break;
7371 8258
7372 case (int)ScriptBaseClass.PRIM_TYPE: 8259 case ScriptBaseClass.PRIM_TYPE:
7373 if (remain < 3) 8260 if (remain < 3)
7374 return null; 8261 return new LSL_List();
7375 8262
7376 code = (int)rules.GetLSLIntegerItem(idx++); 8263 try
8264 {
8265 code = (int)rules.GetLSLIntegerItem(idx++);
8266 }
8267 catch(InvalidCastException)
8268 {
8269 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1));
8270 return new LSL_List();
8271 }
7377 8272
7378 remain = rules.Length - idx; 8273 remain = rules.Length - idx;
7379 float hollow; 8274 float hollow;
@@ -7388,140 +8283,625 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7388 8283
7389 switch (code) 8284 switch (code)
7390 { 8285 {
7391 case (int)ScriptBaseClass.PRIM_TYPE_BOX: 8286 case ScriptBaseClass.PRIM_TYPE_BOX:
7392 if (remain < 6) 8287 if (remain < 6)
7393 return null; 8288 return new LSL_List();
7394 8289
7395 face = (int)rules.GetLSLIntegerItem(idx++); 8290 try
7396 v = rules.GetVector3Item(idx++); // cut 8291 {
7397 hollow = (float)rules.GetLSLFloatItem(idx++); 8292 face = (int)rules.GetLSLIntegerItem(idx++);
7398 twist = rules.GetVector3Item(idx++); 8293 }
7399 taper_b = rules.GetVector3Item(idx++); 8294 catch(InvalidCastException)
7400 topshear = rules.GetVector3Item(idx++); 8295 {
8296 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
8297 return new LSL_List();
8298 }
8299 try
8300 {
8301 v = rules.GetVector3Item(idx++); // cut
8302 }
8303 catch(InvalidCastException)
8304 {
8305 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
8306 return new LSL_List();
8307 }
8308 try
8309 {
8310 hollow = (float)rules.GetLSLFloatItem(idx++);
8311 }
8312 catch(InvalidCastException)
8313 {
8314 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
8315 return new LSL_List();
8316 }
8317 try
8318 {
8319 twist = rules.GetVector3Item(idx++);
8320 }
8321 catch(InvalidCastException)
8322 {
8323 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 5 must be vector", rulesParsed, idx - idxStart - 1));
8324 return new LSL_List();
8325 }
8326 try
8327 {
8328 taper_b = rules.GetVector3Item(idx++);
8329 }
8330 catch(InvalidCastException)
8331 {
8332 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8333 return new LSL_List();
8334 }
8335 try
8336 {
8337 topshear = rules.GetVector3Item(idx++);
8338 }
8339 catch(InvalidCastException)
8340 {
8341 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8342 return new LSL_List();
8343 }
7401 8344
7402 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 8345 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
7403 (byte)ProfileShape.Square, (byte)Extrusion.Straight); 8346 (byte)ProfileShape.Square, (byte)Extrusion.Straight);
7404 break; 8347 break;
7405 8348
7406 case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: 8349 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
7407 if (remain < 6) 8350 if (remain < 6)
7408 return null; 8351 return new LSL_List();
7409 8352
7410 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8353 try
7411 v = rules.GetVector3Item(idx++); // cut 8354 {
7412 hollow = (float)rules.GetLSLFloatItem(idx++); 8355 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
7413 twist = rules.GetVector3Item(idx++); 8356 }
7414 taper_b = rules.GetVector3Item(idx++); 8357 catch(InvalidCastException)
7415 topshear = rules.GetVector3Item(idx++); 8358 {
8359 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8360 return new LSL_List();
8361 }
8362 try
8363 {
8364 v = rules.GetVector3Item(idx++); // cut
8365 }
8366 catch(InvalidCastException)
8367 {
8368 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8369 return new LSL_List();
8370 }
8371 try
8372 {
8373 hollow = (float)rules.GetLSLFloatItem(idx++);
8374 }
8375 catch(InvalidCastException)
8376 {
8377 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8378 return new LSL_List();
8379 }
8380 try
8381 {
8382 twist = rules.GetVector3Item(idx++);
8383 }
8384 catch(InvalidCastException)
8385 {
8386 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8387 return new LSL_List();
8388 }
8389 try
8390 {
8391 taper_b = rules.GetVector3Item(idx++);
8392 }
8393 catch(InvalidCastException)
8394 {
8395 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8396 return new LSL_List();
8397 }
8398 try
8399 {
8400 topshear = rules.GetVector3Item(idx++);
8401 }
8402 catch(InvalidCastException)
8403 {
8404 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8405 return new LSL_List();
8406 }
7416 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 8407 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
7417 (byte)ProfileShape.Circle, (byte)Extrusion.Straight); 8408 (byte)ProfileShape.Circle, (byte)Extrusion.Straight);
7418 break; 8409 break;
7419 8410
7420 case (int)ScriptBaseClass.PRIM_TYPE_PRISM: 8411 case ScriptBaseClass.PRIM_TYPE_PRISM:
7421 if (remain < 6) 8412 if (remain < 6)
7422 return null; 8413 return new LSL_List();
7423 8414
7424 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8415 try
7425 v = rules.GetVector3Item(idx++); //cut 8416 {
7426 hollow = (float)rules.GetLSLFloatItem(idx++); 8417 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
7427 twist = rules.GetVector3Item(idx++); 8418 }
7428 taper_b = rules.GetVector3Item(idx++); 8419 catch(InvalidCastException)
7429 topshear = rules.GetVector3Item(idx++); 8420 {
8421 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8422 return new LSL_List();
8423 }
8424 try
8425 {
8426 v = rules.GetVector3Item(idx++); //cut
8427 }
8428 catch(InvalidCastException)
8429 {
8430 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8431 return new LSL_List();
8432 }
8433 try
8434 {
8435 hollow = (float)rules.GetLSLFloatItem(idx++);
8436 }
8437 catch(InvalidCastException)
8438 {
8439 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8440 return new LSL_List();
8441 }
8442 try
8443 {
8444 twist = rules.GetVector3Item(idx++);
8445 }
8446 catch(InvalidCastException)
8447 {
8448 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8449 return new LSL_List();
8450 }
8451 try
8452 {
8453 taper_b = rules.GetVector3Item(idx++);
8454 }
8455 catch(InvalidCastException)
8456 {
8457 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8458 return new LSL_List();
8459 }
8460 try
8461 {
8462 topshear = rules.GetVector3Item(idx++);
8463 }
8464 catch(InvalidCastException)
8465 {
8466 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8467 return new LSL_List();
8468 }
7430 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 8469 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
7431 (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight); 8470 (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight);
7432 break; 8471 break;
7433 8472
7434 case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: 8473 case ScriptBaseClass.PRIM_TYPE_SPHERE:
7435 if (remain < 5) 8474 if (remain < 5)
7436 return null; 8475 return new LSL_List();
7437 8476
7438 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8477 try
7439 v = rules.GetVector3Item(idx++); // cut 8478 {
7440 hollow = (float)rules.GetLSLFloatItem(idx++); 8479 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
7441 twist = rules.GetVector3Item(idx++); 8480 }
7442 taper_b = rules.GetVector3Item(idx++); // dimple 8481 catch(InvalidCastException)
8482 {
8483 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8484 return new LSL_List();
8485 }
8486 try
8487 {
8488 v = rules.GetVector3Item(idx++); // cut
8489 }
8490 catch(InvalidCastException)
8491 {
8492 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8493 return new LSL_List();
8494 }
8495 try
8496 {
8497 hollow = (float)rules.GetLSLFloatItem(idx++);
8498 }
8499 catch(InvalidCastException)
8500 {
8501 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8502 return new LSL_List();
8503 }
8504 try
8505 {
8506 twist = rules.GetVector3Item(idx++);
8507 }
8508 catch(InvalidCastException)
8509 {
8510 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8511 return new LSL_List();
8512 }
8513 try
8514 {
8515 taper_b = rules.GetVector3Item(idx++); // dimple
8516 }
8517 catch(InvalidCastException)
8518 {
8519 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8520 return new LSL_List();
8521 }
7443 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 8522 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b,
7444 (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1); 8523 (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1);
7445 break; 8524 break;
7446 8525
7447 case (int)ScriptBaseClass.PRIM_TYPE_TORUS: 8526 case ScriptBaseClass.PRIM_TYPE_TORUS:
7448 if (remain < 11) 8527 if (remain < 11)
7449 return null; 8528 return new LSL_List();
7450 8529
7451 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8530 try
7452 v = rules.GetVector3Item(idx++); //cut 8531 {
7453 hollow = (float)rules.GetLSLFloatItem(idx++); 8532 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
7454 twist = rules.GetVector3Item(idx++); 8533 }
7455 holesize = rules.GetVector3Item(idx++); 8534 catch(InvalidCastException)
7456 topshear = rules.GetVector3Item(idx++); 8535 {
7457 profilecut = rules.GetVector3Item(idx++); 8536 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
7458 taper_b = rules.GetVector3Item(idx++); // taper_a 8537 return new LSL_List();
7459 revolutions = (float)rules.GetLSLFloatItem(idx++); 8538 }
7460 radiusoffset = (float)rules.GetLSLFloatItem(idx++); 8539 try
7461 skew = (float)rules.GetLSLFloatItem(idx++); 8540 {
8541 v = rules.GetVector3Item(idx++); //cut
8542 }
8543 catch(InvalidCastException)
8544 {
8545 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8546 return new LSL_List();
8547 }
8548 try
8549 {
8550 hollow = (float)rules.GetLSLFloatItem(idx++);
8551 }
8552 catch(InvalidCastException)
8553 {
8554 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8555 return new LSL_List();
8556 }
8557 try
8558 {
8559 twist = rules.GetVector3Item(idx++);
8560 }
8561 catch(InvalidCastException)
8562 {
8563 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8564 return new LSL_List();
8565 }
8566 try
8567 {
8568 holesize = rules.GetVector3Item(idx++);
8569 }
8570 catch(InvalidCastException)
8571 {
8572 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8573 return new LSL_List();
8574 }
8575 try
8576 {
8577 topshear = rules.GetVector3Item(idx++);
8578 }
8579 catch(InvalidCastException)
8580 {
8581 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8582 return new LSL_List();
8583 }
8584 try
8585 {
8586 profilecut = rules.GetVector3Item(idx++);
8587 }
8588 catch(InvalidCastException)
8589 {
8590 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
8591 return new LSL_List();
8592 }
8593 try
8594 {
8595 taper_b = rules.GetVector3Item(idx++); // taper_a
8596 }
8597 catch(InvalidCastException)
8598 {
8599 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
8600 return new LSL_List();
8601 }
8602 try
8603 {
8604 revolutions = (float)rules.GetLSLFloatItem(idx++);
8605 }
8606 catch(InvalidCastException)
8607 {
8608 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
8609 return new LSL_List();
8610 }
8611 try
8612 {
8613 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
8614 }
8615 catch(InvalidCastException)
8616 {
8617 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
8618 return new LSL_List();
8619 }
8620 try
8621 {
8622 skew = (float)rules.GetLSLFloatItem(idx++);
8623 }
8624 catch(InvalidCastException)
8625 {
8626 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 13 must be vector", rulesParsed, idx - idxStart - 1));
8627 return new LSL_List();
8628 }
7462 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, 8629 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
7463 revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1); 8630 revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1);
7464 break; 8631 break;
7465 8632
7466 case (int)ScriptBaseClass.PRIM_TYPE_TUBE: 8633 case ScriptBaseClass.PRIM_TYPE_TUBE:
7467 if (remain < 11) 8634 if (remain < 11)
7468 return null; 8635 return new LSL_List();
7469 8636
7470 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8637 try
7471 v = rules.GetVector3Item(idx++); //cut 8638 {
7472 hollow = (float)rules.GetLSLFloatItem(idx++); 8639 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
7473 twist = rules.GetVector3Item(idx++); 8640 }
7474 holesize = rules.GetVector3Item(idx++); 8641 catch(InvalidCastException)
7475 topshear = rules.GetVector3Item(idx++); 8642 {
7476 profilecut = rules.GetVector3Item(idx++); 8643 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
7477 taper_b = rules.GetVector3Item(idx++); // taper_a 8644 return new LSL_List();
7478 revolutions = (float)rules.GetLSLFloatItem(idx++); 8645 }
7479 radiusoffset = (float)rules.GetLSLFloatItem(idx++); 8646 try
7480 skew = (float)rules.GetLSLFloatItem(idx++); 8647 {
8648 v = rules.GetVector3Item(idx++); //cut
8649 }
8650 catch(InvalidCastException)
8651 {
8652 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8653 return new LSL_List();
8654 }
8655 try
8656 {
8657 hollow = (float)rules.GetLSLFloatItem(idx++);
8658 }
8659 catch(InvalidCastException)
8660 {
8661 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8662 return new LSL_List();
8663 }
8664 try
8665 {
8666 twist = rules.GetVector3Item(idx++);
8667 }
8668 catch(InvalidCastException)
8669 {
8670 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8671 return new LSL_List();
8672 }
8673 try
8674 {
8675 holesize = rules.GetVector3Item(idx++);
8676 }
8677 catch(InvalidCastException)
8678 {
8679 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8680 return new LSL_List();
8681 }
8682 try
8683 {
8684 topshear = rules.GetVector3Item(idx++);
8685 }
8686 catch(InvalidCastException)
8687 {
8688 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8689 return new LSL_List();
8690 }
8691 try
8692 {
8693 profilecut = rules.GetVector3Item(idx++);
8694 }
8695 catch(InvalidCastException)
8696 {
8697 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
8698 return new LSL_List();
8699 }
8700 try
8701 {
8702 taper_b = rules.GetVector3Item(idx++); // taper_a
8703 }
8704 catch(InvalidCastException)
8705 {
8706 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
8707 return new LSL_List();
8708 }
8709 try
8710 {
8711 revolutions = (float)rules.GetLSLFloatItem(idx++);
8712 }
8713 catch(InvalidCastException)
8714 {
8715 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
8716 return new LSL_List();
8717 }
8718 try
8719 {
8720 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
8721 }
8722 catch(InvalidCastException)
8723 {
8724 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
8725 return new LSL_List();
8726 }
8727 try
8728 {
8729 skew = (float)rules.GetLSLFloatItem(idx++);
8730 }
8731 catch(InvalidCastException)
8732 {
8733 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1));
8734 return new LSL_List();
8735 }
7481 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, 8736 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
7482 revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1); 8737 revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1);
7483 break; 8738 break;
7484 8739
7485 case (int)ScriptBaseClass.PRIM_TYPE_RING: 8740 case ScriptBaseClass.PRIM_TYPE_RING:
7486 if (remain < 11) 8741 if (remain < 11)
7487 return null; 8742 return new LSL_List();
7488 8743
7489 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8744 try
7490 v = rules.GetVector3Item(idx++); //cut 8745 {
7491 hollow = (float)rules.GetLSLFloatItem(idx++); 8746 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
7492 twist = rules.GetVector3Item(idx++); 8747 }
7493 holesize = rules.GetVector3Item(idx++); 8748 catch(InvalidCastException)
7494 topshear = rules.GetVector3Item(idx++); 8749 {
7495 profilecut = rules.GetVector3Item(idx++); 8750 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
7496 taper_b = rules.GetVector3Item(idx++); // taper_a 8751 return new LSL_List();
7497 revolutions = (float)rules.GetLSLFloatItem(idx++); 8752 }
7498 radiusoffset = (float)rules.GetLSLFloatItem(idx++); 8753 try
7499 skew = (float)rules.GetLSLFloatItem(idx++); 8754 {
8755 v = rules.GetVector3Item(idx++); //cut
8756 }
8757 catch(InvalidCastException)
8758 {
8759 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8760 return new LSL_List();
8761 }
8762 try
8763 {
8764 hollow = (float)rules.GetLSLFloatItem(idx++);
8765 }
8766 catch(InvalidCastException)
8767 {
8768 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8769 return new LSL_List();
8770 }
8771 try
8772 {
8773 twist = rules.GetVector3Item(idx++);
8774 }
8775 catch(InvalidCastException)
8776 {
8777 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8778 return new LSL_List();
8779 }
8780 try
8781 {
8782 holesize = rules.GetVector3Item(idx++);
8783 }
8784 catch(InvalidCastException)
8785 {
8786 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8787 return new LSL_List();
8788 }
8789 try
8790 {
8791 topshear = rules.GetVector3Item(idx++);
8792 }
8793 catch(InvalidCastException)
8794 {
8795 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8796 return new LSL_List();
8797 }
8798 try
8799 {
8800 profilecut = rules.GetVector3Item(idx++);
8801 }
8802 catch(InvalidCastException)
8803 {
8804 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
8805 return new LSL_List();
8806 }
8807 try
8808 {
8809 taper_b = rules.GetVector3Item(idx++); // taper_a
8810 }
8811 catch(InvalidCastException)
8812 {
8813 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
8814 return new LSL_List();
8815 }
8816 try
8817 {
8818 revolutions = (float)rules.GetLSLFloatItem(idx++);
8819 }
8820 catch(InvalidCastException)
8821 {
8822 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
8823 return new LSL_List();
8824 }
8825 try
8826 {
8827 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
8828 }
8829 catch(InvalidCastException)
8830 {
8831 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
8832 return new LSL_List();
8833 }
8834 try
8835 {
8836 skew = (float)rules.GetLSLFloatItem(idx++);
8837 }
8838 catch(InvalidCastException)
8839 {
8840 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1));
8841 return new LSL_List();
8842 }
7500 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, 8843 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
7501 revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1); 8844 revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1);
7502 break; 8845 break;
7503 8846
7504 case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: 8847 case ScriptBaseClass.PRIM_TYPE_SCULPT:
7505 if (remain < 2) 8848 if (remain < 2)
7506 return null; 8849 return new LSL_List();
7507 8850
7508 string map = rules.Data[idx++].ToString(); 8851 string map = rules.Data[idx++].ToString();
7509 face = (int)rules.GetLSLIntegerItem(idx++); // type 8852 try
8853 {
8854 face = (int)rules.GetLSLIntegerItem(idx++); // type
8855 }
8856 catch(InvalidCastException)
8857 {
8858 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SCULPT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
8859 return new LSL_List();
8860 }
7510 SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1); 8861 SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1);
7511 break; 8862 break;
7512 } 8863 }
7513 8864
7514 break; 8865 break;
7515 8866
7516 case (int)ScriptBaseClass.PRIM_TEXTURE: 8867 case ScriptBaseClass.PRIM_TEXTURE:
7517 if (remain < 5) 8868 if (remain < 5)
7518 return null; 8869 return new LSL_List();
7519 8870
7520 face=(int)rules.GetLSLIntegerItem(idx++); 8871 face=(int)rules.GetLSLIntegerItem(idx++);
7521 string tex=rules.Data[idx++].ToString(); 8872 string tex;
7522 LSL_Vector repeats=rules.GetVector3Item(idx++); 8873 LSL_Vector repeats;
7523 LSL_Vector offsets=rules.GetVector3Item(idx++); 8874 LSL_Vector offsets;
7524 double rotation=(double)rules.GetLSLFloatItem(idx++); 8875 double rotation;
8876
8877 tex = rules.Data[idx++].ToString();
8878 try
8879 {
8880 repeats = rules.GetVector3Item(idx++);
8881 }
8882 catch(InvalidCastException)
8883 {
8884 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
8885 return new LSL_List();
8886 }
8887 try
8888 {
8889 offsets = rules.GetVector3Item(idx++);
8890 }
8891 catch(InvalidCastException)
8892 {
8893 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8894 return new LSL_List();
8895 }
8896 try
8897 {
8898 rotation = (double)rules.GetLSLFloatItem(idx++);
8899 }
8900 catch(InvalidCastException)
8901 {
8902 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8903 return new LSL_List();
8904 }
7525 8905
7526 SetTexture(part, tex, face); 8906 SetTexture(part, tex, face);
7527 ScaleTexture(part, repeats.x, repeats.y, face); 8907 ScaleTexture(part, repeats.x, repeats.y, face);
@@ -7530,180 +8910,525 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7530 8910
7531 break; 8911 break;
7532 8912
7533 case (int)ScriptBaseClass.PRIM_COLOR: 8913 case ScriptBaseClass.PRIM_COLOR:
7534 if (remain < 3) 8914 if (remain < 3)
7535 return null; 8915 return new LSL_List();
7536 8916
7537 face=(int)rules.GetLSLIntegerItem(idx++); 8917 LSL_Vector color;
7538 LSL_Vector color=rules.GetVector3Item(idx++); 8918 double alpha;
7539 double alpha=(double)rules.GetLSLFloatItem(idx++); 8919
8920 try
8921 {
8922 face = (int)rules.GetLSLIntegerItem(idx++);
8923 }
8924 catch(InvalidCastException)
8925 {
8926 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
8927 return new LSL_List();
8928 }
8929 try
8930 {
8931 color = rules.GetVector3Item(idx++);
8932 }
8933 catch(InvalidCastException)
8934 {
8935 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
8936 return new LSL_List();
8937 }
8938 try
8939 {
8940 alpha = (double)rules.GetLSLFloatItem(idx++);
8941 }
8942 catch(InvalidCastException)
8943 {
8944 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
8945 return new LSL_List();
8946 }
7540 8947
7541 part.SetFaceColorAlpha(face, color, alpha); 8948 part.SetFaceColorAlpha(face, color, alpha);
7542 8949
7543 break; 8950 break;
7544 8951
7545 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 8952 case ScriptBaseClass.PRIM_FLEXIBLE:
7546 if (remain < 7) 8953 if (remain < 7)
7547 return null; 8954 return new LSL_List();
7548 8955 bool flexi;
7549 bool flexi = rules.GetLSLIntegerItem(idx++); 8956 int softness;
7550 int softness = rules.GetLSLIntegerItem(idx++); 8957 float gravity;
7551 float gravity = (float)rules.GetLSLFloatItem(idx++); 8958 float friction;
7552 float friction = (float)rules.GetLSLFloatItem(idx++); 8959 float wind;
7553 float wind = (float)rules.GetLSLFloatItem(idx++); 8960 float tension;
7554 float tension = (float)rules.GetLSLFloatItem(idx++); 8961 LSL_Vector force;
7555 LSL_Vector force = rules.GetVector3Item(idx++); 8962
8963 try
8964 {
8965 flexi = rules.GetLSLIntegerItem(idx++);
8966 }
8967 catch(InvalidCastException)
8968 {
8969 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
8970 return new LSL_List();
8971 }
8972 try
8973 {
8974 softness = rules.GetLSLIntegerItem(idx++);
8975 }
8976 catch(InvalidCastException)
8977 {
8978 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8979 return new LSL_List();
8980 }
8981 try
8982 {
8983 gravity = (float)rules.GetLSLFloatItem(idx++);
8984 }
8985 catch(InvalidCastException)
8986 {
8987 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
8988 return new LSL_List();
8989 }
8990 try
8991 {
8992 friction = (float)rules.GetLSLFloatItem(idx++);
8993 }
8994 catch(InvalidCastException)
8995 {
8996 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8997 return new LSL_List();
8998 }
8999 try
9000 {
9001 wind = (float)rules.GetLSLFloatItem(idx++);
9002 }
9003 catch(InvalidCastException)
9004 {
9005 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1));
9006 return new LSL_List();
9007 }
9008 try
9009 {
9010 tension = (float)rules.GetLSLFloatItem(idx++);
9011 }
9012 catch(InvalidCastException)
9013 {
9014 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 7 must be float", rulesParsed, idx - idxStart - 1));
9015 return new LSL_List();
9016 }
9017 try
9018 {
9019 force = rules.GetVector3Item(idx++);
9020 }
9021 catch(InvalidCastException)
9022 {
9023 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9024 return new LSL_List();
9025 }
7556 9026
7557 SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); 9027 SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
7558 9028
7559 break; 9029 break;
7560 9030
7561 case (int)ScriptBaseClass.PRIM_POINT_LIGHT: 9031 case ScriptBaseClass.PRIM_POINT_LIGHT:
7562 if (remain < 5) 9032 if (remain < 5)
7563 return null; 9033 return new LSL_List();
7564 bool light = rules.GetLSLIntegerItem(idx++); 9034 bool light;
7565 LSL_Vector lightcolor = rules.GetVector3Item(idx++); 9035 LSL_Vector lightcolor;
7566 float intensity = (float)rules.GetLSLFloatItem(idx++); 9036 float intensity;
7567 float radius = (float)rules.GetLSLFloatItem(idx++); 9037 float radius;
7568 float falloff = (float)rules.GetLSLFloatItem(idx++); 9038 float falloff;
9039
9040 try
9041 {
9042 light = rules.GetLSLIntegerItem(idx++);
9043 }
9044 catch(InvalidCastException)
9045 {
9046 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9047 return new LSL_List();
9048 }
9049 try
9050 {
9051 lightcolor = rules.GetVector3Item(idx++);
9052 }
9053 catch(InvalidCastException)
9054 {
9055 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9056 return new LSL_List();
9057 }
9058 try
9059 {
9060 intensity = (float)rules.GetLSLFloatItem(idx++);
9061 }
9062 catch(InvalidCastException)
9063 {
9064 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9065 return new LSL_List();
9066 }
9067 try
9068 {
9069 radius = (float)rules.GetLSLFloatItem(idx++);
9070 }
9071 catch(InvalidCastException)
9072 {
9073 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9074 return new LSL_List();
9075 }
9076 try
9077 {
9078 falloff = (float)rules.GetLSLFloatItem(idx++);
9079 }
9080 catch(InvalidCastException)
9081 {
9082 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1));
9083 return new LSL_List();
9084 }
7569 9085
7570 SetPointLight(part, light, lightcolor, intensity, radius, falloff); 9086 SetPointLight(part, light, lightcolor, intensity, radius, falloff);
7571 9087
7572 break; 9088 break;
7573 9089
7574 case (int)ScriptBaseClass.PRIM_GLOW: 9090 case ScriptBaseClass.PRIM_GLOW:
7575 if (remain < 2) 9091 if (remain < 2)
7576 return null; 9092 return new LSL_List();
7577 face = rules.GetLSLIntegerItem(idx++); 9093
7578 float glow = (float)rules.GetLSLFloatItem(idx++); 9094 float glow;
9095
9096 try
9097 {
9098 face = rules.GetLSLIntegerItem(idx++);
9099 }
9100 catch(InvalidCastException)
9101 {
9102 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9103 return new LSL_List();
9104 }
9105 try
9106 {
9107 glow = (float)rules.GetLSLFloatItem(idx++);
9108 }
9109 catch(InvalidCastException)
9110 {
9111 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1));
9112 return new LSL_List();
9113 }
7579 9114
7580 SetGlow(part, face, glow); 9115 SetGlow(part, face, glow);
7581 9116
7582 break; 9117 break;
7583 9118
7584 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 9119 case ScriptBaseClass.PRIM_BUMP_SHINY:
7585 if (remain < 3) 9120 if (remain < 3)
7586 return null; 9121 return new LSL_List();
7587 face = (int)rules.GetLSLIntegerItem(idx++); 9122
7588 int shiny = (int)rules.GetLSLIntegerItem(idx++); 9123 int shiny;
7589 Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); 9124 Bumpiness bump;
9125
9126 try
9127 {
9128 face = (int)rules.GetLSLIntegerItem(idx++);
9129 }
9130 catch(InvalidCastException)
9131 {
9132 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9133 return new LSL_List();
9134 }
9135 try
9136 {
9137 shiny = (int)rules.GetLSLIntegerItem(idx++);
9138 }
9139 catch(InvalidCastException)
9140 {
9141 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9142 return new LSL_List();
9143 }
9144 try
9145 {
9146 bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++);
9147 }
9148 catch(InvalidCastException)
9149 {
9150 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
9151 return new LSL_List();
9152 }
7590 9153
7591 SetShiny(part, face, shiny, bump); 9154 SetShiny(part, face, shiny, bump);
7592 9155
7593 break; 9156 break;
7594 9157
7595 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 9158 case ScriptBaseClass.PRIM_FULLBRIGHT:
7596 if (remain < 2) 9159 if (remain < 2)
7597 return null; 9160 return new LSL_List();
7598 face = rules.GetLSLIntegerItem(idx++); 9161 bool st;
7599 bool st = rules.GetLSLIntegerItem(idx++); 9162
7600 SetFullBright(part, face , st); 9163 try
7601 break; 9164 {
9165 face = rules.GetLSLIntegerItem(idx++);
9166 }
9167 catch(InvalidCastException)
9168 {
9169 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9170 return new LSL_List();
9171 }
9172 try
9173 {
9174 st = rules.GetLSLIntegerItem(idx++);
9175 }
9176 catch(InvalidCastException)
9177 {
9178 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
9179 return new LSL_List();
9180 }
9181 SetFullBright(part, face , st);
9182 break;
9183
9184 case ScriptBaseClass.PRIM_MATERIAL:
9185 if (remain < 1)
9186 return new LSL_List();
9187 int mat;
9188
9189 try
9190 {
9191 mat = rules.GetLSLIntegerItem(idx++);
9192 }
9193 catch(InvalidCastException)
9194 {
9195 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_MATERIAL: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9196 return new LSL_List();
9197 }
9198 if (mat < 0 || mat > 7)
9199 return new LSL_List();
7602 9200
7603 case (int)ScriptBaseClass.PRIM_MATERIAL: 9201 part.Material = Convert.ToByte(mat);
7604 if (remain < 1) 9202 break;
7605 return null;
7606 int mat = rules.GetLSLIntegerItem(idx++);
7607 if (mat < 0 || mat > 7)
7608 return null;
7609 9203
7610 part.Material = Convert.ToByte(mat); 9204 case ScriptBaseClass.PRIM_PHANTOM:
7611 break; 9205 if (remain < 1)
9206 return new LSL_List();
7612 9207
7613 case (int)ScriptBaseClass.PRIM_PHANTOM: 9208 string ph = rules.Data[idx++].ToString();
7614 if (remain < 1) 9209 part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
7615 return null;
7616 9210
7617 string ph = rules.Data[idx++].ToString(); 9211 break;
7618 m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
7619 9212
7620 break; 9213 case ScriptBaseClass.PRIM_PHYSICS:
9214 if (remain < 1)
9215 return new LSL_List();
9216 string phy = rules.Data[idx++].ToString();
9217 part.ScriptSetPhysicsStatus(phy.Equals("1"));
9218 break;
7621 9219
7622 case (int)ScriptBaseClass.PRIM_PHYSICS: 9220 case ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
7623 if (remain < 1) 9221 if (remain < 1)
7624 return null; 9222 return new LSL_List();
7625 string phy = rules.Data[idx++].ToString();
7626 bool physics;
7627 9223
7628 if (phy.Equals("1")) 9224 int shape_type;
7629 physics = true;
7630 else
7631 physics = false;
7632 9225
7633 part.ScriptSetPhysicsStatus(physics); 9226 try
7634 break; 9227 {
9228 shape_type = rules.GetLSLIntegerItem(idx++);
9229 }
9230 catch(InvalidCastException)
9231 {
9232 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_PHYSICS_SHAPE_TYPE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9233 return new LSL_List();
9234 }
9235
9236 ExtraPhysicsData physdata = new ExtraPhysicsData();
9237 physdata.Density = part.Density;
9238 physdata.Bounce = part.Restitution;
9239 physdata.GravitationModifier = part.GravityModifier;
9240 physdata.PhysShapeType = (PhysShapeType)shape_type;
9241
9242 part.UpdateExtraPhysics(physdata);
7635 9243
7636 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 9244 break;
9245
9246 case ScriptBaseClass.PRIM_TEMP_ON_REZ:
7637 if (remain < 1) 9247 if (remain < 1)
7638 return null; 9248 return new LSL_List();
7639 string temp = rules.Data[idx++].ToString(); 9249 string temp = rules.Data[idx++].ToString();
7640 9250
7641 m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 9251 part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1"));
7642 9252
7643 break; 9253 break;
7644 9254
7645 case (int)ScriptBaseClass.PRIM_TEXGEN: 9255 case ScriptBaseClass.PRIM_TEXGEN:
7646 if (remain < 2) 9256 if (remain < 2)
7647 return null; 9257 return new LSL_List();
7648 //face,type 9258 //face,type
7649 face = rules.GetLSLIntegerItem(idx++); 9259 int style;
7650 int style = rules.GetLSLIntegerItem(idx++); 9260
9261 try
9262 {
9263 face = rules.GetLSLIntegerItem(idx++);
9264 }
9265 catch(InvalidCastException)
9266 {
9267 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9268 return new LSL_List();
9269 }
9270 try
9271 {
9272 style = rules.GetLSLIntegerItem(idx++);
9273 }
9274 catch(InvalidCastException)
9275 {
9276 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9277 return new LSL_List();
9278 }
7651 SetTexGen(part, face, style); 9279 SetTexGen(part, face, style);
7652 break; 9280 break;
7653 case (int)ScriptBaseClass.PRIM_TEXT: 9281 case ScriptBaseClass.PRIM_TEXT:
7654 if (remain < 3) 9282 if (remain < 3)
7655 return null; 9283 return new LSL_List();
7656 string primText = rules.GetLSLStringItem(idx++); 9284 string primText;
7657 LSL_Vector primTextColor = rules.GetVector3Item(idx++); 9285 LSL_Vector primTextColor;
7658 LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); 9286 LSL_Float primTextAlpha;
9287
9288 try
9289 {
9290 primText = rules.GetLSLStringItem(idx++);
9291 }
9292 catch(InvalidCastException)
9293 {
9294 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9295 return new LSL_List();
9296 }
9297 try
9298 {
9299 primTextColor = rules.GetVector3Item(idx++);
9300 }
9301 catch(InvalidCastException)
9302 {
9303 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9304 return new LSL_List();
9305 }
9306 try
9307 {
9308 primTextAlpha = rules.GetLSLFloatItem(idx++);
9309 }
9310 catch(InvalidCastException)
9311 {
9312 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9313 return new LSL_List();
9314 }
7659 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); 9315 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f);
7660 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); 9316 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
7661 9317
7662 break; 9318 break;
7663 case (int)ScriptBaseClass.PRIM_NAME: 9319
9320 case ScriptBaseClass.PRIM_NAME:
7664 if (remain < 1) 9321 if (remain < 1)
7665 return null; 9322 return new LSL_List();
7666 string primName = rules.GetLSLStringItem(idx++); 9323 try
7667 part.Name = primName; 9324 {
9325 string primName = rules.GetLSLStringItem(idx++);
9326 part.Name = primName;
9327 }
9328 catch(InvalidCastException)
9329 {
9330 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NAME: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9331 return new LSL_List();
9332 }
7668 break; 9333 break;
7669 case (int)ScriptBaseClass.PRIM_DESC: 9334 case ScriptBaseClass.PRIM_DESC:
7670 if (remain < 1) 9335 if (remain < 1)
7671 return null; 9336 return new LSL_List();
7672 string primDesc = rules.GetLSLStringItem(idx++); 9337 try
7673 part.Description = primDesc; 9338 {
9339 string primDesc = rules.GetLSLStringItem(idx++);
9340 part.Description = primDesc;
9341 }
9342 catch(InvalidCastException)
9343 {
9344 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_DESC: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9345 return new LSL_List();
9346 }
7674 break; 9347 break;
7675 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 9348 case ScriptBaseClass.PRIM_ROT_LOCAL:
7676 if (remain < 1) 9349 if (remain < 1)
7677 return null; 9350 return new LSL_List();
7678 SetRot(part, rules.GetQuaternionItem(idx++)); 9351 LSL_Rotation rot;
9352 try
9353 {
9354 rot = rules.GetQuaternionItem(idx++);
9355 }
9356 catch(InvalidCastException)
9357 {
9358 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
9359 return new LSL_List();
9360 }
9361 SetRot(part, rot);
7679 break; 9362 break;
7680 case (int)ScriptBaseClass.PRIM_OMEGA: 9363
9364 case ScriptBaseClass.PRIM_OMEGA:
7681 if (remain < 3) 9365 if (remain < 3)
7682 return null; 9366 return new LSL_List();
7683 LSL_Vector axis = rules.GetVector3Item(idx++); 9367 LSL_Vector axis;
7684 LSL_Float spinrate = rules.GetLSLFloatItem(idx++); 9368 LSL_Float spinrate;
7685 LSL_Float gain = rules.GetLSLFloatItem(idx++); 9369 LSL_Float gain;
9370
9371 try
9372 {
9373 axis = rules.GetVector3Item(idx++);
9374 }
9375 catch(InvalidCastException)
9376 {
9377 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9378 return new LSL_List();
9379 }
9380 try
9381 {
9382 spinrate = rules.GetLSLFloatItem(idx++);
9383 }
9384 catch(InvalidCastException)
9385 {
9386 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1));
9387 return new LSL_List();
9388 }
9389 try
9390 {
9391 gain = rules.GetLSLFloatItem(idx++);
9392 }
9393 catch(InvalidCastException)
9394 {
9395 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9396 return new LSL_List();
9397 }
7686 TargetOmega(part, axis, (double)spinrate, (double)gain); 9398 TargetOmega(part, axis, (double)spinrate, (double)gain);
7687 break; 9399 break;
7688 case (int)ScriptBaseClass.PRIM_SLICE: 9400
9401 case ScriptBaseClass.PRIM_SLICE:
7689 if (remain < 1) 9402 if (remain < 1)
7690 return null; 9403 return new LSL_List();
7691 LSL_Vector slice = rules.GetVector3Item(idx++); 9404 LSL_Vector slice;
9405 try
9406 {
9407 slice = rules.GetVector3Item(idx++);
9408 }
9409 catch(InvalidCastException)
9410 {
9411 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SLICE: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9412 return new LSL_List();
9413 }
7692 part.UpdateSlice((float)slice.x, (float)slice.y); 9414 part.UpdateSlice((float)slice.x, (float)slice.y);
7693 break; 9415 break;
7694 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 9416
9417 case ScriptBaseClass.PRIM_LINK_TARGET:
7695 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 9418 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
7696 return null; 9419 return new LSL_List();
7697 9420
7698 return rules.GetSublist(idx, -1); 9421 return rules.GetSublist(idx, -1);
9422
9423 default:
9424 Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - unsupported parameter", rulesParsed, idx - idxStart));
9425 return new LSL_List();
7699 } 9426 }
7700 } 9427 }
7701 } 9428 }
7702 catch (InvalidCastException e) 9429 catch (InvalidCastException e)
7703 { 9430 {
7704 ShoutError(string.Format( 9431 Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
7705 "{0} error running rule #{1}: arg #{2} ",
7706 originFunc, rulesParsed, idx - idxStart) + e.Message);
7707 } 9432 }
7708 finally 9433 finally
7709 { 9434 {
@@ -7723,7 +9448,118 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7723 } 9448 }
7724 } 9449 }
7725 } 9450 }
7726 return null; 9451
9452 return new LSL_List();
9453 }
9454
9455 protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed)
9456 {
9457 int idx = 0;
9458 int idxStart = 0;
9459
9460 try
9461 {
9462 while (idx < rules.Length)
9463 {
9464 ++rulesParsed;
9465 int code = rules.GetLSLIntegerItem(idx++);
9466
9467 int remain = rules.Length - idx;
9468 idxStart = idx;
9469
9470 switch (code)
9471 {
9472 case ScriptBaseClass.PRIM_POSITION:
9473 case ScriptBaseClass.PRIM_POS_LOCAL:
9474 if (remain < 1)
9475 return new LSL_List();
9476
9477 try
9478 {
9479 sp.OffsetPosition = rules.GetVector3Item(idx++);
9480 }
9481 catch(InvalidCastException)
9482 {
9483 if (code == ScriptBaseClass.PRIM_POSITION)
9484 {
9485 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9486 }
9487 else
9488 {
9489 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9490 }
9491 return new LSL_List();
9492 }
9493 break;
9494
9495 case ScriptBaseClass.PRIM_ROTATION:
9496 if (remain < 1)
9497 return new LSL_List();
9498
9499 Quaternion inRot;
9500
9501 try
9502 {
9503 inRot = rules.GetQuaternionItem(idx++);
9504 }
9505 catch(InvalidCastException)
9506 {
9507 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
9508 return new LSL_List();
9509 }
9510
9511 SceneObjectPart parentPart = sp.ParentPart;
9512
9513 if (parentPart != null)
9514 sp.Rotation = m_host.GetWorldRotation() * inRot;
9515
9516 break;
9517
9518 case ScriptBaseClass.PRIM_ROT_LOCAL:
9519 if (remain < 1)
9520 return new LSL_List();
9521
9522 try
9523 {
9524 sp.Rotation = rules.GetQuaternionItem(idx++);
9525 }
9526 catch(InvalidCastException)
9527 {
9528 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
9529 return new LSL_List();
9530 }
9531
9532 break;
9533
9534 case ScriptBaseClass.PRIM_TYPE:
9535 Error(originFunc, "PRIM_TYPE disallowed on agent");
9536 return new LSL_List();
9537
9538 case ScriptBaseClass.PRIM_OMEGA:
9539 Error(originFunc, "PRIM_OMEGA disallowed on agent");
9540 return new LSL_List();
9541
9542 case ScriptBaseClass.PRIM_LINK_TARGET:
9543 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9544 return new LSL_List();
9545
9546 return rules.GetSublist(idx, -1);
9547
9548 default:
9549 Error(originFunc,
9550 string.Format("Error running rule #{0} on agent: arg #{1} - disallowed on agent", rulesParsed, idx - idxStart));
9551 return new LSL_List();
9552 }
9553 }
9554 }
9555 catch (InvalidCastException e)
9556 {
9557 Error(
9558 originFunc,
9559 string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
9560 }
9561
9562 return new LSL_List();
7727 } 9563 }
7728 9564
7729 public LSL_String llStringToBase64(string str) 9565 public LSL_String llStringToBase64(string str)
@@ -7731,14 +9567,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7731 m_host.AddScriptLPS(1); 9567 m_host.AddScriptLPS(1);
7732 try 9568 try
7733 { 9569 {
7734 byte[] encData_byte = new byte[str.Length]; 9570 byte[] encData_byte;
7735 encData_byte = Util.UTF8.GetBytes(str); 9571 encData_byte = Util.UTF8.GetBytes(str);
7736 string encodedData = Convert.ToBase64String(encData_byte); 9572 string encodedData = Convert.ToBase64String(encData_byte);
7737 return encodedData; 9573 return encodedData;
7738 } 9574 }
7739 catch (Exception e) 9575 catch
7740 { 9576 {
7741 throw new Exception("Error in base64Encode" + e.Message); 9577 Error("llBase64ToString", "Error encoding string");
9578 return String.Empty;
7742 } 9579 }
7743 } 9580 }
7744 9581
@@ -7747,26 +9584,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7747 m_host.AddScriptLPS(1); 9584 m_host.AddScriptLPS(1);
7748 try 9585 try
7749 { 9586 {
7750 return Util.Base64ToString(str); 9587 byte[] b = Convert.FromBase64String(str);
9588 return Encoding.UTF8.GetString(b);
7751 } 9589 }
7752 catch (Exception e) 9590 catch
7753 { 9591 {
7754 throw new Exception("Error in base64Decode" + e.Message); 9592 Error("llBase64ToString", "Error decoding string");
9593 return String.Empty;
7755 } 9594 }
7756 } 9595 }
7757 9596
7758 public LSL_String llXorBase64Strings(string str1, string str2) 9597 public LSL_String llXorBase64Strings(string str1, string str2)
7759 { 9598 {
7760 m_host.AddScriptLPS(1); 9599 m_host.AddScriptLPS(1);
7761 Deprecated("llXorBase64Strings"); 9600 Deprecated("llXorBase64Strings", "Use llXorBase64 instead");
7762 ScriptSleep(300); 9601 ScriptSleep(m_sleepMsOnXorBase64Strings);
7763 return String.Empty; 9602 return String.Empty;
7764 } 9603 }
7765 9604
7766 public void llRemoteDataSetRegion() 9605 public void llRemoteDataSetRegion()
7767 { 9606 {
7768 m_host.AddScriptLPS(1); 9607 m_host.AddScriptLPS(1);
7769 Deprecated("llRemoteDataSetRegion"); 9608 Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead");
7770 } 9609 }
7771 9610
7772 public LSL_Float llLog10(double val) 9611 public LSL_Float llLog10(double val)
@@ -7800,21 +9639,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7800 { 9639 {
7801 m_host.AddScriptLPS(1); 9640 m_host.AddScriptLPS(1);
7802 9641
7803 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 9642 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
7804 9643
7805 if (land.LandData.OwnerID != m_host.OwnerID) 9644 if (land.LandData.OwnerID != m_host.OwnerID)
7806 return; 9645 return;
7807 9646
7808 land.SetMusicUrl(url); 9647 land.SetMusicUrl(url);
7809 9648
7810 ScriptSleep(2000); 9649 ScriptSleep(m_sleepMsOnSetParcelMusicURL);
7811 } 9650 }
7812 9651
7813 public LSL_String llGetParcelMusicURL() 9652 public LSL_String llGetParcelMusicURL()
7814 { 9653 {
7815 m_host.AddScriptLPS(1); 9654 m_host.AddScriptLPS(1);
7816 9655
7817 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 9656 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
7818 9657
7819 if (land.LandData.OwnerID != m_host.OwnerID) 9658 if (land.LandData.OwnerID != m_host.OwnerID)
7820 return String.Empty; 9659 return String.Empty;
@@ -7825,8 +9664,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7825 public LSL_Vector llGetRootPosition() 9664 public LSL_Vector llGetRootPosition()
7826 { 9665 {
7827 m_host.AddScriptLPS(1); 9666 m_host.AddScriptLPS(1);
7828 return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, 9667
7829 m_host.ParentGroup.AbsolutePosition.Z); 9668 return new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
7830 } 9669 }
7831 9670
7832 /// <summary> 9671 /// <summary>
@@ -7849,13 +9688,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7849 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 9688 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
7850 q = avatar.CameraRotation; // Mouselook 9689 q = avatar.CameraRotation; // Mouselook
7851 else 9690 else
7852 q = avatar.Rotation; // Currently infrequently updated so may be inaccurate 9691 q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
7853 else 9692 else
7854 q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case 9693 q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case
7855 } 9694 }
7856 else 9695 else
7857 q = m_host.ParentGroup.GroupRotation; // just the group rotation 9696 q = m_host.ParentGroup.GroupRotation; // just the group rotation
7858 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 9697
9698 return new LSL_Rotation(q);
7859 } 9699 }
7860 9700
7861 public LSL_String llGetObjectDesc() 9701 public LSL_String llGetObjectDesc()
@@ -7889,137 +9729,668 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7889 } 9729 }
7890 9730
7891 /// <summary> 9731 /// <summary>
7892 /// A partial implementation. 9732 /// Full implementation of llGetBoundingBox according to SL 2015-04-15.
9733 /// http://wiki.secondlife.com/wiki/LlGetBoundingBox
7893 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox 9734 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
7894 /// So far only valid for standing/flying/ground sitting avatars and single prim objects. 9735 /// Returns local bounding box of avatar without attachments
7895 /// If the object has multiple prims and/or a sitting avatar then the bounding 9736 /// if target is non-seated avatar or prim/mesh in avatar attachment.
7896 /// box is for the root prim only. 9737 /// Returns local bounding box of object including seated avatars
9738 /// if target is seated avatar or prim/mesh in object.
9739 /// Uses meshing of prims for high accuracy
9740 /// or less accurate box models for speed.
7897 /// </summary> 9741 /// </summary>
7898 public LSL_List llGetBoundingBox(string obj) 9742 public LSL_List llGetBoundingBox(string obj)
7899 { 9743 {
7900 m_host.AddScriptLPS(1); 9744 m_host.AddScriptLPS(1);
9745
9746 // Get target avatar if non-seated avatar or attachment, or prim and object
7901 UUID objID = UUID.Zero; 9747 UUID objID = UUID.Zero;
9748 UUID.TryParse(obj, out objID);
9749 ScenePresence agent = World.GetScenePresence(objID);
9750 if (agent != null)
9751 {
9752 if (agent.ParentPart != null)
9753 {
9754 objID = agent.ParentPart.UUID;
9755 agent = null;
9756 }
9757 }
9758 SceneObjectGroup group = null;
9759 SceneObjectPart target = World.GetSceneObjectPart(objID);
9760 if (target != null)
9761 {
9762 group = target.ParentGroup;
9763 if (group.IsAttachment) {
9764 objID = group.AttachedAvatar;
9765 agent = World.GetScenePresence(objID);
9766 group = null;
9767 target = null;
9768 }
9769 }
9770
9771 // Initialize but break if no target
7902 LSL_List result = new LSL_List(); 9772 LSL_List result = new LSL_List();
7903 if (!UUID.TryParse(obj, out objID)) 9773 int groupCount = 0;
9774 int partCount = 0;
9775 int vertexCount = 0;
9776 if (target == null && agent == null)
7904 { 9777 {
7905 result.Add(new LSL_Vector()); 9778 result.Add(new LSL_Vector());
7906 result.Add(new LSL_Vector()); 9779 result.Add(new LSL_Vector());
9780 if (m_addStatsInGetBoundingBox)
9781 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
7907 return result; 9782 return result;
7908 } 9783 }
7909 ScenePresence presence = World.GetScenePresence(objID); 9784 Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
7910 if (presence != null) 9785 Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue);
9786
9787 // Try to get a mesher
9788 IRendering primMesher = null;
9789 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
9790 if (renderers.Count > 0)
9791 primMesher = RenderingLoader.LoadRenderer(renderers[0]);
9792
9793 // Get bounding box of just avatar, seated or not
9794 if (agent != null)
9795 {
9796 bool hasParent = false;
9797 Vector3 lower;
9798 Vector3 upper;
9799 BoundingBoxOfScenePresence(agent, out lower, out upper);
9800 Vector3 offset = Vector3.Zero;
9801
9802 // Since local bounding box unrotated and untilted, keep it simple
9803 AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9804 partCount++;
9805 groupCount++;
9806
9807 // Return lower and upper bounding box corners
9808 result.Add(new LSL_Vector(minPosition));
9809 result.Add(new LSL_Vector(maxPosition));
9810 if (m_addStatsInGetBoundingBox)
9811 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9812 return result;
9813 }
9814 // Get bounding box of object including seated avatars
9815 else if (group != null)
7911 { 9816 {
7912 if (presence.ParentID == 0) // not sat on an object 9817 // Merge bounding boxes of all parts (prims and mesh)
9818 foreach (SceneObjectPart part in group.Parts)
7913 { 9819 {
7914 LSL_Vector lower; 9820 bool hasParent = (!part.IsRoot);
7915 LSL_Vector upper; 9821 // When requested or if no mesher, keep it simple
7916 if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID 9822 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
7917 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7918 { 9823 {
7919 // This is for ground sitting avatars 9824 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
7920 float height = presence.Appearance.AvatarHeight / 2.66666667f;
7921 lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f);
7922 upper = new LSL_Vector(0.3375f, 0.45f, 0.0f);
7923 } 9825 }
9826 // Do the full mounty
7924 else 9827 else
7925 { 9828 {
7926 // This is for standing/flying avatars 9829 Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset);
7927 float height = presence.Appearance.AvatarHeight / 2.0f; 9830 byte[] sculptAsset = null;
7928 lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); 9831 if (omvPrim.Sculpt != null)
7929 upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); 9832 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
9833
9834 // When part is mesh
9835 // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler.
9836 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
9837 {
9838 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
9839 FacetedMesh mesh = null;
9840 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh);
9841 meshAsset = null;
9842 if (mesh != null)
9843 {
9844 AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9845 mesh = null;
9846 }
9847 }
9848
9849 // When part is sculpt
9850 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
9851 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
9852 {
9853 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
9854 if (imgDecoder != null)
9855 {
9856 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
9857 if (sculpt != null)
9858 {
9859 SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium);
9860 sculpt.Dispose();
9861 if (mesh != null)
9862 {
9863 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9864 mesh = null;
9865 }
9866 }
9867 }
9868 }
9869
9870 // When part is prim
9871 else if (omvPrim.Sculpt == null)
9872 {
9873 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9874 if (mesh != null)
9875 {
9876 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9877 mesh = null;
9878 }
9879 }
9880
9881 // When all else fails, try fallback to simple box
9882 else
9883 {
9884 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9885 }
7930 } 9886 }
7931 result.Add(lower); 9887 partCount++;
7932 result.Add(upper);
7933 return result;
7934 } 9888 }
9889 }
9890
9891 // Merge bounding boxes of seated avatars
9892 foreach (ScenePresence sp in group.GetSittingAvatars())
9893 {
9894 Vector3 lower;
9895 Vector3 upper;
9896 BoundingBoxOfScenePresence(sp, out lower, out upper);
9897 Vector3 offset = sp.OffsetPosition;
9898
9899 bool hasParent = true;
9900 // When requested or if no mesher, keep it simple
9901 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
9902 {
9903 AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9904 }
9905 // Do the full mounty
7935 else 9906 else
7936 { 9907 {
7937 // sitting on an object so we need the bounding box of that 9908 // Prim shapes don't do center offsets, so add it here.
7938 // which should include the avatar so set the UUID to the 9909 offset = offset + (lower + upper) * 0.5f * sp.Rotation;
7939 // UUID of the object the avatar is sat on and allow it to fall through 9910 Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE);
7940 // to processing an object 9911 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
7941 SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID); 9912 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
7942 objID = p.UUID; 9913 mesh = null;
7943 } 9914 }
9915 partCount++;
7944 } 9916 }
7945 SceneObjectPart part = World.GetSceneObjectPart(objID); 9917
7946 // Currently only works for single prims without a sitting avatar 9918 groupCount++;
7947 if (part != null) 9919
9920 // Return lower and upper bounding box corners
9921 result.Add(new LSL_Vector(minPosition));
9922 result.Add(new LSL_Vector(maxPosition));
9923 if (m_addStatsInGetBoundingBox)
9924 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9925
9926 primMesher = null;
9927 return result;
9928 }
9929
9930 /// <summary>
9931 /// Helper to calculate bounding box of an avatar.
9932 /// </summary>
9933 private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper)
9934 {
9935 // Adjust from OS model
9936 // avatar height = visual height - 0.2, bounding box height = visual height
9937 // to SL model
9938 // avatar height = visual height, bounding box height = visual height + 0.2
9939 float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection;
9940
9941 // According to avatar bounding box in SL 2015-04-18:
9942 // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h>
9943 // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5>
9944 // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h>
9945
9946 // When avatar is sitting
9947 if (sp.ParentPart != null)
7948 { 9948 {
7949 Vector3 halfSize = part.Scale / 2.0f; 9949 lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height);
7950 LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; 9950 upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height);
7951 LSL_Vector upper = new LSL_Vector(halfSize); 9951 }
7952 result.Add(lower); 9952 // When avatar is groundsitting
7953 result.Add(upper); 9953 else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
7954 return result; 9954 {
9955 lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height);
9956 upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height);
9957 }
9958 // When avatar is standing or flying
9959 else
9960 {
9961 lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height);
9962 upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height);
7955 } 9963 }
9964 }
7956 9965
7957 // Not found so return empty values 9966 /// <summary>
7958 result.Add(new LSL_Vector()); 9967 /// Helper to approximate a part with a simple box.
7959 result.Add(new LSL_Vector()); 9968 /// </summary>
7960 return result; 9969 private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9970 {
9971 // Parse the 8 box corners
9972 for (int i = 0; i < 8; i++)
9973 {
9974 // Calculate each box corner
9975 Vector3 position = corner1;
9976 if ((i & 1) != 0)
9977 position.X = corner2.X;
9978 if ((i & 2) != 0)
9979 position.Y = corner2.Y;
9980 if ((i & 4) != 0)
9981 position.Z = corner2.Z;
9982 // Rotate part unless part is root
9983 if (hasParent)
9984 position = position * rotation;
9985 position = position + offset;
9986 // Adjust lower and upper bounding box corners if needed
9987 lower = Vector3.Min(lower, position);
9988 upper = Vector3.Max(upper, position);
9989 count++;
9990 }
7961 } 9991 }
7962 9992
7963 public LSL_Vector llGetGeometricCenter() 9993 /// <summary>
9994 /// Helper to parse a meshed prim and needed especially
9995 /// for accuracy with tortured prims and sculpts.
9996 /// </summary>
9997 private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
7964 { 9998 {
7965 return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); 9999 // Quirk: A meshed box contains 10 instead of the 8 necessary vertices.
10000 if (mesh != null)
10001 {
10002 // Parse each vertex in mesh
10003 foreach (Vertex vertex in mesh.Vertices)
10004 {
10005 Vector3 position = vertex.Position;
10006 position = position * prim.Scale;
10007 // Rotate part unless part is root
10008 if (hasParent)
10009 position = position * prim.Rotation;
10010 position = position + prim.Position;
10011 // Adjust lower and upper bounding box corners if needed
10012 lower = Vector3.Min(lower, position);
10013 upper = Vector3.Max(upper, position);
10014 count++;
10015 }
10016 }
7966 } 10017 }
7967 10018
7968 public LSL_List llGetPrimitiveParams(LSL_List rules) 10019 /// <summary>
10020 /// Helper to parse mesh because no method exists
10021 /// to parse mesh assets to SimpleMesh.
10022 /// </summary>
10023 private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
7969 { 10024 {
7970 m_host.AddScriptLPS(1); 10025 if (mesh != null)
10026 {
10027 // Parse each face in mesh
10028 // since vertex array isn't populated.
10029 // This parses each unique vertex 3-6 times.
10030 foreach (Face face in mesh.Faces)
10031 {
10032 // Parse each vertex in face
10033 foreach (Vertex vertex in face.Vertices)
10034 {
10035 Vector3 position = vertex.Position;
10036 position = position * prim.Scale;
10037 // Rotate part unless part is root
10038 if (hasParent)
10039 position = position * prim.Rotation;
10040 position = position + prim.Position;
10041 // Adjust lower and upper bounding box corners if needed
10042 lower = Vector3.Min(lower, position);
10043 upper = Vector3.Max(upper, position);
10044 count++;
10045 }
10046 }
10047 }
10048 }
7971 10049
7972 LSL_List result = new LSL_List(); 10050 /// <summary>
10051 /// Helper to make up an OpenMetaverse prim
10052 /// needed to create mesh from parts.
10053 /// </summary>
10054 private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType)
10055 {
10056 // Initialize and set common parameters
10057 Primitive prim = new OpenMetaverse.Primitive();
10058 prim.Scale = scale;
10059 prim.Position = position;
10060 prim.Rotation = rotation;
10061 prim.PrimData.PathShearX = 0.0f;
10062 prim.PrimData.PathShearY = 0.0f;
10063 prim.PrimData.PathBegin = 0.0f;
10064 prim.PrimData.PathEnd = 1.0f;
10065 prim.PrimData.PathScaleX = 1.0f;
10066 prim.PrimData.PathScaleY = 1.0f;
10067 prim.PrimData.PathTaperX = 0.0f;
10068 prim.PrimData.PathTaperY = 0.0f;
10069 prim.PrimData.PathTwistBegin = 0.0f;
10070 prim.PrimData.PathTwist = 0.0f;
10071 prim.PrimData.ProfileBegin = 0.0f;
10072 prim.PrimData.ProfileEnd = 1.0f;
10073 prim.PrimData.ProfileHollow = 0.0f;
10074 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10075 prim.PrimData.ProfileHole = (HoleType)0;
10076 prim.PrimData.PathCurve = (PathCurve)16;
10077 prim.PrimData.PathRadiusOffset = 0.0f;
10078 prim.PrimData.PathRevolutions = 1.0f;
10079 prim.PrimData.PathSkew = 0.0f;
10080 prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
10081 prim.PrimData.State = (byte)0;
10082
10083 // Set type specific parameters
10084 switch (primType)
10085 {
10086 // Set specific parameters for box
10087 case ScriptBaseClass.PRIM_TYPE_BOX:
10088 prim.PrimData.PathScaleY = 1.0f;
10089 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10090 prim.PrimData.PathCurve = (PathCurve)16;
10091 break;
10092 // Set specific parameters for cylinder
10093 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
10094 prim.PrimData.PathScaleY = 1.0f;
10095 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10096 prim.PrimData.PathCurve = (PathCurve)16;
10097 break;
10098 // Set specific parameters for prism
10099 case ScriptBaseClass.PRIM_TYPE_PRISM:
10100 prim.PrimData.PathScaleY = 1.0f;
10101 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10102 prim.PrimData.PathCurve = (PathCurve)16;
10103 break;
10104 // Set specific parameters for sphere
10105 case ScriptBaseClass.PRIM_TYPE_SPHERE:
10106 prim.PrimData.PathScaleY = 1.0f;
10107 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10108 prim.PrimData.PathCurve = (PathCurve)32;
10109 break;
10110 // Set specific parameters for torus
10111 case ScriptBaseClass.PRIM_TYPE_TORUS:
10112 prim.PrimData.PathScaleY = 0.5f;
10113 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10114 prim.PrimData.PathCurve = (PathCurve)32;
10115 break;
10116 // Set specific parameters for tube
10117 case ScriptBaseClass.PRIM_TYPE_TUBE:
10118 prim.PrimData.PathScaleY = 0.5f;
10119 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10120 prim.PrimData.PathCurve = (PathCurve)32;
10121 break;
10122 // Set specific parameters for ring
10123 case ScriptBaseClass.PRIM_TYPE_RING:
10124 prim.PrimData.PathScaleY = 0.5f;
10125 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10126 prim.PrimData.PathCurve = (PathCurve)32;
10127 break;
10128 // Set specific parameters for sculpt
10129 case ScriptBaseClass.PRIM_TYPE_SCULPT:
10130 prim.PrimData.PathScaleY = 1.0f;
10131 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10132 prim.PrimData.PathCurve = (PathCurve)32;
10133 break;
10134 // Default to specific parameters for box
10135 default:
10136 prim.PrimData.PathScaleY = 1.0f;
10137 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10138 prim.PrimData.PathCurve = (PathCurve)16;
10139 break;
10140 }
7973 10141
7974 LSL_List remaining = GetPrimParams(m_host, rules, ref result); 10142 return prim;
10143 }
10144
10145 /// <summary>
10146 /// Implementation of llGetGeometricCenter according to SL 2015-04-30.
10147 /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter
10148 /// Returns the average position offset of all linked parts,
10149 /// including the root prim and seated avatars,
10150 /// relative to the root prim in local coordinates.
10151 /// </summary>
10152 public LSL_Vector llGetGeometricCenter()
10153 {
10154 // Subtract whatever position the root prim has to make it zero
10155 Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f;
10156
10157 // Add all prim/part position offsets
10158 foreach (SceneObjectPart part in m_host.ParentGroup.Parts)
10159 offset = offset + part.OffsetPosition;
10160 // Add all avatar/scene presence position offsets
10161 foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars())
10162 offset = offset + sp.OffsetPosition;
7975 10163
7976 while (remaining != null && remaining.Length > 2) 10164 // Calculate and return the average offset
10165 offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount());
10166 return new LSL_Vector(offset);
10167 }
10168
10169 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules)
10170 {
10171 LSL_List result = new LSL_List();
10172 LSL_List remaining;
10173
10174 while (true)
7977 { 10175 {
10176// m_log.DebugFormat(
10177// "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}",
10178// rules.Length, entity != null ? entity.Name : "NULL");
10179
10180 if (entity == null)
10181 return result;
10182
10183 if (entity is SceneObjectPart)
10184 remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result);
10185 else
10186 remaining = GetAgentParams((ScenePresence)entity, rules, ref result);
10187
10188 if (remaining == null || remaining.Length < 2)
10189 return result;
10190
7978 int linknumber = remaining.GetLSLIntegerItem(0); 10191 int linknumber = remaining.GetLSLIntegerItem(0);
7979 rules = remaining.GetSublist(1, -1); 10192 rules = remaining.GetSublist(1, -1);
7980 List<SceneObjectPart> parts = GetLinkParts(linknumber); 10193 entity = GetLinkEntity(m_host, linknumber);
7981
7982 foreach (SceneObjectPart part in parts)
7983 remaining = GetPrimParams(part, rules, ref result);
7984 } 10194 }
10195 }
7985 10196
7986 return result; 10197 public LSL_List llGetPrimitiveParams(LSL_List rules)
10198 {
10199 m_host.AddScriptLPS(1);
10200
10201 return GetEntityParams(m_host, rules);
7987 } 10202 }
7988 10203
7989 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 10204 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
7990 { 10205 {
7991 m_host.AddScriptLPS(1); 10206 m_host.AddScriptLPS(1);
7992 10207
7993 List<SceneObjectPart> parts = GetLinkParts(linknumber); 10208 return GetEntityParams(GetLinkEntity(m_host, linknumber), rules);
10209 }
7994 10210
7995 LSL_List res = new LSL_List(); 10211 public LSL_Vector GetAgentSize(ScenePresence sp)
7996 LSL_List remaining = null; 10212 {
10213 return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight);
10214 }
7997 10215
7998 foreach (SceneObjectPart part in parts) 10216 /// <summary>
10217 /// Gets params for a seated avatar in a linkset.
10218 /// </summary>
10219 /// <returns></returns>
10220 /// <param name='sp'></param>
10221 /// <param name='rules'></param>
10222 /// <param name='res'></param>
10223 public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res)
10224 {
10225 int idx = 0;
10226 while (idx < rules.Length)
7999 { 10227 {
8000 remaining = GetPrimParams(part, rules, ref res); 10228 int code = (int)rules.GetLSLIntegerItem(idx++);
8001 } 10229 int remain = rules.Length-idx;
8002 10230
8003 while (remaining != null && remaining.Length > 2) 10231 switch (code)
8004 { 10232 {
8005 linknumber = remaining.GetLSLIntegerItem(0); 10233 case (int)ScriptBaseClass.PRIM_MATERIAL:
8006 rules = remaining.GetSublist(1, -1); 10234 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH));
8007 parts = GetLinkParts(linknumber); 10235 break;
8008 10236
8009 foreach (SceneObjectPart part in parts) 10237 case (int)ScriptBaseClass.PRIM_PHYSICS:
8010 remaining = GetPrimParams(part, rules, ref res); 10238 res.Add(ScriptBaseClass.FALSE);
10239 break;
10240
10241 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
10242 res.Add(ScriptBaseClass.FALSE);
10243 break;
10244
10245 case (int)ScriptBaseClass.PRIM_PHANTOM:
10246 res.Add(ScriptBaseClass.FALSE);
10247 break;
10248
10249 case (int)ScriptBaseClass.PRIM_POSITION:
10250 res.Add(new LSL_Vector(sp.AbsolutePosition));
10251 break;
10252
10253 case (int)ScriptBaseClass.PRIM_SIZE:
10254 res.Add(GetAgentSize(sp));
10255 break;
10256
10257 case (int)ScriptBaseClass.PRIM_ROTATION:
10258 res.Add(sp.GetWorldRotation());
10259 break;
10260
10261 case (int)ScriptBaseClass.PRIM_TYPE:
10262 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
10263 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
10264 res.Add(new LSL_Vector(0, 1, 0));
10265 res.Add(new LSL_Float(0));
10266 res.Add(new LSL_Vector(0, 0, 0));
10267 res.Add(new LSL_Vector(1, 1, 0));
10268 res.Add(new LSL_Vector(0, 0, 0));
10269 break;
10270
10271 case (int)ScriptBaseClass.PRIM_TEXTURE:
10272 if (remain < 1)
10273 return new LSL_List();
10274
10275 int face = (int)rules.GetLSLIntegerItem(idx++);
10276 if (face > 21)
10277 break;
10278
10279 res.Add(new LSL_String(""));
10280 res.Add(ScriptBaseClass.ZERO_VECTOR);
10281 res.Add(ScriptBaseClass.ZERO_VECTOR);
10282 res.Add(new LSL_Float(0));
10283 break;
10284
10285 case (int)ScriptBaseClass.PRIM_COLOR:
10286 if (remain < 1)
10287 return new LSL_List();
10288
10289 face = (int)rules.GetLSLIntegerItem(idx++);
10290 if (face > 21)
10291 break;
10292
10293 res.Add(ScriptBaseClass.ZERO_VECTOR);
10294 res.Add(new LSL_Float(0));
10295 break;
10296
10297 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
10298 if (remain < 1)
10299 return new LSL_List();
10300
10301 face = (int)rules.GetLSLIntegerItem(idx++);
10302 if (face > 21)
10303 break;
10304
10305 res.Add(ScriptBaseClass.PRIM_SHINY_NONE);
10306 res.Add(ScriptBaseClass.PRIM_BUMP_NONE);
10307 break;
10308
10309 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
10310 if (remain < 1)
10311 return new LSL_List();
10312
10313 face = (int)rules.GetLSLIntegerItem(idx++);
10314 if (face > 21)
10315 break;
10316
10317 res.Add(ScriptBaseClass.FALSE);
10318 break;
10319
10320 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
10321 res.Add(ScriptBaseClass.FALSE);
10322 res.Add(new LSL_Integer(0));
10323 res.Add(new LSL_Float(0));
10324 res.Add(new LSL_Float(0));
10325 res.Add(new LSL_Float(0));
10326 res.Add(new LSL_Float(0));
10327 res.Add(ScriptBaseClass.ZERO_VECTOR);
10328 break;
10329
10330 case (int)ScriptBaseClass.PRIM_TEXGEN:
10331 if (remain < 1)
10332 return new LSL_List();
10333
10334 face = (int)rules.GetLSLIntegerItem(idx++);
10335 if (face > 21)
10336 break;
10337
10338 res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT);
10339 break;
10340
10341 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
10342 res.Add(ScriptBaseClass.FALSE);
10343 res.Add(ScriptBaseClass.ZERO_VECTOR);
10344 res.Add(ScriptBaseClass.ZERO_VECTOR);
10345 break;
10346
10347 case (int)ScriptBaseClass.PRIM_GLOW:
10348 if (remain < 1)
10349 return new LSL_List();
10350
10351 face = (int)rules.GetLSLIntegerItem(idx++);
10352 if (face > 21)
10353 break;
10354
10355 res.Add(new LSL_Float(0));
10356 break;
10357
10358 case (int)ScriptBaseClass.PRIM_TEXT:
10359 res.Add(new LSL_String(""));
10360 res.Add(ScriptBaseClass.ZERO_VECTOR);
10361 res.Add(new LSL_Float(1));
10362 break;
10363
10364 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
10365 res.Add(new LSL_Rotation(sp.Rotation));
10366 break;
10367
10368 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
10369 res.Add(new LSL_Vector(sp.OffsetPosition));
10370 break;
10371
10372 case (int)ScriptBaseClass.PRIM_SLICE:
10373 res.Add(new LSL_Vector(0, 1, 0));
10374 break;
10375
10376 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
10377 if(remain < 3)
10378 return new LSL_List();
10379
10380 return rules.GetSublist(idx, -1);
10381 }
8011 } 10382 }
8012 10383
8013 return res; 10384 return new LSL_List();
8014 } 10385 }
8015 10386
8016 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) 10387 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
8017 { 10388 {
8018 int idx=0; 10389 int idx = 0;
8019 while (idx < rules.Length) 10390 while (idx < rules.Length)
8020 { 10391 {
8021 int code=(int)rules.GetLSLIntegerItem(idx++); 10392 int code = (int)rules.GetLSLIntegerItem(idx++);
8022 int remain=rules.Length-idx; 10393 int remain = rules.Length - idx;
8023 10394
8024 switch (code) 10395 switch (code)
8025 { 10396 {
@@ -8049,29 +10420,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8049 break; 10420 break;
8050 10421
8051 case (int)ScriptBaseClass.PRIM_POSITION: 10422 case (int)ScriptBaseClass.PRIM_POSITION:
8052 LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, 10423 LSL_Vector v = new LSL_Vector(part.AbsolutePosition);
8053 part.AbsolutePosition.Y, 10424
8054 part.AbsolutePosition.Z);
8055 // For some reason, the part.AbsolutePosition.* values do not change if the 10425 // For some reason, the part.AbsolutePosition.* values do not change if the
8056 // linkset is rotated; they always reflect the child prim's world position 10426 // linkset is rotated; they always reflect the child prim's world position
8057 // as though the linkset is unrotated. This is incompatible behavior with SL's 10427 // as though the linkset is unrotated. This is incompatible behavior with SL's
8058 // implementation, so will break scripts imported from there (not to mention it 10428 // implementation, so will break scripts imported from there (not to mention it
8059 // makes it more difficult to determine a child prim's actual inworld position). 10429 // makes it more difficult to determine a child prim's actual inworld position).
8060 if (part.ParentID != 0) 10430 if (!part.IsRoot)
8061 v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition(); 10431 {
10432 LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
10433 v = ((v - rootPos) * llGetRootRotation()) + rootPos;
10434 }
10435
8062 res.Add(v); 10436 res.Add(v);
8063 break; 10437 break;
8064 10438
8065 case (int)ScriptBaseClass.PRIM_SIZE: 10439 case (int)ScriptBaseClass.PRIM_SIZE:
8066 res.Add(new LSL_Vector(part.Scale.X, 10440 res.Add(new LSL_Vector(part.Scale));
8067 part.Scale.Y,
8068 part.Scale.Z));
8069 break; 10441 break;
8070 10442
8071 case (int)ScriptBaseClass.PRIM_ROTATION: 10443 case (int)ScriptBaseClass.PRIM_ROTATION:
8072 res.Add(GetPartRot(part)); 10444 res.Add(GetPartRot(part));
8073 break; 10445 break;
8074 10446
10447 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
10448 res.Add(new LSL_Integer((int)part.PhysicsShapeType));
10449 break;
10450
8075 case (int)ScriptBaseClass.PRIM_TYPE: 10451 case (int)ScriptBaseClass.PRIM_TYPE:
8076 // implementing box 10452 // implementing box
8077 PrimitiveBaseShape Shape = part.Shape; 10453 PrimitiveBaseShape Shape = part.Shape;
@@ -8101,7 +10477,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8101 break; 10477 break;
8102 10478
8103 case ScriptBaseClass.PRIM_TYPE_SCULPT: 10479 case ScriptBaseClass.PRIM_TYPE_SCULPT:
8104 res.Add(Shape.SculptTexture.ToString()); 10480 res.Add(new LSL_String(Shape.SculptTexture.ToString()));
8105 res.Add(new LSL_Integer(Shape.SculptType)); 10481 res.Add(new LSL_Integer(Shape.SculptType));
8106 break; 10482 break;
8107 10483
@@ -8133,16 +10509,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8133 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); 10509 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
8134 10510
8135 // float revolutions 10511 // float revolutions
8136 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); 10512 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
8137 // Slightly inaccurate, because an unsigned byte is being used to represent 10513 // Slightly inaccurate, because an unsigned byte is being used to represent
8138 // the entire range of floating-point values from 1.0 through 4.0 (which is how 10514 // the entire range of floating-point values from 1.0 through 4.0 (which is how
8139 // SL does it). 10515 // SL does it).
8140 // 10516 //
8141 // Using these formulas to store and retrieve PathRevolutions, it is not 10517 // Using these formulas to store and retrieve PathRevolutions, it is not
8142 // possible to use all values between 1.00 and 4.00. For instance, you can't 10518 // possible to use all values between 1.00 and 4.00. For instance, you can't
8143 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you 10519 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
8144 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them 10520 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
8145 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar 10521 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
8146 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. 10522 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
8147 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value 10523 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
8148 // such as 1.10. So, SL must store and retreive the actual user input rather 10524 // such as 1.10. So, SL must store and retreive the actual user input rather
@@ -8159,7 +10535,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8159 10535
8160 case (int)ScriptBaseClass.PRIM_TEXTURE: 10536 case (int)ScriptBaseClass.PRIM_TEXTURE:
8161 if (remain < 1) 10537 if (remain < 1)
8162 return null; 10538 return new LSL_List();
8163 10539
8164 int face = (int)rules.GetLSLIntegerItem(idx++); 10540 int face = (int)rules.GetLSLIntegerItem(idx++);
8165 Primitive.TextureEntry tex = part.Shape.Textures; 10541 Primitive.TextureEntry tex = part.Shape.Textures;
@@ -8199,7 +10575,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8199 10575
8200 case (int)ScriptBaseClass.PRIM_COLOR: 10576 case (int)ScriptBaseClass.PRIM_COLOR:
8201 if (remain < 1) 10577 if (remain < 1)
8202 return null; 10578 return new LSL_List();
8203 10579
8204 face=(int)rules.GetLSLIntegerItem(idx++); 10580 face=(int)rules.GetLSLIntegerItem(idx++);
8205 10581
@@ -8228,7 +10604,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8228 10604
8229 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 10605 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
8230 if (remain < 1) 10606 if (remain < 1)
8231 return null; 10607 return new LSL_List();
8232 10608
8233 face=(int)rules.GetLSLIntegerItem(idx++); 10609 face=(int)rules.GetLSLIntegerItem(idx++);
8234 10610
@@ -8259,9 +10635,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8259 10635
8260 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 10636 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
8261 if (remain < 1) 10637 if (remain < 1)
8262 return null; 10638 return new LSL_List();
8263 10639
8264 face=(int)rules.GetLSLIntegerItem(idx++); 10640 face = (int)rules.GetLSLIntegerItem(idx++);
8265 10641
8266 tex = part.Shape.Textures; 10642 tex = part.Shape.Textures;
8267 if (face == ScriptBaseClass.ALL_SIDES) 10643 if (face == ScriptBaseClass.ALL_SIDES)
@@ -8301,7 +10677,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8301 10677
8302 case (int)ScriptBaseClass.PRIM_TEXGEN: 10678 case (int)ScriptBaseClass.PRIM_TEXGEN:
8303 if (remain < 1) 10679 if (remain < 1)
8304 return null; 10680 return new LSL_List();
8305 10681
8306 face=(int)rules.GetLSLIntegerItem(idx++); 10682 face=(int)rules.GetLSLIntegerItem(idx++);
8307 10683
@@ -8342,7 +10718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8342 10718
8343 case (int)ScriptBaseClass.PRIM_GLOW: 10719 case (int)ScriptBaseClass.PRIM_GLOW:
8344 if (remain < 1) 10720 if (remain < 1)
8345 return null; 10721 return new LSL_List();
8346 10722
8347 face=(int)rules.GetLSLIntegerItem(idx++); 10723 face=(int)rules.GetLSLIntegerItem(idx++);
8348 10724
@@ -8371,7 +10747,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8371 res.Add(new LSL_Vector(textColor.R, 10747 res.Add(new LSL_Vector(textColor.R,
8372 textColor.G, 10748 textColor.G,
8373 textColor.B)); 10749 textColor.B));
8374 res.Add(new LSL_Float(textColor.A)); 10750 res.Add(new LSL_Float(1.0 - textColor.A));
8375 break; 10751 break;
8376 case (int)ScriptBaseClass.PRIM_NAME: 10752 case (int)ScriptBaseClass.PRIM_NAME:
8377 res.Add(new LSL_String(part.Name)); 10753 res.Add(new LSL_String(part.Name));
@@ -8380,7 +10756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8380 res.Add(new LSL_String(part.Description)); 10756 res.Add(new LSL_String(part.Description));
8381 break; 10757 break;
8382 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 10758 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
8383 res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); 10759 res.Add(new LSL_Rotation(part.RotationOffset));
8384 break; 10760 break;
8385 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 10761 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
8386 res.Add(new LSL_Vector(GetPartLocalPos(part))); 10762 res.Add(new LSL_Vector(GetPartLocalPos(part)));
@@ -8395,27 +10771,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8395 )); 10771 ));
8396 break; 10772 break;
8397 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 10773 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
8398 if(remain < 3) 10774
8399 return null; 10775 // TODO: Should be issuing a runtime script warning in this case.
10776 if (remain < 2)
10777 return new LSL_List();
8400 10778
8401 return rules.GetSublist(idx, -1); 10779 return rules.GetSublist(idx, -1);
8402 } 10780 }
8403 } 10781 }
8404 10782
8405 return null; 10783 return new LSL_List();
8406 } 10784 }
8407 10785
8408 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 10786 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
8409 { 10787 {
8410 m_host.AddScriptLPS(1); 10788 m_host.AddScriptLPS(1);
8411 ScriptSleep(1000); 10789 ScriptSleep(m_sleepMsOnGetPrimMediaParams);
8412 return GetPrimMediaParams(m_host, face, rules); 10790 return GetPrimMediaParams(m_host, face, rules);
8413 } 10791 }
8414 10792
8415 public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) 10793 public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
8416 { 10794 {
8417 m_host.AddScriptLPS(1); 10795 m_host.AddScriptLPS(1);
8418 ScriptSleep(1000); 10796 ScriptSleep(m_sleepMsOnGetLinkMedia);
8419 if (link == ScriptBaseClass.LINK_ROOT) 10797 if (link == ScriptBaseClass.LINK_ROOT)
8420 return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); 10798 return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
8421 else if (link == ScriptBaseClass.LINK_THIS) 10799 else if (link == ScriptBaseClass.LINK_THIS)
@@ -8535,14 +10913,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8535 public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules) 10913 public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules)
8536 { 10914 {
8537 m_host.AddScriptLPS(1); 10915 m_host.AddScriptLPS(1);
8538 ScriptSleep(1000); 10916 ScriptSleep(m_sleepMsOnSetPrimMediaParams);
8539 return SetPrimMediaParams(m_host, face, rules); 10917 return SetPrimMediaParams(m_host, face, rules);
8540 } 10918 }
8541 10919
8542 public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) 10920 public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
8543 { 10921 {
8544 m_host.AddScriptLPS(1); 10922 m_host.AddScriptLPS(1);
8545 ScriptSleep(1000); 10923 ScriptSleep(m_sleepMsOnSetLinkMedia);
8546 if (link == ScriptBaseClass.LINK_ROOT) 10924 if (link == ScriptBaseClass.LINK_ROOT)
8547 return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); 10925 return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
8548 else if (link == ScriptBaseClass.LINK_THIS) 10926 else if (link == ScriptBaseClass.LINK_THIS)
@@ -8661,14 +11039,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8661 public LSL_Integer llClearPrimMedia(LSL_Integer face) 11039 public LSL_Integer llClearPrimMedia(LSL_Integer face)
8662 { 11040 {
8663 m_host.AddScriptLPS(1); 11041 m_host.AddScriptLPS(1);
8664 ScriptSleep(1000); 11042 ScriptSleep(m_sleepMsOnClearPrimMedia);
8665 return ClearPrimMedia(m_host, face); 11043 return ClearPrimMedia(m_host, face);
8666 } 11044 }
8667 11045
8668 public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face) 11046 public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face)
8669 { 11047 {
8670 m_host.AddScriptLPS(1); 11048 m_host.AddScriptLPS(1);
8671 ScriptSleep(1000); 11049 ScriptSleep(m_sleepMsOnClearLinkMedia);
8672 if (link == ScriptBaseClass.LINK_ROOT) 11050 if (link == ScriptBaseClass.LINK_ROOT)
8673 return ClearPrimMedia(m_host.ParentGroup.RootPart, face); 11051 return ClearPrimMedia(m_host.ParentGroup.RootPart, face);
8674 else if (link == ScriptBaseClass.LINK_THIS) 11052 else if (link == ScriptBaseClass.LINK_THIS)
@@ -9307,7 +11685,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9307 11685
9308 if (item == null) 11686 if (item == null)
9309 { 11687 {
9310 llSay(0, "No item name '" + item + "'"); 11688 Error("llGetInventoryCreator", "Can't find item '" + item + "'");
9311 11689
9312 return String.Empty; 11690 return String.Empty;
9313 } 11691 }
@@ -9355,7 +11733,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9355 case ScriptBaseClass.DATA_SIM_POS: 11733 case ScriptBaseClass.DATA_SIM_POS:
9356 if (info == null) 11734 if (info == null)
9357 { 11735 {
9358 ScriptSleep(1000); 11736 ScriptSleep(m_sleepMsOnRequestSimulatorData);
9359 return UUID.Zero.ToString(); 11737 return UUID.Zero.ToString();
9360 } 11738 }
9361 11739
@@ -9402,7 +11780,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9402 case ScriptBaseClass.DATA_SIM_RATING: 11780 case ScriptBaseClass.DATA_SIM_RATING:
9403 if (info == null) 11781 if (info == null)
9404 { 11782 {
9405 ScriptSleep(1000); 11783 ScriptSleep(m_sleepMsOnRequestSimulatorData);
9406 return UUID.Zero.ToString(); 11784 return UUID.Zero.ToString();
9407 } 11785 }
9408 int access = info.Maturity; 11786 int access = info.Maturity;
@@ -9421,7 +11799,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9421 reply = "OpenSim"; 11799 reply = "OpenSim";
9422 break; 11800 break;
9423 default: 11801 default:
9424 ScriptSleep(1000); 11802 ScriptSleep(m_sleepMsOnRequestSimulatorData);
9425 return UUID.Zero.ToString(); // Raise no event 11803 return UUID.Zero.ToString(); // Raise no event
9426 } 11804 }
9427 UUID rq = UUID.Random(); 11805 UUID rq = UUID.Random();
@@ -9432,7 +11810,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9432 AsyncCommands. 11810 AsyncCommands.
9433 DataserverPlugin.DataserverReply(rq.ToString(), reply); 11811 DataserverPlugin.DataserverReply(rq.ToString(), reply);
9434 11812
9435 ScriptSleep(1000); 11813 ScriptSleep(m_sleepMsOnRequestSimulatorData);
9436 return tid.ToString(); 11814 return tid.ToString();
9437 } 11815 }
9438 catch(Exception) 11816 catch(Exception)
@@ -9441,6 +11819,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9441 return UUID.Zero.ToString(); 11819 return UUID.Zero.ToString();
9442 } 11820 }
9443 } 11821 }
11822
9444 public LSL_String llRequestURL() 11823 public LSL_String llRequestURL()
9445 { 11824 {
9446 m_host.AddScriptLPS(1); 11825 m_host.AddScriptLPS(1);
@@ -9499,7 +11878,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9499 11878
9500 public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) 11879 public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
9501 { 11880 {
9502 LSL_List pref = null; 11881 LSL_List pref;
9503 11882
9504 m_host.AddScriptLPS(1); 11883 m_host.AddScriptLPS(1);
9505 11884
@@ -9576,7 +11955,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9576 dm.SendUrlToUser( 11955 dm.SendUrlToUser(
9577 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url); 11956 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
9578 11957
9579 ScriptSleep(10000); 11958 ScriptSleep(m_sleepMsOnLoadURL);
9580 } 11959 }
9581 11960
9582 public void llParcelMediaCommandList(LSL_List commandList) 11961 public void llParcelMediaCommandList(LSL_List commandList)
@@ -9588,7 +11967,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9588 11967
9589 // according to the docs, this command only works if script owner and land owner are the same 11968 // according to the docs, this command only works if script owner and land owner are the same
9590 // lets add estate owners and gods, too, and use the generic permission check. 11969 // lets add estate owners and gods, too, and use the generic permission check.
9591 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 11970 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
9592 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; 11971 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return;
9593 11972
9594 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? 11973 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
@@ -9625,7 +12004,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9625 presence = World.GetScenePresence(agentID); 12004 presence = World.GetScenePresence(agentID);
9626 } 12005 }
9627 } 12006 }
9628 else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); 12007 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
9629 ++i; 12008 ++i;
9630 } 12009 }
9631 break; 12010 break;
@@ -9656,7 +12035,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9656 url = (LSL_String)commandList.Data[i + 1]; 12035 url = (LSL_String)commandList.Data[i + 1];
9657 update = true; 12036 update = true;
9658 } 12037 }
9659 else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string."); 12038 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string");
9660 ++i; 12039 ++i;
9661 } 12040 }
9662 break; 12041 break;
@@ -9669,7 +12048,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9669 texture = (LSL_String)commandList.Data[i + 1]; 12048 texture = (LSL_String)commandList.Data[i + 1];
9670 update = true; 12049 update = true;
9671 } 12050 }
9672 else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key."); 12051 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key");
9673 ++i; 12052 ++i;
9674 } 12053 }
9675 break; 12054 break;
@@ -9681,7 +12060,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9681 { 12060 {
9682 time = (float)(LSL_Float)commandList.Data[i + 1]; 12061 time = (float)(LSL_Float)commandList.Data[i + 1];
9683 } 12062 }
9684 else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float."); 12063 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float");
9685 ++i; 12064 ++i;
9686 } 12065 }
9687 break; 12066 break;
@@ -9695,7 +12074,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9695 update = true; 12074 update = true;
9696 } 12075 }
9697 12076
9698 else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer."); 12077 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer");
9699 ++i; 12078 ++i;
9700 } 12079 }
9701 break; 12080 break;
@@ -9708,7 +12087,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9708 mediaType = (LSL_String)commandList.Data[i + 1]; 12087 mediaType = (LSL_String)commandList.Data[i + 1];
9709 update = true; 12088 update = true;
9710 } 12089 }
9711 else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string."); 12090 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string");
9712 ++i; 12091 ++i;
9713 } 12092 }
9714 break; 12093 break;
@@ -9721,7 +12100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9721 description = (LSL_String)commandList.Data[i + 1]; 12100 description = (LSL_String)commandList.Data[i + 1];
9722 update = true; 12101 update = true;
9723 } 12102 }
9724 else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string."); 12103 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string");
9725 ++i; 12104 ++i;
9726 } 12105 }
9727 break; 12106 break;
@@ -9737,15 +12116,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9737 height = (LSL_Integer)commandList.Data[i + 2]; 12116 height = (LSL_Integer)commandList.Data[i + 2];
9738 update = true; 12117 update = true;
9739 } 12118 }
9740 else ShoutError("The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); 12119 else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
9741 } 12120 }
9742 else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); 12121 else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
9743 i += 2; 12122 i += 2;
9744 } 12123 }
9745 break; 12124 break;
9746 12125
9747 default: 12126 default:
9748 NotImplemented("llParcelMediaCommandList parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString()); 12127 NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString());
9749 break; 12128 break;
9750 }//end switch 12129 }//end switch
9751 }//end for 12130 }//end for
@@ -9819,7 +12198,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9819 time); 12198 time);
9820 } 12199 }
9821 } 12200 }
9822 ScriptSleep(2000); 12201 ScriptSleep(m_sleepMsOnParcelMediaCommandList);
9823 } 12202 }
9824 12203
9825 public LSL_List llParcelMediaQuery(LSL_List aList) 12204 public LSL_List llParcelMediaQuery(LSL_List aList)
@@ -9853,13 +12232,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9853 break; 12232 break;
9854 default: 12233 default:
9855 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; 12234 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
9856 NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); 12235 NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
9857 break; 12236 break;
9858 } 12237 }
9859 12238
9860 } 12239 }
9861 } 12240 }
9862 ScriptSleep(2000); 12241 ScriptSleep(m_sleepMsOnParcelMediaQuery);
9863 return list; 12242 return list;
9864 } 12243 }
9865 12244
@@ -9868,7 +12247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9868 m_host.AddScriptLPS(1); 12247 m_host.AddScriptLPS(1);
9869 Int64 tmp = 0; 12248 Int64 tmp = 0;
9870 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); 12249 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
9871 ScriptSleep(1000); 12250 ScriptSleep(m_sleepMsOnModPow);
9872 return Convert.ToInt32(tmp); 12251 return Convert.ToInt32(tmp);
9873 } 12252 }
9874 12253
@@ -9890,7 +12269,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9890 12269
9891 if (quick_pay_buttons.Data.Length < 4) 12270 if (quick_pay_buttons.Data.Length < 4)
9892 { 12271 {
9893 LSLError("List must have at least 4 elements"); 12272 Error("llSetPayPrice", "List must have at least 4 elements");
9894 return; 12273 return;
9895 } 12274 }
9896 m_host.ParentGroup.RootPart.PayPrice[0]=price; 12275 m_host.ParentGroup.RootPart.PayPrice[0]=price;
@@ -9907,21 +12286,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9907 m_host.AddScriptLPS(1); 12286 m_host.AddScriptLPS(1);
9908 12287
9909 if (m_item.PermsGranter == UUID.Zero) 12288 if (m_item.PermsGranter == UUID.Zero)
9910 return new LSL_Vector(); 12289 return Vector3.Zero;
9911 12290
9912 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 12291 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9913 { 12292 {
9914 ShoutError("No permissions to track the camera"); 12293 Error("llGetCameraPos", "No permissions to track the camera");
9915 return new LSL_Vector(); 12294 return Vector3.Zero;
9916 } 12295 }
9917 12296
9918 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12297 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9919 if (presence != null) 12298 if (presence != null)
9920 { 12299 {
9921 LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); 12300 LSL_Vector pos = new LSL_Vector(presence.CameraPosition);
9922 return pos; 12301 return pos;
9923 } 12302 }
9924 return new LSL_Vector(); 12303
12304 return Vector3.Zero;
9925 } 12305 }
9926 12306
9927 public LSL_Rotation llGetCameraRot() 12307 public LSL_Rotation llGetCameraRot()
@@ -9929,42 +12309,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9929 m_host.AddScriptLPS(1); 12309 m_host.AddScriptLPS(1);
9930 12310
9931 if (m_item.PermsGranter == UUID.Zero) 12311 if (m_item.PermsGranter == UUID.Zero)
9932 return new LSL_Rotation(); 12312 return Quaternion.Identity;
9933 12313
9934 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 12314 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
9935 { 12315 {
9936 ShoutError("No permissions to track the camera"); 12316 Error("llGetCameraRot", "No permissions to track the camera");
9937 return new LSL_Rotation(); 12317 return Quaternion.Identity;
9938 } 12318 }
9939 12319
9940 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12320 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
9941 if (presence != null) 12321 if (presence != null)
9942 { 12322 {
9943 return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); 12323 return new LSL_Rotation(presence.CameraRotation);
9944 } 12324 }
9945 12325
9946 return new LSL_Rotation(); 12326 return Quaternion.Identity;
9947 } 12327 }
9948 12328
9949 /// <summary>
9950 /// The SL implementation does nothing, it is deprecated
9951 /// This duplicates SL
9952 /// </summary>
9953 public void llSetPrimURL(string url) 12329 public void llSetPrimURL(string url)
9954 { 12330 {
9955 m_host.AddScriptLPS(1); 12331 m_host.AddScriptLPS(1);
9956 ScriptSleep(2000); 12332 Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead");
12333 ScriptSleep(m_sleepMsOnSetPrimURL);
9957 } 12334 }
9958 12335
9959 /// <summary>
9960 /// The SL implementation shouts an error, it is deprecated
9961 /// This duplicates SL
9962 /// </summary>
9963 public void llRefreshPrimURL() 12336 public void llRefreshPrimURL()
9964 { 12337 {
9965 m_host.AddScriptLPS(1); 12338 m_host.AddScriptLPS(1);
9966 ShoutError("llRefreshPrimURL - not yet supported"); 12339 Deprecated("llRefreshPrimURL");
9967 ScriptSleep(20000); 12340 ScriptSleep(m_sleepMsOnRefreshPrimURL);
9968 } 12341 }
9969 12342
9970 public LSL_String llEscapeURL(string url) 12343 public LSL_String llEscapeURL(string url)
@@ -10005,14 +12378,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10005 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 12378 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
10006 simname, pos, lookAt); 12379 simname, pos, lookAt);
10007 } 12380 }
10008 ScriptSleep(1000); 12381 ScriptSleep(m_sleepMsOnMapDestination);
10009 } 12382 }
10010 12383
10011 public void llAddToLandBanList(string avatar, double hours) 12384 public void llAddToLandBanList(string avatar, double hours)
10012 { 12385 {
10013 m_host.AddScriptLPS(1); 12386 m_host.AddScriptLPS(1);
10014 UUID key; 12387 UUID key;
10015 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 12388 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
10016 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 12389 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
10017 { 12390 {
10018 int expires = 0; 12391 int expires = 0;
@@ -10046,14 +12419,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10046 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 12419 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
10047 } 12420 }
10048 } 12421 }
10049 ScriptSleep(100); 12422 ScriptSleep(m_sleepMsOnAddToLandBanList);
10050 } 12423 }
10051 12424
10052 public void llRemoveFromLandPassList(string avatar) 12425 public void llRemoveFromLandPassList(string avatar)
10053 { 12426 {
10054 m_host.AddScriptLPS(1); 12427 m_host.AddScriptLPS(1);
10055 UUID key; 12428 UUID key;
10056 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 12429 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
10057 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) 12430 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed))
10058 { 12431 {
10059 if (UUID.TryParse(avatar, out key)) 12432 if (UUID.TryParse(avatar, out key))
@@ -10073,14 +12446,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10073 } 12446 }
10074 } 12447 }
10075 } 12448 }
10076 ScriptSleep(100); 12449 ScriptSleep(m_sleepMsOnRemoveFromLandPassList);
10077 } 12450 }
10078 12451
10079 public void llRemoveFromLandBanList(string avatar) 12452 public void llRemoveFromLandBanList(string avatar)
10080 { 12453 {
10081 m_host.AddScriptLPS(1); 12454 m_host.AddScriptLPS(1);
10082 UUID key; 12455 UUID key;
10083 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 12456 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
10084 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 12457 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
10085 { 12458 {
10086 if (UUID.TryParse(avatar, out key)) 12459 if (UUID.TryParse(avatar, out key))
@@ -10100,7 +12473,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10100 } 12473 }
10101 } 12474 }
10102 } 12475 }
10103 ScriptSleep(100); 12476 ScriptSleep(m_sleepMsOnRemoveFromLandBanList);
10104 } 12477 }
10105 12478
10106 public void llSetCameraParams(LSL_List rules) 12479 public void llSetCameraParams(LSL_List rules)
@@ -10128,19 +12501,84 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10128 12501
10129 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 12502 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
10130 object[] data = rules.Data; 12503 object[] data = rules.Data;
10131 for (int i = 0; i < data.Length; ++i) { 12504 for (int i = 0; i < data.Length; ++i)
10132 int type = Convert.ToInt32(data[i++].ToString()); 12505 {
12506 int type;
12507 try
12508 {
12509 type = Convert.ToInt32(data[i++].ToString());
12510 }
12511 catch
12512 {
12513 Error("llSetCameraParams", string.Format("Invalid camera param type {0}", data[i - 1]));
12514 return;
12515 }
10133 if (i >= data.Length) break; // odd number of entries => ignore the last 12516 if (i >= data.Length) break; // odd number of entries => ignore the last
10134 12517
10135 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 12518 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
10136 switch (type) { 12519 switch (type)
12520 {
10137 case ScriptBaseClass.CAMERA_FOCUS: 12521 case ScriptBaseClass.CAMERA_FOCUS:
10138 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 12522 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
10139 case ScriptBaseClass.CAMERA_POSITION: 12523 case ScriptBaseClass.CAMERA_POSITION:
10140 LSL_Vector v = (LSL_Vector)data[i]; 12524 LSL_Vector v = (LSL_Vector)data[i];
10141 parameters.Add(type + 1, (float)v.x); 12525 try
10142 parameters.Add(type + 2, (float)v.y); 12526 {
10143 parameters.Add(type + 3, (float)v.z); 12527 parameters.Add(type + 1, (float)v.x);
12528 }
12529 catch
12530 {
12531 switch(type)
12532 {
12533 case ScriptBaseClass.CAMERA_FOCUS:
12534 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter x is invalid");
12535 return;
12536 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12537 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter x is invalid");
12538 return;
12539 case ScriptBaseClass.CAMERA_POSITION:
12540 Error("llSetCameraParams", "CAMERA_POSITION: Parameter x is invalid");
12541 return;
12542 }
12543 }
12544 try
12545 {
12546 parameters.Add(type + 2, (float)v.y);
12547 }
12548 catch
12549 {
12550 switch(type)
12551 {
12552 case ScriptBaseClass.CAMERA_FOCUS:
12553 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter y is invalid");
12554 return;
12555 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12556 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter y is invalid");
12557 return;
12558 case ScriptBaseClass.CAMERA_POSITION:
12559 Error("llSetCameraParams", "CAMERA_POSITION: Parameter y is invalid");
12560 return;
12561 }
12562 }
12563 try
12564 {
12565 parameters.Add(type + 3, (float)v.z);
12566 }
12567 catch
12568 {
12569 switch(type)
12570 {
12571 case ScriptBaseClass.CAMERA_FOCUS:
12572 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter z is invalid");
12573 return;
12574 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12575 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter z is invalid");
12576 return;
12577 case ScriptBaseClass.CAMERA_POSITION:
12578 Error("llSetCameraParams", "CAMERA_POSITION: Parameter z is invalid");
12579 return;
12580 }
12581 }
10144 break; 12582 break;
10145 default: 12583 default:
10146 // TODO: clean that up as soon as the implicit casts are in 12584 // TODO: clean that up as soon as the implicit casts are in
@@ -10148,7 +12586,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10148 parameters.Add(type, (float)((LSL_Float)data[i]).value); 12586 parameters.Add(type, (float)((LSL_Float)data[i]).value);
10149 else if (data[i] is LSL_Integer) 12587 else if (data[i] is LSL_Integer)
10150 parameters.Add(type, (float)((LSL_Integer)data[i]).value); 12588 parameters.Add(type, (float)((LSL_Integer)data[i]).value);
10151 else parameters.Add(type, Convert.ToSingle(data[i])); 12589 else
12590 {
12591 try
12592 {
12593 parameters.Add(type, Convert.ToSingle(data[i]));
12594 }
12595 catch
12596 {
12597 Error("llSetCameraParams", string.Format("{0}: Parameter is invalid", type));
12598 }
12599 }
10152 break; 12600 break;
10153 } 12601 }
10154 } 12602 }
@@ -10264,9 +12712,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10264 IHttpRequestModule httpScriptMod = 12712 IHttpRequestModule httpScriptMod =
10265 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); 12713 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
10266 List<string> param = new List<string>(); 12714 List<string> param = new List<string>();
10267 foreach (object o in parameters.Data) 12715 bool ok;
12716 Int32 flag;
12717
12718 for (int i = 0; i < parameters.Data.Length; i += 2)
10268 { 12719 {
10269 param.Add(o.ToString()); 12720 ok = Int32.TryParse(parameters.Data[i].ToString(), out flag);
12721 if (!ok || flag < 0 ||
12722 flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE)
12723 {
12724 Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag");
12725 }
12726
12727 param.Add(parameters.Data[i].ToString()); //Add parameter flag
12728
12729 if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER)
12730 {
12731 param.Add(parameters.Data[i+1].ToString()); //Add parameter value
12732 }
12733 else
12734 {
12735 //Parameters are in pairs and custom header takes
12736 //arguments in pairs so adjust for header marker.
12737 ++i;
12738
12739 //Maximum of 8 headers are allowed based on the
12740 //Second Life documentation for llHTTPRequest.
12741 for (int count = 1; count <= 8; ++count)
12742 {
12743 //Enough parameters remaining for (another) header?
12744 if (parameters.Data.Length - i < 2)
12745 {
12746 //There must be at least one name/value pair for custom header
12747 if (count == 1)
12748 Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString());
12749 break;
12750 }
12751
12752 if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase))
12753 Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString());
12754
12755 param.Add(parameters.Data[i].ToString());
12756 param.Add(parameters.Data[i+1].ToString());
12757
12758 //Have we reached the end of the list of headers?
12759 //End is marked by a string with a single digit.
12760 if (i+2 >= parameters.Data.Length ||
12761 Char.IsDigit(parameters.Data[i].ToString()[0]))
12762 {
12763 break;
12764 }
12765
12766 i += 2;
12767 }
12768 }
10270 } 12769 }
10271 12770
10272 Vector3 position = m_host.AbsolutePosition; 12771 Vector3 position = m_host.AbsolutePosition;
@@ -10318,8 +12817,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10318 } 12817 }
10319 } 12818 }
10320 12819
12820 HttpInitialRequestStatus status;
10321 UUID reqID 12821 UUID reqID
10322 = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body); 12822 = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
12823
12824 if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER)
12825 Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url));
10323 12826
10324 if (reqID != UUID.Zero) 12827 if (reqID != UUID.Zero)
10325 return reqID.ToString(); 12828 return reqID.ToString();
@@ -10342,7 +12845,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10342 public void llResetLandBanList() 12845 public void llResetLandBanList()
10343 { 12846 {
10344 m_host.AddScriptLPS(1); 12847 m_host.AddScriptLPS(1);
10345 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; 12848 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData;
10346 if (land.OwnerID == m_host.OwnerID) 12849 if (land.OwnerID == m_host.OwnerID)
10347 { 12850 {
10348 foreach (LandAccessEntry entry in land.ParcelAccessList) 12851 foreach (LandAccessEntry entry in land.ParcelAccessList)
@@ -10353,13 +12856,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10353 } 12856 }
10354 } 12857 }
10355 } 12858 }
10356 ScriptSleep(100); 12859 ScriptSleep(m_sleepMsOnResetLandBanList);
10357 } 12860 }
10358 12861
10359 public void llResetLandPassList() 12862 public void llResetLandPassList()
10360 { 12863 {
10361 m_host.AddScriptLPS(1); 12864 m_host.AddScriptLPS(1);
10362 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; 12865 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData;
10363 if (land.OwnerID == m_host.OwnerID) 12866 if (land.OwnerID == m_host.OwnerID)
10364 { 12867 {
10365 foreach (LandAccessEntry entry in land.ParcelAccessList) 12868 foreach (LandAccessEntry entry in land.ParcelAccessList)
@@ -10370,18 +12873,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10370 } 12873 }
10371 } 12874 }
10372 } 12875 }
10373 ScriptSleep(100); 12876 ScriptSleep(m_sleepMsOnResetLandPassList);
10374 } 12877 }
10375 12878
10376 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) 12879 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
10377 { 12880 {
10378 m_host.AddScriptLPS(1); 12881 m_host.AddScriptLPS(1);
10379 12882
10380 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); 12883 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
10381 12884
10382 if (lo == null) 12885 if (lo == null)
10383 return 0; 12886 return 0;
10384 12887
10385 IPrimCounts pc = lo.PrimCounts; 12888 IPrimCounts pc = lo.PrimCounts;
10386 12889
10387 if (sim_wide != ScriptBaseClass.FALSE) 12890 if (sim_wide != ScriptBaseClass.FALSE)
@@ -10411,7 +12914,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10411 else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP) 12914 else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP)
10412 return 0; // counts not implemented yet 12915 return 0; // counts not implemented yet
10413 } 12916 }
10414 12917
10415 return 0; 12918 return 0;
10416 } 12919 }
10417 12920
@@ -10428,7 +12931,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10428 ret.Add(new LSL_Integer(detectedParams.Value)); 12931 ret.Add(new LSL_Integer(detectedParams.Value));
10429 } 12932 }
10430 } 12933 }
10431 ScriptSleep(2000); 12934 ScriptSleep(m_sleepMsOnGetParcelPrimOwners);
10432 return ret; 12935 return ret;
10433 } 12936 }
10434 12937
@@ -10535,10 +13038,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10535 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 13038 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
10536 break; 13039 break;
10537 case ScriptBaseClass.OBJECT_ROT: 13040 case ScriptBaseClass.OBJECT_ROT:
10538 ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); 13041 ret.Add(new LSL_Rotation(av.GetWorldRotation()));
10539 break; 13042 break;
10540 case ScriptBaseClass.OBJECT_VELOCITY: 13043 case ScriptBaseClass.OBJECT_VELOCITY:
10541 ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); 13044 ret.Add(new LSL_Vector(av.GetWorldVelocity()));
10542 break; 13045 break;
10543 case ScriptBaseClass.OBJECT_OWNER: 13046 case ScriptBaseClass.OBJECT_OWNER:
10544 ret.Add(new LSL_String(id)); 13047 ret.Add(new LSL_String(id));
@@ -10603,6 +13106,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10603 case ScriptBaseClass.OBJECT_TEMP_ON_REZ: 13106 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
10604 ret.Add(new LSL_Integer(0)); 13107 ret.Add(new LSL_Integer(0));
10605 break; 13108 break;
13109 case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13110 ret.Add(new LSL_Integer(-1));
13111 break;
13112 case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13113 ret.Add(new LSL_Float(0));
13114 break;
13115 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13116 LSL_Float shapeType;
13117 if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0)
13118 shapeType = new LSL_Float(1);
13119 else
13120 shapeType = new LSL_Float(0);
13121 ret.Add(shapeType);
13122 break;
13123 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13124 ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY));
13125 break;
10606 default: 13126 default:
10607 // Invalid or unhandled constant. 13127 // Invalid or unhandled constant.
10608 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 13128 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -10630,20 +13150,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10630 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 13150 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z));
10631 break; 13151 break;
10632 case ScriptBaseClass.OBJECT_ROT: 13152 case ScriptBaseClass.OBJECT_ROT:
13153 Quaternion rot = Quaternion.Identity;
13154
13155 if (obj.ParentGroup.IsAttachment)
10633 { 13156 {
10634 Quaternion rot = Quaternion.Identity; 13157 ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar);
10635 13158
13159 if (sp != null)
13160 rot = sp.GetWorldRotation();
13161 }
13162 else
13163 {
10636 if (obj.ParentGroup.RootPart == obj) 13164 if (obj.ParentGroup.RootPart == obj)
10637 rot = obj.ParentGroup.GroupRotation; 13165 rot = obj.ParentGroup.GroupRotation;
10638 else 13166 else
10639 rot = obj.GetWorldRotation(); 13167 rot = obj.GetWorldRotation();
10640
10641 LSL_Rotation objrot = new LSL_Rotation(rot);
10642 ret.Add(objrot);
10643 } 13168 }
13169
13170 LSL_Rotation objrot = new LSL_Rotation(rot);
13171 ret.Add(objrot);
13172
10644 break; 13173 break;
10645 case ScriptBaseClass.OBJECT_VELOCITY: 13174 case ScriptBaseClass.OBJECT_VELOCITY:
10646 ret.Add(new LSL_Vector(obj.Velocity)); 13175 Vector3 vel = Vector3.Zero;
13176
13177 if (obj.ParentGroup.IsAttachment)
13178 {
13179 ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar);
13180
13181 if (sp != null)
13182 vel = sp.GetWorldVelocity();
13183 }
13184 else
13185 {
13186 vel = obj.Velocity;
13187 }
13188
13189 ret.Add(vel);
10647 break; 13190 break;
10648 case ScriptBaseClass.OBJECT_OWNER: 13191 case ScriptBaseClass.OBJECT_OWNER:
10649 ret.Add(new LSL_String(obj.OwnerID.ToString())); 13192 ret.Add(new LSL_String(obj.OwnerID.ToString()));
@@ -10744,6 +13287,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10744 case ScriptBaseClass.OBJECT_TEMP_ON_REZ: 13287 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
10745 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); 13288 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0));
10746 break; 13289 break;
13290 case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13291 ret.Add(new LSL_Integer(0));
13292 break;
13293 case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13294 ret.Add(new LSL_Float(0));
13295 break;
13296 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13297 ret.Add(new LSL_Float(-1));
13298 break;
13299 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13300 ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString()));
13301 break;
10747 default: 13302 default:
10748 // Invalid or unhandled constant. 13303 // Invalid or unhandled constant.
10749 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 13304 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
@@ -10754,7 +13309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10754 return ret; 13309 return ret;
10755 } 13310 }
10756 } 13311 }
10757 13312
10758 return new LSL_List(); 13313 return new LSL_List();
10759 } 13314 }
10760 13315
@@ -10768,25 +13323,71 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10768 return item.ItemID; 13323 return item.ItemID;
10769 } 13324 }
10770 13325
10771 internal void ShoutError(string msg) 13326 /// <summary>
13327 /// Reports the script error in the viewer's Script Warning/Error dialog and shouts it on the debug channel.
13328 /// </summary>
13329 /// <param name="command">The name of the command that generated the error.</param>
13330 /// <param name="message">The error message to report to the user.</param>
13331 internal void Error(string command, string message)
10772 { 13332 {
10773 llShout(ScriptBaseClass.DEBUG_CHANNEL, msg); 13333 string text = command + ": " + message;
13334 if (text.Length > 1023)
13335 {
13336 text = text.Substring(0, 1023);
13337 }
13338
13339 World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL,
13340 m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
13341
13342 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
13343 if (wComm != null)
13344 {
13345 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text);
13346 }
10774 } 13347 }
10775 13348
10776 internal void NotImplemented(string command) 13349 /// <summary>
13350 /// Reports that the command is not implemented as a script error.
13351 /// </summary>
13352 /// <param name="command">The name of the command that is not implemented.</param>
13353 /// <param name="message">Additional information to report to the user. (Optional)</param>
13354 internal void NotImplemented(string command, string message = "")
10777 { 13355 {
10778 if (throwErrorOnNotImplemented) 13356 if (throwErrorOnNotImplemented)
10779 throw new NotImplementedException("Command not implemented: " + command); 13357 {
10780 } 13358 if (message != "")
13359 {
13360 message = " - " + message;
13361 }
10781 13362
10782 internal void Deprecated(string command) 13363 throw new NotImplementedException("Command not implemented: " + command + message);
10783 { 13364 }
10784 throw new ScriptException("Command deprecated: " + command); 13365 else
13366 {
13367 string text = "Command not implemented";
13368 if (message != "")
13369 {
13370 text = text + " - " + message;
13371 }
13372
13373 Error(command, text);
13374 }
10785 } 13375 }
10786 13376
10787 internal void LSLError(string msg) 13377 /// <summary>
13378 /// Reports that the command is deprecated as a script error.
13379 /// </summary>
13380 /// <param name="command">The name of the command that is deprecated.</param>
13381 /// <param name="message">Additional information to report to the user. (Optional)</param>
13382 internal void Deprecated(string command, string message = "")
10788 { 13383 {
10789 throw new ScriptException("LSL Runtime Error: " + msg); 13384 string text = "Command deprecated";
13385 if (message != "")
13386 {
13387 text = text + " - " + message;
13388 }
13389
13390 Error(command, text);
10790 } 13391 }
10791 13392
10792 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); 13393 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
@@ -10818,20 +13419,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10818 if (assetID == UUID.Zero) 13419 if (assetID == UUID.Zero)
10819 { 13420 {
10820 // => complain loudly, as specified by the LSL docs 13421 // => complain loudly, as specified by the LSL docs
10821 ShoutError("Notecard '" + name + "' could not be found."); 13422 Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
10822 13423
10823 return UUID.Zero.ToString(); 13424 return UUID.Zero.ToString();
10824 } 13425 }
10825 13426
13427 string reqIdentifier = UUID.Random().ToString();
13428
10826 // was: UUID tid = tid = AsyncCommands. 13429 // was: UUID tid = tid = AsyncCommands.
10827 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString()); 13430 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
10828 13431
10829 if (NotecardCache.IsCached(assetID)) 13432 if (NotecardCache.IsCached(assetID))
10830 { 13433 {
10831 AsyncCommands. 13434 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString());
10832 DataserverPlugin.DataserverReply(assetID.ToString(), 13435
10833 NotecardCache.GetLines(assetID).ToString()); 13436 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
10834 ScriptSleep(100);
10835 return tid.ToString(); 13437 return tid.ToString();
10836 } 13438 }
10837 13439
@@ -10839,19 +13441,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10839 { 13441 {
10840 if (a == null || a.Type != 7) 13442 if (a == null || a.Type != 7)
10841 { 13443 {
10842 ShoutError("Notecard '" + name + "' could not be found."); 13444 Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
10843 return; 13445 return;
10844 } 13446 }
10845 13447
10846 string data = Encoding.UTF8.GetString(a.Data); 13448 NotecardCache.Cache(id, a.Data);
10847 //m_log.Debug(data); 13449 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString());
10848 NotecardCache.Cache(id, data);
10849 AsyncCommands.
10850 DataserverPlugin.DataserverReply(id.ToString(),
10851 NotecardCache.GetLines(id).ToString());
10852 }); 13450 });
10853 13451
10854 ScriptSleep(100); 13452 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
10855 return tid.ToString(); 13453 return tid.ToString();
10856 } 13454 }
10857 13455
@@ -10872,19 +13470,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10872 if (assetID == UUID.Zero) 13470 if (assetID == UUID.Zero)
10873 { 13471 {
10874 // => complain loudly, as specified by the LSL docs 13472 // => complain loudly, as specified by the LSL docs
10875 ShoutError("Notecard '" + name + "' could not be found."); 13473 Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
10876 13474
10877 return UUID.Zero.ToString(); 13475 return UUID.Zero.ToString();
10878 } 13476 }
10879 13477
13478 string reqIdentifier = UUID.Random().ToString();
13479
10880 // was: UUID tid = tid = AsyncCommands. 13480 // was: UUID tid = tid = AsyncCommands.
10881 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString()); 13481 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
10882 13482
10883 if (NotecardCache.IsCached(assetID)) 13483 if (NotecardCache.IsCached(assetID))
10884 { 13484 {
10885 AsyncCommands.DataserverPlugin.DataserverReply(assetID.ToString(), 13485 AsyncCommands.DataserverPlugin.DataserverReply(
10886 NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); 13486 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
10887 ScriptSleep(100); 13487
13488 ScriptSleep(m_sleepMsOnGetNotecardLine);
10888 return tid.ToString(); 13489 return tid.ToString();
10889 } 13490 }
10890 13491
@@ -10892,18 +13493,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10892 { 13493 {
10893 if (a == null || a.Type != 7) 13494 if (a == null || a.Type != 7)
10894 { 13495 {
10895 ShoutError("Notecard '" + name + "' could not be found."); 13496 Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
10896 return; 13497 return;
10897 } 13498 }
10898 13499
10899 string data = Encoding.UTF8.GetString(a.Data); 13500 string data = Encoding.UTF8.GetString(a.Data);
10900 //m_log.Debug(data); 13501 //m_log.Debug(data);
10901 NotecardCache.Cache(id, data); 13502 NotecardCache.Cache(id, a.Data);
10902 AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), 13503 AsyncCommands.DataserverPlugin.DataserverReply(
10903 NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); 13504 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
10904 }); 13505 });
10905 13506
10906 ScriptSleep(100); 13507 ScriptSleep(m_sleepMsOnGetNotecardLine);
10907 return tid.ToString(); 13508 return tid.ToString();
10908 } 13509 }
10909 13510
@@ -10916,41 +13517,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
10916 if (obj.OwnerID != m_host.OwnerID) 13517 if (obj.OwnerID != m_host.OwnerID)
10917 return; 13518 return;
10918 13519
10919 uint rulesParsed = 0; 13520 SetEntityParams(new List<ISceneEntity>() { obj }, rules, originFunc);
10920 LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed);
10921
10922 while ((object)remaining != null && remaining.Length > 2)
10923 {
10924 LSL_Integer newLink = remaining.GetLSLIntegerItem(0);
10925 LSL_List newrules = remaining.GetSublist(1, -1);
10926 foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){
10927 remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed);
10928 }
10929 }
10930 } 13521 }
10931 13522
10932 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 13523 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
10933 { 13524 {
10934 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 13525 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
10935 13526
10936 LSL_List result = new LSL_List(); 13527 if (obj != null && obj.OwnerID == m_host.OwnerID)
10937 13528 return GetEntityParams(obj, rules);
10938 if (obj != null && obj.OwnerID != m_host.OwnerID)
10939 {
10940 LSL_List remaining = GetPrimParams(obj, rules, ref result);
10941
10942 while (remaining != null && remaining.Length > 2)
10943 {
10944 int linknumber = remaining.GetLSLIntegerItem(0);
10945 rules = remaining.GetSublist(1, -1);
10946 List<SceneObjectPart> parts = GetLinkParts(linknumber);
10947 13529
10948 foreach (SceneObjectPart part in parts) 13530 return new LSL_List();
10949 remaining = GetPrimParams(part, rules, ref result);
10950 }
10951 }
10952
10953 return result;
10954 } 13531 }
10955 13532
10956 public void print(string str) 13533 public void print(string str)
@@ -11036,7 +13613,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11036 World.ForEachScenePresence(delegate(ScenePresence sp) 13613 World.ForEachScenePresence(delegate(ScenePresence sp)
11037 { 13614 {
11038 Vector3 ac = sp.AbsolutePosition - rayStart; 13615 Vector3 ac = sp.AbsolutePosition - rayStart;
11039 Vector3 bc = sp.AbsolutePosition - rayEnd; 13616// Vector3 bc = sp.AbsolutePosition - rayEnd;
11040 13617
11041 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 13618 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11042 13619
@@ -11124,9 +13701,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11124 radius = Math.Abs(maxY); 13701 radius = Math.Abs(maxY);
11125 if (Math.Abs(maxZ) > radius) 13702 if (Math.Abs(maxZ) > radius)
11126 radius = Math.Abs(maxZ); 13703 radius = Math.Abs(maxZ);
11127 13704 radius = radius*1.413f;
11128 Vector3 ac = group.AbsolutePosition - rayStart; 13705 Vector3 ac = group.AbsolutePosition - rayStart;
11129 Vector3 bc = group.AbsolutePosition - rayEnd; 13706// Vector3 bc = group.AbsolutePosition - rayEnd;
11130 13707
11131 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 13708 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
11132 13709
@@ -11139,11 +13716,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11139 if (d2 > 0) 13716 if (d2 > 0)
11140 return; 13717 return;
11141 13718
13719 ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
11142 EntityIntersection intersection = group.TestIntersection(ray, true, false); 13720 EntityIntersection intersection = group.TestIntersection(ray, true, false);
11143 // Miss. 13721 // Miss.
11144 if (!intersection.HitTF) 13722 if (!intersection.HitTF)
11145 return; 13723 return;
11146 13724
13725 Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ);
13726 Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ);
13727 //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z);
13728 if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
13729 intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
13730 intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
13731 return;
13732
11147 ContactResult result = new ContactResult (); 13733 ContactResult result = new ContactResult ();
11148 result.ConsumerID = group.LocalId; 13734 result.ConsumerID = group.LocalId;
11149 result.Depth = intersection.distance; 13735 result.Depth = intersection.distance;
@@ -11284,6 +13870,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11284 13870
11285 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 13871 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
11286 { 13872 {
13873 // Use llCastRay V3 if configured
13874 if (m_useCastRayV3)
13875 return llCastRayV3(start, end, options);
13876
11287 LSL_List list = new LSL_List(); 13877 LSL_List list = new LSL_List();
11288 13878
11289 m_host.AddScriptLPS(1); 13879 m_host.AddScriptLPS(1);
@@ -11322,25 +13912,93 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11322 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 13912 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
11323 13913
11324 13914
11325 if (checkTerrain) 13915 if (World.SupportsRayCastFiltered())
11326 { 13916 {
11327 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 13917 if (dist == 0)
11328 if (groundContact != null) 13918 return list;
11329 results.Add((ContactResult)groundContact); 13919
11330 } 13920 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
13921 if (checkTerrain)
13922 rayfilter |= RayFilterFlags.land;
13923// if (checkAgents)
13924// rayfilter |= RayFilterFlags.agent;
13925 if (checkPhysical)
13926 rayfilter |= RayFilterFlags.physical;
13927 if (checkNonPhysical)
13928 rayfilter |= RayFilterFlags.nonphysical;
13929 if (detectPhantom)
13930 rayfilter |= RayFilterFlags.LSLPhantom;
11331 13931
11332 if (checkAgents) 13932 Vector3 direction = dir * ( 1/dist);
13933
13934 if(rayfilter == 0)
13935 {
13936 list.Add(new LSL_Integer(0));
13937 return list;
13938 }
13939
13940 // get some more contacts to sort ???
13941 int physcount = 4 * count;
13942 if (physcount > 20)
13943 physcount = 20;
13944
13945 object physresults;
13946 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
13947
13948 if (physresults == null)
13949 {
13950 list.Add(new LSL_Integer(-3)); // timeout error
13951 return list;
13952 }
13953
13954 results = (List<ContactResult>)physresults;
13955
13956 // for now physics doesn't detect sitted avatars so do it outside physics
13957 if (checkAgents)
13958 {
13959 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
13960 foreach (ContactResult r in agentHits)
13961 results.Add(r);
13962 }
13963
13964 // TODO: Replace this with a better solution. ObjectIntersection can only
13965 // detect nonphysical phantoms. They are detected by virtue of being
13966 // nonphysical (e.g. no PhysActor) so will not conflict with detecting
13967 // physicsl phantoms as done by the physics scene
13968 // We don't want anything else but phantoms here.
13969 if (detectPhantom)
13970 {
13971 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true);
13972 foreach (ContactResult r in objectHits)
13973 results.Add(r);
13974 }
13975 }
13976 else
11333 { 13977 {
11334 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 13978 if (checkAgents)
11335 foreach (ContactResult r in agentHits) 13979 {
11336 results.Add(r); 13980 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
13981 foreach (ContactResult r in agentHits)
13982 results.Add(r);
13983 }
13984
13985 if (checkPhysical || checkNonPhysical || detectPhantom)
13986 {
13987 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
13988 for (int iter = 0; iter < objectHits.Length; iter++)
13989 {
13990 // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
13991 objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
13992 results.Add(objectHits[iter]);
13993 }
13994 }
11337 } 13995 }
11338 13996
11339 if (checkPhysical || checkNonPhysical || detectPhantom) 13997 if (checkTerrain)
11340 { 13998 {
11341 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 13999 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
11342 foreach (ContactResult r in objectHits) 14000 if (groundContact != null)
11343 results.Add(r); 14001 results.Add((ContactResult)groundContact);
11344 } 14002 }
11345 14003
11346 results.Sort(delegate(ContactResult a, ContactResult b) 14004 results.Sort(delegate(ContactResult a, ContactResult b)
@@ -11381,7 +14039,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11381 else 14039 else
11382 { 14040 {
11383 ScenePresence sp = World.GetScenePresence(result.ConsumerID); 14041 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
11384 /// It it a boy? a girl? 14042 /// It it a boy? a girl?
11385 if (sp != null) 14043 if (sp != null)
11386 itemID = sp.UUID; 14044 itemID = sp.UUID;
11387 } 14045 }
@@ -11393,7 +14051,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11393 list.Add(new LSL_Integer(linkNum)); 14051 list.Add(new LSL_Integer(linkNum));
11394 14052
11395 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 14053 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
11396 list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z)); 14054 list.Add(new LSL_Vector(result.Normal));
11397 14055
11398 values++; 14056 values++;
11399 if (values >= count) 14057 if (values >= count)
@@ -11405,6 +14063,872 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11405 return list; 14063 return list;
11406 } 14064 }
11407 14065
14066 /// <summary>
14067 /// Implementation of llCastRay similar to SL 2015-04-21.
14068 /// http://wiki.secondlife.com/wiki/LlCastRay
14069 /// Uses pure geometry, bounding shapes, meshing and no physics
14070 /// for prims, sculpts, meshes, avatars and terrain.
14071 /// Implements all flags, reject types and data flags.
14072 /// Can handle both objects/groups and prims/parts, by config.
14073 /// May sometimes be inaccurate owing to calculation precision,
14074 /// meshing detail level and a bug in libopenmetaverse PrimMesher.
14075 /// </summary>
14076 public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options)
14077 {
14078 m_host.AddScriptLPS(1);
14079 LSL_List result = new LSL_List();
14080
14081 // Prepare throttle data
14082 int calledMs = Environment.TickCount;
14083 Stopwatch stopWatch = new Stopwatch();
14084 stopWatch.Start();
14085 UUID regionId = World.RegionInfo.RegionID;
14086 UUID userId = UUID.Zero;
14087 int msAvailable = 0;
14088 // Throttle per owner when attachment or "vehicle" (sat upon)
14089 if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0)
14090 {
14091 userId = m_host.OwnerID;
14092 msAvailable = m_msPerAvatarInCastRay;
14093 }
14094 // Throttle per parcel when not attachment or vehicle
14095 else
14096 {
14097 LandData land = World.GetLandData(m_host.GetWorldPosition());
14098 if (land != null)
14099 msAvailable = m_msPerRegionInCastRay * land.Area / 65536;
14100 }
14101 // Clamp for "oversized" parcels on varregions
14102 if (msAvailable > m_msMaxInCastRay)
14103 msAvailable = m_msMaxInCastRay;
14104
14105 // Check throttle data
14106 int fromCalledMs = calledMs - m_msThrottleInCastRay;
14107 lock (m_castRayCalls)
14108 {
14109 for (int i = m_castRayCalls.Count - 1; i >= 0; i--)
14110 {
14111 // Delete old calls from throttle data
14112 if (m_castRayCalls[i].CalledMs < fromCalledMs)
14113 m_castRayCalls.RemoveAt(i);
14114 // Use current region (in multi-region sims)
14115 else if (m_castRayCalls[i].RegionId == regionId)
14116 {
14117 // Reduce available time with recent calls
14118 if (m_castRayCalls[i].UserId == userId)
14119 msAvailable -= m_castRayCalls[i].UsedMs;
14120 }
14121 }
14122 }
14123
14124 // Return failure if not enough available time
14125 if (msAvailable < m_msMinInCastRay)
14126 {
14127 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED));
14128 return result;
14129 }
14130
14131 // Initialize
14132 List<RayHit> rayHits = new List<RayHit>();
14133 float tol = m_floatToleranceInCastRay;
14134 Vector3 pos1Ray = start;
14135 Vector3 pos2Ray = end;
14136
14137 // Get input options
14138 int rejectTypes = 0;
14139 int dataFlags = 0;
14140 int maxHits = 1;
14141 bool detectPhantom = false;
14142 for (int i = 0; i < options.Length; i += 2)
14143 {
14144 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
14145 rejectTypes = options.GetLSLIntegerItem(i + 1);
14146 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
14147 dataFlags = options.GetLSLIntegerItem(i + 1);
14148 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
14149 maxHits = options.GetLSLIntegerItem(i + 1);
14150 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
14151 detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0);
14152 }
14153 if (maxHits > m_maxHitsInCastRay)
14154 maxHits = m_maxHitsInCastRay;
14155 bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0);
14156 bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0);
14157 bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0);
14158 bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0);
14159 bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0);
14160 bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0);
14161 bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0);
14162
14163 // Calculate some basic parameters
14164 Vector3 vecRay = pos2Ray - pos1Ray;
14165 float rayLength = vecRay.Length();
14166
14167 // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits
14168 IRendering primMesher = null;
14169 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
14170 if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1)
14171 {
14172 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN));
14173 return result;
14174 }
14175 primMesher = RenderingLoader.LoadRenderer(renderers[0]);
14176
14177 // Iterate over all objects/groups and prims/parts in region
14178 World.ForEachSOG(
14179 delegate(SceneObjectGroup group)
14180 {
14181 // Check group filters unless part filters are configured
14182 bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical);
14183 bool isNonphysical = !isPhysical;
14184 bool isPhantom = group.IsPhantom || group.IsVolumeDetect;
14185 bool isAttachment = group.IsAttachment;
14186 bool doGroup = true;
14187 if (isPhysical && rejectPhysical)
14188 doGroup = false;
14189 if (isNonphysical && rejectNonphysical)
14190 doGroup = false;
14191 if (isPhantom && detectPhantom)
14192 doGroup = true;
14193 if (m_filterPartsInCastRay)
14194 doGroup = true;
14195 if (isAttachment && !m_doAttachmentsInCastRay)
14196 doGroup = false;
14197 // Parse object/group if passed filters
14198 if (doGroup)
14199 {
14200 // Iterate over all prims/parts in object/group
14201 foreach(SceneObjectPart part in group.Parts)
14202 {
14203 // Check part filters if configured
14204 if (m_filterPartsInCastRay)
14205 {
14206 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical);
14207 isNonphysical = !isPhysical;
14208 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive);
14209 bool doPart = true;
14210 if (isPhysical && rejectPhysical)
14211 doPart = false;
14212 if (isNonphysical && rejectNonphysical)
14213 doPart = false;
14214 if (isPhantom && detectPhantom)
14215 doPart = true;
14216 if (!doPart)
14217 continue;
14218 }
14219
14220 // Parse prim/part and project ray if passed filters
14221 Vector3 scalePart = part.Scale;
14222 Vector3 posPart = part.GetWorldPosition();
14223 Quaternion rotPart = part.GetWorldRotation();
14224 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14225 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14226 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14227
14228 // Filter parts by shape bounding boxes
14229 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
14230 if (!part.Shape.SculptEntry)
14231 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
14232 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
14233 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14234 {
14235 // Prepare data needed to check for ray hits
14236 RayTrans rayTrans = new RayTrans();
14237 rayTrans.PartId = part.UUID;
14238 rayTrans.GroupId = part.ParentGroup.UUID;
14239 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
14240 rayTrans.ScalePart = scalePart;
14241 rayTrans.PositionPart = posPart;
14242 rayTrans.RotationPart = rotPart;
14243 rayTrans.ShapeNeedsEnds = true;
14244 rayTrans.Position1Ray = pos1Ray;
14245 rayTrans.Position1RayProj = pos1RayProj;
14246 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14247
14248 // Get detail level depending on type
14249 int lod = 0;
14250 // Mesh detail level
14251 if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14252 lod = (int)m_meshLodInCastRay;
14253 // Sculpt detail level
14254 else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14255 lod = (int)m_sculptLodInCastRay;
14256 // Shape detail level
14257 else if (!part.Shape.SculptEntry)
14258 lod = (int)m_primLodInCastRay;
14259
14260 // Try to get cached mesh if configured
14261 ulong meshKey = 0;
14262 FacetedMesh mesh = null;
14263 if (m_useMeshCacheInCastRay)
14264 {
14265 meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod));
14266 lock (m_cachedMeshes)
14267 {
14268 m_cachedMeshes.TryGetValue(meshKey, out mesh);
14269 }
14270 }
14271
14272 // Create mesh if no cached mesh
14273 if (mesh == null)
14274 {
14275 // Make an OMV prim to be able to mesh part
14276 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart);
14277 byte[] sculptAsset = null;
14278 if (omvPrim.Sculpt != null)
14279 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
14280
14281 // When part is mesh, get mesh
14282 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
14283 {
14284 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
14285 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
14286 meshAsset = null;
14287 }
14288
14289 // When part is sculpt, create mesh
14290 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
14291 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
14292 {
14293 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
14294 if (imgDecoder != null)
14295 {
14296 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
14297 if (sculpt != null)
14298 {
14299 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
14300 sculpt.Dispose();
14301 }
14302 }
14303 }
14304
14305 // When part is shape, create mesh
14306 else if (omvPrim.Sculpt == null)
14307 {
14308 if (
14309 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
14310 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
14311 omvPrim.PrimData.PathSkew == 0.0 &&
14312 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
14313 )
14314 rayTrans.ShapeNeedsEnds = false;
14315 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
14316 }
14317
14318 // Cache mesh if configured
14319 if (m_useMeshCacheInCastRay && mesh != null)
14320 {
14321 lock(m_cachedMeshes)
14322 {
14323 if (!m_cachedMeshes.ContainsKey(meshKey))
14324 m_cachedMeshes.Add(meshKey, mesh);
14325 }
14326 }
14327 }
14328 // Check mesh for ray hits
14329 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14330 mesh = null;
14331 }
14332 }
14333 }
14334 }
14335 );
14336
14337 // Check avatar filter
14338 if (!rejectAgents)
14339 {
14340 // Iterate over all avatars in region
14341 World.ForEachRootScenePresence(
14342 delegate (ScenePresence sp)
14343 {
14344 // Get bounding box
14345 Vector3 lower;
14346 Vector3 upper;
14347 BoundingBoxOfScenePresence(sp, out lower, out upper);
14348 // Parse avatar
14349 Vector3 scalePart = upper - lower;
14350 Vector3 posPart = sp.AbsolutePosition;
14351 Quaternion rotPart = sp.GetWorldRotation();
14352 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14353 posPart = posPart + (lower + upper) * 0.5f * rotPart;
14354 // Project ray
14355 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14356 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14357
14358 // Filter avatars by shape bounding boxes
14359 Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol);
14360 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14361 {
14362 // Prepare data needed to check for ray hits
14363 RayTrans rayTrans = new RayTrans();
14364 rayTrans.PartId = sp.UUID;
14365 rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID;
14366 rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0;
14367 rayTrans.ScalePart = scalePart;
14368 rayTrans.PositionPart = posPart;
14369 rayTrans.RotationPart = rotPart;
14370 rayTrans.ShapeNeedsEnds = false;
14371 rayTrans.Position1Ray = pos1Ray;
14372 rayTrans.Position1RayProj = pos1RayProj;
14373 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14374
14375 // Try to get cached mesh if configured
14376 PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere();
14377 int lod = (int)m_avatarLodInCastRay;
14378 ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod));
14379 FacetedMesh mesh = null;
14380 if (m_useMeshCacheInCastRay)
14381 {
14382 lock (m_cachedMeshes)
14383 {
14384 m_cachedMeshes.TryGetValue(meshKey, out mesh);
14385 }
14386 }
14387
14388 // Create mesh if no cached mesh
14389 if (mesh == null)
14390 {
14391 // Make OMV prim and create mesh
14392 prim.Scale = scalePart;
14393 Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart);
14394 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay);
14395
14396 // Cache mesh if configured
14397 if (m_useMeshCacheInCastRay && mesh != null)
14398 {
14399 lock(m_cachedMeshes)
14400 {
14401 if (!m_cachedMeshes.ContainsKey(meshKey))
14402 m_cachedMeshes.Add(meshKey, mesh);
14403 }
14404 }
14405 }
14406
14407 // Check mesh for ray hits
14408 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14409 mesh = null;
14410 }
14411 }
14412 );
14413 }
14414
14415 // Check terrain filter
14416 if (!rejectLand)
14417 {
14418 // Parse terrain
14419
14420 // Mesh terrain and check bounding box
14421 Vector3 lower;
14422 Vector3 upper;
14423 List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper);
14424 lower.Z -= tol;
14425 upper.Z += tol;
14426 if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z))
14427 {
14428 // Prepare data needed to check for ray hits
14429 RayTrans rayTrans = new RayTrans();
14430 rayTrans.PartId = UUID.Zero;
14431 rayTrans.GroupId = UUID.Zero;
14432 rayTrans.Link = 0;
14433 rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f);
14434 rayTrans.PositionPart = Vector3.Zero;
14435 rayTrans.RotationPart = Quaternion.Identity;
14436 rayTrans.ShapeNeedsEnds = true;
14437 rayTrans.Position1Ray = pos1Ray;
14438 rayTrans.Position1RayProj = pos1Ray;
14439 rayTrans.VectorRayProj = vecRay;
14440
14441 // Check mesh
14442 AddRayInTris(triangles, rayTrans, ref rayHits);
14443 triangles = null;
14444 }
14445 }
14446
14447 // Sort hits by ascending distance
14448 rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance));
14449
14450 // Check excess hits per part and group
14451 for (int t = 0; t < 2; t++)
14452 {
14453 int maxHitsPerType = 0;
14454 UUID id = UUID.Zero;
14455 if (t == 0)
14456 maxHitsPerType = m_maxHitsPerPrimInCastRay;
14457 else
14458 maxHitsPerType = m_maxHitsPerObjectInCastRay;
14459
14460 // Handle excess hits only when needed
14461 if (maxHitsPerType < m_maxHitsInCastRay)
14462 {
14463 // Find excess hits
14464 Hashtable hits = new Hashtable();
14465 for (int i = rayHits.Count - 1; i >= 0; i--)
14466 {
14467 if (t == 0)
14468 id = rayHits[i].PartId;
14469 else
14470 id = rayHits[i].GroupId;
14471 if (hits.ContainsKey(id))
14472 hits[id] = (int)hits[id] + 1;
14473 else
14474 hits[id] = 1;
14475 }
14476
14477 // Remove excess hits
14478 for (int i = rayHits.Count - 1; i >= 0; i--)
14479 {
14480 if (t == 0)
14481 id = rayHits[i].PartId;
14482 else
14483 id = rayHits[i].GroupId;
14484 int hit = (int)hits[id];
14485 if (hit > m_maxHitsPerPrimInCastRay)
14486 {
14487 rayHits.RemoveAt(i);
14488 hit--;
14489 hits[id] = hit;
14490 }
14491 }
14492 }
14493 }
14494
14495 // Parse hits into result list according to data flags
14496 int hitCount = rayHits.Count;
14497 if (hitCount > maxHits)
14498 hitCount = maxHits;
14499 for (int i = 0; i < hitCount; i++)
14500 {
14501 RayHit rayHit = rayHits[i];
14502 if (getRootKey)
14503 result.Add(new LSL_Key(rayHit.GroupId.ToString()));
14504 else
14505 result.Add(new LSL_Key(rayHit.PartId.ToString()));
14506 result.Add(new LSL_Vector(rayHit.Position));
14507 if (getLinkNum)
14508 result.Add(new LSL_Integer(rayHit.Link));
14509 if (getNormal)
14510 result.Add(new LSL_Vector(rayHit.Normal));
14511 }
14512 result.Add(new LSL_Integer(hitCount));
14513
14514 // Add to throttle data
14515 stopWatch.Stop();
14516 CastRayCall castRayCall = new CastRayCall();
14517 castRayCall.RegionId = regionId;
14518 castRayCall.UserId = userId;
14519 castRayCall.CalledMs = calledMs;
14520 castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds;
14521 lock (m_castRayCalls)
14522 {
14523 m_castRayCalls.Add(castRayCall);
14524 }
14525
14526 // Return hits
14527 return result;
14528 }
14529
14530 /// <summary>
14531 /// Struct for transmitting parameters required for finding llCastRay ray hits.
14532 /// </summary>
14533 public struct RayTrans
14534 {
14535 public UUID PartId;
14536 public UUID GroupId;
14537 public int Link;
14538 public Vector3 ScalePart;
14539 public Vector3 PositionPart;
14540 public Quaternion RotationPart;
14541 public bool ShapeNeedsEnds;
14542 public Vector3 Position1Ray;
14543 public Vector3 Position1RayProj;
14544 public Vector3 VectorRayProj;
14545 }
14546
14547 /// <summary>
14548 /// Struct for llCastRay ray hits.
14549 /// </summary>
14550 public struct RayHit
14551 {
14552 public UUID PartId;
14553 public UUID GroupId;
14554 public int Link;
14555 public Vector3 Position;
14556 public Vector3 Normal;
14557 public float Distance;
14558 }
14559
14560 /// <summary>
14561 /// Struct for llCastRay throttle data.
14562 /// </summary>
14563 public struct CastRayCall
14564 {
14565 public UUID RegionId;
14566 public UUID UserId;
14567 public int CalledMs;
14568 public int UsedMs;
14569 }
14570
14571 /// <summary>
14572 /// Helper to check if a ray intersects a shape bounding box.
14573 /// </summary>
14574 private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax)
14575 {
14576 // Skip if ray can't intersect bounding box;
14577 Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj);
14578 Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj);
14579 if (
14580 rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z ||
14581 rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z
14582 )
14583 return false;
14584
14585 // Check if ray intersect any bounding box side
14586 int sign = 0;
14587 float dist = 0.0f;
14588 Vector3 posProj = Vector3.Zero;
14589 Vector3 vecRayProj = pos2RayProj - pos1RayProj;
14590
14591 // Check both X sides unless ray is parallell to them
14592 if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay)
14593 {
14594 for (sign = -1; sign <= 1; sign += 2)
14595 {
14596 dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X;
14597 posProj = pos1RayProj + vecRayProj * dist;
14598 if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14599 return true;
14600 }
14601 }
14602
14603 // Check both Y sides unless ray is parallell to them
14604 if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay)
14605 {
14606 for (sign = -1; sign <= 1; sign += 2)
14607 {
14608 dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y;
14609 posProj = pos1RayProj + vecRayProj * dist;
14610 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14611 return true;
14612 }
14613 }
14614
14615 // Check both Z sides unless ray is parallell to them
14616 if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay)
14617 {
14618 for (sign = -1; sign <= 1; sign += 2)
14619 {
14620 dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z;
14621 posProj = pos1RayProj + vecRayProj * dist;
14622 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y)
14623 return true;
14624 }
14625 }
14626
14627 // No hits on bounding box so return false
14628 return false;
14629 }
14630
14631 /// <summary>
14632 /// Helper to parse FacetedMesh for ray hits.
14633 /// </summary>
14634 private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits)
14635 {
14636 if (mesh != null)
14637 {
14638 foreach (Face face in mesh.Faces)
14639 {
14640 for (int i = 0; i < face.Indices.Count; i += 3)
14641 {
14642 Tri triangle = new Tri();
14643 triangle.p1 = face.Vertices[face.Indices[i]].Position;
14644 triangle.p2 = face.Vertices[face.Indices[i + 1]].Position;
14645 triangle.p3 = face.Vertices[face.Indices[i + 2]].Position;
14646 AddRayInTri(triangle, rayTrans, ref rayHits);
14647 }
14648 }
14649 }
14650 }
14651
14652 /// <summary>
14653 /// Helper to parse Tri (triangle) List for ray hits.
14654 /// </summary>
14655 private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits)
14656 {
14657 foreach (Tri triangle in triangles)
14658 {
14659 AddRayInTri(triangle, rayTrans, ref rayHits);
14660 }
14661 }
14662
14663 /// <summary>
14664 /// Helper to add ray hit in a Tri (triangle).
14665 /// </summary>
14666 private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits)
14667 {
14668 // Check for hit in triangle
14669 Vector3 posHitProj;
14670 Vector3 normalProj;
14671 if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj))
14672 {
14673 // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center
14674 if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds)
14675 return;
14676
14677 // Transform hit and normal to region coordinate system
14678 Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart;
14679 Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart);
14680
14681 // Remove duplicate hits at triangle intersections
14682 float distance = Vector3.Distance(rayTrans.Position1Ray, posHit);
14683 for (int i = rayHits.Count - 1; i >= 0; i--)
14684 {
14685 if (rayHits[i].PartId != rayTrans.PartId)
14686 break;
14687 if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay)
14688 return;
14689 }
14690
14691 // Build result data set
14692 RayHit rayHit = new RayHit();
14693 rayHit.PartId = rayTrans.PartId;
14694 rayHit.GroupId = rayTrans.GroupId;
14695 rayHit.Link = rayTrans.Link;
14696 rayHit.Position = posHit;
14697 rayHit.Normal = normal;
14698 rayHit.Distance = distance;
14699 rayHits.Add(rayHit);
14700 }
14701 }
14702
14703 /// <summary>
14704 /// Helper to find ray hit in triangle
14705 /// </summary>
14706 bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj)
14707 {
14708 float tol = m_floatToleranceInCastRay;
14709 posHitProj = Vector3.Zero;
14710
14711 // Calculate triangle edge vectors
14712 Vector3 vec1Proj = triProj.p2 - triProj.p1;
14713 Vector3 vec2Proj = triProj.p3 - triProj.p2;
14714 Vector3 vec3Proj = triProj.p1 - triProj.p3;
14715
14716 // Calculate triangle normal
14717 normalProj = Vector3.Cross(vec1Proj, vec2Proj);
14718
14719 // Skip if degenerate triangle or ray parallell with triangle plane
14720 float divisor = Vector3.Dot(vecRayProj, normalProj);
14721 if (Math.Abs(divisor) < tol)
14722 return false;
14723
14724 // Skip if exit and not configured to detect
14725 if (divisor > tol && !m_detectExitsInCastRay)
14726 return false;
14727
14728 // Skip if outside ray ends
14729 float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor;
14730 if (distanceProj < -tol || distanceProj > 1 + tol)
14731 return false;
14732
14733 // Calculate hit position in triangle
14734 posHitProj = pos1RayProj + vecRayProj * distanceProj;
14735
14736 // Skip if outside triangle bounding box
14737 Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3);
14738 Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3);
14739 if (
14740 posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol ||
14741 posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol
14742 )
14743 return false;
14744
14745 // Skip if outside triangle
14746 if (
14747 Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol ||
14748 Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol ||
14749 Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol
14750 )
14751 return false;
14752
14753 // Return hit
14754 return true;
14755 }
14756
14757 /// <summary>
14758 /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box.
14759 /// </summary>
14760 private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper)
14761 {
14762 // Get bounding X-Y rectangle of terrain under ray
14763 lower = Vector3.Min(posStart, posEnd);
14764 upper = Vector3.Max(posStart, posEnd);
14765 lower.X = (float)Math.Floor(lower.X);
14766 lower.Y = (float)Math.Floor(lower.Y);
14767 float zLower = float.MaxValue;
14768 upper.X = (float)Math.Ceiling(upper.X);
14769 upper.Y = (float)Math.Ceiling(upper.Y);
14770 float zUpper = float.MinValue;
14771
14772 // Initialize Tri (triangle) List
14773 List<Tri> triangles = new List<Tri>();
14774
14775 // Set parsing lane direction to major ray X-Y axis
14776 Vector3 vec = posEnd - posStart;
14777 float xAbs = Math.Abs(vec.X);
14778 float yAbs = Math.Abs(vec.Y);
14779 bool bigX = true;
14780 if (yAbs > xAbs)
14781 {
14782 bigX = false;
14783 vec = vec / yAbs;
14784 }
14785 else if (xAbs > yAbs || xAbs > 0.0f)
14786 vec = vec / xAbs;
14787 else
14788 vec = new Vector3(1.0f, 1.0f, 0.0f);
14789
14790 // Simplify by start parsing in lower end of lane
14791 if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f))
14792 {
14793 Vector3 posTemp = posStart;
14794 posStart = posEnd;
14795 posEnd = posTemp;
14796 vec = vec * -1.0f;
14797 }
14798
14799 // First 1x1 rectangle under ray
14800 float xFloorOld = 0.0f;
14801 float yFloorOld = 0.0f;
14802 Vector3 pos = posStart;
14803 float xFloor = (float)Math.Floor(pos.X);
14804 float yFloor = (float)Math.Floor(pos.Y);
14805 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
14806
14807 // Parse every remaining 1x1 rectangle under ray
14808 while (pos != posEnd)
14809 {
14810 // Next 1x1 rectangle under ray
14811 xFloorOld = xFloor;
14812 yFloorOld = yFloor;
14813 pos = pos + vec;
14814
14815 // Clip position to 1x1 rectangle border
14816 xFloor = (float)Math.Floor(pos.X);
14817 yFloor = (float)Math.Floor(pos.Y);
14818 if (bigX && pos.X > xFloor)
14819 {
14820 pos.Y -= vec.Y * (pos.X - xFloor);
14821 pos.X = xFloor;
14822 }
14823 else if (!bigX && pos.Y > yFloor)
14824 {
14825 pos.X -= vec.X * (pos.Y - yFloor);
14826 pos.Y = yFloor;
14827 }
14828
14829 // Last 1x1 rectangle under ray
14830 if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y))
14831 {
14832 pos = posEnd;
14833 xFloor = (float)Math.Floor(pos.X);
14834 yFloor = (float)Math.Floor(pos.Y);
14835 }
14836
14837 // Add new 1x1 rectangle in lane
14838 if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld))
14839 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
14840 // Add last 1x1 rectangle in old lane at lane shift
14841 if (bigX && yFloor != yFloorOld)
14842 AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper);
14843 if (!bigX && xFloor != xFloorOld)
14844 AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper);
14845 }
14846
14847 // Finalize bounding box Z
14848 lower.Z = zLower;
14849 upper.Z = zUpper;
14850
14851 // Done and returning Tri (triangle)List
14852 return triangles;
14853 }
14854
14855 /// <summary>
14856 /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box.
14857 /// </summary>
14858 private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper)
14859 {
14860 int xInt = (int)xPos;
14861 int yInt = (int)yPos;
14862
14863 // Corner 1 of 1x1 rectangle
14864 int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
14865 int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
14866 Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14867 // Adjust bounding box
14868 zLower = Math.Min(zLower, pos1.Z);
14869 zUpper = Math.Max(zUpper, pos1.Z);
14870
14871 // Corner 2 of 1x1 rectangle
14872 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
14873 y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
14874 Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14875 // Adjust bounding box
14876 zLower = Math.Min(zLower, pos2.Z);
14877 zUpper = Math.Max(zUpper, pos2.Z);
14878
14879 // Corner 3 of 1x1 rectangle
14880 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
14881 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14882 Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14883 // Adjust bounding box
14884 zLower = Math.Min(zLower, pos3.Z);
14885 zUpper = Math.Max(zUpper, pos3.Z);
14886
14887 // Corner 4 of 1x1 rectangle
14888 x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
14889 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14890 Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14891 // Adjust bounding box
14892 zLower = Math.Min(zLower, pos4.Z);
14893 zUpper = Math.Max(zUpper, pos4.Z);
14894
14895 // Add triangle 1
14896 Tri triangle1 = new Tri();
14897 triangle1.p1 = pos1;
14898 triangle1.p2 = pos2;
14899 triangle1.p3 = pos3;
14900 triangles.Add(triangle1);
14901
14902 // Add triangle 2
14903 Tri triangle2 = new Tri();
14904 triangle2.p1 = pos3;
14905 triangle2.p2 = pos4;
14906 triangle2.p3 = pos1;
14907 triangles.Add(triangle2);
14908 }
14909
14910 /// <summary>
14911 /// Helper to get link number for a UUID.
14912 /// </summary>
14913 private int UUID2LinkNumber(SceneObjectPart part, UUID id)
14914 {
14915 SceneObjectGroup group = part.ParentGroup;
14916 if (group != null)
14917 {
14918 // Parse every link for UUID
14919 int linkCount = group.PrimCount + group.GetSittingAvatarsCount();
14920 for (int link = linkCount; link > 0; link--)
14921 {
14922 ISceneEntity entity = GetLinkEntity(part, link);
14923 // Return link number if UUID match
14924 if (entity != null && entity.UUID == id)
14925 return link;
14926 }
14927 }
14928 // Return link number 0 if no links or UUID matches
14929 return 0;
14930 }
14931
11408 public LSL_Integer llManageEstateAccess(int action, string avatar) 14932 public LSL_Integer llManageEstateAccess(int action, string avatar)
11409 { 14933 {
11410 m_host.AddScriptLPS(1); 14934 m_host.AddScriptLPS(1);
@@ -11477,8 +15001,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11477 public LSL_Integer llGetMemoryLimit() 15001 public LSL_Integer llGetMemoryLimit()
11478 { 15002 {
11479 m_host.AddScriptLPS(1); 15003 m_host.AddScriptLPS(1);
11480 // The value returned for LSO scripts in SL 15004 // The value returned for Mono scripts in SL
11481 return 16384; 15005 return 65536;
11482 } 15006 }
11483 15007
11484 public LSL_Integer llSetMemoryLimit(LSL_Integer limit) 15008 public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
@@ -11491,15 +15015,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11491 public LSL_Integer llGetSPMaxMemory() 15015 public LSL_Integer llGetSPMaxMemory()
11492 { 15016 {
11493 m_host.AddScriptLPS(1); 15017 m_host.AddScriptLPS(1);
11494 // The value returned for LSO scripts in SL 15018 // The value returned for Mono scripts in SL
11495 return 16384; 15019 return 65536;
11496 } 15020 }
11497 15021
11498 public LSL_Integer llGetUsedMemory() 15022 public virtual LSL_Integer llGetUsedMemory()
11499 { 15023 {
11500 m_host.AddScriptLPS(1); 15024 m_host.AddScriptLPS(1);
11501 // The value returned for LSO scripts in SL 15025 // The value returned for Mono scripts in SL
11502 return 16384; 15026 return 65536;
11503 } 15027 }
11504 15028
11505 public void llScriptProfiler(LSL_Integer flags) 15029 public void llScriptProfiler(LSL_Integer flags)
@@ -11514,16 +15038,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11514 // them from this region as they are completed 15038 // them from this region as they are completed
11515 // 15039 //
11516 15040
11517 public void llGetEnv(LSL_String name)
11518 {
11519 m_host.AddScriptLPS(1);
11520 NotImplemented("llGetEnv");
11521 }
11522
11523 public void llSetSoundQueueing(int queue) 15041 public void llSetSoundQueueing(int queue)
11524 { 15042 {
11525 m_host.AddScriptLPS(1); 15043 m_host.AddScriptLPS(1);
11526 NotImplemented("llSetSoundQueueing"); 15044
15045 if (m_SoundModule != null)
15046 m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value);
11527 } 15047 }
11528 15048
11529 public void llCollisionSprite(string impact_sprite) 15049 public void llCollisionSprite(string impact_sprite)
@@ -11538,6 +15058,79 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11538 NotImplemented("llGodLikeRezObject"); 15058 NotImplemented("llGodLikeRezObject");
11539 } 15059 }
11540 15060
15061 public LSL_String llTransferLindenDollars(string destination, int amount)
15062 {
15063 UUID txn = UUID.Random();
15064
15065 Util.FireAndForget(delegate(object x)
15066 {
15067 int replycode = 0;
15068 string replydata = destination + "," + amount.ToString();
15069
15070 try
15071 {
15072 TaskInventoryItem item = m_item;
15073 if (item == null)
15074 {
15075 replydata = "SERVICE_ERROR";
15076 return;
15077 }
15078
15079 m_host.AddScriptLPS(1);
15080
15081 if (item.PermsGranter == UUID.Zero)
15082 {
15083 replydata = "MISSING_PERMISSION_DEBIT";
15084 return;
15085 }
15086
15087 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
15088 {
15089 replydata = "MISSING_PERMISSION_DEBIT";
15090 return;
15091 }
15092
15093 UUID toID = new UUID();
15094
15095 if (!UUID.TryParse(destination, out toID))
15096 {
15097 replydata = "INVALID_AGENT";
15098 return;
15099 }
15100
15101 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
15102
15103 if (money == null)
15104 {
15105 replydata = "TRANSFERS_DISABLED";
15106 return;
15107 }
15108
15109 bool result = money.ObjectGiveMoney(
15110 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
15111
15112 if (result)
15113 {
15114 replycode = 1;
15115 return;
15116 }
15117
15118 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
15119 }
15120 finally
15121 {
15122 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
15123 "transaction_result", new Object[] {
15124 new LSL_String(txn.ToString()),
15125 new LSL_Integer(replycode),
15126 new LSL_String(replydata) },
15127 new DetectParams[0]));
15128 }
15129 }, null, "LSL_Api.llTransferLindenDollars");
15130
15131 return txn.ToString();
15132 }
15133
11541 #endregion 15134 #endregion
11542 } 15135 }
11543 15136
@@ -11549,12 +15142,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11549 public DateTime lastRef; 15142 public DateTime lastRef;
11550 } 15143 }
11551 15144
11552 protected static Dictionary<UUID, Notecard> m_Notecards = 15145 private static Dictionary<UUID, Notecard> m_Notecards =
11553 new Dictionary<UUID, Notecard>(); 15146 new Dictionary<UUID, Notecard>();
11554 15147
11555 public static void Cache(UUID assetID, string text) 15148 public static void Cache(UUID assetID, byte[] text)
11556 { 15149 {
11557 CacheCheck(); 15150 CheckCache();
11558 15151
11559 lock (m_Notecards) 15152 lock (m_Notecards)
11560 { 15153 {
@@ -11563,7 +15156,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11563 15156
11564 Notecard nc = new Notecard(); 15157 Notecard nc = new Notecard();
11565 nc.lastRef = DateTime.Now; 15158 nc.lastRef = DateTime.Now;
11566 nc.text = SLUtil.ParseNotecardToList(text).ToArray(); 15159 try
15160 {
15161 nc.text = SLUtil.ParseNotecardToArray(text);
15162 }
15163 catch(SLUtil.NotANotecardFormatException)
15164 {
15165 nc.text = new string[0];
15166 }
11567 m_Notecards[assetID] = nc; 15167 m_Notecards[assetID] = nc;
11568 } 15168 }
11569 } 15169 }
@@ -11639,13 +15239,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
11639 return line; 15239 return line;
11640 } 15240 }
11641 15241
11642 public static void CacheCheck() 15242 public static void CheckCache()
11643 { 15243 {
11644 foreach (UUID key in new List<UUID>(m_Notecards.Keys)) 15244 lock (m_Notecards)
11645 { 15245 {
11646 Notecard nc = m_Notecards[key]; 15246 foreach (UUID key in new List<UUID>(m_Notecards.Keys))
11647 if (nc.lastRef.AddSeconds(30) < DateTime.Now) 15247 {
11648 m_Notecards.Remove(key); 15248 Notecard nc = m_Notecards[key];
15249 if (nc.lastRef.AddSeconds(30) < DateTime.Now)
15250 m_Notecards.Remove(key);
15251 }
11649 } 15252 }
11650 } 15253 }
11651 } 15254 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
index ceb4660..e5e43f8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs
@@ -30,6 +30,7 @@ using System.Reflection;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
33using System.Threading;
33using OpenMetaverse; 34using OpenMetaverse;
34using Nini.Config; 35using Nini.Config;
35using OpenSim; 36using OpenSim;
@@ -61,9 +62,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
61 internal bool m_LSFunctionsEnabled = false; 62 internal bool m_LSFunctionsEnabled = false;
62 internal IScriptModuleComms m_comms = null; 63 internal IScriptModuleComms m_comms = null;
63 64
64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 65 public void Initialize(
66 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
65 { 67 {
66 m_ScriptEngine = ScriptEngine; 68 m_ScriptEngine = scriptEngine;
67 m_host = host; 69 m_host = host;
68 70
69 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) 71 if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false))
@@ -92,10 +94,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
92 get { return m_ScriptEngine.World; } 94 get { return m_ScriptEngine.World; }
93 } 95 }
94 96
95 // 97 /// <summary>
96 //Dumps an error message on the debug console. 98 /// Dumps an error message on the debug console.
97 // 99 /// </summary>
98
99 internal void LSShoutError(string message) 100 internal void LSShoutError(string message)
100 { 101 {
101 if (message.Length > 1023) 102 if (message.Length > 1023)
@@ -264,175 +265,445 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
264 int idx = 0; 265 int idx = 0;
265 while (idx < rules.Length) 266 while (idx < rules.Length)
266 { 267 {
267 uint rule = (uint)rules.GetLSLIntegerItem(idx); 268 uint rule;
269
270 try
271 {
272 rule = (uint)rules.GetLSLIntegerItem(idx);
273 }
274 catch (InvalidCastException)
275 {
276 throw new InvalidCastException(string.Format("Error running rule type: arg #{0} - parameter type must be integer", idx));
277 }
278
268 LSL_Types.Quaternion iQ; 279 LSL_Types.Quaternion iQ;
269 LSL_Types.Vector3 iV; 280 LSL_Types.Vector3 iV;
270 switch (rule) 281 switch (rule)
271 { 282 {
272 case (int)ScriptBaseClass.WL_SUN_MOON_POSITION: 283 case (int)ScriptBaseClass.WL_SUN_MOON_POSITION:
273 idx++; 284 idx++;
274 wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx); 285 try
286 {
287 wl.sunMoonPosition = (float)rules.GetLSLFloatItem(idx);
288 }
289 catch (InvalidCastException)
290 {
291 throw new InvalidCastException(string.Format("Error running rule WL_SUN_MOON_POSITION: arg #{0} - parameter 1 must be float", idx));
292 }
275 break; 293 break;
276 case (int)ScriptBaseClass.WL_AMBIENT: 294 case (int)ScriptBaseClass.WL_AMBIENT:
277 idx++; 295 idx++;
278 iQ = rules.GetQuaternionItem(idx); 296 try
297 {
298 iQ = rules.GetQuaternionItem(idx);
299 }
300 catch (InvalidCastException)
301 {
302 throw new InvalidCastException(string.Format("Error running rule WL_AMBIENT: arg #{0} - parameter 1 must be rotation", idx));
303 }
279 wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); 304 wl.ambient = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s);
280 break; 305 break;
281 case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION: 306 case (int)ScriptBaseClass.WL_BIG_WAVE_DIRECTION:
282 idx++; 307 idx++;
283 iV = rules.GetVector3Item(idx); 308 try
309 {
310 iV = rules.GetVector3Item(idx);
311 }
312 catch (InvalidCastException)
313 {
314 throw new InvalidCastException(string.Format("Error running rule WL_BIG_WAVE_DIRECTION: arg #{0} - parameter 1 must be vector", idx));
315 }
284 wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y); 316 wl.bigWaveDirection = new Vector2((float)iV.x, (float)iV.y);
285 break; 317 break;
286 case (int)ScriptBaseClass.WL_BLUE_DENSITY: 318 case (int)ScriptBaseClass.WL_BLUE_DENSITY:
287 idx++; 319 idx++;
288 iQ = rules.GetQuaternionItem(idx); 320 try
321 {
322 iQ = rules.GetQuaternionItem(idx);
323 }
324 catch (InvalidCastException)
325 {
326 throw new InvalidCastException(string.Format("Error running rule WL_BLUE_DENSITY: arg #{0} - parameter 1 must be rotation", idx));
327 }
289 wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); 328 wl.blueDensity = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s);
290 break; 329 break;
291 case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER: 330 case (int)ScriptBaseClass.WL_BLUR_MULTIPLIER:
292 idx++; 331 idx++;
293 wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx); 332 try
333 {
334 wl.blurMultiplier = (float)rules.GetLSLFloatItem(idx);
335 }
336 catch (InvalidCastException)
337 {
338 throw new InvalidCastException(string.Format("Error running rule WL_BLUR_MULTIPLIER: arg #{0} - parameter 1 must be float", idx));
339 }
294 break; 340 break;
295 case (int)ScriptBaseClass.WL_CLOUD_COLOR: 341 case (int)ScriptBaseClass.WL_CLOUD_COLOR:
296 idx++; 342 idx++;
297 iQ = rules.GetQuaternionItem(idx); 343 try
344 {
345 iQ = rules.GetQuaternionItem(idx);
346 }
347 catch (InvalidCastException)
348 {
349 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_COLOR: arg #{0} - parameter 1 must be rotation", idx));
350 }
298 wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); 351 wl.cloudColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s);
299 break; 352 break;
300 case (int)ScriptBaseClass.WL_CLOUD_COVERAGE: 353 case (int)ScriptBaseClass.WL_CLOUD_COVERAGE:
301 idx++; 354 idx++;
302 wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx); 355 try
356 {
357 wl.cloudCoverage = (float)rules.GetLSLFloatItem(idx);
358 }
359 catch (InvalidCastException)
360 {
361 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_COVERAGE: arg #{0} - parameter 1 must be float", idx));
362 }
303 break; 363 break;
304 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: 364 case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY:
305 idx++; 365 idx++;
306 iV = rules.GetVector3Item(idx); 366 try
367 {
368 iV = rules.GetVector3Item(idx);
369 }
370 catch (InvalidCastException)
371 {
372 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_DETAIL_XY_DENSITY: arg #{0} - parameter 1 must be vector", idx));
373 }
307 wl.cloudDetailXYDensity = iV; 374 wl.cloudDetailXYDensity = iV;
308 break; 375 break;
309 case (int)ScriptBaseClass.WL_CLOUD_SCALE: 376 case (int)ScriptBaseClass.WL_CLOUD_SCALE:
310 idx++; 377 idx++;
311 wl.cloudScale = (float)rules.GetLSLFloatItem(idx); 378 try
379 {
380 wl.cloudScale = (float)rules.GetLSLFloatItem(idx);
381 }
382 catch (InvalidCastException)
383 {
384 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_SCALE: arg #{0} - parameter 1 must be float", idx));
385 }
312 break; 386 break;
313 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X: 387 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X:
314 idx++; 388 idx++;
315 wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx); 389 try
390 {
391 wl.cloudScrollX = (float)rules.GetLSLFloatItem(idx);
392 }
393 catch (InvalidCastException)
394 {
395 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_SCROLL_X: arg #{0} - parameter 1 must be float", idx));
396 }
316 break; 397 break;
317 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK: 398 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_X_LOCK:
318 idx++; 399 idx++;
319 wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; 400 try
401 {
402 wl.cloudScrollXLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false;
403 }
404 catch (InvalidCastException)
405 {
406 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_SCROLL_Y_LOCK: arg #{0} - parameter 1 must be integer", idx));
407 }
320 break; 408 break;
321 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y: 409 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y:
322 idx++; 410 idx++;
323 wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx); 411 try
412 {
413 wl.cloudScrollY = (float)rules.GetLSLFloatItem(idx);
414 }
415 catch (InvalidCastException)
416 {
417 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_SCROLL_Y: arg #{0} - parameter 1 must be float", idx));
418 }
324 break; 419 break;
325 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK: 420 case (int)ScriptBaseClass.WL_CLOUD_SCROLL_Y_LOCK:
326 idx++; 421 idx++;
327 wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; 422 try
423 {
424 wl.cloudScrollYLock = rules.GetLSLIntegerItem(idx).value == 1 ? true : false;
425 }
426 catch (InvalidCastException)
427 {
428 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_SCROLL_Y_LOCK: arg #{0} - parameter 1 must be integer", idx));
429 }
328 break; 430 break;
329 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: 431 case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY:
330 idx++; 432 idx++;
331 iV = rules.GetVector3Item(idx); 433 try
434 {
435 iV = rules.GetVector3Item(idx);
436 }
437 catch (InvalidCastException)
438 {
439 throw new InvalidCastException(string.Format("Error running rule WL_CLOUD_XY_DENSITY: arg #{0} - parameter 1 must be vector", idx));
440 }
332 wl.cloudXYDensity = iV; 441 wl.cloudXYDensity = iV;
333 break; 442 break;
334 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: 443 case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER:
335 idx++; 444 idx++;
336 wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx); 445 try
446 {
447 wl.densityMultiplier = (float)rules.GetLSLFloatItem(idx);
448 }
449 catch (InvalidCastException)
450 {
451 throw new InvalidCastException(string.Format("Error running rule WL_DENSITY_MULTIPLIER: arg #{0} - parameter 1 must be float", idx));
452 }
337 break; 453 break;
338 case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER: 454 case (int)ScriptBaseClass.WL_DISTANCE_MULTIPLIER:
339 idx++; 455 idx++;
340 wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx); 456 try
457 {
458 wl.distanceMultiplier = (float)rules.GetLSLFloatItem(idx);
459 }
460 catch (InvalidCastException)
461 {
462 throw new InvalidCastException(string.Format("Error running rule WL_DISTANCE_MULTIPLIER: arg #{0} - parameter 1 must be float", idx));
463 }
341 break; 464 break;
342 case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS: 465 case (int)ScriptBaseClass.WL_DRAW_CLASSIC_CLOUDS:
343 idx++; 466 idx++;
344 wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false; 467 try
468 {
469 wl.drawClassicClouds = rules.GetLSLIntegerItem(idx).value == 1 ? true : false;
470 }
471 catch (InvalidCastException)
472 {
473 throw new InvalidCastException(string.Format("Error running rule WL_DRAW_CLASSIC_CLOUDS: arg #{0} - parameter 1 must be integer", idx));
474 }
345 break; 475 break;
346 case (int)ScriptBaseClass.WL_EAST_ANGLE: 476 case (int)ScriptBaseClass.WL_EAST_ANGLE:
347 idx++; 477 idx++;
348 wl.eastAngle = (float)rules.GetLSLFloatItem(idx); 478 try
479 {
480 wl.eastAngle = (float)rules.GetLSLFloatItem(idx);
481 }
482 catch (InvalidCastException)
483 {
484 throw new InvalidCastException(string.Format("Error running rule WL_EAST_ANGLE: arg #{0} - parameter 1 must be float", idx));
485 }
349 break; 486 break;
350 case (int)ScriptBaseClass.WL_FRESNEL_OFFSET: 487 case (int)ScriptBaseClass.WL_FRESNEL_OFFSET:
351 idx++; 488 idx++;
352 wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx); 489 try
490 {
491 wl.fresnelOffset = (float)rules.GetLSLFloatItem(idx);
492 }
493 catch (InvalidCastException)
494 {
495 throw new InvalidCastException(string.Format("Error running rule WL_FRESNEL_OFFSET: arg #{0} - parameter 1 must be float", idx));
496 }
353 break; 497 break;
354 case (int)ScriptBaseClass.WL_FRESNEL_SCALE: 498 case (int)ScriptBaseClass.WL_FRESNEL_SCALE:
355 idx++; 499 idx++;
356 wl.fresnelScale = (float)rules.GetLSLFloatItem(idx); 500 try
501 {
502 wl.fresnelScale = (float)rules.GetLSLFloatItem(idx);
503 }
504 catch (InvalidCastException)
505 {
506 throw new InvalidCastException(string.Format("Error running rule WL_FRESNEL_SCALE: arg #{0} - parameter 1 must be float", idx));
507 }
357 break; 508 break;
358 case (int)ScriptBaseClass.WL_HAZE_DENSITY: 509 case (int)ScriptBaseClass.WL_HAZE_DENSITY:
359 idx++; 510 idx++;
360 wl.hazeDensity = (float)rules.GetLSLFloatItem(idx); 511 try
512 {
513 wl.hazeDensity = (float)rules.GetLSLFloatItem(idx);
514 }
515 catch (InvalidCastException)
516 {
517 throw new InvalidCastException(string.Format("Error running rule WL_HAZE_DENSITY: arg #{0} - parameter 1 must be float", idx));
518 }
361 break; 519 break;
362 case (int)ScriptBaseClass.WL_HAZE_HORIZON: 520 case (int)ScriptBaseClass.WL_HAZE_HORIZON:
363 idx++; 521 idx++;
364 wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx); 522 try
523 {
524 wl.hazeHorizon = (float)rules.GetLSLFloatItem(idx);
525 }
526 catch (InvalidCastException)
527 {
528 throw new InvalidCastException(string.Format("Error running rule WL_HAZE_HORIZON: arg #{0} - parameter 1 must be float", idx));
529 }
365 break; 530 break;
366 case (int)ScriptBaseClass.WL_HORIZON: 531 case (int)ScriptBaseClass.WL_HORIZON:
367 idx++; 532 idx++;
368 iQ = rules.GetQuaternionItem(idx); 533 try
534 {
535 iQ = rules.GetQuaternionItem(idx);
536 }
537 catch (InvalidCastException)
538 {
539 throw new InvalidCastException(string.Format("Error running rule WL_HORIZON: arg #{0} - parameter 1 must be rotation", idx));
540 }
369 wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); 541 wl.horizon = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s);
370 break; 542 break;
371 case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION: 543 case (int)ScriptBaseClass.WL_LITTLE_WAVE_DIRECTION:
372 idx++; 544 idx++;
373 iV = rules.GetVector3Item(idx); 545 try
546 {
547 iV = rules.GetVector3Item(idx);
548 }
549 catch (InvalidCastException)
550 {
551 throw new InvalidCastException(string.Format("Error running rule WL_LITTLE_WAVE_DIRECTION: arg #{0} - parameter 1 must be vector", idx));
552 }
374 wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y); 553 wl.littleWaveDirection = new Vector2((float)iV.x, (float)iV.y);
375 break; 554 break;
376 case (int)ScriptBaseClass.WL_MAX_ALTITUDE: 555 case (int)ScriptBaseClass.WL_MAX_ALTITUDE:
377 idx++; 556 idx++;
378 wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value; 557 try
558 {
559 wl.maxAltitude = (ushort)rules.GetLSLIntegerItem(idx).value;
560 }
561 catch (InvalidCastException)
562 {
563 throw new InvalidCastException(string.Format("Error running rule WL_MAX_ALTITUDE: arg #{0} - parameter 1 must be integer", idx));
564 }
379 break; 565 break;
380 case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE: 566 case (int)ScriptBaseClass.WL_NORMAL_MAP_TEXTURE:
381 idx++; 567 idx++;
382 wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string); 568 try
569 {
570 wl.normalMapTexture = new UUID(rules.GetLSLStringItem(idx).m_string);
571 }
572 catch (ArgumentException)
573 {
574 throw new InvalidCastException(string.Format("Error running rule WL_NORMAL_MAP_TEXTURE: arg #{0} - parameter 1 must be key", idx));
575 }
383 break; 576 break;
384 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: 577 case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE:
385 idx++; 578 idx++;
386 iV = rules.GetVector3Item(idx); 579 try
580 {
581 iV = rules.GetVector3Item(idx);
582 }
583 catch (InvalidCastException)
584 {
585 throw new InvalidCastException(string.Format("Error running rule WL_REFLECTION_WAVELET_SCALE: arg #{0} - parameter 1 must be vector", idx));
586 }
387 wl.reflectionWaveletScale = iV; 587 wl.reflectionWaveletScale = iV;
388 break; 588 break;
389 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: 589 case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE:
390 idx++; 590 idx++;
391 wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx); 591 try
592 {
593 wl.refractScaleAbove = (float)rules.GetLSLFloatItem(idx);
594 }
595 catch (InvalidCastException)
596 {
597 throw new InvalidCastException(string.Format("Error running rule WL_REFRACT_SCALE_ABOVE: arg #{0} - parameter 1 must be float", idx));
598 }
392 break; 599 break;
393 case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW: 600 case (int)ScriptBaseClass.WL_REFRACT_SCALE_BELOW:
394 idx++; 601 idx++;
395 wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx); 602 try
603 {
604 wl.refractScaleBelow = (float)rules.GetLSLFloatItem(idx);
605 }
606 catch (InvalidCastException)
607 {
608 throw new InvalidCastException(string.Format("Error running rule WL_REFRACT_SCALE_BELOW: arg #{0} - parameter 1 must be float", idx));
609 }
396 break; 610 break;
397 case (int)ScriptBaseClass.WL_SCENE_GAMMA: 611 case (int)ScriptBaseClass.WL_SCENE_GAMMA:
398 idx++; 612 idx++;
399 wl.sceneGamma = (float)rules.GetLSLFloatItem(idx); 613 try
614 {
615 wl.sceneGamma = (float)rules.GetLSLFloatItem(idx);
616 }
617 catch (InvalidCastException)
618 {
619 throw new InvalidCastException(string.Format("Error running rule WL_SCENE_GAMMA: arg #{0} - parameter 1 must be float", idx));
620 }
400 break; 621 break;
401 case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS: 622 case (int)ScriptBaseClass.WL_STAR_BRIGHTNESS:
402 idx++; 623 idx++;
403 wl.starBrightness = (float)rules.GetLSLFloatItem(idx); 624 try
625 {
626 wl.starBrightness = (float)rules.GetLSLFloatItem(idx);
627 }
628 catch (InvalidCastException)
629 {
630 throw new InvalidCastException(string.Format("Error running rule WL_STAR_BRIGHTNESS: arg #{0} - parameter 1 must be float", idx));
631 }
404 break; 632 break;
405 case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS: 633 case (int)ScriptBaseClass.WL_SUN_GLOW_FOCUS:
406 idx++; 634 idx++;
407 wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx); 635 try
636 {
637 wl.sunGlowFocus = (float)rules.GetLSLFloatItem(idx);
638 }
639 catch (InvalidCastException)
640 {
641 throw new InvalidCastException(string.Format("Error running rule WL_SUN_GLOW_FOCUS: arg #{0} - parameter 1 must be float", idx));
642 }
408 break; 643 break;
409 case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE: 644 case (int)ScriptBaseClass.WL_SUN_GLOW_SIZE:
410 idx++; 645 idx++;
411 wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx); 646 try
647 {
648 wl.sunGlowSize = (float)rules.GetLSLFloatItem(idx);
649 }
650 catch (InvalidCastException)
651 {
652 throw new InvalidCastException(string.Format("Error running rule WL_SUN_GLOW_SIZE: arg #{0} - parameter 1 must be float", idx));
653 }
412 break; 654 break;
413 case (int)ScriptBaseClass.WL_SUN_MOON_COLOR: 655 case (int)ScriptBaseClass.WL_SUN_MOON_COLOR:
414 idx++; 656 idx++;
415 iQ = rules.GetQuaternionItem(idx); 657 iQ = rules.GetQuaternionItem(idx);
416 wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s); 658 try
659 {
660 wl.sunMoonColor = new Vector4((float)iQ.x, (float)iQ.y, (float)iQ.z, (float)iQ.s);
661 }
662 catch (InvalidCastException)
663 {
664 throw new InvalidCastException(string.Format("Error running rule WL_SUN_MOON_COLOR: arg #{0} - parameter 1 must be rotation", idx));
665 }
417 break; 666 break;
418 case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER: 667 case (int)ScriptBaseClass.WL_UNDERWATER_FOG_MODIFIER:
419 idx++; 668 idx++;
420 wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx); 669 try
670 {
671 wl.underwaterFogModifier = (float)rules.GetLSLFloatItem(idx);
672 }
673 catch (InvalidCastException)
674 {
675 throw new InvalidCastException(string.Format("Error running rule WL_UNDERWATER_FOG_MODIFIER: arg #{0} - parameter 1 must be float", idx));
676 }
421 break; 677 break;
422 case (int)ScriptBaseClass.WL_WATER_COLOR: 678 case (int)ScriptBaseClass.WL_WATER_COLOR:
423 idx++; 679 idx++;
424 iV = rules.GetVector3Item(idx); 680 try
681 {
682 iV = rules.GetVector3Item(idx);
683 }
684 catch (InvalidCastException)
685 {
686 throw new InvalidCastException(string.Format("Error running rule WL_WATER_COLOR: arg #{0} - parameter 1 must be vector", idx));
687 }
425 wl.waterColor = iV; 688 wl.waterColor = iV;
426 break; 689 break;
427 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: 690 case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT:
428 idx++; 691 idx++;
429 wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx); 692 try
693 {
694 wl.waterFogDensityExponent = (float)rules.GetLSLFloatItem(idx);
695 }
696 catch (InvalidCastException)
697 {
698 throw new InvalidCastException(string.Format("Error running rule WL_WATER_FOG_DENSITY_EXPONENT: arg #{0} - parameter 1 must be float", idx));
699 }
430 break; 700 break;
431 } 701 }
432 idx++; 702 idx++;
433 } 703 }
434 return wl; 704 return wl;
435 } 705 }
706
436 /// <summary> 707 /// <summary>
437 /// Set the current Windlight scene 708 /// Set the current Windlight scene
438 /// </summary> 709 /// </summary>
@@ -445,16 +716,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
445 LSShoutError("LightShare functions are not enabled."); 716 LSShoutError("LightShare functions are not enabled.");
446 return 0; 717 return 0;
447 } 718 }
448 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 719
720 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
449 { 721 {
450 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 722 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
451 return 0; 723
724 if (sp == null || sp.GodLevel < 200)
725 {
726 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
727 return 0;
728 }
452 } 729 }
730
453 int success = 0; 731 int success = 0;
454 m_host.AddScriptLPS(1); 732 m_host.AddScriptLPS(1);
733
455 if (LightShareModule.EnableWindlight) 734 if (LightShareModule.EnableWindlight)
456 { 735 {
457 RegionLightShareData wl = getWindlightProfileFromRules(rules); 736 RegionLightShareData wl;
737 try
738 {
739 wl = getWindlightProfileFromRules(rules);
740 }
741 catch(InvalidCastException e)
742 {
743 LSShoutError(e.Message);
744 return 0;
745 }
458 wl.valid = true; 746 wl.valid = true;
459 m_host.ParentGroup.Scene.StoreWindlightProfile(wl); 747 m_host.ParentGroup.Scene.StoreWindlightProfile(wl);
460 success = 1; 748 success = 1;
@@ -464,8 +752,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
464 LSShoutError("Windlight module is disabled"); 752 LSShoutError("Windlight module is disabled");
465 return 0; 753 return 0;
466 } 754 }
755
467 return success; 756 return success;
468 } 757 }
758
469 public void lsClearWindlightScene() 759 public void lsClearWindlightScene()
470 { 760 {
471 if (!m_LSFunctionsEnabled) 761 if (!m_LSFunctionsEnabled)
@@ -473,17 +763,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
473 LSShoutError("LightShare functions are not enabled."); 763 LSShoutError("LightShare functions are not enabled.");
474 return; 764 return;
475 } 765 }
476 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 766
767 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
477 { 768 {
478 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); 769 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
479 return; 770
771 if (sp == null || sp.GodLevel < 200)
772 {
773 LSShoutError("lsSetWindlightScene can only be used by estate managers or owners.");
774 return;
775 }
480 } 776 }
481 777
482 m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false; 778 m_host.ParentGroup.Scene.RegionInfo.WindlightSettings.valid = false;
483 if (m_host.ParentGroup.Scene.SimulationDataService != null) 779 if (m_host.ParentGroup.Scene.SimulationDataService != null)
484 m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID); 780 m_host.ParentGroup.Scene.SimulationDataService.RemoveRegionWindlightSettings(m_host.ParentGroup.Scene.RegionInfo.RegionID);
781
485 m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile(); 782 m_host.ParentGroup.Scene.EventManager.TriggerOnSaveNewWindlightProfile();
486 } 783 }
784
487 /// <summary> 785 /// <summary>
488 /// Set the current Windlight scene to a target avatar 786 /// Set the current Windlight scene to a target avatar
489 /// </summary> 787 /// </summary>
@@ -496,16 +794,33 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
496 LSShoutError("LightShare functions are not enabled."); 794 LSShoutError("LightShare functions are not enabled.");
497 return 0; 795 return 0;
498 } 796 }
499 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) 797
798 if (!World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(m_host.OwnerID))
500 { 799 {
501 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); 800 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
502 return 0; 801
802 if (sp == null || sp.GodLevel < 200)
803 {
804 LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners.");
805 return 0;
806 }
503 } 807 }
808
504 int success = 0; 809 int success = 0;
505 m_host.AddScriptLPS(1); 810 m_host.AddScriptLPS(1);
811
506 if (LightShareModule.EnableWindlight) 812 if (LightShareModule.EnableWindlight)
507 { 813 {
508 RegionLightShareData wl = getWindlightProfileFromRules(rules); 814 RegionLightShareData wl;
815 try
816 {
817 wl = getWindlightProfileFromRules(rules);
818 }
819 catch(InvalidCastException e)
820 {
821 LSShoutError(e.Message);
822 return 0;
823 }
509 World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string)); 824 World.EventManager.TriggerOnSendNewWindlightProfileTargeted(wl, new UUID(target.m_string));
510 success = 1; 825 success = 1;
511 } 826 }
@@ -514,8 +829,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
514 LSShoutError("Windlight module is disabled"); 829 LSShoutError("Windlight module is disabled");
515 return 0; 830 return 0;
516 } 831 }
832
517 return success; 833 return success;
518 } 834 }
519
520 } 835 }
521} 836}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
index 8f34833..1458c95 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs
@@ -30,6 +30,8 @@ using System.Reflection;
30using System.Collections; 30using System.Collections;
31using System.Collections.Generic; 31using System.Collections.Generic;
32using System.Runtime.Remoting.Lifetime; 32using System.Runtime.Remoting.Lifetime;
33using System.Threading;
34using log4net;
33using OpenMetaverse; 35using OpenMetaverse;
34using Nini.Config; 36using Nini.Config;
35using OpenSim; 37using OpenSim;
@@ -55,15 +57,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
55 [Serializable] 57 [Serializable]
56 public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi 58 public class MOD_Api : MarshalByRefObject, IMOD_Api, IScriptApi
57 { 59 {
60// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
61
58 internal IScriptEngine m_ScriptEngine; 62 internal IScriptEngine m_ScriptEngine;
59 internal SceneObjectPart m_host; 63 internal SceneObjectPart m_host;
60 internal TaskInventoryItem m_item; 64 internal TaskInventoryItem m_item;
61 internal bool m_MODFunctionsEnabled = false; 65 internal bool m_MODFunctionsEnabled = false;
62 internal IScriptModuleComms m_comms = null; 66 internal IScriptModuleComms m_comms = null;
63 67
64 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 68 public void Initialize(
69 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
65 { 70 {
66 m_ScriptEngine = ScriptEngine; 71 m_ScriptEngine = scriptEngine;
67 m_host = host; 72 m_host = host;
68 m_item = item; 73 m_item = item;
69 74
@@ -107,8 +112,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
107 if (message.Length > 1023) 112 if (message.Length > 1023)
108 message = message.Substring(0, 1023); 113 message = message.Substring(0, 1023);
109 114
110 World.SimChat(Utils.StringToBytes(message), 115 World.SimChat(
111 ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); 116 Utils.StringToBytes(message),
117 ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL,
118 m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
112 119
113 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 120 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
114 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); 121 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
@@ -122,6 +129,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
122 /// <returns>string result of the invocation</returns> 129 /// <returns>string result of the invocation</returns>
123 public void modInvokeN(string fname, params object[] parms) 130 public void modInvokeN(string fname, params object[] parms)
124 { 131 {
132// m_log.DebugFormat(
133// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
134// fname,
135// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
136// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
137
125 Type returntype = m_comms.LookupReturnType(fname); 138 Type returntype = m_comms.LookupReturnType(fname);
126 if (returntype != typeof(string)) 139 if (returntype != typeof(string))
127 MODError(String.Format("return type mismatch for {0}",fname)); 140 MODError(String.Format("return type mismatch for {0}",fname));
@@ -131,6 +144,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
131 144
132 public LSL_String modInvokeS(string fname, params object[] parms) 145 public LSL_String modInvokeS(string fname, params object[] parms)
133 { 146 {
147// m_log.DebugFormat(
148// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
149// fname,
150// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
151// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
152
134 Type returntype = m_comms.LookupReturnType(fname); 153 Type returntype = m_comms.LookupReturnType(fname);
135 if (returntype != typeof(string)) 154 if (returntype != typeof(string))
136 MODError(String.Format("return type mismatch for {0}",fname)); 155 MODError(String.Format("return type mismatch for {0}",fname));
@@ -141,6 +160,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
141 160
142 public LSL_Integer modInvokeI(string fname, params object[] parms) 161 public LSL_Integer modInvokeI(string fname, params object[] parms)
143 { 162 {
163// m_log.DebugFormat(
164// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
165// fname,
166// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
167// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
168
144 Type returntype = m_comms.LookupReturnType(fname); 169 Type returntype = m_comms.LookupReturnType(fname);
145 if (returntype != typeof(int)) 170 if (returntype != typeof(int))
146 MODError(String.Format("return type mismatch for {0}",fname)); 171 MODError(String.Format("return type mismatch for {0}",fname));
@@ -151,6 +176,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
151 176
152 public LSL_Float modInvokeF(string fname, params object[] parms) 177 public LSL_Float modInvokeF(string fname, params object[] parms)
153 { 178 {
179// m_log.DebugFormat(
180// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
181// fname,
182// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
183// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
184
154 Type returntype = m_comms.LookupReturnType(fname); 185 Type returntype = m_comms.LookupReturnType(fname);
155 if (returntype != typeof(float)) 186 if (returntype != typeof(float))
156 MODError(String.Format("return type mismatch for {0}",fname)); 187 MODError(String.Format("return type mismatch for {0}",fname));
@@ -161,6 +192,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
161 192
162 public LSL_Key modInvokeK(string fname, params object[] parms) 193 public LSL_Key modInvokeK(string fname, params object[] parms)
163 { 194 {
195// m_log.DebugFormat(
196// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
197// fname,
198// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
199// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
200
164 Type returntype = m_comms.LookupReturnType(fname); 201 Type returntype = m_comms.LookupReturnType(fname);
165 if (returntype != typeof(UUID)) 202 if (returntype != typeof(UUID))
166 MODError(String.Format("return type mismatch for {0}",fname)); 203 MODError(String.Format("return type mismatch for {0}",fname));
@@ -171,6 +208,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
171 208
172 public LSL_Vector modInvokeV(string fname, params object[] parms) 209 public LSL_Vector modInvokeV(string fname, params object[] parms)
173 { 210 {
211// m_log.DebugFormat(
212// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
213// fname,
214// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
215// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
216
174 Type returntype = m_comms.LookupReturnType(fname); 217 Type returntype = m_comms.LookupReturnType(fname);
175 if (returntype != typeof(OpenMetaverse.Vector3)) 218 if (returntype != typeof(OpenMetaverse.Vector3))
176 MODError(String.Format("return type mismatch for {0}",fname)); 219 MODError(String.Format("return type mismatch for {0}",fname));
@@ -181,6 +224,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
181 224
182 public LSL_Rotation modInvokeR(string fname, params object[] parms) 225 public LSL_Rotation modInvokeR(string fname, params object[] parms)
183 { 226 {
227// m_log.DebugFormat(
228// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
229// fname,
230// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
231// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
232
184 Type returntype = m_comms.LookupReturnType(fname); 233 Type returntype = m_comms.LookupReturnType(fname);
185 if (returntype != typeof(OpenMetaverse.Quaternion)) 234 if (returntype != typeof(OpenMetaverse.Quaternion))
186 MODError(String.Format("return type mismatch for {0}",fname)); 235 MODError(String.Format("return type mismatch for {0}",fname));
@@ -191,6 +240,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
191 240
192 public LSL_List modInvokeL(string fname, params object[] parms) 241 public LSL_List modInvokeL(string fname, params object[] parms)
193 { 242 {
243// m_log.DebugFormat(
244// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
245// fname,
246// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
247// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
248
194 Type returntype = m_comms.LookupReturnType(fname); 249 Type returntype = m_comms.LookupReturnType(fname);
195 if (returntype != typeof(object[])) 250 if (returntype != typeof(object[]))
196 MODError(String.Format("return type mismatch for {0}",fname)); 251 MODError(String.Format("return type mismatch for {0}",fname));
@@ -211,6 +266,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
211 { 266 {
212 llist[i] = new LSL_Float((float)result[i]); 267 llist[i] = new LSL_Float((float)result[i]);
213 } 268 }
269 else if (result[i] is double)
270 {
271 llist[i] = new LSL_Float((double)result[i]);
272 }
214 else if (result[i] is UUID) 273 else if (result[i] is UUID)
215 { 274 {
216 llist[i] = new LSL_Key(result[i].ToString()); 275 llist[i] = new LSL_Key(result[i].ToString());
@@ -248,13 +307,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
248 return ""; 307 return "";
249 } 308 }
250 309
310// m_log.DebugFormat(
311// "[MOD API]: Invoking dynamic function {0}, args '{1}' with {2} return type",
312// fname,
313// string.Join(",", Array.ConvertAll<object, string>(parms, o => o.ToString())),
314// ((MethodInfo)MethodBase.GetCurrentMethod()).ReturnType);
315
251 Type[] signature = m_comms.LookupTypeSignature(fname); 316 Type[] signature = m_comms.LookupTypeSignature(fname);
252 if (signature.Length != parms.Length) 317 if (signature.Length != parms.Length)
253 MODError(String.Format("wrong number of parameters to function {0}",fname)); 318 MODError(String.Format("wrong number of parameters to function {0}",fname));
254 319
255 object[] convertedParms = new object[parms.Length]; 320 object[] convertedParms = new object[parms.Length];
256 for (int i = 0; i < parms.Length; i++) 321 for (int i = 0; i < parms.Length; i++)
257 convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); 322 convertedParms[i] = ConvertFromLSL(parms[i], signature[i], fname);
258 323
259 // now call the function, the contract with the function is that it will always return 324 // now call the function, the contract with the function is that it will always return
260 // non-null but don't trust it completely 325 // non-null but don't trust it completely
@@ -351,7 +416,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
351 { 416 {
352 if (type == typeof(object[])) 417 if (type == typeof(object[]))
353 { 418 {
354 object[] plist = (lslparm as LSL_List).Data; 419 object[] plist = ((LSL_List)lslparm).Data;
355 object[] result = new object[plist.Length]; 420 object[] result = new object[plist.Length];
356 for (int i = 0; i < plist.Length; i++) 421 for (int i = 0; i < plist.Length; i++)
357 { 422 {
@@ -379,7 +444,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
379 } 444 }
380 } 445 }
381 446
382 MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); 447 MODError(String.Format("{0}: parameter type mismatch; expecting {1}, type(parm)={2}", fname, type.Name, lslparm.GetType()));
383 return null; 448 return null;
384 } 449 }
385 450
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index dcc85c4..e799714 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -62,6 +62,8 @@ using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
62using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; 62using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
63using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 63using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
64using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 64using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
65using PermissionMask = OpenSim.Framework.PermissionMask;
66using OpenSim.Services.Connectors.Hypergrid;
65 67
66namespace OpenSim.Region.ScriptEngine.Shared.Api 68namespace OpenSim.Region.ScriptEngine.Shared.Api
67{ 69{
@@ -142,16 +144,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
142 144
143 protected IUrlModule m_UrlModule = null; 145 protected IUrlModule m_UrlModule = null;
144 146
145 public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) 147 public void Initialize(
148 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item)
146 { 149 {
147 m_ScriptEngine = ScriptEngine; 150 m_ScriptEngine = scriptEngine;
148 m_host = host; 151 m_host = host;
149 m_item = item; 152 m_item = item;
150 153
151 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 154 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
152 155
153 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) 156 if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false))
157 {
154 m_OSFunctionsEnabled = true; 158 m_OSFunctionsEnabled = true;
159 // m_log.Warn("[OSSL] OSSL FUNCTIONS ENABLED");
160 }
155 161
156 m_ScriptDelayFactor = 162 m_ScriptDelayFactor =
157 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); 163 m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f);
@@ -245,11 +251,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
245 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); 251 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message);
246 } 252 }
247 253
254 // Returns of the function is allowed. Throws a script exception if not allowed.
248 public void CheckThreatLevel(ThreatLevel level, string function) 255 public void CheckThreatLevel(ThreatLevel level, string function)
249 { 256 {
250 if (!m_OSFunctionsEnabled) 257 if (!m_OSFunctionsEnabled)
251 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws 258 OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws
252 259
260 string reasonWhyNot = CheckThreatLevelTest(level, function);
261 if (!String.IsNullOrEmpty(reasonWhyNot))
262 {
263 OSSLError(reasonWhyNot);
264 }
265 }
266
267 // Check to see if function is allowed. Returns an empty string if function permitted
268 // or a string explaining why this function can't be used.
269 private string CheckThreatLevelTest(ThreatLevel level, string function)
270 {
253 if (!m_FunctionPerms.ContainsKey(function)) 271 if (!m_FunctionPerms.ContainsKey(function))
254 { 272 {
255 FunctionPerms perms = new FunctionPerms(); 273 FunctionPerms perms = new FunctionPerms();
@@ -329,10 +347,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
329 { 347 {
330 // Allow / disallow by threat level 348 // Allow / disallow by threat level
331 if (level > m_MaxThreatLevel) 349 if (level > m_MaxThreatLevel)
332 OSSLError( 350 return
333 String.Format( 351 String.Format(
334 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.", 352 "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.",
335 function, m_MaxThreatLevel, level)); 353 function, m_MaxThreatLevel, level);
336 } 354 }
337 else 355 else
338 { 356 {
@@ -342,7 +360,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
342 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID)) 360 if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID))
343 { 361 {
344 // prim owner is in the list of allowed owners 362 // prim owner is in the list of allowed owners
345 return; 363 return String.Empty;
346 } 364 }
347 365
348 UUID ownerID = m_item.OwnerID; 366 UUID ownerID = m_item.OwnerID;
@@ -350,22 +368,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
350 //OSSL only may be used if object is in the same group as the parcel 368 //OSSL only may be used if object is in the same group as the parcel
351 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER")) 369 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER"))
352 { 370 {
353 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 371 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
354 372
355 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) 373 if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero)
356 { 374 {
357 return; 375 return String.Empty;
358 } 376 }
359 } 377 }
360 378
361 //Only Parcelowners may use the function 379 //Only Parcelowners may use the function
362 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_OWNER")) 380 if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_OWNER"))
363 { 381 {
364 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 382 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
365 383
366 if (land.LandData.OwnerID == ownerID) 384 if (land.LandData.OwnerID == ownerID)
367 { 385 {
368 return; 386 return String.Empty;
369 } 387 }
370 } 388 }
371 389
@@ -375,7 +393,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
375 //Only Estate Managers may use the function 393 //Only Estate Managers may use the function
376 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) 394 if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID)
377 { 395 {
378 return; 396 return String.Empty;
379 } 397 }
380 } 398 }
381 399
@@ -384,25 +402,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
384 { 402 {
385 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID) 403 if (World.RegionInfo.EstateSettings.EstateOwner == ownerID)
386 { 404 {
387 return; 405 return String.Empty;
388 } 406 }
389 } 407 }
390 408
391 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) 409 if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID))
392 OSSLError( 410 return(
393 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", 411 String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.",
394 function)); 412 function));
395 413
396 if (m_item.CreatorID != ownerID) 414 if (m_item.CreatorID != ownerID)
397 { 415 {
398 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0) 416 if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0)
399 OSSLError( 417 return String.Format("{0} permission denied. Script permissions error.", function);
400 String.Format("{0} permission denied. Script permissions error.",
401 function));
402 418
403 } 419 }
404 } 420 }
405 } 421 }
422 return String.Empty;
406 } 423 }
407 424
408 internal void OSSLDeprecated(string function, string replacement) 425 internal void OSSLDeprecated(string function, string replacement)
@@ -437,7 +454,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
437 { 454 {
438 m_host.AddScriptLPS(1); 455 m_host.AddScriptLPS(1);
439 456
440 if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0) 457 if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
441 OSSLError("osSetTerrainHeight: Coordinate out of bounds"); 458 OSSLError("osSetTerrainHeight: Coordinate out of bounds");
442 459
443 if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0))) 460 if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0)))
@@ -467,7 +484,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
467 private LSL_Float GetTerrainHeight(int x, int y) 484 private LSL_Float GetTerrainHeight(int x, int y)
468 { 485 {
469 m_host.AddScriptLPS(1); 486 m_host.AddScriptLPS(1);
470 if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0) 487 if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0)
471 OSSLError("osGetTerrainHeight: Coordinate out of bounds"); 488 OSSLError("osGetTerrainHeight: Coordinate out of bounds");
472 489
473 return World.Heightmap[x, y]; 490 return World.Heightmap[x, y];
@@ -777,9 +794,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
777 794
778 // We will launch the teleport on a new thread so that when the script threads are terminated 795 // We will launch the teleport on a new thread so that when the script threads are terminated
779 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 796 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
780 Util.FireAndForget(o => World.RequestTeleportLocation( 797 Util.FireAndForget(
781 presence.ControllingClient, regionName, position, 798 o => World.RequestTeleportLocation(
782 lookat, (uint)TPFlags.ViaLocation)); 799 presence.ControllingClient, regionName, position,
800 lookat, (uint)TPFlags.ViaLocation),
801 null, "OSSL_Api.TeleportAgentByRegionCoords");
783 802
784 ScriptSleep(5000); 803 ScriptSleep(5000);
785 804
@@ -801,7 +820,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
801 private void TeleportAgent(string agent, int regionX, int regionY, 820 private void TeleportAgent(string agent, int regionX, int regionY,
802 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) 821 LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions)
803 { 822 {
804 ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize)); 823 // ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize));
824 ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY);
805 825
806 m_host.AddScriptLPS(1); 826 m_host.AddScriptLPS(1);
807 UUID agentId = new UUID(); 827 UUID agentId = new UUID();
@@ -822,9 +842,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
822 842
823 // We will launch the teleport on a new thread so that when the script threads are terminated 843 // We will launch the teleport on a new thread so that when the script threads are terminated
824 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. 844 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
825 Util.FireAndForget(o => World.RequestTeleportLocation( 845 Util.FireAndForget(
826 presence.ControllingClient, regionHandle, 846 o => World.RequestTeleportLocation(
827 position, lookat, (uint)TPFlags.ViaLocation)); 847 presence.ControllingClient, regionHandle,
848 position, lookat, (uint)TPFlags.ViaLocation),
849 null, "OSSL_Api.TeleportAgentByRegionName");
828 850
829 ScriptSleep(5000); 851 ScriptSleep(5000);
830 852
@@ -859,6 +881,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
859 TeleportAgent(m_host.OwnerID.ToString(), regionX, regionY, position, lookat, true); 881 TeleportAgent(m_host.OwnerID.ToString(), regionX, regionY, position, lookat, true);
860 } 882 }
861 883
884 ///<summary>
885 /// Allows a script IN the target prim to force an avatar to sit on it using normal methods
886 /// as if called by the client.
887 /// Silent fail if agent (or target if overloaded) not found.
888 /// Does work if passed key (or keys if overloaded).
889 /// </summary>
890 /// <param name="avatar"></param>
891 public void osForceOtherSit(string avatar)
892 {
893 CheckThreatLevel(ThreatLevel.VeryHigh, "osForceOtherSit");
894
895 m_host.AddScriptLPS(1);
896
897 ForceSit(avatar, m_host.UUID);
898 }
899
900 /// <summary>
901 /// Overload method of osForceOtherSit(string avatar) to allow a script NOT in the target prim to force
902 /// an avatar to sit on the target prim using normal methods as if called by the client.
903 /// </summary>
904 /// <param name="avatar"></param>
905 /// <param name="target"></param>
906 public void osForceOtherSit(string avatar, string target)
907 {
908 CheckThreatLevel(ThreatLevel.VeryHigh, "osForceOtherSit");
909
910 m_host.AddScriptLPS(1);
911
912 UUID targetID = new UUID(target);
913
914 ForceSit(avatar, targetID);
915 }
916
917 public void ForceSit(string avatar, UUID targetID)
918 {
919 UUID agentID;
920
921 if (!UUID.TryParse(avatar, out agentID))
922 return;
923
924 ScenePresence presence = World.GetScenePresence(agentID);
925
926 SceneObjectPart part = World.GetSceneObjectPart(targetID);
927
928 if (presence != null &&
929 part != null &&
930 part.SitTargetAvatar == UUID.Zero)
931 presence.HandleAgentRequestSit(presence.ControllingClient,
932 agentID,
933 targetID,
934 part.SitTargetPosition);
935 }
936
862 // Functions that get information from the agent itself. 937 // Functions that get information from the agent itself.
863 // 938 //
864 // osGetAgentIP - this is used to determine the IP address of 939 // osGetAgentIP - this is used to determine the IP address of
@@ -1205,12 +1280,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1205 sunHour += 24.0; 1280 sunHour += 24.0;
1206 1281
1207 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun; 1282 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun;
1208 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30 1283 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30
1209 World.RegionInfo.RegionSettings.FixedSun = sunFixed; 1284 World.RegionInfo.RegionSettings.FixedSun = sunFixed;
1210 World.RegionInfo.RegionSettings.Save(); 1285 World.RegionInfo.RegionSettings.Save();
1211 1286
1212 World.EventManager.TriggerEstateToolsSunUpdate( 1287 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1213 World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour);
1214 } 1288 }
1215 1289
1216 /// <summary> 1290 /// <summary>
@@ -1233,10 +1307,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1233 World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed; 1307 World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed;
1234 World.RegionInfo.EstateSettings.SunPosition = sunHour; 1308 World.RegionInfo.EstateSettings.SunPosition = sunHour;
1235 World.RegionInfo.EstateSettings.FixedSun = sunFixed; 1309 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1236 World.RegionInfo.EstateSettings.Save(); 1310 World.EstateDataService.StoreEstateSettings(World.RegionInfo.EstateSettings);
1237 1311
1238 World.EventManager.TriggerEstateToolsSunUpdate( 1312 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1239 World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour);
1240 } 1313 }
1241 1314
1242 /// <summary> 1315 /// <summary>
@@ -1492,8 +1565,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1492 1565
1493 m_host.AddScriptLPS(1); 1566 m_host.AddScriptLPS(1);
1494 1567
1495 ILandObject land 1568 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
1496 = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
1497 1569
1498 if (land.LandData.OwnerID != m_host.OwnerID) 1570 if (land.LandData.OwnerID != m_host.OwnerID)
1499 return; 1571 return;
@@ -1509,8 +1581,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1509 1581
1510 m_host.AddScriptLPS(1); 1582 m_host.AddScriptLPS(1);
1511 1583
1512 ILandObject land 1584 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
1513 = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
1514 1585
1515 if (land.LandData.OwnerID != m_host.OwnerID) 1586 if (land.LandData.OwnerID != m_host.OwnerID)
1516 { 1587 {
@@ -1560,6 +1631,47 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1560 } 1631 }
1561 } 1632 }
1562 1633
1634 public LSL_Integer osCheckODE()
1635 {
1636 m_host.AddScriptLPS(1);
1637 LSL_Integer ret = 0; // false
1638 if (m_ScriptEngine.World.PhysicsScene != null)
1639 {
1640 string physEngine = m_ScriptEngine.World.PhysicsScene.EngineType;
1641 if (physEngine == "OpenDynamicsEngine")
1642 {
1643 ret = 1; // true
1644 }
1645 }
1646 return ret;
1647 }
1648
1649 public string osGetPhysicsEngineType()
1650 {
1651 // High because it can be used to target attacks to known weaknesses
1652 // This would allow a new class of griefer scripts that don't even
1653 // require their user to know what they are doing (see script
1654 // kiddie)
1655 // Because it would be nice if scripts didn't blow up if the information
1656 // about the physics engine, this function returns an empty string if
1657 // the user does not have permission to see it. This as opposed to
1658 // throwing an exception.
1659 m_host.AddScriptLPS(1);
1660 string ret = String.Empty;
1661 if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType")))
1662 {
1663 if (m_ScriptEngine.World.PhysicsScene != null)
1664 {
1665 ret = m_ScriptEngine.World.PhysicsScene.EngineType;
1666 // An old physics engine might have an uninitialized engine type
1667 if (ret == null)
1668 ret = "unknown";
1669 }
1670 }
1671
1672 return ret;
1673 }
1674
1563 public string osGetSimulatorVersion() 1675 public string osGetSimulatorVersion()
1564 { 1676 {
1565 // High because it can be used to target attacks to known weaknesses 1677 // High because it can be used to target attacks to known weaknesses
@@ -1732,13 +1844,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1732 // Create new asset 1844 // Create new asset
1733 AssetBase asset = new AssetBase(UUID.Random(), name, (sbyte)AssetType.Notecard, m_host.OwnerID.ToString()); 1845 AssetBase asset = new AssetBase(UUID.Random(), name, (sbyte)AssetType.Notecard, m_host.OwnerID.ToString());
1734 asset.Description = description; 1846 asset.Description = description;
1847 byte[] a;
1848 byte[] b;
1849 byte[] c;
1850
1851 b = Util.UTF8.GetBytes(data);
1735 1852
1736 int textLength = data.Length; 1853 a = Util.UTF8.GetBytes(
1737 data 1854 "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length " + b.Length.ToString() + "\n");
1738 = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length "
1739 + textLength.ToString() + "\n" + data + "}\n";
1740 1855
1741 asset.Data = Util.UTF8.GetBytes(data); 1856 c = Util.UTF8.GetBytes("}");
1857
1858 byte[] d = new byte[a.Length + b.Length + c.Length];
1859 Buffer.BlockCopy(a, 0, d, 0, a.Length);
1860 Buffer.BlockCopy(b, 0, d, a.Length, b.Length);
1861 Buffer.BlockCopy(c, 0, d, a.Length + b.Length, c.Length);
1862
1863 asset.Data = d;
1742 World.AssetService.Store(asset); 1864 World.AssetService.Store(asset);
1743 1865
1744 // Create Task Entry 1866 // Create Task Entry
@@ -1753,8 +1875,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1753 taskItem.InvType = (int)InventoryType.Notecard; 1875 taskItem.InvType = (int)InventoryType.Notecard;
1754 taskItem.OwnerID = m_host.OwnerID; 1876 taskItem.OwnerID = m_host.OwnerID;
1755 taskItem.CreatorID = m_host.OwnerID; 1877 taskItem.CreatorID = m_host.OwnerID;
1756 taskItem.BasePermissions = (uint)PermissionMask.All; 1878 taskItem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1757 taskItem.CurrentPermissions = (uint)PermissionMask.All; 1879 taskItem.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export;
1758 taskItem.EveryonePermissions = 0; 1880 taskItem.EveryonePermissions = 0;
1759 taskItem.NextPermissions = (uint)PermissionMask.All; 1881 taskItem.NextPermissions = (uint)PermissionMask.All;
1760 taskItem.GroupID = m_host.GroupID; 1882 taskItem.GroupID = m_host.GroupID;
@@ -1833,8 +1955,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1833 if (a == null) 1955 if (a == null)
1834 return UUID.Zero; 1956 return UUID.Zero;
1835 1957
1836 string data = Encoding.UTF8.GetString(a.Data); 1958 NotecardCache.Cache(assetID, a.Data);
1837 NotecardCache.Cache(assetID, data);
1838 }; 1959 };
1839 1960
1840 return assetID; 1961 return assetID;
@@ -1932,15 +2053,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1932 CheckThreatLevel(ThreatLevel.Low, "osAvatarName2Key"); 2053 CheckThreatLevel(ThreatLevel.Low, "osAvatarName2Key");
1933 m_host.AddScriptLPS(1); 2054 m_host.AddScriptLPS(1);
1934 2055
1935 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, firstname, lastname); 2056 IUserManagement userManager = World.RequestModuleInterface<IUserManagement>();
1936 if (null == account) 2057 if (userManager == null)
1937 { 2058 {
1938 return UUID.Zero.ToString(); 2059 OSSLShoutError("osAvatarName2Key: UserManagement module not available");
2060 return string.Empty;
2061 }
2062
2063 // Check if the user is already cached
2064
2065 UUID userID = userManager.GetUserIdByName(firstname, lastname);
2066 if (userID != UUID.Zero)
2067 return userID.ToString();
2068
2069 // Query for the user
2070
2071 String realFirstName; String realLastName; String serverURI;
2072 if (Util.ParseForeignAvatarName(firstname, lastname, out realFirstName, out realLastName, out serverURI))
2073 {
2074 try
2075 {
2076 UserAgentServiceConnector userConnection = new UserAgentServiceConnector(serverURI, true);
2077
2078 if (userConnection != null)
2079 {
2080 userID = userConnection.GetUUID(realFirstName, realLastName);
2081 if (userID != UUID.Zero)
2082 {
2083 userManager.AddUser(userID, realFirstName, realLastName, serverURI);
2084 return userID.ToString();
2085 }
2086 }
2087 }
2088 catch (Exception /*e*/)
2089 {
2090 // m_log.Warn("[osAvatarName2Key] UserAgentServiceConnector - Unable to connect to destination grid ", e);
2091 }
1939 } 2092 }
1940 else 2093 else
1941 { 2094 {
1942 return account.PrincipalID.ToString(); 2095 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, firstname, lastname);
2096 if (account != null)
2097 return account.PrincipalID.ToString();
1943 } 2098 }
2099
2100 return UUID.Zero.ToString();
1944 } 2101 }
1945 2102
1946 public string osKey2Name(string id) 2103 public string osKey2Name(string id)
@@ -1953,19 +2110,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1953 if (UUID.TryParse(id, out key)) 2110 if (UUID.TryParse(id, out key))
1954 { 2111 {
1955 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, key); 2112 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, key);
1956 if (null == account) 2113 if (account != null)
1957 {
1958 return "";
1959 }
1960 else
1961 {
1962 return account.Name; 2114 return account.Name;
2115
2116 if (m_ScriptEngine.World.GridUserService != null)
2117 {
2118 GridUserInfo uInfo = m_ScriptEngine.World.GridUserService.GetGridUserInfo(key.ToString());
2119
2120 if (uInfo != null)
2121 {
2122 UUID userUUID; String gridURL; String firstName; String lastName; String tmp;
2123
2124 if (Util.ParseUniversalUserIdentifier(uInfo.UserID, out userUUID, out gridURL, out firstName, out lastName, out tmp))
2125 {
2126 string grid = new Uri(gridURL).Authority;
2127 return firstName + "." + lastName + " @" + grid;
2128 }
2129 }
1963 } 2130 }
1964 } 2131 }
1965 else 2132
1966 { 2133 return "";
1967 return "";
1968 }
1969 } 2134 }
1970 2135
1971 private enum InfoType 2136 private enum InfoType
@@ -2101,9 +2266,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2101 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI"); 2266 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI");
2102 m_host.AddScriptLPS(1); 2267 m_host.AddScriptLPS(1);
2103 2268
2104 string HomeURI = String.Empty;
2105 IConfigSource config = m_ScriptEngine.ConfigSource; 2269 IConfigSource config = m_ScriptEngine.ConfigSource;
2270 string HomeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI",
2271 new string[] { "Startup", "Hypergrid" }, String.Empty);
2106 2272
2273 if (!string.IsNullOrEmpty(HomeURI))
2274 return HomeURI;
2275
2276 // Legacy. Remove soon!
2107 if (config.Configs["LoginService"] != null) 2277 if (config.Configs["LoginService"] != null)
2108 HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI); 2278 HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI);
2109 2279
@@ -2118,9 +2288,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2118 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI"); 2288 CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI");
2119 m_host.AddScriptLPS(1); 2289 m_host.AddScriptLPS(1);
2120 2290
2121 string gatekeeperURI = String.Empty;
2122 IConfigSource config = m_ScriptEngine.ConfigSource; 2291 IConfigSource config = m_ScriptEngine.ConfigSource;
2292 string gatekeeperURI = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI",
2293 new string[] { "Startup", "Hypergrid" }, String.Empty);
2294
2295 if (!string.IsNullOrEmpty(gatekeeperURI))
2296 return gatekeeperURI;
2123 2297
2298 // Legacy. Remove soon!
2124 if (config.Configs["GridService"] != null) 2299 if (config.Configs["GridService"] != null)
2125 gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI); 2300 gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI);
2126 2301
@@ -2144,6 +2319,39 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2144 return retval; 2319 return retval;
2145 } 2320 }
2146 2321
2322 public string osGetAvatarHomeURI(string uuid)
2323 {
2324 CheckThreatLevel(ThreatLevel.Low, "osGetAvatarHomeURI");
2325 m_host.AddScriptLPS(1);
2326
2327 IUserManagement userManager = m_ScriptEngine.World.RequestModuleInterface<IUserManagement>();
2328 string returnValue = "";
2329
2330 if (userManager != null)
2331 {
2332 returnValue = userManager.GetUserServerURL(new UUID(uuid), "HomeURI");
2333 }
2334
2335 if (returnValue == "")
2336 {
2337 IConfigSource config = m_ScriptEngine.ConfigSource;
2338 returnValue = Util.GetConfigVarFromSections<string>(config, "HomeURI",
2339 new string[] { "Startup", "Hypergrid" }, String.Empty);
2340
2341 if (!string.IsNullOrEmpty(returnValue))
2342 return returnValue;
2343
2344 // Legacy. Remove soon!
2345 if (config.Configs["LoginService"] != null)
2346 returnValue = config.Configs["LoginService"].GetString("SRV_HomeURI", returnValue);
2347
2348 if (String.IsNullOrEmpty(returnValue))
2349 returnValue = GridUserInfo(InfoType.Home);
2350 }
2351
2352 return returnValue;
2353 }
2354
2147 public LSL_String osFormatString(string str, LSL_List strings) 2355 public LSL_String osFormatString(string str, LSL_List strings)
2148 { 2356 {
2149 CheckThreatLevel(ThreatLevel.VeryLow, "osFormatString"); 2357 CheckThreatLevel(ThreatLevel.VeryLow, "osFormatString");
@@ -2265,14 +2473,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2265 // on the ILSL_Api interface. 2473 // on the ILSL_Api interface.
2266 LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; 2474 LSL_Api LSL_Api = (LSL_Api)m_LSL_Api;
2267 LSL_List retVal = new LSL_List(); 2475 LSL_List retVal = new LSL_List();
2268 LSL_List remaining = null; 2476 LSL_List remaining = new LSL_List();
2269 List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber); 2477 List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber);
2270 foreach (SceneObjectPart part in parts) 2478 foreach (SceneObjectPart part in parts)
2271 { 2479 {
2272 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); 2480 remaining = LSL_Api.GetPrimParams(part, rules, ref retVal);
2273 } 2481 }
2274 2482
2275 while (remaining != null && remaining.Length > 2) 2483 while (remaining.Length > 2)
2276 { 2484 {
2277 linknumber = remaining.GetLSLIntegerItem(0); 2485 linknumber = remaining.GetLSLIntegerItem(0);
2278 rules = remaining.GetSublist(1, -1); 2486 rules = remaining.GetSublist(1, -1);
@@ -2284,6 +2492,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2284 return retVal; 2492 return retVal;
2285 } 2493 }
2286 2494
2495 public void osForceCreateLink(string target, int parent)
2496 {
2497 CheckThreatLevel(ThreatLevel.VeryLow, "osForceCreateLink");
2498
2499 m_host.AddScriptLPS(1);
2500
2501 InitLSL();
2502 ((LSL_Api)m_LSL_Api).CreateLink(target, parent);
2503 }
2504
2505 public void osForceBreakLink(int linknum)
2506 {
2507 CheckThreatLevel(ThreatLevel.VeryLow, "osForceBreakLink");
2508
2509 m_host.AddScriptLPS(1);
2510
2511 InitLSL();
2512 ((LSL_Api)m_LSL_Api).BreakLink(linknum);
2513 }
2514
2515 public void osForceBreakAllLinks()
2516 {
2517 CheckThreatLevel(ThreatLevel.VeryLow, "osForceBreakAllLinks");
2518
2519 m_host.AddScriptLPS(1);
2520
2521 InitLSL();
2522 ((LSL_Api)m_LSL_Api).BreakAllLinks();
2523 }
2524
2287 public LSL_Integer osIsNpc(LSL_Key npc) 2525 public LSL_Integer osIsNpc(LSL_Key npc)
2288 { 2526 {
2289 CheckThreatLevel(ThreatLevel.None, "osIsNpc"); 2527 CheckThreatLevel(ThreatLevel.None, "osIsNpc");
@@ -2469,13 +2707,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2469 ScenePresence sp = World.GetScenePresence(npcId); 2707 ScenePresence sp = World.GetScenePresence(npcId);
2470 2708
2471 if (sp != null) 2709 if (sp != null)
2472 { 2710 return new LSL_Vector(sp.AbsolutePosition);
2473 Vector3 pos = sp.AbsolutePosition;
2474 return new LSL_Vector(pos.X, pos.Y, pos.Z);
2475 }
2476 } 2711 }
2477 2712
2478 return new LSL_Vector(0, 0, 0); 2713 return Vector3.Zero;
2479 } 2714 }
2480 2715
2481 public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) 2716 public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos)
@@ -2532,21 +2767,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2532 { 2767 {
2533 UUID npcId; 2768 UUID npcId;
2534 if (!UUID.TryParse(npc.m_string, out npcId)) 2769 if (!UUID.TryParse(npc.m_string, out npcId))
2535 return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); 2770 return new LSL_Rotation(Quaternion.Identity);
2536 2771
2537 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) 2772 if (!npcModule.CheckPermissions(npcId, m_host.OwnerID))
2538 return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); 2773 return new LSL_Rotation(Quaternion.Identity);
2539 2774
2540 ScenePresence sp = World.GetScenePresence(npcId); 2775 ScenePresence sp = World.GetScenePresence(npcId);
2541 2776
2542 if (sp != null) 2777 if (sp != null)
2543 { 2778 return new LSL_Rotation(sp.GetWorldRotation());
2544 Quaternion rot = sp.Rotation;
2545 return new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W);
2546 }
2547 } 2779 }
2548 2780
2549 return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); 2781 return Quaternion.Identity;
2550 } 2782 }
2551 2783
2552 public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation) 2784 public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation)
@@ -2824,6 +3056,51 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2824 3056
2825 return SaveAppearanceToNotecard(avatarId, notecard); 3057 return SaveAppearanceToNotecard(avatarId, notecard);
2826 } 3058 }
3059
3060 /// <summary>
3061 /// Get the gender as specified in avatar appearance for a given avatar key
3062 /// </summary>
3063 /// <param name="rawAvatarId"></param>
3064 /// <returns>"male" or "female" or "unknown"</returns>
3065 public LSL_String osGetGender(LSL_Key rawAvatarId)
3066 {
3067 CheckThreatLevel(ThreatLevel.None, "osGetGender");
3068 m_host.AddScriptLPS(1);
3069
3070 UUID avatarId;
3071 if (!UUID.TryParse(rawAvatarId, out avatarId))
3072 return new LSL_String("unknown");
3073
3074 ScenePresence sp = World.GetScenePresence(avatarId);
3075
3076 if (sp == null || sp.IsChildAgent || sp.Appearance == null || sp.Appearance.VisualParams == null)
3077 return new LSL_String("unknown");
3078
3079 // find the index of "shape" parameter "male"
3080 int vpShapeMaleIndex = 0;
3081 bool indexFound = false;
3082 VisualParam param = new VisualParam();
3083 foreach(var vpEntry in VisualParams.Params)
3084 {
3085 param = vpEntry.Value;
3086 if (param.Name == "male" && param.Wearable == "shape")
3087 {
3088 indexFound = true;
3089 break;
3090 }
3091
3092 if (param.Group == 0)
3093 vpShapeMaleIndex++;
3094 }
3095
3096 if (!indexFound)
3097 return new LSL_String("unknown");
3098
3099 float vpShapeMale = Utils.ByteToFloat(sp.Appearance.VisualParams[vpShapeMaleIndex], param.MinValue, param.MaxValue);
3100
3101 bool isMale = vpShapeMale > 0.5f;
3102 return new LSL_String(isMale ? "male" : "female");
3103 }
2827 3104
2828 /// <summary> 3105 /// <summary>
2829 /// Get current region's map texture UUID 3106 /// Get current region's map texture UUID
@@ -2887,6 +3164,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2887 return ret; 3164 return ret;
2888 } 3165 }
2889 3166
3167 public LSL_Vector osGetRegionSize()
3168 {
3169 CheckThreatLevel(ThreatLevel.None, "osGetRegionSize");
3170 m_host.AddScriptLPS(1);
3171
3172 bool isMegaregion;
3173 IRegionCombinerModule rcMod = World.RequestModuleInterface<IRegionCombinerModule>();
3174 if (rcMod != null)
3175 isMegaregion = rcMod.IsRootForMegaregion(World.RegionInfo.RegionID);
3176 else
3177 isMegaregion = false;
3178
3179 if (isMegaregion)
3180 {
3181 Vector2 size = rcMod.GetSizeOfMegaregion(World.RegionInfo.RegionID);
3182 return new LSL_Vector(size.X, size.Y, Constants.RegionHeight);
3183 }
3184 else
3185 {
3186 Scene scene = m_ScriptEngine.World;
3187 GridRegion region = scene.GridService.GetRegionByUUID(UUID.Zero, World.RegionInfo.RegionID);
3188 return new LSL_Vector((float)region.RegionSizeX, (float)region.RegionSizeX, Constants.RegionHeight);
3189 }
3190 }
3191
2890 public int osGetSimulatorMemory() 3192 public int osGetSimulatorMemory()
2891 { 3193 {
2892 CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory"); 3194 CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory");
@@ -2925,7 +3227,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2925 sp.ControllingClient.Kick(alert); 3227 sp.ControllingClient.Kick(alert);
2926 3228
2927 // ...and close on our side 3229 // ...and close on our side
2928 sp.Scene.IncomingCloseAgent(sp.UUID, false); 3230 sp.Scene.CloseAgent(sp.UUID, false);
2929 } 3231 }
2930 }); 3232 });
2931 } 3233 }
@@ -2976,20 +3278,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2976 3278
2977 UUID avatarId = new UUID(avatar); 3279 UUID avatarId = new UUID(avatar);
2978 ScenePresence presence = World.GetScenePresence(avatarId); 3280 ScenePresence presence = World.GetScenePresence(avatarId);
2979 Vector3 pos = m_host.GetWorldPosition(); 3281
2980 bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.X, (float)pos.Y, (float)pos.Z)); 3282 if (presence != null && World.ScriptDanger(m_host.LocalId, m_host.GetWorldPosition()))
2981 if (result)
2982 { 3283 {
2983 if (presence != null) 3284 float health = presence.Health;
2984 { 3285 health += (float)healing;
2985 float health = presence.Health; 3286
2986 health += (float)healing; 3287 if (health >= 100)
2987 if (health >= 100) 3288 health = 100;
2988 { 3289
2989 health = 100; 3290 presence.setHealthWithUpdate(health);
2990 }
2991 presence.setHealthWithUpdate(health);
2992 }
2993 } 3291 }
2994 } 3292 }
2995 3293
@@ -3066,8 +3364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3066 if (avatar != null && avatar.UUID != m_host.OwnerID) 3364 if (avatar != null && avatar.UUID != m_host.OwnerID)
3067 { 3365 {
3068 result.Add(new LSL_String(avatar.UUID.ToString())); 3366 result.Add(new LSL_String(avatar.UUID.ToString()));
3069 OpenMetaverse.Vector3 ap = avatar.AbsolutePosition; 3367 result.Add(new LSL_Vector(avatar.AbsolutePosition));
3070 result.Add(new LSL_Vector(ap.X, ap.Y, ap.Z));
3071 result.Add(new LSL_String(avatar.Name)); 3368 result.Add(new LSL_String(avatar.Name));
3072 } 3369 }
3073 }); 3370 });
@@ -3263,7 +3560,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3263 3560
3264 public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint) 3561 public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint)
3265 { 3562 {
3266 CheckThreatLevel(ThreatLevel.Severe, "osForceAttachToOtherAvatarFromInventory"); 3563 CheckThreatLevel(ThreatLevel.VeryHigh, "osForceAttachToOtherAvatarFromInventory");
3267 3564
3268 m_host.AddScriptLPS(1); 3565 m_host.AddScriptLPS(1);
3269 3566
@@ -3307,14 +3604,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3307 if (sp == null) 3604 if (sp == null)
3308 return; 3605 return;
3309 3606
3310 InventoryItemBase newItem = World.MoveTaskInventoryItem(sp.UUID, UUID.Zero, m_host, item.ItemID); 3607 string message;
3608 InventoryItemBase newItem = World.MoveTaskInventoryItem(sp.UUID, UUID.Zero, m_host, item.ItemID, out message);
3311 3609
3312 if (newItem == null) 3610 if (newItem == null)
3313 { 3611 {
3314 m_log.ErrorFormat( 3612 m_log.ErrorFormat(
3315 "[OSSL API]: Could not create user inventory item {0} for {1}, attach point {2} in {3}", 3613 "[OSSL API]: Could not create user inventory item {0} for {1}, attach point {2} in {3}: {4}",
3316 itemName, m_host.Name, attachmentPoint, World.Name); 3614 itemName, m_host.Name, attachmentPoint, World.Name, message);
3317 3615 ((LSL_Api)m_LSL_Api).llSay(0, message);
3318 return; 3616 return;
3319 } 3617 }
3320 3618
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
index dd45406..64dc2e2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs
@@ -353,7 +353,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
353 // Position of a sensor in a child prim attached to an avatar 353 // Position of a sensor in a child prim attached to an avatar
354 // will be still wrong. 354 // will be still wrong.
355 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 355 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
356 q = avatar.Rotation * q; 356
357 // Don't proceed if the avatar for this attachment has since been removed from the scene.
358 if (avatar == null)
359 return sensedEntities;
360
361 q = avatar.GetWorldRotation() * q;
357 } 362 }
358 363
359 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); 364 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
@@ -362,7 +367,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
362 367
363 Vector3 ZeroVector = new Vector3(0, 0, 0); 368 Vector3 ZeroVector = new Vector3(0, 0, 0);
364 369
365 bool nameSearch = (ts.name != null && ts.name != ""); 370 bool nameSearch = !string.IsNullOrEmpty(ts.name);
366 371
367 foreach (EntityBase ent in Entities) 372 foreach (EntityBase ent in Entities)
368 { 373 {
@@ -480,7 +485,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
480 // Position of a sensor in a child prim attached to an avatar 485 // Position of a sensor in a child prim attached to an avatar
481 // will be still wrong. 486 // will be still wrong.
482 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar); 487 ScenePresence avatar = m_CmdManager.m_ScriptEngine.World.GetScenePresence(SensePoint.ParentGroup.AttachedAvatar);
483 q = avatar.Rotation * q; 488
489 // Don't proceed if the avatar for this attachment has since been removed from the scene.
490 if (avatar == null)
491 return sensedEntities;
492
493 q = avatar.GetWorldRotation() * q;
484 } 494 }
485 495
486 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); 496 LSL_Types.Quaternion r = new LSL_Types.Quaternion(q);
@@ -595,7 +605,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins
595 return sensedEntities; 605 return sensedEntities;
596 senseEntity(sp); 606 senseEntity(sp);
597 } 607 }
598 else if (ts.name != null && ts.name != "") 608 else if (!string.IsNullOrEmpty(ts.name))
599 { 609 {
600 ScenePresence sp; 610 ScenePresence sp;
601 // Try lookup by name will return if/when found 611 // Try lookup by name will return if/when found
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
index d173db0..215c087 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Properties/AssemblyInfo.cs
@@ -29,5 +29,5 @@ using System.Runtime.InteropServices;
29// Build Number 29// Build Number
30// Revision 30// Revision
31// 31//
32[assembly: AssemblyVersion("0.7.5.*")] 32[assembly: AssemblyVersion("0.8.3.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")] 33