aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs
diff options
context:
space:
mode:
authorlbsa712008-06-24 21:09:49 +0000
committerlbsa712008-06-24 21:09:49 +0000
commit6b7930104bdb845d3b9c085dc04f52b6446f23b1 (patch)
tree05ee45781a455817fa400bb99f30f4d19d4eb1f8 /OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs
parentbased on positive feedback on performance of making keys fixed length (diff)
downloadopensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.zip
opensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.tar.gz
opensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.tar.bz2
opensim-SC_OLD-6b7930104bdb845d3b9c085dc04f52b6446f23b1.tar.xz
* Applied patch from Melanie, mantis issue #1581 - "Refactor LSL language, api and compiler out of XEngine"
"First stage in a major Script Engine refactor, that will result in the LSL implementaions ebing reconverged. Not there yet, but one major part is done." Thank you, Melanie!
Diffstat (limited to 'OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs')
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs6593
1 files changed, 0 insertions, 6593 deletions
diff --git a/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs b/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs
deleted file mode 100644
index 9c660c1..0000000
--- a/OpenSim/Region/ScriptEngine/XEngine/LSL_ScriptCommands.cs
+++ /dev/null
@@ -1,6593 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSim Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections;
30using System.Collections.Generic;
31using System.Runtime.Remoting.Lifetime;
32using System.Text;
33using System.Threading;
34using Nini.Config;
35using Axiom.Math;
36using libsecondlife;
37using OpenSim;
38using OpenSim.Framework;
39using OpenSim.Region.Environment;
40using OpenSim.Region.Environment.Interfaces;
41using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney;
42using OpenSim.Region.Environment.Modules.World.Land;
43using OpenSim.Region.Environment.Scenes;
44using OpenSim.Region.ScriptEngine.XEngine;
45using OpenSim.Region.ScriptEngine.XEngine.Script;
46
47
48namespace OpenSim.Region.ScriptEngine.XEngine
49{
50 /// <summary>
51 /// Contains all LSL ll-functions. This class will be in Default AppDomain.
52 /// </summary>
53 public class LSL_ScriptCommands : MarshalByRefObject, ILSL_ScriptCommands
54 {
55 // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
56
57 internal XEngine m_ScriptEngine;
58 internal XScriptInstance m_Instance;
59 internal SceneObjectPart m_host;
60 internal uint m_localID;
61 internal LLUUID m_itemID;
62 internal bool throwErrorOnNotImplemented = true;
63
64 public LSL_ScriptCommands(XEngine ScriptEngine, XScriptInstance instance, SceneObjectPart host, uint localID, LLUUID itemID)
65 {
66 m_ScriptEngine = ScriptEngine;
67 m_Instance = instance;
68 m_host = host;
69 m_localID = localID;
70 m_itemID = itemID;
71
72 //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]");
73 }
74
75 private DateTime m_timer = DateTime.Now;
76 private string m_state = "default";
77 private bool m_waitingForScriptAnswer=false;
78
79
80 public string State
81 {
82 get { return m_Instance.State; }
83 set { m_Instance.State = value; }
84 }
85
86 public void state(string newState)
87 {
88 m_Instance.SetState(newState);
89 }
90
91 // Object never expires
92 public override Object InitializeLifetimeService()
93 {
94 //Console.WriteLine("LSL_BuiltIn_Commands: InitializeLifetimeService()");
95 // return null;
96 ILease lease = (ILease)base.InitializeLifetimeService();
97
98 if (lease.CurrentState == LeaseState.Initial)
99 {
100 lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1);
101 // lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
102 // lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
103 }
104 return lease;
105 }
106
107 public Scene World
108 {
109 get { return m_ScriptEngine.World; }
110 }
111
112 public void llSay(int channelID, string text)
113 {
114 m_host.AddScriptLPS(1);
115
116 if (text.Length > 1023)
117 text = text.Substring(0, 1023);
118
119 World.SimChat(Helpers.StringToField(text),
120 ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
121
122 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
123 wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
124 }
125
126 // Extension commands use this:
127 public ICommander GetCommander(string name)
128 {
129 return World.GetCommander(name);
130 }
131
132 private LLUUID InventorySelf()
133 {
134 LLUUID invItemID = new LLUUID();
135
136 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
137 {
138 if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID)
139 {
140 invItemID = inv.Key;
141 break;
142 }
143 }
144
145 return invItemID;
146 }
147
148 private LLUUID InventoryKey(string name, int type)
149 {
150 m_host.AddScriptLPS(1);
151 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
152 {
153 if (inv.Value.Name == name)
154 {
155 if (inv.Value.Type != type)
156 return LLUUID.Zero;
157
158 return inv.Value.AssetID.ToString();
159 }
160 }
161 return LLUUID.Zero;
162 }
163
164 private LLUUID InventoryKey(string name)
165 {
166 m_host.AddScriptLPS(1);
167 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
168 {
169 if (inv.Value.Name == name)
170 {
171 return inv.Value.AssetID.ToString();
172 }
173 }
174 return LLUUID.Zero;
175 }
176
177
178 /// <summary>
179 /// accepts a valid LLUUID, -or- a name of an inventory item.
180 /// Returns a valid LLUUID or LLUUID.Zero if key invalid and item not found
181 /// in prim inventory.
182 /// </summary>
183 /// <param name="k"></param>
184 /// <returns></returns>
185 private LLUUID KeyOrName(string k)
186 {
187 LLUUID key = LLUUID.Zero;
188
189 // if we can parse the string as a key, use it.
190 if (LLUUID.TryParse(k, out key))
191 {
192 return key;
193 }
194 // else try to locate the name in inventory of object. found returns key,
195 // not found returns LLUUID.Zero which will translate to the default particle texture
196 else
197 {
198 return InventoryKey(k);
199 }
200 }
201
202 public void osSetRegionWaterHeight(double height)
203 {
204 m_host.AddScriptLPS(1);
205 //Check to make sure that the script's owner is the estate manager/master
206 //World.Permissions.GenericEstatePermission(
207 if (World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
208 {
209 World.EventManager.TriggerRequestChangeWaterHeight((float)height);
210 }
211 }
212
213 //These are the implementations of the various ll-functions used by the LSL scripts.
214 //starting out, we use the System.Math library for trig functions. - ckrinke 8-14-07
215 public double llSin(double f)
216 {
217 m_host.AddScriptLPS(1);
218 return (double)Math.Sin(f);
219 }
220
221 public double llCos(double f)
222 {
223 m_host.AddScriptLPS(1);
224 return (double)Math.Cos(f);
225 }
226
227 public double llTan(double f)
228 {
229 m_host.AddScriptLPS(1);
230 return (double)Math.Tan(f);
231 }
232
233 public double llAtan2(double x, double y)
234 {
235 m_host.AddScriptLPS(1);
236 return (double)Math.Atan2(y, x);
237 }
238
239 public double llSqrt(double f)
240 {
241 m_host.AddScriptLPS(1);
242 return (double)Math.Sqrt(f);
243 }
244
245 public double llPow(double fbase, double fexponent)
246 {
247 m_host.AddScriptLPS(1);
248 return (double)Math.Pow(fbase, fexponent);
249 }
250
251 public LSL_Types.LSLInteger llAbs(int i)
252 {
253 m_host.AddScriptLPS(1);
254 return (int)Math.Abs(i);
255 }
256
257 public double llFabs(double f)
258 {
259 m_host.AddScriptLPS(1);
260 return (double)Math.Abs(f);
261 }
262
263 public double llFrand(double mag)
264 {
265 m_host.AddScriptLPS(1);
266 lock (Util.RandomClass)
267 {
268 return Util.RandomClass.NextDouble() * mag;
269 }
270 }
271
272 public LSL_Types.LSLInteger llFloor(double f)
273 {
274 m_host.AddScriptLPS(1);
275 return (int)Math.Floor(f);
276 }
277
278 public LSL_Types.LSLInteger llCeil(double f)
279 {
280 m_host.AddScriptLPS(1);
281 return (int)Math.Ceiling(f);
282 }
283
284 // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
285 public LSL_Types.LSLInteger llRound(double f)
286 {
287 m_host.AddScriptLPS(1);
288 return (int)Math.Round(f, MidpointRounding.AwayFromZero);
289 }
290
291 //This next group are vector operations involving squaring and square root. ckrinke
292 public double llVecMag(LSL_Types.Vector3 v)
293 {
294 m_host.AddScriptLPS(1);
295 return LSL_Types.Vector3.Mag(v);
296 }
297
298 public LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v)
299 {
300 m_host.AddScriptLPS(1);
301 double mag = LSL_Types.Vector3.Mag(v);
302 LSL_Types.Vector3 nor = new LSL_Types.Vector3();
303 nor.x = v.x / mag;
304 nor.y = v.y / mag;
305 nor.z = v.z / mag;
306 return nor;
307 }
308
309 public double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b)
310 {
311 m_host.AddScriptLPS(1);
312 double dx = a.x - b.x;
313 double dy = a.y - b.y;
314 double dz = a.z - b.z;
315 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
316 }
317
318 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
319
320 // Utility function for llRot2Euler
321
322 // normalize an angle between 0 - 2*PI (0 and 360 degrees)
323 private double NormalizeAngle(double angle)
324 {
325 angle = angle % (Math.PI * 2);
326 if (angle < 0) angle = angle + Math.PI * 2;
327 return angle;
328 }
329
330 // Old implementation of llRot2Euler, now normalized
331
332 public LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r)
333 {
334 m_host.AddScriptLPS(1);
335 //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke
336 LSL_Types.Quaternion t = new LSL_Types.Quaternion(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s);
337 double m = (t.x + t.y + t.z + t.s);
338 if (m == 0) return new LSL_Types.Vector3();
339 double n = 2 * (r.y * r.s + r.x * r.z);
340 double p = m * m - n * n;
341 if (p > 0)
342 return new LSL_Types.Vector3(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))),
343 NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))),
344 NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))));
345 else if (n > 0)
346 return new LSL_Types.Vector3(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
347 else
348 return new LSL_Types.Vector3(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)));
349 }
350
351 // Xantor's newer llEuler2Rot() *try the second* inverted quaternions (-x,-y,-z,w) as LL seems to like
352 // New and improved, now actually works as described. Prim rotates as expected as does llRot2Euler.
353
354 /* From wiki:
355 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
356 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
357 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
358 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
359 */
360
361 public LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v)
362 {
363 m_host.AddScriptLPS(1);
364
365 double x,y,z,s,s_i;
366
367 double cosX = Math.Cos(v.x);
368 double cosY = Math.Cos(v.y);
369 double cosZ = Math.Cos(v.z);
370 double sinX = Math.Sin(v.x);
371 double sinY = Math.Sin(v.y);
372 double sinZ = Math.Sin(v.z);
373
374 s = Math.Sqrt(cosY * cosZ - sinX * sinY * sinZ + cosX * cosZ + cosX * cosY + 1.0f) * 0.5f;
375 if (Math.Abs(s) < 0.00001) // null rotation
376 {
377 x = 0.0f;
378 y = 1.0f;
379 z = 0.0f;
380 }
381 else
382 {
383 s_i = 1.0f / (4.0f * s);
384 x = - (-sinX * cosY - cosX * sinY * sinZ - sinX * cosZ) * s_i;
385 y = - (-cosX * sinY * cosZ + sinX * sinZ - sinY) * s_i;
386 z = - (-cosY * sinZ - sinX * sinY * cosZ - cosX * sinZ) * s_i;
387 }
388 return new LSL_Types.Quaternion(x, y, z, s);
389 }
390
391 public LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up)
392 {
393 m_host.AddScriptLPS(1);
394 NotImplemented("llAxes2Rot");
395 return new LSL_Types.Quaternion();
396 }
397
398 public LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r)
399 {
400 m_host.AddScriptLPS(1);
401 return (new LSL_Types.Vector3(1,0,0) * r);
402 }
403
404 public LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r)
405 {
406 m_host.AddScriptLPS(1);
407 return (new LSL_Types.Vector3(0, 1, 0) * r);
408 }
409
410 public LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r)
411 {
412 m_host.AddScriptLPS(1);
413 return (new LSL_Types.Vector3(0, 0, 1) * r);
414 }
415
416 public LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 a, LSL_Types.Vector3 b)
417 {
418 //A and B should both be normalized
419 m_host.AddScriptLPS(1);
420 double dotProduct = LSL_Types.Vector3.Dot(a, b);
421 LSL_Types.Vector3 crossProduct = LSL_Types.Vector3.Cross(a, b);
422 double magProduct = LSL_Types.Vector3.Mag(a) * LSL_Types.Vector3.Mag(b);
423 double angle = Math.Acos(dotProduct / magProduct);
424 LSL_Types.Vector3 axis = LSL_Types.Vector3.Norm(crossProduct);
425 double s = Math.Sin(angle / 2);
426
427 return new LSL_Types.Quaternion(axis.x * s, axis.y * s, axis.z * s, (float)Math.Cos(angle / 2));
428 }
429
430 public void llWhisper(int channelID, string text)
431 {
432 m_host.AddScriptLPS(1);
433
434 if (text.Length > 1023)
435 text = text.Substring(0, 1023);
436
437 World.SimChat(Helpers.StringToField(text),
438 ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
439
440 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
441 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
442 }
443
444 public void llShout(int channelID, string text)
445 {
446 m_host.AddScriptLPS(1);
447
448 if (text.Length > 1023)
449 text = text.Substring(0, 1023);
450
451 World.SimChat(Helpers.StringToField(text),
452 ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true);
453
454 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
455 wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
456 }
457
458 public void llRegionSay(int channelID, string text)
459 {
460 if (channelID == 0)
461 {
462 LSLError("Cannot use llRegionSay() on channel 0");
463 return;
464 }
465
466 if (text.Length > 1023)
467 text = text.Substring(0, 1023);
468
469 m_host.AddScriptLPS(1);
470
471 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
472 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
473 }
474
475 public LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg)
476 {
477 m_host.AddScriptLPS(1);
478 LLUUID keyID;
479 LLUUID.TryParse(ID, out keyID);
480 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
481 return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg);
482 }
483
484 public void llListenControl(int number, int active)
485 {
486 m_host.AddScriptLPS(1);
487 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
488 wComm.ListenControl(m_itemID, number, active);
489 }
490
491 public void llListenRemove(int number)
492 {
493 m_host.AddScriptLPS(1);
494 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
495 wComm.ListenRemove(m_itemID, number);
496 }
497
498 public void llSensor(string name, string id, int type, double range, double arc)
499 {
500 m_host.AddScriptLPS(1);
501 LLUUID keyID = LLUUID.Zero;
502 LLUUID.TryParse(id, out keyID);
503
504 m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host);
505 }
506
507 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
508 {
509 m_host.AddScriptLPS(1);
510 LLUUID keyID = LLUUID.Zero;
511 LLUUID.TryParse(id, out keyID);
512
513 m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host);
514 }
515
516 public void llSensorRemove()
517 {
518 m_host.AddScriptLPS(1);
519 m_ScriptEngine.m_ASYNCLSLCommandManager.m_SensorRepeat.UnSetSenseRepeaterEvents(m_localID, m_itemID);
520 }
521
522 public string resolveName(LLUUID objecUUID)
523 {
524 // try avatar username surname
525 UserProfileData profile = World.CommsManager.UserService.GetUserProfile(objecUUID);
526 if (profile != null)
527 {
528 string avatarname = profile.FirstName + " " + profile.SurName;
529 return avatarname;
530 }
531 // try an scene object
532 SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
533 if (SOP != null)
534 {
535 string objectname = SOP.Name;
536 return objectname;
537 }
538
539 EntityBase SensedObject;
540 lock (World.Entities)
541 {
542 World.Entities.TryGetValue(objecUUID, out SensedObject);
543 }
544
545 if (SensedObject == null)
546 return String.Empty;
547 return SensedObject.Name;
548 }
549
550 public string llDetectedName(int number)
551 {
552 m_host.AddScriptLPS(1);
553 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
554 if (d == null)
555 return String.Empty;
556 return d.Name;
557 }
558
559 public string llDetectedKey(int number)
560 {
561 m_host.AddScriptLPS(1);
562 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
563 if (d == null)
564 return String.Empty;
565 return d.Key.ToString();
566 }
567
568 public string llDetectedOwner(int number)
569 {
570 m_host.AddScriptLPS(1);
571 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
572 if (d == null)
573 return String.Empty;
574 return d.Owner.ToString();
575 }
576
577 public LSL_Types.LSLInteger llDetectedType(int number)
578 {
579 m_host.AddScriptLPS(1);
580 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
581 if (d == null)
582 return 0;
583 return new LSL_Types.LSLInteger(d.Type);
584 }
585
586 public LSL_Types.Vector3 llDetectedPos(int number)
587 {
588 m_host.AddScriptLPS(1);
589 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
590 if (d == null)
591 return new LSL_Types.Vector3();
592 return d.Position;
593 }
594
595 public LSL_Types.Vector3 llDetectedVel(int number)
596 {
597 m_host.AddScriptLPS(1);
598 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
599 if (d == null)
600 return new LSL_Types.Vector3();
601 return d.Velocity;
602 }
603
604 public LSL_Types.Vector3 llDetectedGrab(int number)
605 {
606 m_host.AddScriptLPS(1);
607 XDetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
608 if (parms == null)
609 return new LSL_Types.Vector3(0, 0, 0);
610
611 return parms.OffsetPos;
612 }
613
614 public LSL_Types.Quaternion llDetectedRot(int number)
615 {
616 m_host.AddScriptLPS(1);
617 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
618 if (d == null)
619 return new LSL_Types.Quaternion();
620 return d.Rotation;
621 }
622
623 public LSL_Types.LSLInteger llDetectedGroup(int number)
624 {
625 m_host.AddScriptLPS(1);
626 XDetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number);
627 if (d == null)
628 return new LSL_Types.LSLInteger(0);
629 if (m_host.GroupID == d.Group)
630 return new LSL_Types.LSLInteger(1);
631 return new LSL_Types.LSLInteger(0);
632 }
633
634 public LSL_Types.LSLInteger llDetectedLinkNumber(int number)
635 {
636 m_host.AddScriptLPS(1);
637 XDetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number);
638 if (parms == null)
639 return new LSL_Types.LSLInteger(0);
640
641 return new LSL_Types.LSLInteger(parms.LinkNum);
642 }
643
644 public void llDie()
645 {
646 m_host.AddScriptLPS(1);
647 World.DeleteSceneObject(m_host.ParentGroup);
648 }
649
650 public double llGround(LSL_Types.Vector3 offset)
651 {
652 m_host.AddScriptLPS(1);
653 int x = (int)(m_host.AbsolutePosition.X + offset.x);
654 int y = (int)(m_host.AbsolutePosition.Y + offset.y);
655 return World.GetLandHeight(x, y);
656 }
657
658 public double llCloud(LSL_Types.Vector3 offset)
659 {
660 m_host.AddScriptLPS(1);
661 NotImplemented("llCloud");
662 return 0;
663 }
664
665 public LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset)
666 {
667 m_host.AddScriptLPS(1);
668 NotImplemented("llWind");
669 return new LSL_Types.Vector3();
670 }
671
672 public void llSetStatus(int status, int value)
673 {
674 m_host.AddScriptLPS(1);
675
676 int statusrotationaxis = 0;
677
678 if ((status & BuiltIn_Commands_BaseClass.STATUS_PHYSICS) == BuiltIn_Commands_BaseClass.STATUS_PHYSICS)
679 {
680 if (value == 1)
681 m_host.ScriptSetPhysicsStatus(true);
682 else
683 m_host.ScriptSetPhysicsStatus(false);
684 }
685
686 if ((status & BuiltIn_Commands_BaseClass.STATUS_PHANTOM) == BuiltIn_Commands_BaseClass.STATUS_PHANTOM)
687 {
688 if (value == 1)
689 m_host.ScriptSetPhantomStatus(true);
690 else
691 m_host.ScriptSetPhantomStatus(false);
692 }
693
694 if ((status & BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS) == BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS)
695 {
696 m_host.AddFlag(LLObject.ObjectFlags.CastShadows);
697 }
698
699 if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_X) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_X)
700 {
701 statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_X;
702 }
703
704 if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y)
705 {
706 statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y;
707 }
708
709 if ((status & BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z) == BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z)
710 {
711 statusrotationaxis |= BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z;
712 }
713
714 if ((status & BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB) == BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB)
715 {
716 NotImplemented("llSetStatus - STATUS_BLOCK_GRAB");
717 }
718
719 if ((status & BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE) == BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE)
720 {
721 if (value == 1)
722 m_host.SetDieAtEdge(true);
723 else
724 m_host.SetDieAtEdge(false);
725 }
726
727 if ((status & BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE) == BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE)
728 {
729 NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE");
730 }
731
732 if ((status & BuiltIn_Commands_BaseClass.STATUS_SANDBOX) == BuiltIn_Commands_BaseClass.STATUS_SANDBOX)
733 {
734 NotImplemented("llSetStatus - STATUS_SANDBOX");
735 }
736
737 if (statusrotationaxis != 0)
738 {
739 m_host.SetAxisRotation(statusrotationaxis, value);
740 }
741 }
742
743 public LSL_Types.LSLInteger llGetStatus(int status)
744 {
745 m_host.AddScriptLPS(1);
746 // Console.WriteLine(m_host.UUID.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
747 switch (status)
748 {
749 case BuiltIn_Commands_BaseClass.STATUS_PHYSICS:
750 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) == (uint)LLObject.ObjectFlags.Physics)
751 {
752 return 1;
753 }
754 return 0;
755
756 case BuiltIn_Commands_BaseClass.STATUS_PHANTOM:
757 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Phantom) == (uint)LLObject.ObjectFlags.Phantom)
758 {
759 return 1;
760 }
761 return 0;
762
763 case BuiltIn_Commands_BaseClass.STATUS_CAST_SHADOWS:
764 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.CastShadows) == (uint)LLObject.ObjectFlags.CastShadows)
765 {
766 return 1;
767 }
768 return 0;
769
770 case BuiltIn_Commands_BaseClass.STATUS_BLOCK_GRAB:
771 NotImplemented("llGetStatus - STATUS_BLOCK_GRAB");
772 return 0;
773
774 case BuiltIn_Commands_BaseClass.STATUS_DIE_AT_EDGE:
775 if (m_host.GetDieAtEdge())
776 return 1;
777 else
778 return 0;
779
780 case BuiltIn_Commands_BaseClass.STATUS_RETURN_AT_EDGE:
781 NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE");
782 return 0;
783
784 case BuiltIn_Commands_BaseClass.STATUS_ROTATE_X:
785 NotImplemented("llGetStatus - STATUS_ROTATE_X");
786 return 0;
787
788 case BuiltIn_Commands_BaseClass.STATUS_ROTATE_Y:
789 NotImplemented("llGetStatus - STATUS_ROTATE_Y");
790 return 0;
791
792 case BuiltIn_Commands_BaseClass.STATUS_ROTATE_Z:
793 NotImplemented("llGetStatus - STATUS_ROTATE_Z");
794 return 0;
795
796 case BuiltIn_Commands_BaseClass.STATUS_SANDBOX:
797 NotImplemented("llGetStatus - STATUS_SANDBOX");
798 return 0;
799 }
800 return 0;
801 }
802
803 public void llSetScale(LSL_Types.Vector3 scale)
804 {
805 m_host.AddScriptLPS(1);
806 SetScale(m_host, scale);
807 }
808
809 private void SetScale(SceneObjectPart part, LSL_Types.Vector3 scale)
810 {
811 // TODO: this needs to trigger a persistance save as well
812 LLVector3 tmp = part.Scale;
813 tmp.X = (float)scale.x;
814 tmp.Y = (float)scale.y;
815 tmp.Z = (float)scale.z;
816 part.Scale = tmp;
817 part.SendFullUpdateToAllClients();
818 }
819
820 public LSL_Types.Vector3 llGetScale()
821 {
822 m_host.AddScriptLPS(1);
823 return new LSL_Types.Vector3(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
824 }
825
826 public void llSetColor(LSL_Types.Vector3 color, int face)
827 {
828 m_host.AddScriptLPS(1);
829
830 SetColor(m_host, color, face);
831 }
832
833 private void SetColor(SceneObjectPart part, LSL_Types.Vector3 color, int face)
834 {
835 LLObject.TextureEntry tex = part.Shape.Textures;
836 LLColor texcolor;
837 if (face > -1)
838 {
839 texcolor = tex.CreateFace((uint)face).RGBA;
840 texcolor.R = (float)Math.Abs(color.x - 1);
841 texcolor.G = (float)Math.Abs(color.y - 1);
842 texcolor.B = (float)Math.Abs(color.z - 1);
843 tex.FaceTextures[face].RGBA = texcolor;
844 part.UpdateTexture(tex);
845 return;
846 }
847 else if (face == -1)
848 {
849 for (uint i = 0; i < 32; i++)
850 {
851 if (tex.FaceTextures[i] != null)
852 {
853 texcolor = tex.FaceTextures[i].RGBA;
854 texcolor.R = (float)Math.Abs(color.x - 1);
855 texcolor.G = (float)Math.Abs(color.y - 1);
856 texcolor.B = (float)Math.Abs(color.z - 1);
857 tex.FaceTextures[i].RGBA = texcolor;
858 }
859 texcolor = tex.DefaultTexture.RGBA;
860 texcolor.R = (float)Math.Abs(color.x - 1);
861 texcolor.G = (float)Math.Abs(color.y - 1);
862 texcolor.B = (float)Math.Abs(color.z - 1);
863 tex.DefaultTexture.RGBA = texcolor;
864 }
865 part.UpdateTexture(tex);
866 return;
867 }
868 }
869
870 public double llGetAlpha(int face)
871 {
872 m_host.AddScriptLPS(1);
873 LLObject.TextureEntry tex = m_host.Shape.Textures;
874 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
875 {
876 return (double)((tex.DefaultTexture.RGBA.A * 255) / 255);
877 }
878 if (face > -1)
879 {
880 return (double)((tex.GetFace((uint)face).RGBA.A * 255) / 255);
881 }
882 return 0;
883 }
884
885 public void llSetAlpha(double alpha, int face)
886 {
887 m_host.AddScriptLPS(1);
888
889 SetAlpha(m_host, alpha, face);
890 }
891
892 private void SetAlpha(SceneObjectPart part, double alpha, int face)
893 {
894 LLObject.TextureEntry tex = part.Shape.Textures;
895 LLColor texcolor;
896 if (face > -1)
897 {
898 texcolor = tex.CreateFace((uint)face).RGBA;
899 texcolor.A = (float)Math.Abs(alpha - 1);
900 tex.FaceTextures[face].RGBA = texcolor;
901 part.UpdateTexture(tex);
902 return;
903 }
904 else if (face == -1)
905 {
906 for (int i = 0; i < 32; i++)
907 {
908 if (tex.FaceTextures[i] != null)
909 {
910 texcolor = tex.FaceTextures[i].RGBA;
911 texcolor.A = (float)Math.Abs(alpha - 1);
912 tex.FaceTextures[i].RGBA = texcolor;
913 }
914 }
915 texcolor = tex.DefaultTexture.RGBA;
916 texcolor.A = (float)Math.Abs(alpha - 1);
917 tex.DefaultTexture.RGBA = texcolor;
918 part.UpdateTexture(tex);
919 return;
920 }
921 }
922
923 private void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
924 float wind, float tension, LSL_Types.Vector3 Force)
925 {
926 if (part == null)
927 return;
928
929 bool needs_fakedelete = false;
930 if (flexi)
931 {
932 if (!part.Shape.FlexiEntry)
933 {
934 needs_fakedelete = true;
935 }
936 part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
937 // work once the prim is already flexi
938 part.Shape.FlexiSoftness = softness;
939 part.Shape.FlexiGravity = gravity;
940 part.Shape.FlexiDrag = friction;
941 part.Shape.FlexiWind = wind;
942 part.Shape.FlexiTension = tension;
943 part.Shape.FlexiForceX = (float)Force.x;
944 part.Shape.FlexiForceY = (float)Force.y;
945 part.Shape.FlexiForceZ = (float)Force.z;
946 part.Shape.PathCurve = 0x80;
947
948 }
949 else
950 {
951 if (part.Shape.FlexiEntry)
952 {
953 needs_fakedelete = true;
954 }
955 part.Shape.FlexiEntry = false;
956 }
957
958 needs_fakedelete = false;
959 if (needs_fakedelete)
960 {
961 if (part.ParentGroup != null)
962 {
963 part.ParentGroup.FakeDeleteGroup();
964 }
965 }
966
967 part.ScheduleFullUpdate();
968 }
969
970 private void SetPointLight(SceneObjectPart part, bool light, LSL_Types.Vector3 color, float intensity, float radius, float falloff)
971 {
972 if (part == null)
973 return;
974
975 if (light)
976 {
977 part.Shape.LightEntry = true;
978 part.Shape.LightColorR = (float)color.x;
979 part.Shape.LightColorG = (float)color.y;
980 part.Shape.LightColorB = (float)color.z;
981 part.Shape.LightIntensity = intensity;
982 part.Shape.LightRadius = radius;
983 part.Shape.LightFalloff = falloff;
984 }
985 else
986 {
987 part.Shape.LightEntry = false;
988 }
989
990 part.ScheduleFullUpdate();
991 }
992
993
994
995 public LSL_Types.Vector3 llGetColor(int face)
996 {
997 m_host.AddScriptLPS(1);
998 LLObject.TextureEntry tex = m_host.Shape.Textures;
999 LLColor texcolor;
1000 LSL_Types.Vector3 rgb;
1001 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
1002 {
1003 texcolor = tex.DefaultTexture.RGBA;
1004 rgb.x = (255 - (texcolor.R * 255)) / 255;
1005 rgb.y = (255 - (texcolor.G * 255)) / 255;
1006 rgb.z = (255 - (texcolor.B * 255)) / 255;
1007 return rgb;
1008 }
1009 if (face > -1)
1010 {
1011 texcolor = tex.GetFace((uint)face).RGBA;
1012 rgb.x = (255 - (texcolor.R * 255)) / 255;
1013 rgb.y = (255 - (texcolor.G * 255)) / 255;
1014 rgb.z = (255 - (texcolor.B * 255)) / 255;
1015 return rgb;
1016 }
1017 else
1018 {
1019 return new LSL_Types.Vector3();
1020 }
1021 }
1022
1023 public void llSetTexture(string texture, int face)
1024 {
1025 m_host.AddScriptLPS(1);
1026 SetTexture(m_host, texture, face);
1027 }
1028
1029 private void SetTexture(SceneObjectPart part, string texture, int face)
1030 {
1031 LLUUID textureID=new LLUUID();
1032
1033 if (!LLUUID.TryParse(texture, out textureID))
1034 {
1035 textureID=InventoryKey(texture, (int)AssetType.Texture);
1036 }
1037
1038 if (textureID == LLUUID.Zero)
1039 return;
1040
1041 LLObject.TextureEntry tex = part.Shape.Textures;
1042
1043 if (face > -1)
1044 {
1045 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
1046 texface.TextureID = textureID;
1047 tex.FaceTextures[face] = texface;
1048 part.UpdateTexture(tex);
1049 return;
1050 }
1051 else if (face == -1)
1052 {
1053 for (uint i = 0; i < 32; i++)
1054 {
1055 if (tex.FaceTextures[i] != null)
1056 {
1057 tex.FaceTextures[i].TextureID = textureID;
1058 }
1059 }
1060 tex.DefaultTexture.TextureID = textureID;
1061 part.UpdateTexture(tex);
1062 return;
1063 }
1064 }
1065
1066 public void llScaleTexture(double u, double v, int face)
1067 {
1068 m_host.AddScriptLPS(1);
1069
1070 ScaleTexture(m_host, u, v, face);
1071 }
1072
1073 private void ScaleTexture(SceneObjectPart part, double u, double v, int face)
1074 {
1075 LLObject.TextureEntry tex = part.Shape.Textures;
1076 if (face > -1)
1077 {
1078 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
1079 texface.RepeatU = (float)u;
1080 texface.RepeatV = (float)v;
1081 tex.FaceTextures[face] = texface;
1082 part.UpdateTexture(tex);
1083 return;
1084 }
1085 if (face == -1)
1086 {
1087 for (int i = 0; i < 32; i++)
1088 {
1089 if (tex.FaceTextures[i] != null)
1090 {
1091 tex.FaceTextures[i].RepeatU = (float)u;
1092 tex.FaceTextures[i].RepeatV = (float)v;
1093 }
1094 }
1095 tex.DefaultTexture.RepeatU = (float)u;
1096 tex.DefaultTexture.RepeatV = (float)v;
1097 part.UpdateTexture(tex);
1098 return;
1099 }
1100 }
1101
1102 public void llOffsetTexture(double u, double v, int face)
1103 {
1104 m_host.AddScriptLPS(1);
1105 OffsetTexture(m_host, u, v, face);
1106 }
1107
1108 private void OffsetTexture(SceneObjectPart part, double u, double v, int face)
1109 {
1110 LLObject.TextureEntry tex = part.Shape.Textures;
1111 if (face > -1)
1112 {
1113 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
1114 texface.OffsetU = (float)u;
1115 texface.OffsetV = (float)v;
1116 tex.FaceTextures[face] = texface;
1117 part.UpdateTexture(tex);
1118 return;
1119 }
1120 if (face == -1)
1121 {
1122 for (int i = 0; i < 32; i++)
1123 {
1124 if (tex.FaceTextures[i] != null)
1125 {
1126 tex.FaceTextures[i].OffsetU = (float)u;
1127 tex.FaceTextures[i].OffsetV = (float)v;
1128 }
1129 }
1130 tex.DefaultTexture.OffsetU = (float)u;
1131 tex.DefaultTexture.OffsetV = (float)v;
1132 part.UpdateTexture(tex);
1133 return;
1134 }
1135 }
1136
1137 public void llRotateTexture(double rotation, int face)
1138 {
1139 m_host.AddScriptLPS(1);
1140 RotateTexture(m_host, rotation, face);
1141 }
1142
1143 private void RotateTexture(SceneObjectPart part, double rotation, int face)
1144 {
1145 LLObject.TextureEntry tex = part.Shape.Textures;
1146 if (face > -1)
1147 {
1148 LLObject.TextureEntryFace texface = tex.CreateFace((uint)face);
1149 texface.Rotation = (float)rotation;
1150 tex.FaceTextures[face] = texface;
1151 part.UpdateTexture(tex);
1152 return;
1153 }
1154 if (face == -1)
1155 {
1156 for (int i = 0; i < 32; i++)
1157 {
1158 if (tex.FaceTextures[i] != null)
1159 {
1160 tex.FaceTextures[i].Rotation = (float)rotation;
1161 }
1162 }
1163 tex.DefaultTexture.Rotation = (float)rotation;
1164 part.UpdateTexture(tex);
1165 return;
1166 }
1167 }
1168
1169 public string llGetTexture(int face)
1170 {
1171 m_host.AddScriptLPS(1);
1172 LLObject.TextureEntry tex = m_host.Shape.Textures;
1173 if (face == -1)
1174 {
1175 face = 0;
1176 }
1177 if (face > -1)
1178 {
1179 LLObject.TextureEntryFace texface;
1180 texface = tex.GetFace((uint)face);
1181 return texface.TextureID.ToString();
1182 }
1183 else
1184 {
1185 return String.Empty;
1186 }
1187 }
1188
1189 public void llSetPos(LSL_Types.Vector3 pos)
1190 {
1191 m_host.AddScriptLPS(1);
1192
1193 SetPos(m_host, pos);
1194 }
1195
1196 private void SetPos(SceneObjectPart part, LSL_Types.Vector3 pos)
1197 {
1198 if (part.ParentID != 0)
1199 {
1200 part.UpdateOffSet(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z));
1201 }
1202 else
1203 {
1204 part.UpdateGroupPosition(new LLVector3((float)pos.x, (float)pos.y, (float)pos.z));
1205 }
1206 }
1207
1208 public LSL_Types.Vector3 llGetPos()
1209 {
1210 m_host.AddScriptLPS(1);
1211 return new LSL_Types.Vector3(m_host.AbsolutePosition.X,
1212 m_host.AbsolutePosition.Y,
1213 m_host.AbsolutePosition.Z);
1214 }
1215
1216 public LSL_Types.Vector3 llGetLocalPos()
1217 {
1218 m_host.AddScriptLPS(1);
1219 if (m_host.ParentID != 0)
1220 {
1221 return new LSL_Types.Vector3(m_host.OffsetPosition.X,
1222 m_host.OffsetPosition.Y,
1223 m_host.OffsetPosition.Z);
1224 }
1225 else
1226 {
1227 return new LSL_Types.Vector3(m_host.AbsolutePosition.X,
1228 m_host.AbsolutePosition.Y,
1229 m_host.AbsolutePosition.Z);
1230 }
1231 }
1232
1233 public void llSetRot(LSL_Types.Quaternion rot)
1234 {
1235 m_host.AddScriptLPS(1);
1236
1237 SetRot(m_host, rot);
1238 }
1239
1240 private void SetRot(SceneObjectPart part, LSL_Types.Quaternion rot)
1241 {
1242 part.UpdateRotation(new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s));
1243 // Update rotation does not move the object in the physics scene if it's a linkset.
1244 part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
1245 }
1246
1247 public LSL_Types.Quaternion llGetRot()
1248 {
1249 m_host.AddScriptLPS(1);
1250 LLQuaternion q = m_host.RotationOffset;
1251 return new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
1252 }
1253
1254 public LSL_Types.Quaternion llGetLocalRot()
1255 {
1256 m_host.AddScriptLPS(1);
1257 return new LSL_Types.Quaternion(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W);
1258 }
1259
1260 public void llSetForce(LSL_Types.Vector3 force, int local)
1261 {
1262 m_host.AddScriptLPS(1);
1263 NotImplemented("llSetForce");
1264 }
1265
1266 public LSL_Types.Vector3 llGetForce()
1267 {
1268 m_host.AddScriptLPS(1);
1269 NotImplemented("llGetForce");
1270 return new LSL_Types.Vector3();
1271 }
1272
1273 public LSL_Types.LSLInteger llTarget(LSL_Types.Vector3 position, double range)
1274 {
1275 m_host.AddScriptLPS(1);
1276 return m_host.registerTargetWaypoint(new LLVector3((float)position.x, (float)position.y, (float)position.z), (float)range);
1277
1278 }
1279
1280 public void llTargetRemove(int number)
1281 {
1282 m_host.AddScriptLPS(1);
1283 m_host.unregisterTargetWaypoint(number);
1284 }
1285
1286 public LSL_Types.LSLInteger llRotTarget(LSL_Types.Quaternion rot, double error)
1287 {
1288 m_host.AddScriptLPS(1);
1289 NotImplemented("llRotTarget");
1290 return 0;
1291 }
1292
1293 public void llRotTargetRemove(int number)
1294 {
1295 m_host.AddScriptLPS(1);
1296 NotImplemented("llRotTargetRemove");
1297 }
1298
1299 public void llMoveToTarget(LSL_Types.Vector3 target, double tau)
1300 {
1301 m_host.AddScriptLPS(1);
1302 m_host.MoveToTarget(new LLVector3((float)target.x, (float)target.y, (float)target.z), (float)tau);
1303 }
1304
1305 public void llStopMoveToTarget()
1306 {
1307 m_host.AddScriptLPS(1);
1308 m_host.StopMoveToTarget();
1309 }
1310
1311 public void llApplyImpulse(LSL_Types.Vector3 force, int local)
1312 {
1313 m_host.AddScriptLPS(1);
1314 //No energy force yet
1315
1316 if (force.x > 20000)
1317 force.x = 20000;
1318 if (force.y > 20000)
1319 force.y = 20000;
1320 if (force.z > 20000)
1321 force.z = 20000;
1322
1323 if (local == 1)
1324 {
1325 m_host.ApplyImpulse(new LLVector3((float)force.x, (float)force.y, (float)force.z), true);
1326 }
1327 else
1328 {
1329
1330 m_host.ApplyImpulse(new LLVector3((float)force.x,(float)force.y,(float)force.z), false);
1331 }
1332 }
1333
1334 public void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local)
1335 {
1336 m_host.AddScriptLPS(1);
1337 NotImplemented("llApplyRotationalImpulse");
1338 }
1339
1340 public void llSetTorque(LSL_Types.Vector3 torque, int local)
1341 {
1342 m_host.AddScriptLPS(1);
1343 NotImplemented("llSetTorque");
1344 }
1345
1346 public LSL_Types.Vector3 llGetTorque()
1347 {
1348 m_host.AddScriptLPS(1);
1349 NotImplemented("llGetTorque");
1350 return new LSL_Types.Vector3();
1351 }
1352
1353 public void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local)
1354 {
1355 m_host.AddScriptLPS(1);
1356 NotImplemented("llSetForceAndTorque");
1357 }
1358
1359 public LSL_Types.Vector3 llGetVel()
1360 {
1361 m_host.AddScriptLPS(1);
1362 return new LSL_Types.Vector3(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z);
1363 }
1364
1365 public LSL_Types.Vector3 llGetAccel()
1366 {
1367 m_host.AddScriptLPS(1);
1368 return new LSL_Types.Vector3(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z);
1369 }
1370
1371 public LSL_Types.Vector3 llGetOmega()
1372 {
1373 m_host.AddScriptLPS(1);
1374 return new LSL_Types.Vector3(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z);
1375 }
1376
1377 public double llGetTimeOfDay()
1378 {
1379 m_host.AddScriptLPS(1);
1380 NotImplemented("llGetTimeOfDay");
1381 return 0;
1382 }
1383
1384 public double llGetWallclock()
1385 {
1386 m_host.AddScriptLPS(1);
1387 return DateTime.Now.TimeOfDay.TotalSeconds;
1388 }
1389
1390 public double llGetTime()
1391 {
1392 m_host.AddScriptLPS(1);
1393 TimeSpan ScriptTime = DateTime.Now - m_timer;
1394 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1395 }
1396
1397 public void llResetTime()
1398 {
1399 m_host.AddScriptLPS(1);
1400 m_timer = DateTime.Now;
1401 }
1402
1403 public double llGetAndResetTime()
1404 {
1405 m_host.AddScriptLPS(1);
1406 TimeSpan ScriptTime = DateTime.Now - m_timer;
1407 m_timer = DateTime.Now;
1408 return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation);
1409 }
1410
1411 public void llSound()
1412 {
1413 m_host.AddScriptLPS(1);
1414 // This function has been deprecated
1415 // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound
1416 Deprecated("llSound");
1417 }
1418
1419 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
1420 // 20080530 Updated to remove code duplication
1421 public void llPlaySound(string sound, double volume)
1422 {
1423 m_host.AddScriptLPS(1);
1424
1425 // send the sound, once, to all clients in range
1426 m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0);
1427 }
1428
1429 // Xantor 20080528 we should do this differently.
1430 // 1) apply the sound to the object
1431 // 2) schedule full update
1432 // just sending the sound out once doesn't work so well when other avatars come in view later on
1433 // or when the prim gets moved, changed, sat on, whatever
1434 // see large number of mantises (mantes?)
1435 // 20080530 Updated to remove code duplication
1436 // 20080530 Stop sound if there is one, otherwise volume only changes don't work
1437 public void llLoopSound(string sound, double volume)
1438 {
1439 m_host.AddScriptLPS(1);
1440
1441 if (m_host.Sound != LLUUID.Zero)
1442 llStopSound();
1443
1444 m_host.Sound = KeyOrName(sound);
1445 m_host.SoundGain = volume;
1446 m_host.SoundFlags = 1; // looping
1447 m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable?
1448
1449 m_host.ScheduleFullUpdate();
1450 m_host.SendFullUpdateToAllClients();
1451 }
1452
1453 public void llLoopSoundMaster(string sound, double volume)
1454 {
1455 m_host.AddScriptLPS(1);
1456 NotImplemented("llLoopSoundMaster");
1457 }
1458
1459 public void llLoopSoundSlave(string sound, double volume)
1460 {
1461 m_host.AddScriptLPS(1);
1462 NotImplemented("llLoopSoundSlave");
1463 }
1464
1465 public void llPlaySoundSlave(string sound, double volume)
1466 {
1467 m_host.AddScriptLPS(1);
1468 NotImplemented("llPlaySoundSlave");
1469 }
1470
1471 public void llTriggerSound(string sound, double volume)
1472 {
1473 m_host.AddScriptLPS(1);
1474 m_host.SendSound(sound, volume, true, 0);
1475 }
1476
1477 // Xantor 20080528: Clear prim data of sound instead
1478 public void llStopSound()
1479 {
1480 m_host.AddScriptLPS(1);
1481
1482 m_host.Sound = LLUUID.Zero;
1483 m_host.SoundGain = 0;
1484 m_host.SoundFlags = 0;
1485 m_host.SoundRadius = 0;
1486
1487 m_host.ScheduleFullUpdate();
1488 m_host.SendFullUpdateToAllClients();
1489
1490 // m_host.SendSound(LLUUID.Zero.ToString(), 1.0, false, 2);
1491 }
1492
1493 public void llPreloadSound(string sound)
1494 {
1495 m_host.AddScriptLPS(1);
1496 m_host.PreloadSound(sound);
1497 }
1498
1499 /// <summary>
1500 /// Return a portion of the designated string bounded by
1501 /// inclusive indices (start and end). As usual, the negative
1502 /// indices, and the tolerance for out-of-bound values, makes
1503 /// this more complicated than it might otherwise seem.
1504 /// </summary>
1505
1506 public string llGetSubString(string src, int start, int end)
1507 {
1508
1509 m_host.AddScriptLPS(1);
1510
1511 // Normalize indices (if negative).
1512 // After normlaization they may still be
1513 // negative, but that is now relative to
1514 // the start, rather than the end, of the
1515 // sequence.
1516
1517 if (start < 0)
1518 {
1519 start = src.Length+start;
1520 }
1521 if (end < 0)
1522 {
1523 end = src.Length+end;
1524 }
1525
1526 // Conventional substring
1527 if (start <= end)
1528 {
1529 // Implies both bounds are out-of-range.
1530 if (end < 0 || start >= src.Length)
1531 {
1532 return String.Empty;
1533 }
1534 // If end is positive, then it directly
1535 // corresponds to the lengt of the substring
1536 // needed (plus one of course). BUT, it
1537 // must be within bounds.
1538 if (end >= src.Length)
1539 {
1540 end = src.Length-1;
1541 }
1542
1543 if (start < 0)
1544 {
1545 return src.Substring(0,end+1);
1546 }
1547 // Both indices are positive
1548 return src.Substring(start, (end+1) - start);
1549 }
1550
1551 // Inverted substring (end < start)
1552 else
1553 {
1554 // Implies both indices are below the
1555 // lower bound. In the inverted case, that
1556 // means the entire string will be returned
1557 // unchanged.
1558 if (start < 0)
1559 {
1560 return src;
1561 }
1562 // If both indices are greater than the upper
1563 // bound the result may seem initially counter
1564 // intuitive.
1565 if (end >= src.Length)
1566 {
1567 return src;
1568 }
1569
1570 if (end < 0)
1571 {
1572 if (start < src.Length)
1573 {
1574 return src.Substring(start);
1575 }
1576 else
1577 {
1578 return String.Empty;
1579 }
1580 }
1581 else
1582 {
1583 if (start < src.Length)
1584 {
1585 return src.Substring(0,end+1) + src.Substring(start);
1586 }
1587 else
1588 {
1589 return src.Substring(0,end+1);
1590 }
1591 }
1592 }
1593 }
1594
1595 /// <summary>
1596 /// Delete substring removes the specified substring bounded
1597 /// by the inclusive indices start and end. Indices may be
1598 /// negative (indicating end-relative) and may be inverted,
1599 /// i.e. end < start.
1600 /// </summary>
1601
1602 public string llDeleteSubString(string src, int start, int end)
1603 {
1604
1605 m_host.AddScriptLPS(1);
1606
1607 // Normalize indices (if negative).
1608 // After normlaization they may still be
1609 // negative, but that is now relative to
1610 // the start, rather than the end, of the
1611 // sequence.
1612 if (start < 0)
1613 {
1614 start = src.Length+start;
1615 }
1616 if (end < 0)
1617 {
1618 end = src.Length+end;
1619 }
1620 // Conventionally delimited substring
1621 if (start <= end)
1622 {
1623 // If both bounds are outside of the existing
1624 // string, then return unchanges.
1625 if (end < 0 || start >= src.Length)
1626 {
1627 return src;
1628 }
1629 // At least one bound is in-range, so we
1630 // need to clip the out-of-bound argument.
1631 if (start < 0)
1632 {
1633 start = 0;
1634 }
1635
1636 if (end >= src.Length)
1637 {
1638 end = src.Length-1;
1639 }
1640
1641 return src.Remove(start,end-start+1);
1642 }
1643 // Inverted substring
1644 else
1645 {
1646 // In this case, out of bounds means that
1647 // the existing string is part of the cut.
1648 if (start < 0 || end >= src.Length)
1649 {
1650 return String.Empty;
1651 }
1652
1653 if (end > 0)
1654 {
1655 if (start < src.Length)
1656 {
1657 return src.Remove(start).Remove(0,end+1);
1658 }
1659 else
1660 {
1661 return src.Remove(0,end+1);
1662 }
1663 }
1664 else
1665 {
1666 if (start < src.Length)
1667 {
1668 return src.Remove(start);
1669 }
1670 else
1671 {
1672 return src;
1673 }
1674 }
1675 }
1676 }
1677
1678 /// <summary>
1679 /// Insert string inserts the specified string identified by src
1680 /// at the index indicated by index. Index may be negative, in
1681 /// which case it is end-relative. The index may exceed either
1682 /// string bound, with the result being a concatenation.
1683 /// </summary>
1684
1685 public string llInsertString(string dest, int index, string src)
1686 {
1687
1688 m_host.AddScriptLPS(1);
1689
1690 // Normalize indices (if negative).
1691 // After normlaization they may still be
1692 // negative, but that is now relative to
1693 // the start, rather than the end, of the
1694 // sequence.
1695 if (index < 0)
1696 {
1697 index = dest.Length+index;
1698
1699 // Negative now means it is less than the lower
1700 // bound of the string.
1701
1702 if (index < 0)
1703 {
1704 return src+dest;
1705 }
1706
1707 }
1708
1709 if (index >= dest.Length)
1710 {
1711 return dest+src;
1712 }
1713
1714 // The index is in bounds.
1715 // In this case the index refers to the index that will
1716 // be assigned to the first character of the inserted string.
1717 // So unlike the other string operations, we do not add one
1718 // to get the correct string length.
1719 return dest.Substring(0,index)+src+dest.Substring(index);
1720
1721 }
1722
1723 public string llToUpper(string src)
1724 {
1725 m_host.AddScriptLPS(1);
1726 return src.ToUpper();
1727 }
1728
1729 public string llToLower(string src)
1730 {
1731 m_host.AddScriptLPS(1);
1732 return src.ToLower();
1733 }
1734
1735 public LSL_Types.LSLInteger llGiveMoney(string destination, int amount)
1736 {
1737 LLUUID invItemID=InventorySelf();
1738 if (invItemID == LLUUID.Zero)
1739 return 0;
1740
1741 m_host.AddScriptLPS(1);
1742
1743 if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero)
1744 return 0;
1745
1746 if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_DEBIT) == 0)
1747 {
1748 LSLError("No permissions to give money");
1749 return 0;
1750 }
1751
1752 LLUUID toID=new LLUUID();
1753
1754 if (!LLUUID.TryParse(destination, out toID))
1755 {
1756 LSLError("Bad key in llGiveMoney");
1757 return 0;
1758 }
1759
1760 IMoneyModule money=World.RequestModuleInterface<IMoneyModule>();
1761
1762 if (money == null)
1763 {
1764 NotImplemented("llGiveMoney");
1765 return 0;
1766 }
1767
1768 bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
1769
1770 if (result)
1771 return 1;
1772
1773 return 0;
1774 }
1775
1776 public void llMakeExplosion()
1777 {
1778 m_host.AddScriptLPS(1);
1779 NotImplemented("llMakeExplosion");
1780 }
1781
1782 public void llMakeFountain()
1783 {
1784 m_host.AddScriptLPS(1);
1785 NotImplemented("llMakeFountain");
1786 }
1787
1788 public void llMakeSmoke()
1789 {
1790 m_host.AddScriptLPS(1);
1791 NotImplemented("llMakeSmoke");
1792 }
1793
1794 public void llMakeFire()
1795 {
1796 m_host.AddScriptLPS(1);
1797 NotImplemented("llMakeFire");
1798 }
1799
1800 public void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param)
1801 {
1802 m_host.AddScriptLPS(1);
1803 //NotImplemented("llRezObject");
1804 bool found = false;
1805
1806 // Instead of using return;, I'm using continue; because in our TaskInventory implementation
1807 // it's possible to have two items with the same task inventory name.
1808 // this is an easter egg of sorts.
1809
1810 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
1811 {
1812 if (inv.Value.Name == inventory)
1813 {
1814 // make sure we're an object.
1815 if (inv.Value.InvType != (int)InventoryType.Object)
1816 {
1817 llSay(0, "Unable to create requested object. Object is missing from database.");
1818 continue;
1819 }
1820
1821 LLVector3 llpos = new LLVector3((float)pos.x, (float)pos.y, (float)pos.z);
1822
1823 // test if we're further away then 10m
1824 if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10)
1825 return; // wiki says, if it's further away then 10m, silently fail.
1826
1827 LLVector3 llvel = new LLVector3((float)vel.x, (float)vel.y, (float)vel.z);
1828
1829 // need the magnitude later
1830 float velmag = (float)Util.GetMagnitude(llvel);
1831
1832 SceneObjectGroup new_group = World.RezObject(inv.Value, llpos, new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param);
1833
1834 // If either of these are null, then there was an unknown error.
1835 if (new_group == null)
1836 continue;
1837 if (new_group.RootPart == null)
1838 continue;
1839
1840 // objects rezzed with this method are die_at_edge by default.
1841 new_group.RootPart.SetDieAtEdge(true);
1842
1843 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
1844 "object_rez", new Object[] {
1845 new LSL_Types.LSLString(
1846 new_group.RootPart.UUID.ToString()) },
1847 new XDetectParams[0]));
1848
1849 float groupmass = new_group.GetMass();
1850
1851 //Recoil.
1852 llApplyImpulse(new LSL_Types.Vector3(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0);
1853 found = true;
1854 //script delay
1855 System.Threading.Thread.Sleep((int)((groupmass * velmag) / 10));
1856 break;
1857 }
1858 }
1859 if (!found)
1860 llSay(0, "Could not find object " + inventory);
1861 }
1862
1863 public void llLookAt(LSL_Types.Vector3 target, double strength, double damping)
1864 {
1865 m_host.AddScriptLPS(1);
1866 NotImplemented("llLookAt");
1867 }
1868
1869 public void llStopLookAt()
1870 {
1871 m_host.AddScriptLPS(1);
1872 NotImplemented("llStopLookAt");
1873 }
1874
1875 public void llSetTimerEvent(double sec)
1876 {
1877 m_host.AddScriptLPS(1);
1878 // Setting timer repeat
1879 m_ScriptEngine.m_ASYNCLSLCommandManager.m_Timer.SetTimerEvent(m_localID, m_itemID, sec);
1880 }
1881
1882 public void llSleep(double sec)
1883 {
1884 m_host.AddScriptLPS(1);
1885 Thread.Sleep((int)(sec * 1000));
1886 }
1887
1888 public double llGetMass()
1889 {
1890 m_host.AddScriptLPS(1);
1891 return m_host.GetMass();
1892 }
1893
1894 public void llCollisionFilter(string name, string id, int accept)
1895 {
1896 m_host.AddScriptLPS(1);
1897 NotImplemented("llCollisionFilter");
1898 }
1899
1900 public void llTakeControls(int controls, int accept, int pass_on)
1901 {
1902 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
1903 {
1904 return;
1905 }
1906
1907 if (m_host.TaskInventory[InventorySelf()].PermsGranter != LLUUID.Zero)
1908 {
1909 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
1910
1911 if (presence != null)
1912 {
1913 if ((m_host.TaskInventory[InventorySelf()].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS) != 0)
1914 {
1915 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID);
1916
1917 }
1918 }
1919 }
1920
1921 m_host.AddScriptLPS(1);
1922 //NotImplemented("llTakeControls");
1923 }
1924
1925 public void llReleaseControls()
1926 {
1927 m_host.AddScriptLPS(1);
1928
1929 if (!m_host.TaskInventory.ContainsKey(InventorySelf()))
1930 {
1931 return;
1932 }
1933
1934 if (m_host.TaskInventory[InventorySelf()].PermsGranter != LLUUID.Zero)
1935 {
1936 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter);
1937
1938 if (presence != null)
1939 {
1940 if ((m_host.TaskInventory[InventorySelf()].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS) != 0)
1941 {
1942 // Unregister controls from Presence
1943 presence.UnRegisterControlEventsToScript(m_localID, m_itemID);
1944 // Remove Take Control permission.
1945 m_host.TaskInventory[InventorySelf()].PermsMask &= ~BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS;
1946 }
1947 }
1948 }
1949 }
1950
1951 public void llAttachToAvatar(int attachment)
1952 {
1953 m_host.AddScriptLPS(1);
1954 NotImplemented("llAttachToAvatar");
1955 }
1956
1957 public void llDetachFromAvatar()
1958 {
1959 m_host.AddScriptLPS(1);
1960 NotImplemented("llDetachFromAvatar");
1961 }
1962
1963 public void llTakeCamera()
1964 {
1965 m_host.AddScriptLPS(1);
1966 NotImplemented("llTakeCamera");
1967 }
1968
1969 public void llReleaseCamera()
1970 {
1971 m_host.AddScriptLPS(1);
1972 NotImplemented("llReleaseCamera");
1973 }
1974
1975 public string llGetOwner()
1976 {
1977 m_host.AddScriptLPS(1);
1978
1979 return m_host.ObjectOwner.ToString();
1980 }
1981
1982 public void llInstantMessage(string user, string message)
1983 {
1984 m_host.AddScriptLPS(1);
1985
1986 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
1987 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
1988 // but I don't think we have a list of scenes available from here.
1989 // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
1990
1991 // user is a UUID
1992
1993 // TODO: figure out values for client, fromSession, and imSessionID
1994 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
1995 LLUUID friendTransactionID = LLUUID.Random();
1996
1997 //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID);
1998
1999 GridInstantMessage msg = new GridInstantMessage();
2000 msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.UUID;
2001 msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID;
2002 msg.toAgentID = new Guid(user); // toAgentID.UUID;
2003 msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here
2004// Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
2005// Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
2006 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
2007 //if (client != null)
2008 //{
2009 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
2010 //}
2011 //else
2012 //{
2013 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
2014 //}
2015 msg.message = message;
2016 msg.dialog = (byte)19; // messgage from script ??? // dialog;
2017 msg.fromGroup = false;// fromGroup;
2018 msg.offline = (byte)0; //offline;
2019 msg.ParentEstateID = 0; //ParentEstateID;
2020 msg.Position = new sLLVector3();// new sLLVector3(m_host.AbsolutePosition);
2021 msg.RegionID = World.RegionInfo.RegionID.UUID;//RegionID.UUID;
2022 msg.binaryBucket = new byte[0];// binaryBucket;
2023 World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule);
2024 // NotImplemented("llInstantMessage");
2025 }
2026
2027 public void llEmail(string address, string subject, string message)
2028 {
2029 m_host.AddScriptLPS(1);
2030 NotImplemented("llEmail");
2031 }
2032
2033 public void llGetNextEmail(string address, string subject)
2034 {
2035 m_host.AddScriptLPS(1);
2036 NotImplemented("llGetNextEmail");
2037 }
2038
2039 public string llGetKey()
2040 {
2041 m_host.AddScriptLPS(1);
2042 return m_host.UUID.ToString();
2043 }
2044
2045 public void llSetBuoyancy(double buoyancy)
2046 {
2047 m_host.AddScriptLPS(1);
2048 if (m_host.ParentGroup != null)
2049 {
2050 if (m_host.ParentGroup.RootPart != null)
2051 {
2052 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
2053 }
2054 }
2055 }
2056
2057
2058
2059 public void llSetHoverHeight(double height, int water, double tau)
2060 {
2061 m_host.AddScriptLPS(1);
2062 NotImplemented("llSetHoverHeight");
2063 }
2064
2065 public void llStopHover()
2066 {
2067 m_host.AddScriptLPS(1);
2068 NotImplemented("llStopHover");
2069 }
2070
2071 public void llMinEventDelay(double delay)
2072 {
2073 m_host.AddScriptLPS(1);
2074 NotImplemented("llMinEventDelay");
2075 }
2076
2077 public void llSoundPreload()
2078 {
2079 m_host.AddScriptLPS(1);
2080 NotImplemented("llSoundPreload");
2081 }
2082
2083 public void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping)
2084 {
2085 m_host.AddScriptLPS(1);
2086 NotImplemented("llRotLookAt");
2087 }
2088
2089 public LSL_Types.LSLInteger llStringLength(string str)
2090 {
2091 m_host.AddScriptLPS(1);
2092 if (str.Length > 0)
2093 {
2094 return str.Length;
2095 }
2096 else
2097 {
2098 return 0;
2099 }
2100 }
2101
2102 public void llStartAnimation(string anim)
2103 {
2104 m_host.AddScriptLPS(1);
2105
2106 LLUUID invItemID=InventorySelf();
2107 if (invItemID == LLUUID.Zero)
2108 return;
2109
2110 if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero)
2111 return;
2112
2113 if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2114 {
2115 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2116
2117 if (presence != null)
2118 {
2119 // Do NOT try to parse LLUUID, animations cannot be triggered by ID
2120 LLUUID animID=InventoryKey(anim, (int)AssetType.Animation);
2121 if (animID == LLUUID.Zero)
2122 presence.AddAnimation(anim);
2123 else
2124 presence.AddAnimation(animID);
2125 }
2126 }
2127 }
2128
2129 public void llStopAnimation(string anim)
2130 {
2131 m_host.AddScriptLPS(1);
2132
2133 LLUUID invItemID=InventorySelf();
2134 if (invItemID == LLUUID.Zero)
2135 return;
2136
2137 if (m_host.TaskInventory[invItemID].PermsGranter == LLUUID.Zero)
2138 return;
2139
2140 if ((m_host.TaskInventory[invItemID].PermsMask & BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
2141 {
2142 LLUUID animID = new LLUUID();
2143
2144 if (!LLUUID.TryParse(anim, out animID))
2145 {
2146 animID=InventoryKey(anim);
2147 }
2148
2149 if (animID == LLUUID.Zero)
2150 return;
2151
2152 ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter);
2153
2154 if (presence != null)
2155 {
2156 if (animID == LLUUID.Zero)
2157 presence.RemoveAnimation(anim);
2158 else
2159 presence.RemoveAnimation(animID);
2160 }
2161 }
2162 }
2163
2164 public void llPointAt()
2165 {
2166 m_host.AddScriptLPS(1);
2167 NotImplemented("llPointAt");
2168 }
2169
2170 public void llStopPointAt()
2171 {
2172 m_host.AddScriptLPS(1);
2173 NotImplemented("llStopPointAt");
2174 }
2175
2176 public void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain)
2177 {
2178 m_host.AddScriptLPS(1);
2179 m_host.RotationalVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2180 m_host.AngularVelocity = new LLVector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate));
2181 m_host.ScheduleTerseUpdate();
2182 m_host.SendTerseUpdateToAllClients();
2183 }
2184
2185 public LSL_Types.LSLInteger llGetStartParameter()
2186 {
2187 m_host.AddScriptLPS(1);
2188 // NotImplemented("llGetStartParameter");
2189 return m_host.ParentGroup.StartParameter;
2190 }
2191
2192 public void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos)
2193 {
2194 m_host.AddScriptLPS(1);
2195 NotImplemented("llGodLikeRezObject");
2196 }
2197
2198 public void llRequestPermissions(string agent, int perm)
2199 {
2200 LLUUID agentID=new LLUUID();
2201
2202 if (!LLUUID.TryParse(agent, out agentID))
2203 return;
2204
2205 LLUUID invItemID=InventorySelf();
2206
2207 if (invItemID == LLUUID.Zero)
2208 return; // Not in a prim? How??
2209
2210 if (agentID == LLUUID.Zero || perm == 0) // Releasing permissions
2211 {
2212 m_host.TaskInventory[invItemID].PermsGranter=LLUUID.Zero;
2213 m_host.TaskInventory[invItemID].PermsMask=0;
2214
2215 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2216 "run_time_permissions", new Object[] {
2217 new LSL_Types.LSLInteger(0) },
2218 new XDetectParams[0]));
2219
2220 return;
2221 }
2222
2223 m_host.AddScriptLPS(1);
2224
2225 if (m_host.ParentGroup.RootPart.m_IsAttachment && agent == m_host.ParentGroup.RootPart.m_attachedAvatar)
2226 {
2227 // When attached, certain permissions are implicit if requested from owner
2228 int implicitPerms = BuiltIn_Commands_BaseClass.PERMISSION_TAKE_CONTROLS |
2229 BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION |
2230 BuiltIn_Commands_BaseClass.PERMISSION_ATTACH;
2231
2232 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2233 {
2234 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2235 m_host.TaskInventory[invItemID].PermsMask=perm;
2236
2237 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2238 "run_time_permissions", new Object[] {
2239 new LSL_Types.LSLInteger(perm) },
2240 new XDetectParams[0]));
2241
2242 return;
2243 }
2244 }
2245 else if (m_host.m_sitTargetAvatar == agentID) // Sitting avatar
2246 {
2247 // When agent is sitting, certain permissions are implicit if requested from sitting agent
2248 int implicitPerms = BuiltIn_Commands_BaseClass.PERMISSION_TRIGGER_ANIMATION |
2249 BuiltIn_Commands_BaseClass.PERMISSION_TRACK_CAMERA;
2250
2251 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
2252 {
2253 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2254 m_host.TaskInventory[invItemID].PermsMask=perm;
2255
2256 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2257 "run_time_permissions", new Object[] {
2258 new LSL_Types.LSLInteger(perm) },
2259 new XDetectParams[0]));
2260
2261 return;
2262 }
2263 }
2264
2265 ScenePresence presence = World.GetScenePresence(agentID);
2266
2267 if (presence != null)
2268 {
2269 string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID);
2270 if (ownerName == String.Empty)
2271 ownerName="(hippos)";
2272
2273 if (!m_waitingForScriptAnswer)
2274 {
2275 m_host.TaskInventory[invItemID].PermsGranter=agentID;
2276 m_host.TaskInventory[invItemID].PermsMask=0;
2277 presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer;
2278 m_waitingForScriptAnswer=true;
2279 }
2280
2281 presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm);
2282 return;
2283 }
2284
2285 // Requested agent is not in range, refuse perms
2286 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2287 "run_time_permissions", new Object[] {
2288 new LSL_Types.LSLInteger(0) },
2289 new XDetectParams[0]));
2290 }
2291
2292 void handleScriptAnswer(IClientAPI client, LLUUID taskID, LLUUID itemID, int answer)
2293 {
2294 if (taskID != m_host.UUID)
2295 return;
2296
2297 LLUUID invItemID=InventorySelf();
2298
2299 if (invItemID == LLUUID.Zero)
2300 return;
2301
2302 client.OnScriptAnswer-=handleScriptAnswer;
2303 m_waitingForScriptAnswer=false;
2304
2305 m_host.TaskInventory[invItemID].PermsMask=answer;
2306 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
2307 "run_time_permissions", new Object[] {
2308 new LSL_Types.LSLInteger(answer) },
2309 new XDetectParams[0]));
2310 }
2311
2312 public string llGetPermissionsKey()
2313 {
2314 m_host.AddScriptLPS(1);
2315
2316 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2317 {
2318 if (item.Type == 10 && item.ItemID == m_itemID)
2319 {
2320 return item.PermsGranter.ToString();
2321 }
2322 }
2323
2324 return LLUUID.Zero.ToString();
2325 }
2326
2327 public LSL_Types.LSLInteger llGetPermissions()
2328 {
2329 m_host.AddScriptLPS(1);
2330
2331 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2332 {
2333 if (item.Type == 10 && item.ItemID == m_itemID)
2334 {
2335 return item.PermsMask;
2336 }
2337 }
2338
2339 return 0;
2340 }
2341
2342 public LSL_Types.LSLInteger llGetLinkNumber()
2343 {
2344 m_host.AddScriptLPS(1);
2345
2346 if (m_host.ParentGroup.Children.Count > 0)
2347 {
2348 return m_host.LinkNum + 1;
2349 }
2350 else
2351 {
2352 return 0;
2353 }
2354 }
2355
2356 public void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face)
2357 {
2358 m_host.AddScriptLPS(1);
2359 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
2360 if (linknumber > -1)
2361 {
2362 LLObject.TextureEntry tex = part.Shape.Textures;
2363 LLColor texcolor;
2364 if (face > -1)
2365 {
2366 texcolor = tex.CreateFace((uint)face).RGBA;
2367 texcolor.R = (float)Math.Abs(color.x - 1);
2368 texcolor.G = (float)Math.Abs(color.y - 1);
2369 texcolor.B = (float)Math.Abs(color.z - 1);
2370 tex.FaceTextures[face].RGBA = texcolor;
2371 part.UpdateTexture(tex);
2372 return;
2373 }
2374 else if (face == -1)
2375 {
2376 texcolor = tex.DefaultTexture.RGBA;
2377 texcolor.R = (float)Math.Abs(color.x - 1);
2378 texcolor.G = (float)Math.Abs(color.y - 1);
2379 texcolor.B = (float)Math.Abs(color.z - 1);
2380 tex.DefaultTexture.RGBA = texcolor;
2381 for (uint i = 0; i < 32; i++)
2382 {
2383 if (tex.FaceTextures[i] != null)
2384 {
2385 texcolor = tex.FaceTextures[i].RGBA;
2386 texcolor.R = (float)Math.Abs(color.x - 1);
2387 texcolor.G = (float)Math.Abs(color.y - 1);
2388 texcolor.B = (float)Math.Abs(color.z - 1);
2389 tex.FaceTextures[i].RGBA = texcolor;
2390 }
2391 }
2392 texcolor = tex.DefaultTexture.RGBA;
2393 texcolor.R = (float)Math.Abs(color.x - 1);
2394 texcolor.G = (float)Math.Abs(color.y - 1);
2395 texcolor.B = (float)Math.Abs(color.z - 1);
2396 tex.DefaultTexture.RGBA = texcolor;
2397 part.UpdateTexture(tex);
2398 return;
2399 }
2400 return;
2401 }
2402 else if (linknumber == -1)
2403 {
2404 int num = m_host.ParentGroup.PrimCount;
2405 for (int w = 0; w < num; w++)
2406 {
2407 linknumber = w;
2408 part = m_host.ParentGroup.GetLinkNumPart(linknumber);
2409 LLObject.TextureEntry tex = part.Shape.Textures;
2410 LLColor texcolor;
2411 if (face > -1)
2412 {
2413 texcolor = tex.CreateFace((uint)face).RGBA;
2414 texcolor.R = (float)Math.Abs(color.x - 1);
2415 texcolor.G = (float)Math.Abs(color.y - 1);
2416 texcolor.B = (float)Math.Abs(color.z - 1);
2417 tex.FaceTextures[face].RGBA = texcolor;
2418 part.UpdateTexture(tex);
2419 }
2420 else if (face == -1)
2421 {
2422 texcolor = tex.DefaultTexture.RGBA;
2423 texcolor.R = (float)Math.Abs(color.x - 1);
2424 texcolor.G = (float)Math.Abs(color.y - 1);
2425 texcolor.B = (float)Math.Abs(color.z - 1);
2426 tex.DefaultTexture.RGBA = texcolor;
2427 for (uint i = 0; i < 32; i++)
2428 {
2429 if (tex.FaceTextures[i] != null)
2430 {
2431 texcolor = tex.FaceTextures[i].RGBA;
2432 texcolor.R = (float)Math.Abs(color.x - 1);
2433 texcolor.G = (float)Math.Abs(color.y - 1);
2434 texcolor.B = (float)Math.Abs(color.z - 1);
2435 tex.FaceTextures[i].RGBA = texcolor;
2436 }
2437 }
2438 texcolor = tex.DefaultTexture.RGBA;
2439 texcolor.R = (float)Math.Abs(color.x - 1);
2440 texcolor.G = (float)Math.Abs(color.y - 1);
2441 texcolor.B = (float)Math.Abs(color.z - 1);
2442 tex.DefaultTexture.RGBA = texcolor;
2443 part.UpdateTexture(tex);
2444 }
2445 }
2446 return;
2447 }
2448 }
2449
2450 public void llCreateLink(string target, int parent)
2451 {
2452 m_host.AddScriptLPS(1);
2453 NotImplemented("llCreateLink");
2454 }
2455
2456 public void llBreakLink(int linknum)
2457 {
2458 m_host.AddScriptLPS(1);
2459 NotImplemented("llBreakLink");
2460 }
2461
2462 public void llBreakAllLinks()
2463 {
2464 m_host.AddScriptLPS(1);
2465 NotImplemented("llBreakAllLinks");
2466 }
2467
2468 public string llGetLinkKey(int linknum)
2469 {
2470 m_host.AddScriptLPS(1);
2471 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2472 if (part != null)
2473 {
2474 return part.UUID.ToString();
2475 }
2476 else
2477 {
2478 return LLUUID.Zero.ToString();
2479 }
2480 }
2481
2482 public string llGetLinkName(int linknum)
2483 {
2484 m_host.AddScriptLPS(1);
2485 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum);
2486 if (part != null)
2487 {
2488 return part.Name;
2489 }
2490 else
2491 {
2492 return LLUUID.Zero.ToString();
2493 }
2494 }
2495
2496 public LSL_Types.LSLInteger llGetInventoryNumber(int type)
2497 {
2498 m_host.AddScriptLPS(1);
2499 int count = 0;
2500 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
2501 {
2502 if (inv.Value.Type == type || type == -1)
2503 {
2504 count = count + 1;
2505 }
2506 }
2507 return count;
2508 }
2509
2510 public string llGetInventoryName(int type, int number)
2511 {
2512 m_host.AddScriptLPS(1);
2513 ArrayList keys = new ArrayList();
2514 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
2515 {
2516 if (inv.Value.Type == type || type == -1)
2517 {
2518 keys.Add(inv.Value.Name);
2519 }
2520 }
2521 if (keys.Count == 0)
2522 {
2523 return String.Empty;
2524 }
2525 keys.Sort();
2526 if (keys.Count > number)
2527 {
2528 return (string)keys[number];
2529 }
2530 return String.Empty;
2531 }
2532
2533 public void llSetScriptState(string name, int run)
2534 {
2535 LLUUID item;
2536
2537 m_host.AddScriptLPS(1);
2538
2539 // These functions are supposed to be robust,
2540 // so get the state one step at a time.
2541
2542 if ((item = ScriptByName(name)) != LLUUID.Zero)
2543 {
2544 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
2545 }
2546 else
2547 {
2548 ShoutError("llSetScriptState: script "+name+" not found");
2549 }
2550 }
2551
2552 public double llGetEnergy()
2553 {
2554 m_host.AddScriptLPS(1);
2555 // TODO: figure out real energy value
2556 return 1.0f;
2557 }
2558
2559 public void llGiveInventory(string destination, string inventory)
2560 {
2561 m_host.AddScriptLPS(1);
2562 NotImplemented("llGiveInventory");
2563 }
2564
2565 public void llRemoveInventory(string item)
2566 {
2567 m_host.AddScriptLPS(1);
2568 NotImplemented("llRemoveInventory");
2569 }
2570
2571 public void llSetText(string text, LSL_Types.Vector3 color, double alpha)
2572 {
2573 m_host.AddScriptLPS(1);
2574 Vector3 av3 = new Vector3((float)color.x, (float)color.y, (float)color.z);
2575 m_host.SetText(text, av3, alpha);
2576 }
2577
2578 public double llWater(LSL_Types.Vector3 offset)
2579 {
2580 m_host.AddScriptLPS(1);
2581 return World.RegionInfo.EstateSettings.waterHeight;
2582 }
2583
2584 public void llPassTouches(int pass)
2585 {
2586 m_host.AddScriptLPS(1);
2587 NotImplemented("llPassTouches");
2588 }
2589
2590 public string llRequestAgentData(string id, int data)
2591 {
2592 m_host.AddScriptLPS(1);
2593
2594 UserProfileData userProfile =
2595 World.CommsManager.UserService.GetUserProfile(id);
2596
2597 UserAgentData userAgent =
2598 World.CommsManager.UserService.GetAgentByUUID(id);
2599
2600 if (userProfile == null || userAgent == null)
2601 return LLUUID.Zero.ToString();
2602
2603 string reply = String.Empty;
2604
2605 switch (data)
2606 {
2607 case 1: // DATA_ONLINE (0|1)
2608 // TODO: implement fetching of this information
2609 if (userProfile.CurrentAgent.AgentOnline)
2610 reply = "1";
2611 else
2612 reply = "0";
2613 break;
2614 case 2: // DATA_NAME (First Last)
2615 reply = userProfile.FirstName + " " + userProfile.SurName;
2616 break;
2617 case 3: // DATA_BORN (YYYY-MM-DD)
2618 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
2619 born = born.AddSeconds(userProfile.Created);
2620 reply = born.ToString("yyyy-MM-dd");
2621 break;
2622 case 4: // DATA_RATING (0,0,0,0,0,0)
2623 reply = "0,0,0,0,0,0";
2624 break;
2625 case 8: // DATA_PAYINFO (0|1|2|3)
2626 reply = "0";
2627 break;
2628 default:
2629 return LLUUID.Zero.ToString(); // Raise no event
2630 }
2631
2632 LLUUID rq = LLUUID.Random();
2633
2634 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
2635 m_Dataserver.RegisterRequest(m_localID,
2636 m_itemID, rq.ToString());
2637
2638 m_ScriptEngine.m_ASYNCLSLCommandManager.
2639 m_Dataserver.DataserverReply(rq.ToString(), reply);
2640
2641 return tid.ToString();
2642 }
2643
2644 public string llRequestInventoryData(string name)
2645 {
2646 m_host.AddScriptLPS(1);
2647
2648 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2649 {
2650 if (item.Type == 3 && item.Name == name)
2651 {
2652 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
2653 m_Dataserver.RegisterRequest(m_localID,
2654 m_itemID, item.AssetID.ToString());
2655
2656 LLVector3 region = new LLVector3(
2657 World.RegionInfo.RegionLocX * Constants.RegionSize,
2658 World.RegionInfo.RegionLocY * Constants.RegionSize,
2659 0);
2660
2661 World.AssetCache.GetAsset(item.AssetID,
2662 delegate(LLUUID i, AssetBase a)
2663 {
2664 AssetLandmark lm = new AssetLandmark(a);
2665
2666 region += lm.Position;
2667
2668 string reply = region.ToString();
2669
2670 m_ScriptEngine.m_ASYNCLSLCommandManager.
2671 m_Dataserver.DataserverReply(i.ToString(),
2672 reply);
2673 }, false);
2674
2675 return tid.ToString();
2676 }
2677 }
2678
2679 return String.Empty;
2680 }
2681
2682 public void llSetDamage(double damage)
2683 {
2684 m_host.AddScriptLPS(1);
2685 NotImplemented("llSetDamage");
2686 }
2687
2688 public void llTeleportAgentHome(string agent)
2689 {
2690 m_host.AddScriptLPS(1);
2691 NotImplemented("llTeleportAgentHome");
2692 }
2693
2694 public void llModifyLand(int action, int brush)
2695 {
2696 m_host.AddScriptLPS(1);
2697 World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new LLVector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0));
2698 }
2699
2700 public void llCollisionSound(string impact_sound, double impact_volume)
2701 {
2702 m_host.AddScriptLPS(1);
2703 NotImplemented("llCollisionSound");
2704 }
2705
2706 public void llCollisionSprite(string impact_sprite)
2707 {
2708 m_host.AddScriptLPS(1);
2709 NotImplemented("llCollisionSprite");
2710 }
2711
2712 public string llGetAnimation(string id)
2713 {
2714 m_host.AddScriptLPS(1);
2715 NotImplemented("llGetAnimation");
2716 return String.Empty;
2717 }
2718
2719 public void llResetScript()
2720 {
2721 m_host.AddScriptLPS(1);
2722 m_ScriptEngine.ResetScript(m_itemID);
2723 }
2724
2725 public void llMessageLinked(int linknum, int num, string msg, string id)
2726 {
2727
2728 m_host.AddScriptLPS(1);
2729
2730 uint partLocalID;
2731 LLUUID partItemID;
2732
2733 switch ((int)linknum)
2734 {
2735
2736 case (int)BuiltIn_Commands_BaseClass.LINK_ROOT:
2737
2738 SceneObjectPart part = m_host.ParentGroup.RootPart;
2739
2740 foreach (TaskInventoryItem item in part.TaskInventory.Values)
2741 {
2742 if (item.Type == 10)
2743 {
2744 partLocalID = part.LocalId;
2745 partItemID = item.ItemID;
2746
2747 object[] resobj = new object[]
2748 {
2749 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2750 };
2751
2752 m_ScriptEngine.PostScriptEvent(partItemID,
2753 new XEventParams("link_message",
2754 resobj, new XDetectParams[0]));
2755 }
2756 }
2757
2758 break;
2759
2760 case (int)BuiltIn_Commands_BaseClass.LINK_SET:
2761
2762 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2763 {
2764
2765 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2766 {
2767 if (item.Type == 10)
2768 {
2769 partLocalID = partInst.LocalId;
2770 partItemID = item.ItemID;
2771 Object[] resobj = new object[]
2772 {
2773 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2774 };
2775
2776 m_ScriptEngine.PostScriptEvent(partItemID,
2777 new XEventParams("link_message",
2778 resobj, new XDetectParams[0]));
2779 }
2780 }
2781 }
2782
2783 break;
2784
2785 case (int)BuiltIn_Commands_BaseClass.LINK_ALL_OTHERS:
2786
2787 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2788 {
2789
2790 if (partInst.LocalId != m_host.LocalId)
2791 {
2792
2793 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2794 {
2795 if (item.Type == 10)
2796 {
2797 partLocalID = partInst.LocalId;
2798 partItemID = item.ItemID;
2799 Object[] resobj = new object[]
2800 {
2801 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2802 };
2803
2804 m_ScriptEngine.PostScriptEvent(partItemID,
2805 new XEventParams("link_message",
2806 resobj, new XDetectParams[0]));
2807 }
2808 }
2809
2810 }
2811 }
2812
2813 break;
2814
2815 case (int)BuiltIn_Commands_BaseClass.LINK_ALL_CHILDREN:
2816
2817 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2818 {
2819
2820 if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId)
2821 {
2822
2823 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2824 {
2825 if (item.Type == 10)
2826 {
2827 partLocalID = partInst.LocalId;
2828 partItemID = item.ItemID;
2829 Object[] resobj = new object[]
2830 {
2831 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2832 };
2833
2834 m_ScriptEngine.PostScriptEvent(partItemID,
2835 new XEventParams("link_message",
2836 resobj, new XDetectParams[0]));
2837 }
2838 }
2839
2840 }
2841 }
2842
2843 break;
2844
2845 case (int)BuiltIn_Commands_BaseClass.LINK_THIS:
2846
2847 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2848 {
2849 if (item.Type == 10)
2850 {
2851 partItemID = item.ItemID;
2852
2853 object[] resobj = new object[]
2854 {
2855 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2856 };
2857
2858 m_ScriptEngine.PostScriptEvent(partItemID,
2859 new XEventParams("link_message",
2860 resobj, new XDetectParams[0]));
2861 }
2862 }
2863
2864 break;
2865
2866 default:
2867
2868 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
2869 {
2870
2871 if ((partInst.LinkNum + 1) == linknum)
2872 {
2873
2874 foreach (TaskInventoryItem item in partInst.TaskInventory.Values)
2875 {
2876 if (item.Type == 10)
2877 {
2878 partLocalID = partInst.LocalId;
2879 partItemID = item.ItemID;
2880 Object[] resObjDef = new object[]
2881 {
2882 new LSL_Types.LSLInteger(m_host.LinkNum + 1), new LSL_Types.LSLInteger(num), new LSL_Types.LSLString(msg), new LSL_Types.LSLString(id)
2883 };
2884
2885 m_ScriptEngine.PostScriptEvent(partItemID,
2886 new XEventParams("link_message",
2887 resObjDef, new XDetectParams[0]));
2888 }
2889 }
2890
2891 }
2892 }
2893
2894 break;
2895
2896 }
2897
2898 }
2899
2900 public void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local)
2901 {
2902 m_host.AddScriptLPS(1);
2903 NotImplemented("llPushObject");
2904 }
2905
2906 public void llPassCollisions(int pass)
2907 {
2908 m_host.AddScriptLPS(1);
2909 NotImplemented("llPassCollisions");
2910 }
2911
2912 public string llGetScriptName()
2913 {
2914
2915 string result = String.Empty;
2916
2917 m_host.AddScriptLPS(1);
2918
2919 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
2920 {
2921 if (item.Type == 10 && item.ItemID == m_itemID)
2922 {
2923 result = item.Name!=null?item.Name:String.Empty;
2924 break;
2925 }
2926 }
2927
2928 return result;
2929
2930 }
2931
2932 public LSL_Types.LSLInteger llGetNumberOfSides()
2933 {
2934 m_host.AddScriptLPS(1);
2935 NotImplemented("llGetNumberOfSides");
2936 return 0;
2937 }
2938
2939
2940 /* The new / changed functions were tested with the following LSL script:
2941
2942 default
2943 {
2944 state_entry()
2945 {
2946 rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
2947
2948 llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
2949 llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
2950
2951 // convert back and forth between quaternion <-> vector and angle
2952
2953 rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
2954
2955 llOwnerSay("Old rotation was: "+(string) rot);
2956 llOwnerSay("re-converted rotation is: "+(string) newrot);
2957
2958 llSetRot(rot); // to check the parameters in the prim
2959 }
2960 }
2961 */
2962
2963
2964
2965 // Xantor 29/apr/2008
2966 // Returns rotation described by rotating angle radians about axis.
2967 // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
2968 public LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle)
2969 {
2970 m_host.AddScriptLPS(1);
2971
2972 double x, y, z, s, t;
2973
2974 s = Math.Cos(angle / 2);
2975 t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs
2976 x = axis.x * t;
2977 y = axis.y * t;
2978 z = axis.z * t;
2979
2980 return new LSL_Types.Quaternion(x,y,z,s);
2981 }
2982
2983
2984 // Xantor 29/apr/2008
2985 // converts a Quaternion to X,Y,Z axis rotations
2986 public LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot)
2987 {
2988 m_host.AddScriptLPS(1);
2989 double x,y,z;
2990
2991 if (rot.s > 1) // normalization needed
2992 {
2993 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
2994 rot.z * rot.z + rot.s * rot.s);
2995
2996 rot.x /= length;
2997 rot.y /= length;
2998 rot.z /= length;
2999 rot.s /= length;
3000
3001 }
3002
3003 double angle = 2 * Math.Acos(rot.s);
3004 double s = Math.Sqrt(1 - rot.s * rot.s);
3005 if (s < 0.001)
3006 {
3007 x = 1;
3008 y = z = 0;
3009 }
3010 else
3011 {
3012 x = rot.x / s; // normalise axis
3013 y = rot.y / s;
3014 z = rot.z / s;
3015 }
3016
3017
3018 return new LSL_Types.Vector3(x,y,z);
3019
3020
3021// NotImplemented("llRot2Axis");
3022 }
3023
3024
3025 // Returns the angle of a quaternion (see llRot2Axis for the axis)
3026 public double llRot2Angle(LSL_Types.Quaternion rot)
3027 {
3028 m_host.AddScriptLPS(1);
3029
3030 if (rot.s > 1) // normalization needed
3031 {
3032 double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y +
3033 rot.z * rot.z + rot.s * rot.s);
3034
3035 rot.x /= length;
3036 rot.y /= length;
3037 rot.z /= length;
3038 rot.s /= length;
3039
3040 }
3041
3042 double angle = 2 * Math.Acos(rot.s);
3043
3044 return angle;
3045
3046// NotImplemented("llRot2Angle");
3047 }
3048
3049 public double llAcos(double val)
3050 {
3051 m_host.AddScriptLPS(1);
3052 return (double)Math.Acos(val);
3053 }
3054
3055 public double llAsin(double val)
3056 {
3057 m_host.AddScriptLPS(1);
3058 return (double)Math.Asin(val);
3059 }
3060
3061 // Xantor 30/apr/2008
3062 public double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b)
3063 {
3064 m_host.AddScriptLPS(1);
3065
3066 return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2;
3067 }
3068
3069 public string llGetInventoryKey(string name)
3070 {
3071 m_host.AddScriptLPS(1);
3072 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
3073 {
3074 if (inv.Value.Name == name)
3075 {
3076 if ((inv.Value.OwnerMask & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
3077 {
3078 return inv.Value.AssetID.ToString();
3079 }
3080 else
3081 {
3082 return LLUUID.Zero.ToString();
3083 }
3084 }
3085 }
3086 return LLUUID.Zero.ToString();
3087 }
3088
3089 public void llAllowInventoryDrop(int add)
3090 {
3091 m_host.AddScriptLPS(1);
3092 NotImplemented("llAllowInventoryDrop");
3093 }
3094
3095 public LSL_Types.Vector3 llGetSunDirection()
3096 {
3097 m_host.AddScriptLPS(1);
3098
3099 LSL_Types.Vector3 SunDoubleVector3;
3100 LLVector3 SunFloatVector3;
3101
3102 // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule
3103 // have to convert from LLVector3 (float) to LSL_Types.Vector3 (double)
3104 SunFloatVector3 = World.RegionInfo.EstateSettings.sunPosition;
3105 SunDoubleVector3.x = (double)SunFloatVector3.X;
3106 SunDoubleVector3.y = (double)SunFloatVector3.Y;
3107 SunDoubleVector3.z = (double)SunFloatVector3.Z;
3108
3109 return SunDoubleVector3;
3110 }
3111
3112 public LSL_Types.Vector3 llGetTextureOffset(int face)
3113 {
3114 m_host.AddScriptLPS(1);
3115 LLObject.TextureEntry tex = m_host.Shape.Textures;
3116 LSL_Types.Vector3 offset;
3117 if (face == -1)
3118 {
3119 face = 0;
3120 }
3121 offset.x = tex.GetFace((uint)face).OffsetU;
3122 offset.y = tex.GetFace((uint)face).OffsetV;
3123 offset.z = 0.0;
3124 return offset;
3125 }
3126
3127 public LSL_Types.Vector3 llGetTextureScale(int side)
3128 {
3129 m_host.AddScriptLPS(1);
3130 LLObject.TextureEntry tex = m_host.Shape.Textures;
3131 LSL_Types.Vector3 scale;
3132 if (side == -1)
3133 {
3134 side = 0;
3135 }
3136 scale.x = tex.GetFace((uint)side).RepeatU;
3137 scale.y = tex.GetFace((uint)side).RepeatV;
3138 scale.z = 0.0;
3139 return scale;
3140 }
3141
3142 public double llGetTextureRot(int face)
3143 {
3144 m_host.AddScriptLPS(1);
3145 LLObject.TextureEntry tex = m_host.Shape.Textures;
3146 if (face == -1)
3147 {
3148 face = 0;
3149 }
3150 return tex.GetFace((uint)face).Rotation;
3151 }
3152
3153 public LSL_Types.LSLInteger llSubStringIndex(string source, string pattern)
3154 {
3155 m_host.AddScriptLPS(1);
3156 return source.IndexOf(pattern);
3157 }
3158
3159 public string llGetOwnerKey(string id)
3160 {
3161 m_host.AddScriptLPS(1);
3162 LLUUID key = new LLUUID();
3163 if (LLUUID.TryParse(id, out key))
3164 {
3165 return World.GetSceneObjectPart(World.Entities[key].LocalId).OwnerID.ToString();
3166 }
3167 else
3168 {
3169 return LLUUID.Zero.ToString();
3170 }
3171 }
3172
3173 public LSL_Types.Vector3 llGetCenterOfMass()
3174 {
3175 m_host.AddScriptLPS(1);
3176 NotImplemented("llGetCenterOfMass");
3177 return new LSL_Types.Vector3();
3178 }
3179
3180 public LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending)
3181 {
3182 m_host.AddScriptLPS(1);
3183 return src.Sort(stride, ascending);
3184 }
3185
3186 public LSL_Types.LSLInteger llGetListLength(LSL_Types.list src)
3187 {
3188 m_host.AddScriptLPS(1);
3189 return src.Length;
3190 }
3191
3192 public LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index)
3193 {
3194 m_host.AddScriptLPS(1);
3195 if (index < 0)
3196 {
3197 index = src.Length + index;
3198 }
3199 if (index >= src.Length)
3200 {
3201 return 0;
3202 }
3203 try
3204 {
3205 return Convert.ToInt32(src.Data[index]);
3206 }
3207 catch (FormatException)
3208 {
3209 return 0;
3210 }
3211 }
3212
3213 public double osList2Double(LSL_Types.list src, int index)
3214 {
3215 m_host.AddScriptLPS(1);
3216 if (index < 0)
3217 {
3218 index = src.Length + index;
3219 }
3220 if (index >= src.Length)
3221 {
3222 return 0.0;
3223 }
3224 return Convert.ToDouble(src.Data[index]);
3225 }
3226
3227 public double llList2Float(LSL_Types.list src, int index)
3228 {
3229 m_host.AddScriptLPS(1);
3230 if (index < 0)
3231 {
3232 index = src.Length + index;
3233 }
3234 if (index >= src.Length)
3235 {
3236 return 0.0;
3237 }
3238 try
3239 {
3240 return Convert.ToDouble(src.Data[index]);
3241 }
3242 catch (FormatException)
3243 {
3244 return 0.0;
3245 }
3246 }
3247
3248 public string llList2String(LSL_Types.list src, int index)
3249 {
3250 m_host.AddScriptLPS(1);
3251 if (index < 0)
3252 {
3253 index = src.Length + index;
3254 }
3255 if (index >= src.Length)
3256 {
3257 return String.Empty;
3258 }
3259 return src.Data[index].ToString();
3260 }
3261
3262 public string llList2Key(LSL_Types.list src, int index)
3263 {
3264 m_host.AddScriptLPS(1);
3265 if (index < 0)
3266 {
3267 index = src.Length + index;
3268 }
3269 if (index >= src.Length)
3270 {
3271 return "";
3272 }
3273 return src.Data[index].ToString();
3274 }
3275
3276 public LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index)
3277 {
3278 m_host.AddScriptLPS(1);
3279 if (index < 0)
3280 {
3281 index = src.Length + index;
3282 }
3283 if (index >= src.Length)
3284 {
3285 return new LSL_Types.Vector3(0, 0, 0);
3286 }
3287 if (src.Data[index].GetType() == typeof(LSL_Types.Vector3))
3288 {
3289 return (LSL_Types.Vector3)src.Data[index];
3290 }
3291 else
3292 {
3293 return new LSL_Types.Vector3(src.Data[index].ToString());
3294 }
3295 }
3296
3297 public LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index)
3298 {
3299 m_host.AddScriptLPS(1);
3300 if (index < 0)
3301 {
3302 index = src.Length + index;
3303 }
3304 if (index >= src.Length)
3305 {
3306 return new LSL_Types.Quaternion(0, 0, 0, 1);
3307 }
3308 if (src.Data[index].GetType() == typeof(LSL_Types.Quaternion))
3309 {
3310 return (LSL_Types.Quaternion)src.Data[index];
3311 }
3312 else
3313 {
3314 return new LSL_Types.Quaternion(src.Data[index].ToString());
3315 }
3316 }
3317
3318 public LSL_Types.list llList2List(LSL_Types.list src, int start, int end)
3319 {
3320 m_host.AddScriptLPS(1);
3321 return src.GetSublist(start, end);
3322 }
3323
3324 public LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end)
3325 {
3326 return src.DeleteSublist(end, start);
3327 }
3328
3329 public LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index)
3330 {
3331 m_host.AddScriptLPS(1);
3332 if (index < 0)
3333 {
3334 index = src.Length + index;
3335 }
3336 if (index >= src.Length)
3337 {
3338 return 0;
3339 }
3340
3341 if (src.Data[index] is Int32)
3342 return 1;
3343 if (src.Data[index] is Double)
3344 return 2;
3345 if (src.Data[index] is String)
3346 {
3347 LLUUID tuuid;
3348 if (LLUUID.TryParse(src.Data[index].ToString(), out tuuid))
3349 {
3350 return 3;
3351 }
3352 else
3353 {
3354 return 4;
3355 }
3356 }
3357 if (src.Data[index] is LSL_Types.Vector3)
3358 return 5;
3359 if (src.Data[index] is LSL_Types.Quaternion)
3360 return 6;
3361 if (src.Data[index] is LSL_Types.list)
3362 return 7;
3363 return 0;
3364
3365 }
3366
3367 /// <summary>
3368 /// Process the supplied list and return the
3369 /// content of the list formatted as a comma
3370 /// separated list. There is a space after
3371 /// each comma.
3372 /// </summary>
3373
3374 public string llList2CSV(LSL_Types.list src)
3375 {
3376
3377 string ret = String.Empty;
3378 int x = 0;
3379
3380 m_host.AddScriptLPS(1);
3381
3382 if (src.Data.Length > 0)
3383 {
3384 ret = src.Data[x++].ToString();
3385 for (; x < src.Data.Length; x++)
3386 {
3387 ret += ", "+src.Data[x].ToString();
3388 }
3389 }
3390
3391 return ret;
3392 }
3393
3394 /// <summary>
3395 /// The supplied string is scanned for commas
3396 /// and converted into a list. Commas are only
3397 /// effective if they are encountered outside
3398 /// of '<' '>' delimiters. Any whitespace
3399 /// before or after an element is trimmed.
3400 /// </summary>
3401
3402 public LSL_Types.list llCSV2List(string src)
3403 {
3404
3405 LSL_Types.list result = new LSL_Types.list();
3406 int parens = 0;
3407 int start = 0;
3408 int length = 0;
3409
3410 m_host.AddScriptLPS(1);
3411
3412 for (int i = 0; i < src.Length; i++)
3413 {
3414 switch (src[i])
3415 {
3416 case '<':
3417 parens++;
3418 length++;
3419 break;
3420 case '>':
3421 if (parens > 0)
3422 parens--;
3423 length++;
3424 break;
3425 case ',':
3426 if (parens == 0)
3427 {
3428 result.Add(src.Substring(start,length).Trim());
3429 start += length+1;
3430 length = 0;
3431 }
3432 else
3433 {
3434 length++;
3435 }
3436 break;
3437 default:
3438 length++;
3439 break;
3440 }
3441 }
3442
3443 result.Add(src.Substring(start,length).Trim());
3444
3445 return result;
3446 }
3447
3448 /// <summary>
3449 /// Randomizes the list, be arbitrarily reordering
3450 /// sublists of stride elements. As the stride approaches
3451 /// the size of the list, the options become very
3452 /// limited.
3453 /// </summary>
3454 /// <remarks>
3455 /// This could take a while for very large list
3456 /// sizes.
3457 /// </remarks>
3458
3459 public LSL_Types.list llListRandomize(LSL_Types.list src, int stride)
3460 {
3461
3462 LSL_Types.list result;
3463 Random rand = new Random();
3464
3465 int chunkk;
3466 int[] chunks;
3467 int index1;
3468 int index2;
3469 int tmp;
3470
3471 m_host.AddScriptLPS(1);
3472
3473 if (stride == 0)
3474 stride = 1;
3475
3476 // Stride MUST be a factor of the list length
3477 // If not, then return the src list. This also
3478 // traps those cases where stride > length.
3479
3480 if (src.Length != stride && src.Length%stride == 0)
3481 {
3482 chunkk = src.Length/stride;
3483
3484 chunks = new int[chunkk];
3485
3486 for (int i = 0; i < chunkk; i++)
3487 chunks[i] = i;
3488
3489 for (int i = 0; i < chunkk - 1; i++)
3490 {
3491 // randomly select 2 chunks
3492 index1 = rand.Next(rand.Next(65536));
3493 index1 = index1%chunkk;
3494 index2 = rand.Next(rand.Next(65536));
3495 index2 = index2%chunkk;
3496
3497 // and swap their relative positions
3498 tmp = chunks[index1];
3499 chunks[index1] = chunks[index2];
3500 chunks[index2] = tmp;
3501 }
3502
3503 // Construct the randomized list
3504
3505 result = new LSL_Types.list();
3506
3507 for (int i = 0; i < chunkk; i++)
3508 {
3509 for (int j = 0; j < stride; j++)
3510 {
3511 result.Add(src.Data[chunks[i]*stride+j]);
3512 }
3513 }
3514 }
3515 else {
3516 object[] array = new object[src.Length];
3517 Array.Copy(src.Data, 0, array, 0, src.Length);
3518 result = new LSL_Types.list(array);
3519 }
3520
3521 return result;
3522
3523 }
3524
3525 /// <summary>
3526 /// Elements in the source list starting with 0 and then
3527 /// every i+stride. If the stride is negative then the scan
3528 /// is backwards producing an inverted result.
3529 /// Only those elements that are also in the specified
3530 /// range are included in the result.
3531 /// </summary>
3532
3533 public LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride)
3534 {
3535
3536 LSL_Types.list result = new LSL_Types.list();
3537 int[] si = new int[2];
3538 int[] ei = new int[2];
3539 bool twopass = false;
3540
3541 m_host.AddScriptLPS(1);
3542
3543 // First step is always to deal with negative indices
3544
3545 if (start < 0)
3546 start = src.Length+start;
3547 if (end < 0)
3548 end = src.Length+end;
3549
3550 // Out of bounds indices are OK, just trim them
3551 // accordingly
3552
3553 if (start > src.Length)
3554 start = src.Length;
3555
3556 if (end > src.Length)
3557 end = src.Length;
3558
3559 // There may be one or two ranges to be considered
3560
3561 if (start != end)
3562 {
3563
3564 if (start <= end)
3565 {
3566 si[0] = start;
3567 ei[0] = end;
3568 }
3569 else
3570 {
3571 si[1] = start;
3572 ei[1] = src.Length;
3573 si[0] = 0;
3574 ei[0] = end;
3575 twopass = true;
3576 }
3577
3578 // The scan always starts from the beginning of the
3579 // source list, but members are only selected if they
3580 // fall within the specified sub-range. The specified
3581 // range values are inclusive.
3582 // A negative stride reverses the direction of the
3583 // scan producing an inverted list as a result.
3584
3585 if (stride == 0)
3586 stride = 1;
3587
3588 if (stride > 0)
3589 {
3590 for (int i = 0; i < src.Length; i += stride)
3591 {
3592 if (i<=ei[0] && i>=si[0])
3593 result.Add(src.Data[i]);
3594 if (twopass && i>=si[1] && i<=ei[1])
3595 result.Add(src.Data[i]);
3596 }
3597 }
3598 else if (stride < 0)
3599 {
3600 for (int i = src.Length - 1; i >= 0; i += stride)
3601 {
3602 if (i <= ei[0] && i >= si[0])
3603 result.Add(src.Data[i]);
3604 if (twopass && i >= si[1] && i <= ei[1])
3605 result.Add(src.Data[i]);
3606 }
3607 }
3608 }
3609
3610 return result;
3611 }
3612
3613 public LSL_Types.Vector3 llGetRegionCorner()
3614 {
3615 m_host.AddScriptLPS(1);
3616 return new LSL_Types.Vector3(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
3617 }
3618
3619 /// <summary>
3620 /// Insert the list identified by <src> into the
3621 /// list designated by <dest> such that the first
3622 /// new element has the index specified by <index>
3623 /// </summary>
3624
3625 public LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int index)
3626 {
3627
3628 LSL_Types.list pref = null;
3629 LSL_Types.list suff = null;
3630
3631 m_host.AddScriptLPS(1);
3632
3633 if (index < 0)
3634 {
3635 index = index+dest.Length;
3636 if (index < 0)
3637 {
3638 index = 0;
3639 }
3640 }
3641
3642 if (index != 0)
3643 {
3644 pref = dest.GetSublist(0,index-1);
3645 if (index < dest.Length)
3646 {
3647 suff = dest.GetSublist(index,-1);
3648 return pref + src + suff;
3649 }
3650 else
3651 {
3652 return pref + src;
3653 }
3654 }
3655 else
3656 {
3657 if (index < dest.Length)
3658 {
3659 suff = dest.GetSublist(index,-1);
3660 return src + suff;
3661 }
3662 else
3663 {
3664 return src;
3665 }
3666 }
3667
3668 }
3669
3670 /// <summary>
3671 /// Returns the index of the first occurrence of test
3672 /// in src.
3673 /// </summary>
3674
3675 public LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test)
3676 {
3677
3678 int index = -1;
3679 int length = src.Length - test.Length + 1;
3680
3681 m_host.AddScriptLPS(1);
3682
3683 // If either list is empty, do not match
3684
3685 if (src.Length != 0 && test.Length != 0)
3686 {
3687 for (int i = 0; i < length; i++)
3688 {
3689 if (src.Data[i].Equals(test.Data[0]))
3690 {
3691 int j;
3692 for (j = 1; j < test.Length; j++)
3693 if (!src.Data[i+j].Equals(test.Data[j]))
3694 break;
3695 if (j == test.Length)
3696 {
3697 index = i;
3698 break;
3699 }
3700 }
3701 }
3702 }
3703
3704 return index;
3705
3706 }
3707
3708 public string llGetObjectName()
3709 {
3710 m_host.AddScriptLPS(1);
3711 return m_host.Name!=null?m_host.Name:String.Empty;
3712 }
3713
3714 public void llSetObjectName(string name)
3715 {
3716 m_host.AddScriptLPS(1);
3717 m_host.Name = name!=null?name:String.Empty;
3718 }
3719
3720 public string llGetDate()
3721 {
3722 m_host.AddScriptLPS(1);
3723 DateTime date = DateTime.Now.ToUniversalTime();
3724 string result = date.ToString("yyyy-MM-dd");
3725 return result;
3726 }
3727
3728 public LSL_Types.LSLInteger llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir)
3729 {
3730 m_host.AddScriptLPS(1);
3731 NotImplemented("llEdgeOfWorld");
3732 return 0;
3733 }
3734
3735 public LSL_Types.LSLInteger llGetAgentInfo(string id)
3736 {
3737 m_host.AddScriptLPS(1);
3738 NotImplemented("llGetAgentInfo");
3739 return 0;
3740 }
3741
3742 public void llAdjustSoundVolume(double volume)
3743 {
3744 m_host.AddScriptLPS(1);
3745 m_host.AdjustSoundGain(volume);
3746 }
3747
3748 public void llSetSoundQueueing(int queue)
3749 {
3750 m_host.AddScriptLPS(1);
3751 NotImplemented("llSetSoundQueueing");
3752 }
3753
3754 public void llSetSoundRadius(double radius)
3755 {
3756 m_host.AddScriptLPS(1);
3757 NotImplemented("llSetSoundRadius");
3758 }
3759
3760 public string llKey2Name(string id)
3761 {
3762 m_host.AddScriptLPS(1);
3763 LLUUID key = new LLUUID();
3764 if (LLUUID.TryParse(id,out key))
3765 {
3766 ScenePresence presence = World.GetScenePresence(key);
3767
3768 if (presence != null)
3769 {
3770 return presence.ControllingClient.Name;
3771 //return presence.Name;
3772 }
3773
3774 if (World.GetSceneObjectPart(key) != null)
3775 {
3776 return World.GetSceneObjectPart(key).Name;
3777 }
3778 }
3779 return String.Empty;
3780 }
3781
3782
3783
3784 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
3785 {
3786 m_host.AddScriptLPS(1);
3787 Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
3788 pTexAnim.Flags =(uint) mode;
3789
3790 //ALL_SIDES
3791 if (face == -1)
3792 face = 255;
3793
3794 pTexAnim.Face = (uint)face;
3795 pTexAnim.Length = (float)length;
3796 pTexAnim.Rate = (float)rate;
3797 pTexAnim.SizeX = (uint)sizex;
3798 pTexAnim.SizeY = (uint)sizey;
3799 pTexAnim.Start = (float)start;
3800
3801 m_host.AddTextureAnimation(pTexAnim);
3802 m_host.SendFullUpdateToAllClients();
3803 }
3804
3805 public void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east,
3806 LSL_Types.Vector3 bottom_south_west)
3807 {
3808 m_host.AddScriptLPS(1);
3809 NotImplemented("llTriggerSoundLimited");
3810 }
3811
3812 public void llEjectFromLand(string pest)
3813 {
3814 m_host.AddScriptLPS(1);
3815 NotImplemented("llEjectFromLand");
3816 }
3817
3818 public LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers)
3819 {
3820 m_host.AddScriptLPS(1);
3821 LSL_Types.list ret = new LSL_Types.list();
3822 object[] delimiters = new object[separators.Length + spacers.Length];
3823 separators.Data.CopyTo(delimiters, 0);
3824 spacers.Data.CopyTo(delimiters, separators.Length);
3825 bool dfound = false;
3826 do
3827 {
3828 dfound = false;
3829 int cindex = -1;
3830 string cdeli = "";
3831 for (int i = 0; i < delimiters.Length; i++)
3832 {
3833 int index = str.IndexOf(delimiters[i].ToString());
3834 bool found = index != -1;
3835 if (found)
3836 {
3837 if ((cindex > index) || (cindex == -1))
3838 {
3839 cindex = index;
3840 cdeli = (string)delimiters[i];
3841 }
3842 dfound = dfound || found;
3843 }
3844 }
3845 if (cindex != -1)
3846 {
3847 if (cindex > 0)
3848 {
3849 ret.Add(str.Substring(0, cindex));
3850 if (spacers.Contains(cdeli))
3851 {
3852 ret.Add(cdeli);
3853 }
3854 }
3855 if (cindex == 0 && spacers.Contains(cdeli))
3856 {
3857 ret.Add(cdeli);
3858 }
3859 str = str.Substring(cindex + cdeli.Length);
3860 }
3861 } while (dfound);
3862 if (str != "")
3863 {
3864 ret.Add(str);
3865 }
3866 return ret;
3867 }
3868
3869 public LSL_Types.LSLInteger llOverMyLand(string id)
3870 {
3871
3872 m_host.AddScriptLPS(1);
3873 LLUUID key = new LLUUID();
3874 if (LLUUID.TryParse(id,out key))
3875 {
3876 SceneObjectPart obj = new SceneObjectPart();
3877 obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
3878 if (obj.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y))
3879 {
3880 return 1;
3881 }
3882 else
3883 {
3884 return 0;
3885 }
3886 }
3887 else
3888 {
3889 return 0;
3890 }
3891 }
3892
3893 public string llGetLandOwnerAt(LSL_Types.Vector3 pos)
3894 {
3895 m_host.AddScriptLPS(1);
3896 return World.GetLandOwner((float)pos.x, (float)pos.y).ToString();
3897 }
3898
3899 public LSL_Types.Vector3 llGetAgentSize(string id)
3900 {
3901 m_host.AddScriptLPS(1);
3902 NotImplemented("llGetAgentSize");
3903 return new LSL_Types.Vector3();
3904 }
3905
3906 public LSL_Types.LSLInteger llSameGroup(string agent)
3907 {
3908 m_host.AddScriptLPS(1);
3909 NotImplemented("llSameGroup");
3910 return 0;
3911 }
3912
3913 public void llUnSit(string id)
3914 {
3915 m_host.AddScriptLPS(1);
3916
3917 LLUUID key = new LLUUID();
3918 if (LLUUID.TryParse(id, out key))
3919 {
3920 ScenePresence av = World.GetScenePresence(key);
3921
3922 if (av != null)
3923 {
3924 if (llAvatarOnSitTarget() == id)
3925 {
3926 // if the avatar is sitting on this object, then
3927 // we can unsit them. We don't want random scripts unsitting random people
3928 // Lets avoid the popcorn avatar scenario.
3929 av.StandUp();
3930 }
3931 else
3932 {
3933 // If the object owner also owns the parcel
3934 // or
3935 // if the land is group owned and the object is group owned by the same group
3936 // or
3937 // if the object is owned by a person with estate access.
3938
3939 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
3940 if (parcel != null)
3941 {
3942 if (m_host.ObjectOwner == parcel.landData.ownerID ||
3943 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.groupID
3944 && parcel.landData.isGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
3945 {
3946 av.StandUp();
3947 }
3948 }
3949 }
3950 }
3951
3952 }
3953
3954 }
3955
3956 public LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset)
3957 {
3958 m_host.AddScriptLPS(1);
3959 NotImplemented("llGroundSlope");
3960 return new LSL_Types.Vector3();
3961 }
3962
3963 public LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset)
3964 {
3965 m_host.AddScriptLPS(1);
3966 NotImplemented("llGroundNormal");
3967 return new LSL_Types.Vector3();
3968 }
3969
3970 public LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset)
3971 {
3972 m_host.AddScriptLPS(1);
3973 NotImplemented("llGroundContour");
3974 return new LSL_Types.Vector3();
3975 }
3976
3977 public LSL_Types.LSLInteger llGetAttached()
3978 {
3979 m_host.AddScriptLPS(1);
3980 NotImplemented("llGetAttached");
3981 return 0;
3982 }
3983
3984 public LSL_Types.LSLInteger llGetFreeMemory()
3985 {
3986 m_host.AddScriptLPS(1);
3987 NotImplemented("llGetFreeMemory");
3988 return 0;
3989 }
3990
3991 public string llGetRegionName()
3992 {
3993 m_host.AddScriptLPS(1);
3994 return World.RegionInfo.RegionName;
3995 }
3996
3997 public double llGetRegionTimeDilation()
3998 {
3999 m_host.AddScriptLPS(1);
4000 return (double)World.TimeDilation;
4001 }
4002
4003 public double llGetRegionFPS()
4004 {
4005 m_host.AddScriptLPS(1);
4006 //TODO: return actual FPS
4007 return 10.0f;
4008 }
4009
4010 /* particle system rules should be coming into this routine as doubles, that is
4011 rule[0] should be an integer from this list and rule[1] should be the arg
4012 for the same integer. wiki.secondlife.com has most of this mapping, but some
4013 came from http://www.caligari-designs.com/p4u2
4014
4015 We iterate through the list for 'Count' elements, incrementing by two for each
4016 iteration and set the members of Primitive.ParticleSystem, one at a time.
4017 */
4018
4019 public enum PrimitiveRule : int
4020 {
4021 PSYS_PART_FLAGS = 0,
4022 PSYS_PART_START_COLOR = 1,
4023 PSYS_PART_START_ALPHA = 2,
4024 PSYS_PART_END_COLOR = 3,
4025 PSYS_PART_END_ALPHA = 4,
4026 PSYS_PART_START_SCALE = 5,
4027 PSYS_PART_END_SCALE = 6,
4028 PSYS_PART_MAX_AGE = 7,
4029 PSYS_SRC_ACCEL = 8,
4030 PSYS_SRC_PATTERN = 9,
4031 PSYS_SRC_TEXTURE = 12,
4032 PSYS_SRC_BURST_RATE = 13,
4033 PSYS_SRC_BURST_PART_COUNT = 15,
4034 PSYS_SRC_BURST_RADIUS = 16,
4035 PSYS_SRC_BURST_SPEED_MIN = 17,
4036 PSYS_SRC_BURST_SPEED_MAX = 18,
4037 PSYS_SRC_MAX_AGE = 19,
4038 PSYS_SRC_TARGET_KEY = 20,
4039 PSYS_SRC_OMEGA = 21,
4040 PSYS_SRC_ANGLE_BEGIN = 22,
4041 PSYS_SRC_ANGLE_END = 23
4042 }
4043
4044 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
4045 {
4046 Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
4047
4048 return returnval;
4049 }
4050
4051
4052 public void llParticleSystem(LSL_Types.list rules)
4053 {
4054 m_host.AddScriptLPS(1);
4055 Primitive.ParticleSystem prules = new Primitive.ParticleSystem();
4056 LSL_Types.Vector3 tempv = new LSL_Types.Vector3();
4057
4058 float tempf = 0;
4059
4060 for (int i = 0; i < rules.Length; i += 2)
4061 {
4062 switch ((int)rules.Data[i])
4063 {
4064 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_FLAGS:
4065 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)((uint)Convert.ToInt32(rules.Data[i + 1].ToString()));
4066 break;
4067
4068 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_COLOR:
4069 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4070 prules.PartStartColor.R = (float)tempv.x;
4071 prules.PartStartColor.G = (float)tempv.y;
4072 prules.PartStartColor.B = (float)tempv.z;
4073 break;
4074
4075 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_ALPHA:
4076 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4077 prules.PartStartColor.A = (float)tempf;
4078 break;
4079
4080 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_COLOR:
4081 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4082 //prules.PartEndColor = new LLColor(tempv.x,tempv.y,tempv.z,1);
4083
4084 prules.PartEndColor.R = (float)tempv.x;
4085 prules.PartEndColor.G = (float)tempv.y;
4086 prules.PartEndColor.B = (float)tempv.z;
4087 break;
4088
4089 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_ALPHA:
4090 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4091 prules.PartEndColor.A = (float)tempf;
4092 break;
4093
4094 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_START_SCALE:
4095 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4096 prules.PartStartScaleX = (float)tempv.x;
4097 prules.PartStartScaleY = (float)tempv.y;
4098 break;
4099
4100 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_END_SCALE:
4101 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4102 prules.PartEndScaleX = (float)tempv.x;
4103 prules.PartEndScaleY = (float)tempv.y;
4104 break;
4105
4106 case (int)BuiltIn_Commands_BaseClass.PSYS_PART_MAX_AGE:
4107 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4108 prules.PartMaxAge = (float)tempf;
4109 break;
4110
4111 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ACCEL:
4112 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4113 prules.PartAcceleration.X = (float)tempv.x;
4114 prules.PartAcceleration.Y = (float)tempv.y;
4115 prules.PartAcceleration.Z = (float)tempv.z;
4116 break;
4117
4118 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_PATTERN:
4119 int tmpi = int.Parse(rules.Data[i + 1].ToString());
4120 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
4121 break;
4122
4123 // Xantor 20080503
4124 // Wiki: PSYS_SRC_TEXTURE string inventory item name or key of the particle texture
4125 // "" = default texture.
4126 // 20080530 Updated to remove code duplication
4127 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_TEXTURE:
4128 prules.Texture = KeyOrName(rules.Data[i + 1].ToString());
4129 break;
4130
4131 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_RATE:
4132 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4133 prules.BurstRate = (float)tempf;
4134 break;
4135
4136 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_PART_COUNT:
4137 prules.BurstPartCount = (byte)Convert.ToByte(rules.Data[i + 1].ToString());
4138 break;
4139
4140 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_RADIUS:
4141 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4142 prules.BurstRadius = (float)tempf;
4143 break;
4144
4145 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_SPEED_MIN:
4146 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4147 prules.BurstSpeedMin = (float)tempf;
4148 break;
4149
4150 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_BURST_SPEED_MAX:
4151 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4152 prules.BurstSpeedMax = (float)tempf;
4153 break;
4154
4155 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_MAX_AGE:
4156 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4157 prules.MaxAge = (float)tempf;
4158 break;
4159
4160 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_TARGET_KEY:
4161 LLUUID key = LLUUID.Zero;
4162 if (LLUUID.TryParse(rules.Data[i + 1].ToString(), out key))
4163 {
4164 prules.Target = key;
4165 }
4166 else
4167 {
4168 prules.Target = m_host.UUID;
4169 }
4170 break;
4171
4172 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_OMEGA:
4173 // AL: This is an assumption, since it is the only thing that would match.
4174 tempv = (LSL_Types.Vector3)rules.Data[i + 1];
4175 prules.AngularVelocity.X = (float)tempv.x;
4176 prules.AngularVelocity.Y = (float)tempv.y;
4177 prules.AngularVelocity.Z = (float)tempv.z;
4178 //cast?? prules.MaxAge = (float)rules[i + 1];
4179 break;
4180
4181 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ANGLE_BEGIN:
4182 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4183 prules.InnerAngle = (float)tempf;
4184 break;
4185
4186 case (int)BuiltIn_Commands_BaseClass.PSYS_SRC_ANGLE_END:
4187 tempf = Convert.ToSingle(rules.Data[i + 1].ToString());
4188 prules.OuterAngle = (float)tempf;
4189 break;
4190 }
4191
4192 }
4193 prules.CRC = 1;
4194
4195 m_host.AddNewParticleSystem(prules);
4196 m_host.SendFullUpdateToAllClients();
4197 }
4198
4199 public void llGroundRepel(double height, int water, double tau)
4200 {
4201 m_host.AddScriptLPS(1);
4202 NotImplemented("llGroundRepel");
4203 }
4204
4205 public void llGiveInventoryList(string destination, string category, LSL_Types.list inventory)
4206 {
4207 m_host.AddScriptLPS(1);
4208 NotImplemented("llGiveInventoryList");
4209 }
4210
4211 public void llSetVehicleType(int type)
4212 {
4213 m_host.AddScriptLPS(1);
4214 NotImplemented("llSetVehicleType");
4215 }
4216
4217 public void llSetVehicledoubleParam(int param, double value)
4218 {
4219 m_host.AddScriptLPS(1);
4220 NotImplemented("llSetVehicledoubleParam");
4221 }
4222
4223 public void llSetVehicleFloatParam(int param, float value)
4224 {
4225 m_host.AddScriptLPS(1);
4226 NotImplemented("llSetVehicleFloatParam");
4227 }
4228
4229 public void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec)
4230 {
4231 m_host.AddScriptLPS(1);
4232 NotImplemented("llSetVehicleVectorParam");
4233 }
4234
4235 public void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot)
4236 {
4237 m_host.AddScriptLPS(1);
4238 NotImplemented("llSetVehicleRotationParam");
4239 }
4240
4241 public void llSetVehicleFlags(int flags)
4242 {
4243 m_host.AddScriptLPS(1);
4244 NotImplemented("llSetVehicleFlags");
4245 }
4246
4247 public void llRemoveVehicleFlags(int flags)
4248 {
4249 m_host.AddScriptLPS(1);
4250 NotImplemented("llRemoveVehicleFlags");
4251 }
4252
4253 public void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot)
4254 {
4255 m_host.AddScriptLPS(1);
4256 // LSL quaternions can normalize to 0, normal Quaternions can't.
4257 if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0)
4258 rot.z = 1; // ZERO_ROTATION = 0,0,0,1
4259
4260 m_host.SetSitTarget(new Vector3((float)offset.x, (float)offset.y, (float)offset.z), new Quaternion((float)rot.s, (float)rot.x, (float)rot.y, (float)rot.z));
4261 }
4262
4263 public string llAvatarOnSitTarget()
4264 {
4265 m_host.AddScriptLPS(1);
4266 return m_host.GetAvatarOnSitTarget().ToString();
4267 }
4268
4269 public void llAddToLandPassList(string avatar, double hours)
4270 {
4271 m_host.AddScriptLPS(1);
4272 LLUUID key;
4273 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
4274 if (land.ownerID == m_host.OwnerID)
4275 {
4276 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
4277 if (LLUUID.TryParse(avatar, out key))
4278 {
4279 entry.AgentID = key;
4280 entry.Flags = ParcelManager.AccessList.Access;
4281 entry.Time = DateTime.Now.AddHours(hours);
4282 land.parcelAccessList.Add(entry);
4283 }
4284 }
4285 }
4286
4287 public void llSetTouchText(string text)
4288 {
4289 m_host.AddScriptLPS(1);
4290 m_host.TouchName = text;
4291 }
4292
4293 public void llSetSitText(string text)
4294 {
4295 m_host.AddScriptLPS(1);
4296 m_host.SitName = text;
4297 }
4298
4299 public void llSetCameraEyeOffset(LSL_Types.Vector3 offset)
4300 {
4301 m_host.AddScriptLPS(1);
4302 NotImplemented("llSetCameraEyeOffset");
4303 }
4304
4305 public void llSetCameraAtOffset(LSL_Types.Vector3 offset)
4306 {
4307 m_host.AddScriptLPS(1);
4308 NotImplemented("llSetCameraAtOffset");
4309 }
4310
4311 public string llDumpList2String(LSL_Types.list src, string seperator)
4312 {
4313 m_host.AddScriptLPS(1);
4314 if (src.Length == 0)
4315 {
4316 return String.Empty;
4317 }
4318 string ret = String.Empty;
4319 foreach (object o in src.Data)
4320 {
4321 ret = ret + o.ToString() + seperator;
4322 }
4323 ret = ret.Substring(0, ret.Length - seperator.Length);
4324 return ret;
4325 }
4326
4327 public LSL_Types.LSLInteger llScriptDanger(LSL_Types.Vector3 pos)
4328 {
4329 m_host.AddScriptLPS(1);
4330 bool result = World.scriptDanger(m_host.LocalId, new LLVector3((float)pos.x, (float)pos.y, (float)pos.z));
4331 if (result)
4332 {
4333 return 1;
4334 }
4335 else
4336 {
4337 return 0;
4338 }
4339
4340 }
4341
4342 public void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel)
4343 {
4344 m_host.AddScriptLPS(1);
4345 LLUUID av = new LLUUID();
4346 if (!LLUUID.TryParse(avatar,out av))
4347 {
4348 LSLError("First parameter to llDialog needs to be a key");
4349 return;
4350 }
4351 if (buttons.Length > 12)
4352 {
4353 LSLError("No more than 12 buttons can be shown");
4354 return;
4355 }
4356 string[] buts = new string[buttons.Length];
4357 for (int i = 0; i < buttons.Length; i++)
4358 {
4359 if (buttons.Data[i].ToString() == String.Empty)
4360 {
4361 LSLError("button label cannot be blank");
4362 return;
4363 }
4364 if (buttons.Data[i].ToString().Length > 24)
4365 {
4366 LSLError("button label cannot be longer than 24 characters");
4367 return;
4368 }
4369 buts[i] = buttons.Data[i].ToString();
4370 }
4371 World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new LLUUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
4372 }
4373
4374 public void llVolumeDetect(int detect)
4375 {
4376 m_host.AddScriptLPS(1);
4377 NotImplemented("llVolumeDetect");
4378 }
4379
4380 /// <summary>
4381 /// Reset the named script. The script must be present
4382 /// in the same prim.
4383 /// </summary>
4384
4385 public void llResetOtherScript(string name)
4386 {
4387 LLUUID item;
4388
4389 m_host.AddScriptLPS(1);
4390
4391 if ((item = ScriptByName(name)) != LLUUID.Zero)
4392 m_ScriptEngine.ResetScript(item);
4393 else
4394 ShoutError("llResetOtherScript: script "+name+" not found");
4395 }
4396
4397 public LSL_Types.LSLInteger llGetScriptState(string name)
4398 {
4399 LLUUID item;
4400
4401 m_host.AddScriptLPS(1);
4402
4403 if ((item = ScriptByName(name)) != LLUUID.Zero)
4404 {
4405 return m_ScriptEngine.GetScriptState(item) ?1:0;
4406 }
4407
4408 ShoutError("llGetScriptState: script "+name+" not found");
4409
4410 // If we didn't find it, then it's safe to
4411 // assume it is not running.
4412
4413 return 0;
4414 }
4415
4416 public void llRemoteLoadScript()
4417 {
4418 m_host.AddScriptLPS(1);
4419 Deprecated("llRemoteLoadScript");
4420 }
4421
4422 public void llSetRemoteScriptAccessPin(int pin)
4423 {
4424 m_host.AddScriptLPS(1);
4425 NotImplemented("llSetRemoteScriptAccessPin");
4426 }
4427
4428 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
4429 {
4430 m_host.AddScriptLPS(1);
4431 NotImplemented("llRemoteLoadScriptPin");
4432 }
4433
4434 // remote_data(integer type, key channel, key message_id, string sender, integer ival, string sval)
4435 // Not sure where these constants should live:
4436 // REMOTE_DATA_CHANNEL = 1
4437 // REMOTE_DATA_REQUEST = 2
4438 // REMOTE_DATA_REPLY = 3
4439 public void llOpenRemoteDataChannel()
4440 {
4441 m_host.AddScriptLPS(1);
4442 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4443 if (xmlrpcMod.IsEnabled())
4444 {
4445 LLUUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, LLUUID.Zero);
4446 object[] resobj = new object[] { new LSL_Types.LSLInteger(1), new LSL_Types.LSLString(channelID.ToString()), new LSL_Types.LSLString(LLUUID.Zero.ToString()), new LSL_Types.LSLString(String.Empty), new LSL_Types.LSLInteger(0), new LSL_Types.LSLString(String.Empty) };
4447 m_ScriptEngine.PostScriptEvent(m_itemID, new XEventParams(
4448 "remote_data", resobj,
4449 new XDetectParams[0]));
4450 }
4451 }
4452
4453 public string llSendRemoteData(string channel, string dest, int idata, string sdata)
4454 {
4455 m_host.AddScriptLPS(1);
4456 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4457 return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString();
4458 }
4459
4460 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
4461 {
4462 m_host.AddScriptLPS(1);
4463 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4464 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
4465 }
4466
4467 public void llCloseRemoteDataChannel(string channel)
4468 {
4469 m_host.AddScriptLPS(1);
4470 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
4471 xmlrpcMod.CloseXMLRPCChannel(channel);
4472 }
4473
4474 public string llMD5String(string src, int nonce)
4475 {
4476 m_host.AddScriptLPS(1);
4477 return Util.Md5Hash(src + ":" + nonce.ToString());
4478 }
4479
4480 public void llSetPrimitiveParams(LSL_Types.list rules)
4481 {
4482 llSetLinkPrimitiveParams(m_host.LinkNum+1, rules);
4483 }
4484
4485 public void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules)
4486 {
4487 m_host.AddScriptLPS(1);
4488
4489 SceneObjectPart part=null;
4490
4491 if (m_host.LinkNum+1 != linknumber)
4492 {
4493 foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts())
4494 {
4495 if ((partInst.LinkNum + 1) == linknumber)
4496 {
4497 part = partInst;
4498 break;
4499 }
4500 }
4501 }
4502 else
4503 {
4504 part = m_host;
4505 }
4506
4507 if (part == null)
4508 return;
4509
4510 int idx = 0;
4511
4512 while (idx < rules.Length)
4513 {
4514 int code = Convert.ToInt32(rules.Data[idx++]);
4515
4516 int remain = rules.Length - idx;
4517
4518 int face;
4519 LSL_Types.Vector3 v;
4520
4521 switch (code)
4522 {
4523 case 6: // PRIM_POSITION
4524 if (remain < 1)
4525 return;
4526
4527 v=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4528 SetPos(part, v);
4529
4530 break;
4531 case 7: // PRIM_SIZE
4532 if (remain < 1)
4533 return;
4534
4535 v=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4536 SetScale(part, v);
4537
4538 break;
4539 case 8: // PRIM_ROTATION
4540 if (remain < 1)
4541 return;
4542
4543 LSL_Types.Quaternion q = new LSL_Types.Quaternion(rules.Data[idx++].ToString());
4544 SetRot(part, q);
4545
4546 break;
4547
4548 case 17: // PRIM_TEXTURE
4549 if (remain < 5)
4550 return;
4551
4552 face=Convert.ToInt32(rules.Data[idx++]);
4553 string tex=rules.Data[idx++].ToString();
4554 LSL_Types.Vector3 repeats=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4555 LSL_Types.Vector3 offsets=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4556 double rotation=Convert.ToDouble(rules.Data[idx++]);
4557
4558 SetTexture(part, tex, face);
4559 ScaleTexture(part, repeats.x, repeats.y, face);
4560 OffsetTexture(part, offsets.x, offsets.y, face);
4561 RotateTexture(part, rotation, face);
4562
4563 break;
4564
4565 case 18: // PRIM_COLOR
4566 if (remain < 3)
4567 return;
4568
4569 face=Convert.ToInt32(rules.Data[idx++]);
4570 LSL_Types.Vector3 color=new LSL_Types.Vector3(rules.Data[idx++].ToString());
4571 double alpha=Convert.ToDouble(rules.Data[idx++]);
4572
4573 SetColor(part, color, face);
4574 SetAlpha(part, alpha, face);
4575
4576 break;
4577 case 21: // PRIM_FLEXI
4578 if (remain < 7)
4579 return;
4580
4581 int flexi = Convert.ToInt32(rules.Data[idx++]);
4582 int softness = Convert.ToInt32(rules.Data[idx++]);
4583 float gravity = (float)Convert.ToDouble(rules.Data[idx++]);
4584 float friction = (float)Convert.ToDouble(rules.Data[idx++]);
4585 float wind = (float)Convert.ToDouble(rules.Data[idx++]);
4586 float tension = (float)Convert.ToDouble(rules.Data[idx++]);
4587 LSL_Types.Vector3 force =new LSL_Types.Vector3(rules.Data[idx++].ToString());
4588
4589 SetFlexi(part, (flexi == 1), softness, gravity, friction, wind, tension, force);
4590
4591 break;
4592 case 23: // PRIM_POINT_LIGHT
4593 if (remain < 5)
4594 return;
4595 int light = Convert.ToInt32(rules.Data[idx++]);
4596 LSL_Types.Vector3 lightcolor =new LSL_Types.Vector3(rules.Data[idx++].ToString());
4597 float intensity = (float)Convert.ToDouble(rules.Data[idx++]);
4598 float radius = (float)Convert.ToDouble(rules.Data[idx++]);
4599 float falloff = (float)Convert.ToDouble(rules.Data[idx++]);
4600
4601 SetPointLight(part, (light == 1), lightcolor, intensity, radius, falloff);
4602
4603 break;
4604 }
4605 }
4606 }
4607
4608 public string llStringToBase64(string str)
4609 {
4610 m_host.AddScriptLPS(1);
4611 try
4612 {
4613 byte[] encData_byte = new byte[str.Length];
4614 encData_byte = Encoding.UTF8.GetBytes(str);
4615 string encodedData = Convert.ToBase64String(encData_byte);
4616 return encodedData;
4617 }
4618 catch (Exception e)
4619 {
4620 throw new Exception("Error in base64Encode" + e.Message);
4621 }
4622 }
4623
4624 public string llBase64ToString(string str)
4625 {
4626 m_host.AddScriptLPS(1);
4627 UTF8Encoding encoder = new UTF8Encoding();
4628 Decoder utf8Decode = encoder.GetDecoder();
4629 try
4630 {
4631 byte[] todecode_byte = Convert.FromBase64String(str);
4632 int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
4633 char[] decoded_char = new char[charCount];
4634 utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
4635 string result = new String(decoded_char);
4636 return result;
4637 }
4638 catch (Exception e)
4639 {
4640 throw new Exception("Error in base64Decode" + e.Message);
4641 }
4642 }
4643
4644 public void llXorBase64Strings()
4645 {
4646 m_host.AddScriptLPS(1);
4647 Deprecated("llXorBase64Strings");
4648 }
4649
4650 public void llRemoteDataSetRegion()
4651 {
4652 m_host.AddScriptLPS(1);
4653 NotImplemented("llRemoteDataSetRegion");
4654 }
4655
4656 public double llLog10(double val)
4657 {
4658 m_host.AddScriptLPS(1);
4659 return (double)Math.Log10(val);
4660 }
4661
4662 public double llLog(double val)
4663 {
4664 m_host.AddScriptLPS(1);
4665 return (double)Math.Log(val);
4666 }
4667
4668 public LSL_Types.list llGetAnimationList(string id)
4669 {
4670 m_host.AddScriptLPS(1);
4671 NotImplemented("llGetAnimationList");
4672 return new LSL_Types.list();
4673 }
4674
4675 public void llSetParcelMusicURL(string url)
4676 {
4677 m_host.AddScriptLPS(1);
4678 LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
4679 if (landowner == LLUUID.Zero)
4680 {
4681 return;
4682 }
4683 if (landowner != m_host.ObjectOwner)
4684 {
4685 return;
4686 }
4687 World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
4688 }
4689
4690 public void osSetParcelMediaURL(string url)
4691 {
4692 m_host.AddScriptLPS(1);
4693 LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
4694
4695 if (landowner == LLUUID.Zero)
4696 {
4697 return;
4698 }
4699
4700 if (landowner != m_host.ObjectOwner)
4701 {
4702 return;
4703 }
4704
4705 World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
4706 }
4707
4708 public LSL_Types.Vector3 llGetRootPosition()
4709 {
4710 m_host.AddScriptLPS(1);
4711 return new LSL_Types.Vector3(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z);
4712 }
4713
4714 public LSL_Types.Quaternion llGetRootRotation()
4715 {
4716 m_host.AddScriptLPS(1);
4717 return new LSL_Types.Quaternion(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W);
4718 }
4719
4720 public string llGetObjectDesc()
4721 {
4722 return m_host.Description!=null?m_host.Description:String.Empty;
4723 }
4724
4725 public void llSetObjectDesc(string desc)
4726 {
4727 m_host.AddScriptLPS(1);
4728 m_host.Description = desc!=null?desc:String.Empty;
4729 }
4730
4731 public string llGetCreator()
4732 {
4733 m_host.AddScriptLPS(1);
4734 return m_host.ObjectCreator.ToString();
4735 }
4736
4737 public string llGetTimestamp()
4738 {
4739 m_host.AddScriptLPS(1);
4740 return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
4741 }
4742
4743 public void llSetLinkAlpha(int linknumber, double alpha, int face)
4744 {
4745 m_host.AddScriptLPS(1);
4746 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber);
4747 if (linknumber > -1)
4748 {
4749 LLObject.TextureEntry tex = part.Shape.Textures;
4750 LLColor texcolor;
4751 if (face > -1)
4752 {
4753 texcolor = tex.CreateFace((uint)face).RGBA;
4754 texcolor.A = (float)Math.Abs(alpha - 1);
4755 tex.FaceTextures[face].RGBA = texcolor;
4756 part.UpdateTexture(tex);
4757 return;
4758 }
4759 else if (face == -1)
4760 {
4761 texcolor = tex.DefaultTexture.RGBA;
4762 texcolor.A = (float)Math.Abs(alpha - 1);
4763 tex.DefaultTexture.RGBA = texcolor;
4764 for (uint i = 0; i < 32; i++)
4765 {
4766 if (tex.FaceTextures[i] != null)
4767 {
4768 texcolor = tex.FaceTextures[i].RGBA;
4769 texcolor.A = (float)Math.Abs(alpha - 1);
4770 tex.FaceTextures[i].RGBA = texcolor;
4771 }
4772 }
4773 texcolor = tex.DefaultTexture.RGBA;
4774 texcolor.A = (float)Math.Abs(alpha - 1);
4775 tex.DefaultTexture.RGBA = texcolor;
4776 part.UpdateTexture(tex);
4777 return;
4778 }
4779 return;
4780 }
4781 else if (linknumber == -1)
4782 {
4783 int num = m_host.ParentGroup.PrimCount;
4784 for (int w = 0; w < num; w++)
4785 {
4786 linknumber = w;
4787 part = m_host.ParentGroup.GetLinkNumPart(linknumber);
4788 LLObject.TextureEntry tex = part.Shape.Textures;
4789 LLColor texcolor;
4790 if (face > -1)
4791 {
4792 texcolor = tex.CreateFace((uint)face).RGBA;
4793 texcolor.A = (float)Math.Abs(alpha - 1);
4794 tex.FaceTextures[face].RGBA = texcolor;
4795 part.UpdateTexture(tex);
4796 }
4797 else if (face == -1)
4798 {
4799 texcolor = tex.DefaultTexture.RGBA;
4800 texcolor.A = (float)Math.Abs(alpha - 1);
4801 tex.DefaultTexture.RGBA = texcolor;
4802 for (uint i = 0; i < 32; i++)
4803 {
4804 if (tex.FaceTextures[i] != null)
4805 {
4806 texcolor = tex.FaceTextures[i].RGBA;
4807 texcolor.A = (float)Math.Abs(alpha - 1);
4808 tex.FaceTextures[i].RGBA = texcolor;
4809 }
4810 }
4811 texcolor = tex.DefaultTexture.RGBA;
4812 texcolor.A = (float)Math.Abs(alpha - 1);
4813 tex.DefaultTexture.RGBA = texcolor;
4814 part.UpdateTexture(tex);
4815 }
4816 }
4817 return;
4818 }
4819 }
4820
4821 public LSL_Types.LSLInteger llGetNumberOfPrims()
4822 {
4823 m_host.AddScriptLPS(1);
4824 return m_host.ParentGroup.PrimCount;
4825 }
4826
4827 public LSL_Types.list llGetBoundingBox(string obj)
4828 {
4829 m_host.AddScriptLPS(1);
4830 NotImplemented("llGetBoundingBox");
4831 return new LSL_Types.list();
4832 }
4833
4834 public LSL_Types.Vector3 llGetGeometricCenter()
4835 {
4836 return new LSL_Types.Vector3(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z);
4837 }
4838
4839 public LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules)
4840 {
4841 m_host.AddScriptLPS(1);
4842
4843 LSL_Types.list res = new LSL_Types.list();
4844 int idx=0;
4845 while (idx < rules.Length)
4846 {
4847 int code=Convert.ToInt32(rules.Data[idx++]);
4848 int remain=rules.Length-idx;
4849
4850 switch (code)
4851 {
4852 case 2: // PRIM_MATERIAL
4853 res.Add(new LSL_Types.LSLInteger(m_host.Material));
4854 break;
4855
4856 case 3: // PRIM_PHYSICS
4857 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Physics) != 0)
4858 res.Add(new LSL_Types.LSLInteger(1));
4859 else
4860 res.Add(new LSL_Types.LSLInteger(0));
4861 break;
4862
4863 case 4: // PRIM_TEMP_ON_REZ
4864 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.TemporaryOnRez) != 0)
4865 res.Add(new LSL_Types.LSLInteger(1));
4866 else
4867 res.Add(new LSL_Types.LSLInteger(0));
4868 break;
4869
4870 case 5: // PRIM_PHANTOM
4871 if ((m_host.GetEffectiveObjectFlags() & (uint)LLObject.ObjectFlags.Phantom) != 0)
4872 res.Add(new LSL_Types.LSLInteger(1));
4873 else
4874 res.Add(new LSL_Types.LSLInteger(0));
4875 break;
4876
4877 case 6: // PRIM_POSITION
4878 res.Add(new LSL_Types.Vector3(m_host.AbsolutePosition.X,
4879 m_host.AbsolutePosition.Y,
4880 m_host.AbsolutePosition.Z));
4881 break;
4882
4883 case 7: // PRIM_SIZE
4884 res.Add(new LSL_Types.Vector3(m_host.Scale.X,
4885 m_host.Scale.Y,
4886 m_host.Scale.Z));
4887 break;
4888
4889 case 8: // PRIM_ROTATION
4890 res.Add(new LSL_Types.Quaternion(m_host.RotationOffset.X,
4891 m_host.RotationOffset.Y,
4892 m_host.RotationOffset.Z,
4893 m_host.RotationOffset.W));
4894 break;
4895
4896 case 9: // PRIM_TYPE
4897 // TODO--------------
4898 res.Add(new LSL_Types.LSLInteger(0));
4899 break;
4900
4901 case 17: // PRIM_TEXTURE
4902 if (remain < 1)
4903 return res;
4904
4905 int face=Convert.ToInt32(rules.Data[idx++]);
4906 if (face == -1)
4907 face = 0;
4908
4909 LLObject.TextureEntry tex = m_host.Shape.Textures;
4910 LLObject.TextureEntryFace texface = tex.GetFace((uint)face);
4911
4912 res.Add(new LSL_Types.LSLString(texface.TextureID.ToString()));
4913 res.Add(new LSL_Types.Vector3(texface.RepeatU,
4914 texface.RepeatV,
4915 0));
4916 res.Add(new LSL_Types.Vector3(texface.OffsetU,
4917 texface.OffsetV,
4918 0));
4919 res.Add(new LSL_Types.LSLFloat(texface.Rotation));
4920 break;
4921
4922 case 18: // PRIM_COLOR
4923 if (remain < 1)
4924 return res;
4925
4926 face=Convert.ToInt32(rules.Data[idx++]);
4927
4928 tex = m_host.Shape.Textures;
4929 LLColor texcolor;
4930 if (face == -1) // TMP: Until we can determine number of sides, ALL_SIDES (-1) will return default color
4931 texcolor = tex.DefaultTexture.RGBA;
4932 else
4933 texcolor = tex.GetFace((uint)face).RGBA;
4934 res.Add(new LSL_Types.Vector3((255 - (texcolor.R * 255)) / 255,
4935 (255 - (texcolor.G * 255)) / 255,
4936 (255 - (texcolor.B * 255)) / 255));
4937 res.Add(new LSL_Types.LSLFloat((texcolor.A * 255) / 255));
4938 break;
4939
4940 case 19: // PRIM_BUMP_SHINY
4941 // TODO--------------
4942 if (remain < 1)
4943 return res;
4944
4945 face=Convert.ToInt32(rules.Data[idx++]);
4946
4947 res.Add(new LSL_Types.LSLInteger(0));
4948 res.Add(new LSL_Types.LSLInteger(0));
4949 break;
4950
4951 case 20: // PRIM_FULLBRIGHT
4952 // TODO--------------
4953 if (remain < 1)
4954 return res;
4955
4956 face=Convert.ToInt32(rules.Data[idx++]);
4957
4958 res.Add(new LSL_Types.LSLInteger(0));
4959 break;
4960
4961 case 21: // PRIM_FLEXIBLE
4962 PrimitiveBaseShape shape = m_host.Shape;
4963
4964 if (shape.FlexiEntry)
4965 res.Add(new LSL_Types.LSLInteger(1)); // active
4966 else
4967 res.Add(new LSL_Types.LSLInteger(0));
4968 res.Add(new LSL_Types.LSLInteger(shape.FlexiSoftness));// softness
4969 res.Add(new LSL_Types.LSLFloat(shape.FlexiGravity)); // gravity
4970 res.Add(new LSL_Types.LSLFloat(shape.FlexiDrag)); // friction
4971 res.Add(new LSL_Types.LSLFloat(shape.FlexiWind)); // wind
4972 res.Add(new LSL_Types.LSLFloat(shape.FlexiTension)); // tension
4973 res.Add(new LSL_Types.Vector3(shape.FlexiForceX, // force
4974 shape.FlexiForceY,
4975 shape.FlexiForceZ));
4976 break;
4977
4978 case 22: // PRIM_TEXGEN
4979 // TODO--------------
4980 // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR)
4981 if (remain < 1)
4982 return res;
4983
4984 face=Convert.ToInt32(rules.Data[idx++]);
4985
4986 res.Add(new LSL_Types.LSLInteger(0));
4987 break;
4988
4989 case 23: // PRIM_POINT_LIGHT:
4990 shape = m_host.Shape;
4991
4992 if (shape.LightEntry)
4993 res.Add(new LSL_Types.LSLInteger(1)); // active
4994 else
4995 res.Add(new LSL_Types.LSLInteger(0));
4996 res.Add(new LSL_Types.Vector3(shape.LightColorR, // color
4997 shape.LightColorG,
4998 shape.LightColorB));
4999 res.Add(new LSL_Types.LSLFloat(shape.LightIntensity)); // intensity
5000 res.Add(new LSL_Types.LSLFloat(shape.LightRadius)); // radius
5001 res.Add(new LSL_Types.LSLFloat(shape.LightFalloff)); // falloff
5002 break;
5003
5004 case 24: // PRIM_GLOW
5005 // TODO--------------
5006 if (remain < 1)
5007 return res;
5008
5009 face=Convert.ToInt32(rules.Data[idx++]);
5010
5011 res.Add(new LSL_Types.LSLFloat(0));
5012 break;
5013 }
5014 }
5015 return res;
5016 }
5017
5018 // <remarks>
5019 // <para>
5020 // The .NET definition of base 64 is:
5021 // <list>
5022 // <item>
5023 // Significant: A-Z a-z 0-9 + -
5024 // </item>
5025 // <item>
5026 // Whitespace: \t \n \r ' '
5027 // </item>
5028 // <item>
5029 // Valueless: =
5030 // </item>
5031 // <item>
5032 // End-of-string: \0 or '=='
5033 // </item>
5034 // </list>
5035 // </para>
5036 // <para>
5037 // Each point in a base-64 string represents
5038 // a 6 bit value. A 32-bit integer can be
5039 // represented using 6 characters (with some
5040 // redundancy).
5041 // </para>
5042 // <para>
5043 // LSL requires a base64 string to be 8
5044 // characters in length. LSL also uses '/'
5045 // rather than '-' (MIME compliant).
5046 // </para>
5047 // <para>
5048 // RFC 1341 used as a reference (as specified
5049 // by the SecondLife Wiki).
5050 // </para>
5051 // <para>
5052 // SL do not record any kind of exception for
5053 // these functions, so the string to integer
5054 // conversion returns '0' if an invalid
5055 // character is encountered during conversion.
5056 // </para>
5057 // <para>
5058 // References
5059 // <list>
5060 // <item>
5061 // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
5062 // </item>
5063 // <item>
5064 // </item>
5065 // </list>
5066 // </para>
5067 // </remarks>
5068
5069 // <summary>
5070 // Table for converting 6-bit integers into
5071 // base-64 characters
5072 // </summary>
5073
5074 private static readonly char[] i2ctable =
5075 {
5076 'A','B','C','D','E','F','G','H',
5077 'I','J','K','L','M','N','O','P',
5078 'Q','R','S','T','U','V','W','X',
5079 'Y','Z',
5080 'a','b','c','d','e','f','g','h',
5081 'i','j','k','l','m','n','o','p',
5082 'q','r','s','t','u','v','w','x',
5083 'y','z',
5084 '0','1','2','3','4','5','6','7',
5085 '8','9',
5086 '+','/'
5087 };
5088
5089 // <summary>
5090 // Table for converting base-64 characters
5091 // into 6-bit integers.
5092 // </summary>
5093
5094 private static readonly int[] c2itable =
5095 {
5096 -1,-1,-1,-1,-1,-1,-1,-1, // 0x
5097 -1,-1,-1,-1,-1,-1,-1,-1,
5098 -1,-1,-1,-1,-1,-1,-1,-1, // 1x
5099 -1,-1,-1,-1,-1,-1,-1,-1,
5100 -1,-1,-1,-1,-1,-1,-1,-1, // 2x
5101 -1,-1,-1,63,-1,-1,-1,64,
5102 53,54,55,56,57,58,59,60, // 3x
5103 61,62,-1,-1,-1,0,-1,-1,
5104 -1,1,2,3,4,5,6,7, // 4x
5105 8,9,10,11,12,13,14,15,
5106 16,17,18,19,20,21,22,23, // 5x
5107 24,25,26,-1,-1,-1,-1,-1,
5108 -1,27,28,29,30,31,32,33, // 6x
5109 34,35,36,37,38,39,40,41,
5110 42,43,44,45,46,47,48,49, // 7x
5111 50,51,52,-1,-1,-1,-1,-1,
5112 -1,-1,-1,-1,-1,-1,-1,-1, // 8x
5113 -1,-1,-1,-1,-1,-1,-1,-1,
5114 -1,-1,-1,-1,-1,-1,-1,-1, // 9x
5115 -1,-1,-1,-1,-1,-1,-1,-1,
5116 -1,-1,-1,-1,-1,-1,-1,-1, // Ax
5117 -1,-1,-1,-1,-1,-1,-1,-1,
5118 -1,-1,-1,-1,-1,-1,-1,-1, // Bx
5119 -1,-1,-1,-1,-1,-1,-1,-1,
5120 -1,-1,-1,-1,-1,-1,-1,-1, // Cx
5121 -1,-1,-1,-1,-1,-1,-1,-1,
5122 -1,-1,-1,-1,-1,-1,-1,-1, // Dx
5123 -1,-1,-1,-1,-1,-1,-1,-1,
5124 -1,-1,-1,-1,-1,-1,-1,-1, // Ex
5125 -1,-1,-1,-1,-1,-1,-1,-1,
5126 -1,-1,-1,-1,-1,-1,-1,-1, // Fx
5127 -1,-1,-1,-1,-1,-1,-1,-1
5128 };
5129
5130 // <summary>
5131 // Converts a 32-bit integer into a Base64
5132 // character string. Base64 character strings
5133 // are always 8 characters long. All iinteger
5134 // values are acceptable.
5135 // </summary>
5136 // <param name="number">
5137 // 32-bit integer to be converted.
5138 // </param>
5139 // <returns>
5140 // 8 character string. The 1st six characters
5141 // contain the encoded number, the last two
5142 // characters are padded with "=".
5143 // </returns>
5144
5145 public string llIntegerToBase64(int number)
5146 {
5147 // uninitialized string
5148
5149 char[] imdt = new char[8];
5150
5151 m_host.AddScriptLPS(1);
5152
5153 // Manually unroll the loop
5154
5155 imdt[7] = '=';
5156 imdt[6] = '=';
5157 imdt[5] = i2ctable[number<<4 & 0x3F];
5158 imdt[4] = i2ctable[number>>2 & 0x3F];
5159 imdt[3] = i2ctable[number>>8 & 0x3F];
5160 imdt[2] = i2ctable[number>>14 & 0x3F];
5161 imdt[1] = i2ctable[number>>20 & 0x3F];
5162 imdt[0] = i2ctable[number>>26 & 0x3F];
5163
5164 return new string(imdt);
5165 }
5166
5167 // <summary>
5168 // Converts an eight character base-64 string
5169 // into a 32-bit integer.
5170 // </summary>
5171 // <param name="str">
5172 // 8 characters string to be converted. Other
5173 // length strings return zero.
5174 // </param>
5175 // <returns>
5176 // Returns an integer representing the
5177 // encoded value providedint he 1st 6
5178 // characters of the string.
5179 // </returns>
5180 // <remarks>
5181 // This is coded to behave like LSL's
5182 // implementation (I think), based upon the
5183 // information available at the Wiki.
5184 // If more than 8 characters are supplied,
5185 // zero is returned.
5186 // If a NULL string is supplied, zero will
5187 // be returned.
5188 // If fewer than 6 characters are supplied, then
5189 // the answer will reflect a partial
5190 // accumulation.
5191 // <para>
5192 // The 6-bit segments are
5193 // extracted left-to-right in big-endian mode,
5194 // which means that segment 6 only contains the
5195 // two low-order bits of the 32 bit integer as
5196 // its high order 2 bits. A short string therefore
5197 // means loss of low-order information. E.g.
5198 //
5199 // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
5200 // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
5201 // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
5202 // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
5203 // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
5204 //
5205 // </para>
5206 // </remarks>
5207
5208 public LSL_Types.LSLInteger llBase64ToInteger(string str)
5209 {
5210 int number = 0;
5211 int digit;
5212
5213 m_host.AddScriptLPS(1);
5214
5215 // Require a well-fromed base64 string
5216
5217 if (str.Length > 8)
5218 return 0;
5219
5220 // The loop is unrolled in the interests
5221 // of performance and simple necessity.
5222 //
5223 // MUST find 6 digits to be well formed
5224 // -1 == invalid
5225 // 0 == padding
5226
5227 if ((digit=c2itable[str[0]])<=0)
5228 {
5229 return digit<0?(int)0:number;
5230 }
5231 number += --digit<<26;
5232
5233 if ((digit=c2itable[str[1]])<=0)
5234 {
5235 return digit<0?(int)0:number;
5236 }
5237 number += --digit<<20;
5238
5239 if ((digit=c2itable[str[2]])<=0)
5240 {
5241 return digit<0?(int)0:number;
5242 }
5243 number += --digit<<14;
5244
5245 if ((digit=c2itable[str[3]])<=0)
5246 {
5247 return digit<0?(int)0:number;
5248 }
5249 number += --digit<<8;
5250
5251 if ((digit=c2itable[str[4]])<=0)
5252 {
5253 return digit<0?(int)0:number;
5254 }
5255 number += --digit<<2;
5256
5257 if ((digit=c2itable[str[5]])<=0)
5258 {
5259 return digit<0?(int)0:number;
5260 }
5261 number += --digit>>4;
5262
5263 // ignore trailing padding
5264
5265 return number;
5266 }
5267
5268 public double llGetGMTclock()
5269 {
5270 m_host.AddScriptLPS(1);
5271 return DateTime.UtcNow.TimeOfDay.TotalSeconds;
5272 }
5273
5274 public string llGetSimulatorHostname()
5275 {
5276 m_host.AddScriptLPS(1);
5277 return System.Environment.MachineName;
5278 }
5279
5280 public void llSetLocalRot(LSL_Types.Quaternion rot)
5281 {
5282 m_host.AddScriptLPS(1);
5283 m_host.RotationOffset = new LLQuaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s);
5284 }
5285
5286 // <summary>
5287 // Scan the string supplied in 'src' and
5288 // tokenize it based upon two sets of
5289 // tokenizers provided in two lists,
5290 // separators and spacers.
5291 // </summary>
5292 //
5293 // <remarks>
5294 // Separators demarcate tokens and are
5295 // elided as they are encountered. Spacers
5296 // also demarcate tokens, but are themselves
5297 // retained as tokens.
5298 //
5299 // Both separators and spacers may be arbitrarily
5300 // long strings. i.e. ":::".
5301 //
5302 // The function returns an ordered list
5303 // representing the tokens found in the supplied
5304 // sources string. If two successive tokenizers
5305 // are encountered, then a NULL entry is added
5306 // to the list.
5307 //
5308 // It is a precondition that the source and
5309 // toekizer lisst are non-null. If they are null,
5310 // then a null pointer exception will be thrown
5311 // while their lengths are being determined.
5312 //
5313 // A small amount of working memoryis required
5314 // of approximately 8*#tokenizers.
5315 //
5316 // There are many ways in which this function
5317 // can be implemented, this implementation is
5318 // fairly naive and assumes that when the
5319 // function is invooked with a short source
5320 // string and/or short lists of tokenizers, then
5321 // performance will not be an issue.
5322 //
5323 // In order to minimize the perofrmance
5324 // effects of long strings, or large numbers
5325 // of tokeizers, the function skips as far as
5326 // possible whenever a toekenizer is found,
5327 // and eliminates redundant tokenizers as soon
5328 // as is possible.
5329 //
5330 // The implementation tries to avoid any copying
5331 // of arrays or other objects.
5332 // </remarks>
5333
5334 public LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list separators, LSL_Types.list spacers)
5335 {
5336 int beginning = 0;
5337 int srclen = src.Length;
5338 int seplen = separators.Length;
5339 object[] separray = separators.Data;
5340 int spclen = spacers.Length;
5341 object[] spcarray = spacers.Data;
5342 int mlen = seplen+spclen;
5343
5344 int[] offset = new int[mlen+1];
5345 bool[] active = new bool[mlen];
5346
5347 int best;
5348 int j;
5349
5350 // Initial capacity reduces resize cost
5351
5352 LSL_Types.list tokens = new LSL_Types.list();
5353
5354 m_host.AddScriptLPS(1);
5355
5356 // All entries are initially valid
5357
5358 for (int i = 0; i < mlen; i++)
5359 active[i] = true;
5360
5361 offset[mlen] = srclen;
5362
5363 while (beginning < srclen)
5364 {
5365
5366 best = mlen; // as bad as it gets
5367
5368 // Scan for separators
5369
5370 for (j = 0; j < seplen; j++)
5371 {
5372 if (active[j])
5373 {
5374 // scan all of the markers
5375 if ((offset[j] = src.IndexOf((string)separray[j],beginning)) == -1)
5376 {
5377 // not present at all
5378 active[j] = false;
5379 }
5380 else
5381 {
5382 // present and correct
5383 if (offset[j] < offset[best])
5384 {
5385 // closest so far
5386 best = j;
5387 if (offset[best] == beginning)
5388 break;
5389 }
5390 }
5391 }
5392 }
5393
5394 // Scan for spacers
5395
5396 if (offset[best] != beginning)
5397 {
5398 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
5399 {
5400 if (active[j])
5401 {
5402 // scan all of the markers
5403 if ((offset[j] = src.IndexOf((string)spcarray[j-seplen], beginning)) == -1)
5404 {
5405 // not present at all
5406 active[j] = false;
5407 }
5408 else
5409 {
5410 // present and correct
5411 if (offset[j] < offset[best])
5412 {
5413 // closest so far
5414 best = j;
5415 }
5416 }
5417 }
5418 }
5419 }
5420
5421 // This is the normal exit from the scanning loop
5422
5423 if (best == mlen)
5424 {
5425 // no markers were found on this pass
5426 // so we're pretty much done
5427 tokens.Add(src.Substring(beginning, srclen - beginning));
5428 break;
5429 }
5430
5431 // Otherwise we just add the newly delimited token
5432 // and recalculate where the search should continue.
5433
5434 tokens.Add(src.Substring(beginning,offset[best]-beginning));
5435
5436 if (best < seplen)
5437 {
5438 beginning = offset[best] + ((string)separray[best]).Length;
5439 }
5440 else
5441 {
5442 beginning = offset[best] + ((string)spcarray[best - seplen]).Length;
5443 tokens.Add(spcarray[best - seplen]);
5444 }
5445 }
5446
5447 // This an awkward an not very intuitive boundary case. If the
5448 // last substring is a tokenizer, then there is an implied trailing
5449 // null list entry. Hopefully the single comparison will not be too
5450 // arduous. Alternatively the 'break' could be replced with a return
5451 // but that's shabby programming.
5452
5453 if (beginning == srclen)
5454 {
5455 if (srclen != 0)
5456 tokens.Add("");
5457 }
5458
5459 return tokens;
5460 }
5461
5462 public void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity,
5463 LSL_Types.Quaternion rot, int param)
5464 {
5465 m_host.AddScriptLPS(1);
5466 NotImplemented("llRezAtRoot");
5467 }
5468
5469 public LSL_Types.LSLInteger llGetObjectPermMask(int mask)
5470 {
5471 m_host.AddScriptLPS(1);
5472
5473 int permmask = 0;
5474
5475 if (mask == BuiltIn_Commands_BaseClass.MASK_BASE)//0
5476 {
5477 permmask = (int)m_host.BaseMask;
5478 }
5479
5480 else if (mask == BuiltIn_Commands_BaseClass.MASK_OWNER)//1
5481 {
5482 permmask = (int)m_host.OwnerMask;
5483 }
5484
5485 else if (mask == BuiltIn_Commands_BaseClass.MASK_GROUP)//2
5486 {
5487 permmask = (int)m_host.GroupMask;
5488 }
5489
5490 else if (mask == BuiltIn_Commands_BaseClass.MASK_EVERYONE)//3
5491 {
5492 permmask = (int)m_host.EveryoneMask;
5493 }
5494
5495 else if (mask == BuiltIn_Commands_BaseClass.MASK_NEXT)//4
5496 {
5497 permmask = (int)m_host.NextOwnerMask;
5498 }
5499
5500 return permmask;
5501 }
5502
5503 public void llSetObjectPermMask(int mask, int value)
5504 {
5505 m_host.AddScriptLPS(1);
5506 IConfigSource config = new IniConfigSource(Application.iniFilePath);
5507 if (config.Configs["XEngine"] == null)
5508 config.AddConfig("XEngine");
5509
5510 if (config.Configs["XEngine"].GetBoolean("AllowGodFunctions", false))
5511 {
5512 if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID))
5513 {
5514 if (mask == BuiltIn_Commands_BaseClass.MASK_BASE)//0
5515 {
5516 m_host.BaseMask = (uint)value;
5517 }
5518
5519 else if (mask == BuiltIn_Commands_BaseClass.MASK_OWNER)//1
5520 {
5521 m_host.OwnerMask = (uint)value;
5522 }
5523
5524 else if (mask == BuiltIn_Commands_BaseClass.MASK_GROUP)//2
5525 {
5526 m_host.GroupMask = (uint)value;
5527 }
5528
5529 else if (mask == BuiltIn_Commands_BaseClass.MASK_EVERYONE)//3
5530 {
5531 m_host.EveryoneMask = (uint)value;
5532 }
5533
5534 else if (mask == BuiltIn_Commands_BaseClass.MASK_NEXT)//4
5535 {
5536 m_host.NextOwnerMask = (uint)value;
5537 }
5538 }
5539 }
5540 }
5541
5542 public LSL_Types.LSLInteger llGetInventoryPermMask(string item, int mask)
5543 {
5544 m_host.AddScriptLPS(1);
5545 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
5546 {
5547 if (inv.Value.Name == item)
5548 {
5549 switch (mask)
5550 {
5551 case 0:
5552 return (int)inv.Value.BaseMask;
5553 case 1:
5554 return (int)inv.Value.OwnerMask;
5555 case 2:
5556 return (int)inv.Value.GroupMask;
5557 case 3:
5558 return (int)inv.Value.EveryoneMask;
5559 case 4:
5560 return (int)inv.Value.NextOwnerMask;
5561 }
5562 }
5563 }
5564 return -1;
5565 }
5566
5567 public void llSetInventoryPermMask(string item, int mask, int value)
5568 {
5569 m_host.AddScriptLPS(1);
5570 NotImplemented("llSetInventoryPermMask");
5571 }
5572
5573 public string llGetInventoryCreator(string item)
5574 {
5575 m_host.AddScriptLPS(1);
5576 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
5577 {
5578 if (inv.Value.Name == item)
5579 {
5580 return inv.Value.CreatorID.ToString();
5581 }
5582 }
5583 llSay(0, "No item name '" + item + "'");
5584 return String.Empty;
5585 }
5586
5587 public void llOwnerSay(string msg)
5588 {
5589 m_host.AddScriptLPS(1);
5590
5591 World.SimChatBroadcast(Helpers.StringToField(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
5592// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
5593// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
5594 }
5595
5596 public string llRequestSimulatorData(string simulator, int data)
5597 {
5598 try
5599 {
5600 m_host.AddScriptLPS(1);
5601
5602 string reply = String.Empty;
5603
5604 RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator);
5605
5606 switch (data)
5607 {
5608 case 5: // DATA_SIM_POS
5609 if (info == null)
5610 return LLUUID.Zero.ToString();
5611 reply = new LSL_Types.Vector3(
5612 info.RegionLocX * Constants.RegionSize,
5613 info.RegionLocY * Constants.RegionSize,
5614 0).ToString();
5615 break;
5616 case 6: // DATA_SIM_STATUS
5617 if (info != null)
5618 reply = "up"; // Duh!
5619 else
5620 reply = "unknown";
5621 break;
5622 case 7: // DATA_SIM_RATING
5623 if (info == null)
5624 return LLUUID.Zero.ToString();
5625 int access = (int)info.EstateSettings.simAccess;
5626 if (access == 21)
5627 reply = "MATURE";
5628 else if (access == 13)
5629 reply = "MATURE";
5630 else
5631 reply = "UNKNOWN";
5632 break;
5633 default:
5634 return LLUUID.Zero.ToString(); // Raise no event
5635 }
5636 LLUUID rq = LLUUID.Random();
5637
5638 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
5639 m_Dataserver.RegisterRequest(m_localID,
5640 m_itemID, rq.ToString());
5641
5642 m_ScriptEngine.m_ASYNCLSLCommandManager.
5643 m_Dataserver.DataserverReply(rq.ToString(), reply);
5644
5645 return tid.ToString();
5646 }
5647 catch(Exception e)
5648 {
5649 Console.WriteLine(e.ToString());
5650 return LLUUID.Zero.ToString();
5651 }
5652 }
5653
5654 public void llForceMouselook(int mouselook)
5655 {
5656 m_host.AddScriptLPS(1);
5657 NotImplemented("llForceMouselook");
5658 }
5659
5660 public double llGetObjectMass(string id)
5661 {
5662 m_host.AddScriptLPS(1);
5663 LLUUID key = new LLUUID();
5664 if (LLUUID.TryParse(id,out key))
5665 {
5666 return (double) World.GetSceneObjectPart(World.Entities[key].LocalId).GetMass();
5667 }
5668 return 0;
5669 }
5670
5671 /// <summary>
5672 /// illListReplaceList removes the sub-list defined by the inclusive indices
5673 /// start and end and inserts the src list in its place. The inclusive
5674 /// nature of the indices means that at least one element must be deleted
5675 /// if the indices are within the bounds of the existing list. I.e. 2,2
5676 /// will remove the element at index 2 and replace it with the source
5677 /// list. Both indices may be negative, with the usual interpretation. An
5678 /// interesting case is where end is lower than start. As these indices
5679 /// bound the list to be removed, then 0->end, and start->lim are removed
5680 /// and the source list is added as a suffix.
5681 /// </summary>
5682
5683 public LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end)
5684 {
5685 LSL_Types.list pref = null;
5686
5687 m_host.AddScriptLPS(1);
5688
5689 // Note that although we have normalized, both
5690 // indices could still be negative.
5691 if (start < 0)
5692 {
5693 start = start+dest.Length;
5694 }
5695
5696 if (end < 0)
5697 {
5698 end = end+dest.Length;
5699 }
5700 // The comventional case, remove a sequence starting with
5701 // start and ending with end. And then insert the source
5702 // list.
5703 if (start <= end)
5704 {
5705 // If greater than zero, then there is going to be a
5706 // surviving prefix. Otherwise the inclusive nature
5707 // of the indices mean that we're going to add the
5708 // source list as a prefix.
5709 if (start > 0)
5710 {
5711 pref = dest.GetSublist(0,start-1);
5712 // Only add a suffix if there is something
5713 // beyond the end index (it's inclusive too).
5714 if (end + 1 < dest.Length)
5715 {
5716 return pref + src + dest.GetSublist(end + 1, -1);
5717 }
5718 else
5719 {
5720 return pref + src;
5721 }
5722 }
5723 // If start is less than or equal to zero, then
5724 // the new list is simply a prefix. We still need to
5725 // figure out any necessary surgery to the destination
5726 // based upon end. Note that if end exceeds the upper
5727 // bound in this case, the entire destination list
5728 // is removed.
5729 else
5730 {
5731 if (end + 1 < dest.Length)
5732 {
5733 return src + dest.GetSublist(end + 1, -1);
5734 }
5735 else
5736 {
5737 return src;
5738 }
5739 }
5740 }
5741 // Finally, if start > end, we strip away a prefix and
5742 // a suffix, to leave the list that sits <between> ens
5743 // and start, and then tag on the src list. AT least
5744 // that's my interpretation. We can get sublist to do
5745 // this for us. Note that one, or both of the indices
5746 // might have been negative.
5747 else
5748 {
5749 return dest.GetSublist(end + 1, start - 1) + src;
5750 }
5751 }
5752
5753 public void llLoadURL(string avatar_id, string message, string url)
5754 {
5755 m_host.AddScriptLPS(1);
5756 LLUUID avatarId = new LLUUID(avatar_id);
5757 m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message,
5758 url);
5759 }
5760
5761 public void llParcelMediaCommandList(LSL_Types.list commandList)
5762 {
5763 m_host.AddScriptLPS(1);
5764 NotImplemented("llParcelMediaCommandList");
5765 }
5766
5767 public void llParcelMediaQuery()
5768 {
5769 m_host.AddScriptLPS(1);
5770 NotImplemented("llParcelMediaQuery");
5771 }
5772
5773 public LSL_Types.LSLInteger llModPow(int a, int b, int c)
5774 {
5775 m_host.AddScriptLPS(1);
5776 Int64 tmp = 0;
5777 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
5778 return Convert.ToInt32(tmp);
5779 }
5780
5781 public LSL_Types.LSLInteger llGetInventoryType(string name)
5782 {
5783 m_host.AddScriptLPS(1);
5784 foreach (KeyValuePair<LLUUID, TaskInventoryItem> inv in m_host.TaskInventory)
5785 {
5786 if (inv.Value.Name == name)
5787 {
5788 return inv.Value.InvType;
5789 }
5790 }
5791 return -1;
5792 }
5793
5794 public void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons)
5795 {
5796 m_host.AddScriptLPS(1);
5797
5798 if (quick_pay_buttons.Data.Length != 4)
5799 {
5800 LSLError("List must have 4 elements");
5801 return;
5802 }
5803 m_host.ParentGroup.RootPart.PayPrice[0]=price;
5804 m_host.ParentGroup.RootPart.PayPrice[1]=(int)quick_pay_buttons.Data[0];
5805 m_host.ParentGroup.RootPart.PayPrice[2]=(int)quick_pay_buttons.Data[1];
5806 m_host.ParentGroup.RootPart.PayPrice[3]=(int)quick_pay_buttons.Data[2];
5807 m_host.ParentGroup.RootPart.PayPrice[4]=(int)quick_pay_buttons.Data[3];
5808 }
5809
5810 public LSL_Types.Vector3 llGetCameraPos()
5811 {
5812 m_host.AddScriptLPS(1);
5813 NotImplemented("llGetCameraPos");
5814 return new LSL_Types.Vector3();
5815 }
5816
5817 public LSL_Types.Quaternion llGetCameraRot()
5818 {
5819 m_host.AddScriptLPS(1);
5820 NotImplemented("llGetCameraRot");
5821 return new LSL_Types.Quaternion();
5822 }
5823
5824 public void llSetPrimURL()
5825 {
5826 m_host.AddScriptLPS(1);
5827 NotImplemented("llSetPrimURL");
5828 }
5829
5830 public void llRefreshPrimURL()
5831 {
5832 m_host.AddScriptLPS(1);
5833 NotImplemented("llRefreshPrimURL");
5834 }
5835
5836 public string llEscapeURL(string url)
5837 {
5838 m_host.AddScriptLPS(1);
5839 try
5840 {
5841 return Uri.EscapeUriString(url);
5842 }
5843 catch (Exception ex)
5844 {
5845 return "llEscapeURL: " + ex.ToString();
5846 }
5847 }
5848
5849 public string llUnescapeURL(string url)
5850 {
5851 m_host.AddScriptLPS(1);
5852 try
5853 {
5854 return Uri.UnescapeDataString(url);
5855 }
5856 catch (Exception ex)
5857 {
5858 return "llUnescapeURL: " + ex.ToString();
5859 }
5860 }
5861
5862 public void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at)
5863 {
5864 m_host.AddScriptLPS(1);
5865 NotImplemented("llMapDestination");
5866 }
5867
5868 public void llAddToLandBanList(string avatar, double hours)
5869 {
5870 m_host.AddScriptLPS(1);
5871 LLUUID key;
5872 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5873 if (land.ownerID == m_host.OwnerID)
5874 {
5875 ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry();
5876 if (LLUUID.TryParse(avatar, out key))
5877 {
5878 entry.AgentID = key;
5879 entry.Flags = ParcelManager.AccessList.Ban;
5880 entry.Time = DateTime.Now.AddHours(hours);
5881 land.parcelAccessList.Add(entry);
5882 }
5883 }
5884 }
5885
5886 public void llRemoveFromLandPassList(string avatar)
5887 {
5888 m_host.AddScriptLPS(1);
5889 LLUUID key;
5890 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5891 if (land.ownerID == m_host.OwnerID)
5892 {
5893 if (LLUUID.TryParse(avatar, out key))
5894 {
5895 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
5896 {
5897 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access)
5898 {
5899 land.parcelAccessList.Remove(entry);
5900 break;
5901 }
5902 }
5903 }
5904 }
5905 }
5906
5907 public void llRemoveFromLandBanList(string avatar)
5908 {
5909 m_host.AddScriptLPS(1);
5910 LLUUID key;
5911 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
5912 if (land.ownerID == m_host.OwnerID)
5913 {
5914 if (LLUUID.TryParse(avatar, out key))
5915 {
5916 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
5917 {
5918 if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban)
5919 {
5920 land.parcelAccessList.Remove(entry);
5921 break;
5922 }
5923 }
5924 }
5925 }
5926 }
5927
5928 public void llSetCameraParams(LSL_Types.list rules)
5929 {
5930 m_host.AddScriptLPS(1);
5931 NotImplemented("llSetCameraParams");
5932 }
5933
5934 public void llClearCameraParams()
5935 {
5936 m_host.AddScriptLPS(1);
5937 NotImplemented("llClearCameraParams");
5938 }
5939
5940 public double llListStatistics(int operation, LSL_Types.list src)
5941 {
5942 m_host.AddScriptLPS(1);
5943 LSL_Types.list nums = LSL_Types.list.ToDoubleList(src);
5944 switch (operation)
5945 {
5946 case BuiltIn_Commands_BaseClass.LIST_STAT_RANGE:
5947 return nums.Range();
5948 case BuiltIn_Commands_BaseClass.LIST_STAT_MIN:
5949 return nums.Min();
5950 case BuiltIn_Commands_BaseClass.LIST_STAT_MAX:
5951 return nums.Max();
5952 case BuiltIn_Commands_BaseClass.LIST_STAT_MEAN:
5953 return nums.Mean();
5954 case BuiltIn_Commands_BaseClass.LIST_STAT_MEDIAN:
5955 return nums.Median();
5956 case BuiltIn_Commands_BaseClass.LIST_STAT_NUM_COUNT:
5957 return nums.NumericLength();
5958 case BuiltIn_Commands_BaseClass.LIST_STAT_STD_DEV:
5959 return nums.StdDev();
5960 case BuiltIn_Commands_BaseClass.LIST_STAT_SUM:
5961 return nums.Sum();
5962 case BuiltIn_Commands_BaseClass.LIST_STAT_SUM_SQUARES:
5963 return nums.SumSqrs();
5964 case BuiltIn_Commands_BaseClass.LIST_STAT_GEOMETRIC_MEAN:
5965 return nums.GeometricMean();
5966 case BuiltIn_Commands_BaseClass.LIST_STAT_HARMONIC_MEAN:
5967 return nums.HarmonicMean();
5968 default:
5969 return 0.0;
5970 }
5971 }
5972
5973 public LSL_Types.LSLInteger llGetUnixTime()
5974 {
5975 m_host.AddScriptLPS(1);
5976 return Util.UnixTimeSinceEpoch();
5977 }
5978
5979 public LSL_Types.LSLInteger llGetParcelFlags(LSL_Types.Vector3 pos)
5980 {
5981 m_host.AddScriptLPS(1);
5982 return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.landFlags;
5983 }
5984
5985 public LSL_Types.LSLInteger llGetRegionFlags()
5986 {
5987 m_host.AddScriptLPS(1);
5988 return (int)World.RegionInfo.EstateSettings.regionFlags;
5989 }
5990
5991 public string llXorBase64StringsCorrect(string str1, string str2)
5992 {
5993 m_host.AddScriptLPS(1);
5994 string ret = String.Empty;
5995 string src1 = llBase64ToString(str1);
5996 string src2 = llBase64ToString(str2);
5997 int c = 0;
5998 for (int i = 0; i < src1.Length; i++)
5999 {
6000 ret += src1[i] ^ src2[c];
6001
6002 c++;
6003 if (c > src2.Length)
6004 c = 0;
6005 }
6006 return llStringToBase64(ret);
6007 }
6008
6009 public string llHTTPRequest(string url, LSL_Types.list parameters, string body)
6010 {
6011 // Partial implementation: support for parameter flags needed
6012 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
6013 // parameter flags support are implemented in ScriptsHttpRequests.cs
6014 // in StartHttpRequest
6015
6016 m_host.AddScriptLPS(1);
6017 IHttpRequests httpScriptMod =
6018 m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
6019 List<string> param = new List<string>();
6020 foreach (object o in parameters.Data)
6021 {
6022 param.Add(o.ToString());
6023 }
6024 LLUUID reqID = httpScriptMod.
6025 StartHttpRequest(m_localID, m_itemID, url, param, body);
6026
6027 if (reqID != LLUUID.Zero)
6028 return reqID.ToString();
6029 else
6030 return null;
6031 }
6032
6033 public void llResetLandBanList()
6034 {
6035 m_host.AddScriptLPS(1);
6036 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
6037 if (land.ownerID == m_host.OwnerID)
6038 {
6039 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
6040 {
6041 if (entry.Flags == ParcelManager.AccessList.Ban)
6042 {
6043 land.parcelAccessList.Remove(entry);
6044 }
6045 }
6046 }
6047 }
6048
6049 public void llResetLandPassList()
6050 {
6051 m_host.AddScriptLPS(1);
6052 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData;
6053 if (land.ownerID == m_host.OwnerID)
6054 {
6055 foreach (ParcelManager.ParcelAccessEntry entry in land.parcelAccessList)
6056 {
6057 if (entry.Flags == ParcelManager.AccessList.Access)
6058 {
6059 land.parcelAccessList.Remove(entry);
6060 }
6061 }
6062 }
6063 }
6064
6065 public LSL_Types.LSLInteger llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide)
6066 {
6067 m_host.AddScriptLPS(1);
6068
6069 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
6070
6071 if (land == null)
6072 {
6073 return 0;
6074 }
6075
6076 else
6077 {
6078 if (sim_wide == 1)
6079 {
6080 if (category == 0)
6081 {
6082 return land.simwidePrims;
6083 }
6084
6085 else
6086 {
6087 //public int simwideArea = 0;
6088 return 0;
6089 }
6090 }
6091
6092 else
6093 {
6094 if (category == 0)//Total Prims
6095 {
6096 return 0;//land.
6097 }
6098
6099 else if (category == 1)//Owner Prims
6100 {
6101 return land.ownerPrims;
6102 }
6103
6104 else if (category == 2)//Group Prims
6105 {
6106 return land.groupPrims;
6107 }
6108
6109 else if (category == 3)//Other Prims
6110 {
6111 return land.otherPrims;
6112 }
6113
6114 else if (category == 4)//Selected
6115 {
6116 return land.selectedPrims;
6117 }
6118
6119 else if (category == 5)//Temp
6120 {
6121 return 0;//land.
6122 }
6123 }
6124 }
6125 return 0;
6126 }
6127
6128 public LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos)
6129 {
6130 m_host.AddScriptLPS(1);
6131 LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
6132 LSL_Types.list ret = new LSL_Types.list();
6133 if (land != null)
6134 {
6135 foreach (KeyValuePair<LLUUID, int> d in land.getLandObjectOwners())
6136 {
6137 ret.Add(d.Key.ToString());
6138 ret.Add(d.Value);
6139 }
6140 }
6141 return ret;
6142 }
6143
6144 public LSL_Types.LSLInteger llGetObjectPrimCount(string object_id)
6145 {
6146 m_host.AddScriptLPS(1);
6147 SceneObjectPart part = World.GetSceneObjectPart(new LLUUID(object_id));
6148 if (part == null)
6149 {
6150 return 0;
6151 }
6152 else
6153 {
6154 return part.ParentGroup.Children.Count;
6155 }
6156 }
6157
6158 public LSL_Types.LSLInteger llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide)
6159 {
6160 m_host.AddScriptLPS(1);
6161 // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation
6162 // Which probably will be irrelevent in OpenSim....
6163 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
6164
6165 float bonusfactor = World.RegionInfo.EstateSettings.objectBonusFactor;
6166
6167 if (land == null)
6168 {
6169 return 0;
6170 }
6171
6172 if (sim_wide == 1)
6173 {
6174 decimal v = land.simwideArea * (decimal)(0.22) * (decimal)bonusfactor;
6175
6176 return (int)v;
6177 }
6178
6179 else
6180 {
6181 decimal v = land.area * (decimal)(0.22) * (decimal)bonusfactor;
6182
6183 return (int)v;
6184 }
6185
6186 }
6187
6188 public LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param)
6189 {
6190 m_host.AddScriptLPS(1);
6191 LandData land = World.GetLandData((float)pos.x, (float)pos.y);
6192 if (land == null)
6193 {
6194 return new LSL_Types.list(0);
6195 }
6196 LSL_Types.list ret = new LSL_Types.list();
6197 foreach (object o in param.Data)
6198 {
6199 switch (o.ToString())
6200 {
6201 case "0":
6202 ret = ret + new LSL_Types.list(land.landName);
6203 break;
6204 case "1":
6205 ret = ret + new LSL_Types.list(land.landDesc);
6206 break;
6207 case "2":
6208 ret = ret + new LSL_Types.list(land.ownerID.ToString());
6209 break;
6210 case "3":
6211 ret = ret + new LSL_Types.list(land.groupID.ToString());
6212 break;
6213 case "4":
6214 ret = ret + new LSL_Types.list(land.area);
6215 break;
6216 default:
6217 ret = ret + new LSL_Types.list(0);
6218 break;
6219 }
6220 }
6221 return ret;
6222 }
6223
6224 public void llSetLinkTexture(int linknumber, string texture, int face)
6225 {
6226 m_host.AddScriptLPS(1);
6227 NotImplemented("llSetLinkTexture");
6228 }
6229
6230 public string llStringTrim(string src, int type)
6231 {
6232 m_host.AddScriptLPS(1);
6233 if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
6234 if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
6235 if (type == (int)BuiltIn_Commands_BaseClass.STRING_TRIM) { return src.Trim(); }
6236 return src;
6237 }
6238
6239 public LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args)
6240 {
6241 m_host.AddScriptLPS(1);
6242 LSL_Types.list ret = new LSL_Types.list();
6243 LLUUID key = new LLUUID();
6244 if (LLUUID.TryParse(id, out key))
6245 {
6246 ScenePresence av = World.GetScenePresence(key);
6247
6248 if (av != null)
6249 {
6250 foreach (object o in args.Data)
6251 {
6252 switch (o.ToString())
6253 {
6254 case "1":
6255 ret.Add(av.Firstname + " " + av.Lastname);
6256 break;
6257 case "2":
6258 ret.Add("");
6259 break;
6260 case "3":
6261 ret.Add(new LSL_Types.Vector3((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
6262 break;
6263 case "4":
6264 ret.Add(new LSL_Types.Quaternion((double)av.Rotation.x, (double)av.Rotation.y, (double)av.Rotation.z, (double)av.Rotation.w));
6265 break;
6266 case "5":
6267 ret.Add(new LSL_Types.Vector3(av.Velocity.X,av.Velocity.Y,av.Velocity.Z));
6268 break;
6269 case "6":
6270 ret.Add(id);
6271 break;
6272 case "7":
6273 ret.Add(LLUUID.Zero.ToString());
6274 break;
6275 case "8":
6276 ret.Add(LLUUID.Zero.ToString());
6277 break;
6278 }
6279 }
6280 return ret;
6281 }
6282 SceneObjectPart obj = World.GetSceneObjectPart(key);
6283 if (obj != null)
6284 {
6285 foreach (object o in args.Data)
6286 {
6287 switch (o.ToString())
6288 {
6289 case "1":
6290 ret.Add(obj.Name);
6291 break;
6292 case "2":
6293 ret.Add(obj.Description);
6294 break;
6295 case "3":
6296 ret.Add(new LSL_Types.Vector3(obj.AbsolutePosition.X,obj.AbsolutePosition.Y,obj.AbsolutePosition.Z));
6297 break;
6298 case "4":
6299 ret.Add(new LSL_Types.Quaternion(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W));
6300 break;
6301 case "5":
6302 ret.Add(new LSL_Types.Vector3(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z));
6303 break;
6304 case "6":
6305 ret.Add(obj.OwnerID.ToString());
6306 break;
6307 case "7":
6308 ret.Add(obj.GroupID.ToString());
6309 break;
6310 case "8":
6311 ret.Add(obj.CreatorID.ToString());
6312 break;
6313 }
6314 }
6315 return ret;
6316 }
6317 }
6318 return new LSL_Types.list();
6319 }
6320
6321
6322 internal LLUUID ScriptByName(string name)
6323 {
6324 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
6325 {
6326 if (item.Type == 10 && item.Name == name)
6327 return item.ItemID;
6328 }
6329 return LLUUID.Zero;
6330 }
6331
6332 internal void ShoutError(string msg)
6333 {
6334 llShout(BuiltIn_Commands_BaseClass.DEBUG_CHANNEL, msg);
6335 }
6336
6337
6338
6339 internal void NotImplemented(string command)
6340 {
6341 if (throwErrorOnNotImplemented)
6342 throw new NotImplementedException("Command not implemented: " + command);
6343 }
6344
6345 internal void Deprecated(string command)
6346 {
6347 throw new Exception("Command deprecated: " + command);
6348 }
6349
6350 internal void LSLError(string msg)
6351 {
6352 throw new Exception("LSL Runtime Error: " + msg);
6353 }
6354
6355 public delegate void AssetRequestCallback(LLUUID assetID, AssetBase asset);
6356 private void WithNotecard(LLUUID assetID, AssetRequestCallback cb)
6357 {
6358 World.AssetCache.GetAsset(assetID, delegate(LLUUID i, AssetBase a) { cb(i, a); }, false);
6359 }
6360
6361 public string llGetNumberOfNotecardLines(string name)
6362 {
6363 m_host.AddScriptLPS(1);
6364
6365 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
6366 {
6367 if (item.Type == 7 && item.Name == name)
6368 {
6369 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
6370 m_Dataserver.RegisterRequest(m_localID,
6371 m_itemID, item.AssetID.ToString());
6372 if (NotecardCache.IsCached(item.AssetID))
6373 {
6374 m_ScriptEngine.m_ASYNCLSLCommandManager.
6375 m_Dataserver.DataserverReply(item.AssetID.ToString(),
6376 NotecardCache.GetLines(item.AssetID).ToString());
6377 return tid.ToString();
6378 }
6379 WithNotecard(item.AssetID, delegate (LLUUID id, AssetBase a)
6380 {
6381 System.Text.ASCIIEncoding enc =
6382 new System.Text.ASCIIEncoding();
6383 string data = enc.GetString(a.Data);
6384 //Console.WriteLine(data);
6385 NotecardCache.Cache(id, data);
6386 m_ScriptEngine.m_ASYNCLSLCommandManager.
6387 m_Dataserver.DataserverReply(id.ToString(),
6388 NotecardCache.GetLines(id).ToString());
6389 });
6390
6391 return tid.ToString();
6392 }
6393 }
6394 return LLUUID.Zero.ToString();
6395 }
6396
6397 public string llGetNotecardLine(string name, int line)
6398 {
6399 m_host.AddScriptLPS(1);
6400
6401 foreach (TaskInventoryItem item in m_host.TaskInventory.Values)
6402 {
6403 if (item.Type == 7 && item.Name == name)
6404 {
6405 LLUUID tid = m_ScriptEngine.m_ASYNCLSLCommandManager.
6406 m_Dataserver.RegisterRequest(m_localID,
6407 m_itemID, item.AssetID.ToString());
6408 if (NotecardCache.IsCached(item.AssetID))
6409 {
6410 m_ScriptEngine.m_ASYNCLSLCommandManager.
6411 m_Dataserver.DataserverReply(item.AssetID.ToString(),
6412 NotecardCache.GetLine(item.AssetID, line));
6413 return tid.ToString();
6414 }
6415 WithNotecard(item.AssetID, delegate (LLUUID id, AssetBase a)
6416 {
6417 System.Text.ASCIIEncoding enc =
6418 new System.Text.ASCIIEncoding();
6419 string data = enc.GetString(a.Data);
6420 //Console.WriteLine(data);
6421 NotecardCache.Cache(id, data);
6422 m_ScriptEngine.m_ASYNCLSLCommandManager.
6423 m_Dataserver.DataserverReply(id.ToString(),
6424 NotecardCache.GetLine(id, line));
6425 });
6426
6427 return tid.ToString();
6428 }
6429 }
6430
6431 return String.Empty;
6432 }
6433
6434 }
6435
6436 public class NotecardCache
6437 {
6438 private class Notecard
6439 {
6440 public string[] text;
6441 public DateTime lastRef;
6442 }
6443
6444 private static Dictionary<LLUUID, Notecard> m_Notecards =
6445 new Dictionary<LLUUID, Notecard>();
6446
6447 public static void Cache(LLUUID assetID, string text)
6448 {
6449 CacheCheck();
6450
6451 lock (m_Notecards)
6452 {
6453 if (m_Notecards.ContainsKey(assetID))
6454 return;
6455
6456 Notecard nc = new Notecard();
6457 nc.lastRef = DateTime.Now;
6458 nc.text = ParseText(text.Replace("\r", "").Split('\n'));
6459 m_Notecards[assetID] = nc;
6460 }
6461 }
6462
6463 private static string[] ParseText(string[] input)
6464 {
6465 int idx = 0;
6466 int level = 0;
6467 List<string> output = new List<string>();
6468 string[] words;
6469
6470 while (idx < input.Length)
6471 {
6472 if (input[idx] == "{")
6473 {
6474 level++;
6475 idx++;
6476 continue;
6477 }
6478
6479 if (input[idx]== "}")
6480 {
6481 level--;
6482 idx++;
6483 continue;
6484 }
6485
6486 switch (level)
6487 {
6488 case 0:
6489 words = input[idx].Split(' '); // Linden text ver
6490 int version = int.Parse(words[3]);
6491 if (version != 2)
6492 return new String[0];
6493 break;
6494 case 1:
6495 words = input[idx].Split(' ');
6496 if (words[0] == "LLEmbeddedItems")
6497 break;
6498 if (words[0] == "Text")
6499 {
6500 int len = int.Parse(words[2]);
6501 idx++;
6502
6503 int count = -1;
6504
6505 while (count < len)
6506 {
6507 int l = input[idx].Length;
6508 string ln = input[idx];
6509
6510 int need = len-count-1;
6511 if (ln.Length > need)
6512 ln = ln.Substring(0, need);
6513
6514 output.Add(ln);
6515 count += ln.Length + 1;
6516 idx++;
6517 }
6518
6519 return output.ToArray();
6520 }
6521 break;
6522 case 2:
6523 words = input[idx].Split(' '); // count
6524 if (words[0] == "count")
6525 {
6526 int c = int.Parse(words[1]);
6527 if (c > 0)
6528 return new String[0];
6529 break;
6530 }
6531 break;
6532 }
6533 idx++;
6534 }
6535 return output.ToArray();
6536 }
6537
6538 public static bool IsCached(LLUUID assetID)
6539 {
6540 lock (m_Notecards)
6541 {
6542 return m_Notecards.ContainsKey(assetID);
6543 }
6544 }
6545
6546 public static int GetLines(LLUUID assetID)
6547 {
6548 if (!IsCached(assetID))
6549 return -1;
6550
6551 lock (m_Notecards)
6552 {
6553 m_Notecards[assetID].lastRef = DateTime.Now;
6554 return m_Notecards[assetID].text.Length;
6555 }
6556 }
6557
6558 public static string GetLine(LLUUID assetID, int line)
6559 {
6560 if (line < 0)
6561 return "";
6562
6563 string data;
6564
6565 if (!IsCached(assetID))
6566 return "";
6567
6568 lock (m_Notecards)
6569 {
6570 m_Notecards[assetID].lastRef = DateTime.Now;
6571
6572 if (line >= m_Notecards[assetID].text.Length)
6573 return "\n\n\n";
6574
6575 data = m_Notecards[assetID].text[line];
6576 if (data.Length > 255)
6577 data = data.Substring(0, 255);
6578
6579 return data;
6580 }
6581 }
6582
6583 public static void CacheCheck()
6584 {
6585 foreach (LLUUID key in new List<LLUUID>(m_Notecards.Keys))
6586 {
6587 Notecard nc = m_Notecards[key];
6588 if (nc.lastRef.AddSeconds(30) < DateTime.Now)
6589 m_Notecards.Remove(key);
6590 }
6591 }
6592 }
6593}