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