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