opensim – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | eva | 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 OpenSimulator Project nor the |
||
13 | * names of its contributors may be used to endorse or promote products |
||
14 | * derived from this software without specific prior written permission. |
||
15 | * |
||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
||
26 | */ |
||
27 | |||
28 | using System; |
||
29 | using System.Collections; |
||
30 | using System.Collections.Generic; |
||
31 | using System.IO; |
||
32 | using System.Reflection; |
||
33 | using System.Runtime.Remoting.Lifetime; |
||
34 | using System.Text; |
||
35 | using System.Net; |
||
36 | using System.Threading; |
||
37 | using System.Xml; |
||
38 | using log4net; |
||
39 | using OpenMetaverse; |
||
40 | using OpenMetaverse.StructuredData; |
||
41 | using Nini.Config; |
||
42 | using OpenSim; |
||
43 | using OpenSim.Framework; |
||
44 | |||
45 | using OpenSim.Framework.Console; |
||
46 | using OpenSim.Region.Framework.Interfaces; |
||
47 | using OpenSim.Region.Framework.Scenes; |
||
48 | using OpenSim.Region.ScriptEngine.Shared; |
||
49 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; |
||
50 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
||
51 | using OpenSim.Region.ScriptEngine.Interfaces; |
||
52 | using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; |
||
53 | using TPFlags = OpenSim.Framework.Constants.TeleportFlags; |
||
54 | using OpenSim.Services.Interfaces; |
||
55 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; |
||
56 | using System.Text.RegularExpressions; |
||
57 | |||
58 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; |
||
59 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; |
||
60 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
||
61 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; |
||
62 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; |
||
63 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
||
64 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; |
||
65 | using PermissionMask = OpenSim.Framework.PermissionMask; |
||
66 | |||
67 | namespace OpenSim.Region.ScriptEngine.Shared.Api |
||
68 | { |
||
69 | ////////////////////////////////////////////////////////////// |
||
70 | // |
||
71 | // Level description |
||
72 | // |
||
73 | // None - Function is no threat at all. It doesn't constitute |
||
74 | // an threat to either users or the system and has no |
||
75 | // known side effects |
||
76 | // |
||
77 | // Nuisance - Abuse of this command can cause a nuisance to the |
||
78 | // region operator, such as log message spew |
||
79 | // |
||
80 | // VeryLow - Extreme levels ob abuse of this function can cause |
||
81 | // impaired functioning of the region, or very gullible |
||
82 | // users can be tricked into experiencing harmless effects |
||
83 | // |
||
84 | // Low - Intentional abuse can cause crashes or malfunction |
||
85 | // under certain circumstances, which can easily be rectified, |
||
86 | // or certain users can be tricked into certain situations |
||
87 | // in an avoidable manner. |
||
88 | // |
||
89 | // Moderate - Intentional abuse can cause denial of service and crashes |
||
90 | // with potential of data or state loss, or trusting users |
||
91 | // can be tricked into embarrassing or uncomfortable |
||
92 | // situationsa. |
||
93 | // |
||
94 | // High - Casual abuse can cause impaired functionality or temporary |
||
95 | // denial of service conditions. Intentional abuse can easily |
||
96 | // cause crashes with potential data loss, or can be used to |
||
97 | // trick experienced and cautious users into unwanted situations, |
||
98 | // or changes global data permanently and without undo ability |
||
99 | // Malicious scripting can allow theft of content |
||
100 | // |
||
101 | // VeryHigh - Even normal use may, depending on the number of instances, |
||
102 | // or frequency of use, result in severe service impairment |
||
103 | // or crash with loss of data, or can be used to cause |
||
104 | // unwanted or harmful effects on users without giving the |
||
105 | // user a means to avoid it. |
||
106 | // |
||
107 | // Severe - Even casual use is a danger to region stability, or function |
||
108 | // allows console or OS command execution, or function allows |
||
109 | // taking money without consent, or allows deletion or |
||
110 | // modification of user data, or allows the compromise of |
||
111 | // sensitive data by design. |
||
112 | |||
113 | class FunctionPerms |
||
114 | { |
||
115 | public List<UUID> AllowedCreators; |
||
116 | public List<UUID> AllowedOwners; |
||
117 | public List<string> AllowedOwnerClasses; |
||
118 | |||
119 | public FunctionPerms() |
||
120 | { |
||
121 | AllowedCreators = new List<UUID>(); |
||
122 | AllowedOwners = new List<UUID>(); |
||
123 | AllowedOwnerClasses = new List<string>(); |
||
124 | } |
||
125 | } |
||
126 | |||
127 | [Serializable] |
||
128 | public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi |
||
129 | { |
||
130 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
||
131 | |||
132 | public const string GridInfoServiceConfigSectionName = "GridInfoService"; |
||
133 | |||
134 | internal IScriptEngine m_ScriptEngine; |
||
135 | internal ILSL_Api m_LSL_Api = null; // get a reference to the LSL API so we can call methods housed there |
||
136 | internal SceneObjectPart m_host; |
||
137 | internal TaskInventoryItem m_item; |
||
138 | internal bool m_OSFunctionsEnabled = false; |
||
139 | internal ThreatLevel m_MaxThreatLevel = ThreatLevel.VeryLow; |
||
140 | internal float m_ScriptDelayFactor = 1.0f; |
||
141 | internal float m_ScriptDistanceFactor = 1.0f; |
||
142 | internal Dictionary<string, FunctionPerms > m_FunctionPerms = new Dictionary<string, FunctionPerms >(); |
||
143 | |||
144 | protected IUrlModule m_UrlModule = null; |
||
145 | |||
146 | public void Initialize( |
||
147 | IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle) |
||
148 | { |
||
149 | m_ScriptEngine = scriptEngine; |
||
150 | m_host = host; |
||
151 | m_item = item; |
||
152 | |||
153 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); |
||
154 | |||
155 | if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) |
||
156 | m_OSFunctionsEnabled = true; |
||
157 | |||
158 | m_ScriptDelayFactor = |
||
159 | m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); |
||
160 | m_ScriptDistanceFactor = |
||
161 | m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f); |
||
162 | |||
163 | string risk = m_ScriptEngine.Config.GetString("OSFunctionThreatLevel", "VeryLow"); |
||
164 | switch (risk) |
||
165 | { |
||
166 | case "NoAccess": |
||
167 | m_MaxThreatLevel = ThreatLevel.NoAccess; |
||
168 | break; |
||
169 | case "None": |
||
170 | m_MaxThreatLevel = ThreatLevel.None; |
||
171 | break; |
||
172 | case "VeryLow": |
||
173 | m_MaxThreatLevel = ThreatLevel.VeryLow; |
||
174 | break; |
||
175 | case "Low": |
||
176 | m_MaxThreatLevel = ThreatLevel.Low; |
||
177 | break; |
||
178 | case "Moderate": |
||
179 | m_MaxThreatLevel = ThreatLevel.Moderate; |
||
180 | break; |
||
181 | case "High": |
||
182 | m_MaxThreatLevel = ThreatLevel.High; |
||
183 | break; |
||
184 | case "VeryHigh": |
||
185 | m_MaxThreatLevel = ThreatLevel.VeryHigh; |
||
186 | break; |
||
187 | case "Severe": |
||
188 | m_MaxThreatLevel = ThreatLevel.Severe; |
||
189 | break; |
||
190 | default: |
||
191 | break; |
||
192 | } |
||
193 | } |
||
194 | |||
195 | public override Object InitializeLifetimeService() |
||
196 | { |
||
197 | ILease lease = (ILease)base.InitializeLifetimeService(); |
||
198 | |||
199 | if (lease.CurrentState == LeaseState.Initial) |
||
200 | { |
||
201 | lease.InitialLeaseTime = TimeSpan.FromMinutes(0); |
||
202 | // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); |
||
203 | // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); |
||
204 | } |
||
205 | return lease; |
||
206 | } |
||
207 | |||
208 | public Scene World |
||
209 | { |
||
210 | get { return m_ScriptEngine.World; } |
||
211 | } |
||
212 | |||
213 | internal void OSSLError(string msg) |
||
214 | { |
||
215 | throw new ScriptException("OSSL Runtime Error: " + msg); |
||
216 | } |
||
217 | |||
218 | /// <summary> |
||
219 | /// Initialize the LSL interface. |
||
220 | /// </summary> |
||
221 | /// <remarks> |
||
222 | /// FIXME: This is an abomination. We should be able to set this up earlier but currently we have no |
||
223 | /// guarantee the interface is present on Initialize(). There needs to be another post initialize call from |
||
224 | /// ScriptInstance. |
||
225 | /// </remarks> |
||
226 | private void InitLSL() |
||
227 | { |
||
228 | if (m_LSL_Api != null) |
||
229 | return; |
||
230 | |||
231 | m_LSL_Api = (ILSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "LSL"); |
||
232 | } |
||
233 | |||
234 | // |
||
235 | //Dumps an error message on the debug console. |
||
236 | // |
||
237 | |||
238 | internal void OSSLShoutError(string message) |
||
239 | { |
||
240 | if (message.Length > 1023) |
||
241 | message = message.Substring(0, 1023); |
||
242 | |||
243 | World.SimChat(Utils.StringToBytes(message), |
||
244 | ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); |
||
245 | |||
246 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
||
247 | wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); |
||
248 | } |
||
249 | |||
250 | // Returns of the function is allowed. Throws a script exception if not allowed. |
||
251 | public void CheckThreatLevel(ThreatLevel level, string function) |
||
252 | { |
||
253 | if (!m_OSFunctionsEnabled) |
||
254 | OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws |
||
255 | |||
256 | string reasonWhyNot = CheckThreatLevelTest(level, function); |
||
257 | if (!String.IsNullOrEmpty(reasonWhyNot)) |
||
258 | { |
||
259 | OSSLError(reasonWhyNot); |
||
260 | } |
||
261 | } |
||
262 | |||
263 | // Check to see if function is allowed. Returns an empty string if function permitted |
||
264 | // or a string explaining why this function can't be used. |
||
265 | private string CheckThreatLevelTest(ThreatLevel level, string function) |
||
266 | { |
||
267 | if (!m_FunctionPerms.ContainsKey(function)) |
||
268 | { |
||
269 | FunctionPerms perms = new FunctionPerms(); |
||
270 | m_FunctionPerms[function] = perms; |
||
271 | |||
272 | string ownerPerm = m_ScriptEngine.Config.GetString("Allow_" + function, ""); |
||
273 | string creatorPerm = m_ScriptEngine.Config.GetString("Creators_" + function, ""); |
||
274 | if (ownerPerm == "" && creatorPerm == "") |
||
275 | { |
||
276 | // Default behavior |
||
277 | perms.AllowedOwners = null; |
||
278 | perms.AllowedCreators = null; |
||
279 | perms.AllowedOwnerClasses = null; |
||
280 | } |
||
281 | else |
||
282 | { |
||
283 | bool allowed; |
||
284 | |||
285 | if (bool.TryParse(ownerPerm, out allowed)) |
||
286 | { |
||
287 | // Boolean given |
||
288 | if (allowed) |
||
289 | { |
||
290 | // Allow globally |
||
291 | perms.AllowedOwners.Add(UUID.Zero); |
||
292 | } |
||
293 | } |
||
294 | else |
||
295 | { |
||
296 | string[] ids = ownerPerm.Split(new char[] {','}); |
||
297 | foreach (string id in ids) |
||
298 | { |
||
299 | string current = id.Trim(); |
||
300 | if (current.ToUpper() == "PARCEL_GROUP_MEMBER" || current.ToUpper() == "PARCEL_OWNER" || current.ToUpper() == "ESTATE_MANAGER" || current.ToUpper() == "ESTATE_OWNER") |
||
301 | { |
||
302 | if (!perms.AllowedOwnerClasses.Contains(current)) |
||
303 | perms.AllowedOwnerClasses.Add(current.ToUpper()); |
||
304 | } |
||
305 | else |
||
306 | { |
||
307 | UUID uuid; |
||
308 | |||
309 | if (UUID.TryParse(current, out uuid)) |
||
310 | { |
||
311 | if (uuid != UUID.Zero) |
||
312 | perms.AllowedOwners.Add(uuid); |
||
313 | } |
||
314 | } |
||
315 | } |
||
316 | |||
317 | ids = creatorPerm.Split(new char[] {','}); |
||
318 | foreach (string id in ids) |
||
319 | { |
||
320 | string current = id.Trim(); |
||
321 | UUID uuid; |
||
322 | |||
323 | if (UUID.TryParse(current, out uuid)) |
||
324 | { |
||
325 | if (uuid != UUID.Zero) |
||
326 | perms.AllowedCreators.Add(uuid); |
||
327 | } |
||
328 | } |
||
329 | } |
||
330 | } |
||
331 | } |
||
332 | |||
333 | // If the list is null, then the value was true / undefined |
||
334 | // Threat level governs permissions in this case |
||
335 | // |
||
336 | // If the list is non-null, then it is a list of UUIDs allowed |
||
337 | // to use that particular function. False causes an empty |
||
338 | // list and therefore means "no one" |
||
339 | // |
||
340 | // To allow use by anyone, the list contains UUID.Zero |
||
341 | // |
||
342 | if (m_FunctionPerms[function].AllowedOwners == null) |
||
343 | { |
||
344 | // Allow / disallow by threat level |
||
345 | if (level > m_MaxThreatLevel) |
||
346 | return |
||
347 | String.Format( |
||
348 | "{0} permission denied. Allowed threat level is {1} but function threat level is {2}.", |
||
349 | function, m_MaxThreatLevel, level); |
||
350 | } |
||
351 | else |
||
352 | { |
||
353 | if (!m_FunctionPerms[function].AllowedOwners.Contains(UUID.Zero)) |
||
354 | { |
||
355 | // Not anyone. Do detailed checks |
||
356 | if (m_FunctionPerms[function].AllowedOwners.Contains(m_host.OwnerID)) |
||
357 | { |
||
358 | // prim owner is in the list of allowed owners |
||
359 | return String.Empty; |
||
360 | } |
||
361 | |||
362 | UUID ownerID = m_item.OwnerID; |
||
363 | |||
364 | //OSSL only may be used if object is in the same group as the parcel |
||
365 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_GROUP_MEMBER")) |
||
366 | { |
||
367 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
||
368 | |||
369 | if (land.LandData.GroupID == m_item.GroupID && land.LandData.GroupID != UUID.Zero) |
||
370 | { |
||
371 | return String.Empty; |
||
372 | } |
||
373 | } |
||
374 | |||
375 | //Only Parcelowners may use the function |
||
376 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("PARCEL_OWNER")) |
||
377 | { |
||
378 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
||
379 | |||
380 | if (land.LandData.OwnerID == ownerID) |
||
381 | { |
||
382 | return String.Empty; |
||
383 | } |
||
384 | } |
||
385 | |||
386 | //Only Estate Managers may use the function |
||
387 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_MANAGER")) |
||
388 | { |
||
389 | //Only Estate Managers may use the function |
||
390 | if (World.RegionInfo.EstateSettings.IsEstateManagerOrOwner(ownerID) && World.RegionInfo.EstateSettings.EstateOwner != ownerID) |
||
391 | { |
||
392 | return String.Empty; |
||
393 | } |
||
394 | } |
||
395 | |||
396 | //Only regionowners may use the function |
||
397 | if (m_FunctionPerms[function].AllowedOwnerClasses.Contains("ESTATE_OWNER")) |
||
398 | { |
||
399 | if (World.RegionInfo.EstateSettings.EstateOwner == ownerID) |
||
400 | { |
||
401 | return String.Empty; |
||
402 | } |
||
403 | } |
||
404 | |||
405 | if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) |
||
406 | return( |
||
407 | String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", |
||
408 | function)); |
||
409 | |||
410 | if (m_item.CreatorID != ownerID) |
||
411 | { |
||
412 | if ((m_item.CurrentPermissions & (uint)PermissionMask.Modify) != 0) |
||
413 | return String.Format("{0} permission denied. Script permissions error.", function); |
||
414 | |||
415 | } |
||
416 | } |
||
417 | } |
||
418 | return String.Empty; |
||
419 | } |
||
420 | |||
421 | internal void OSSLDeprecated(string function, string replacement) |
||
422 | { |
||
423 | OSSLShoutError(string.Format("Use of function {0} is deprecated. Use {1} instead.", function, replacement)); |
||
424 | } |
||
425 | |||
426 | protected void ScriptSleep(int delay) |
||
427 | { |
||
428 | delay = (int)((float)delay * m_ScriptDelayFactor); |
||
429 | if (delay == 0) |
||
430 | return; |
||
431 | System.Threading.Thread.Sleep(delay); |
||
432 | } |
||
433 | |||
434 | public LSL_Integer osSetTerrainHeight(int x, int y, double val) |
||
435 | { |
||
436 | CheckThreatLevel(ThreatLevel.High, "osSetTerrainHeight"); |
||
437 | |||
438 | return SetTerrainHeight(x, y, val); |
||
439 | } |
||
440 | |||
441 | public LSL_Integer osTerrainSetHeight(int x, int y, double val) |
||
442 | { |
||
443 | CheckThreatLevel(ThreatLevel.High, "osTerrainSetHeight"); |
||
444 | OSSLDeprecated("osTerrainSetHeight", "osSetTerrainHeight"); |
||
445 | |||
446 | return SetTerrainHeight(x, y, val); |
||
447 | } |
||
448 | |||
449 | private LSL_Integer SetTerrainHeight(int x, int y, double val) |
||
450 | { |
||
451 | m_host.AddScriptLPS(1); |
||
452 | |||
453 | if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0) |
||
454 | OSSLError("osSetTerrainHeight: Coordinate out of bounds"); |
||
455 | |||
456 | if (World.Permissions.CanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0))) |
||
457 | { |
||
458 | World.Heightmap[x, y] = val; |
||
459 | return 1; |
||
460 | } |
||
461 | else |
||
462 | { |
||
463 | return 0; |
||
464 | } |
||
465 | } |
||
466 | |||
467 | public LSL_Float osGetTerrainHeight(int x, int y) |
||
468 | { |
||
469 | CheckThreatLevel(ThreatLevel.None, "osGetTerrainHeight"); |
||
470 | return GetTerrainHeight(x, y); |
||
471 | } |
||
472 | |||
473 | public LSL_Float osTerrainGetHeight(int x, int y) |
||
474 | { |
||
475 | CheckThreatLevel(ThreatLevel.None, "osTerrainGetHeight"); |
||
476 | OSSLDeprecated("osTerrainGetHeight", "osGetTerrainHeight"); |
||
477 | return GetTerrainHeight(x, y); |
||
478 | } |
||
479 | |||
480 | private LSL_Float GetTerrainHeight(int x, int y) |
||
481 | { |
||
482 | m_host.AddScriptLPS(1); |
||
483 | if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0) |
||
484 | OSSLError("osGetTerrainHeight: Coordinate out of bounds"); |
||
485 | |||
486 | return World.Heightmap[x, y]; |
||
487 | } |
||
488 | |||
489 | public void osTerrainFlush() |
||
490 | { |
||
491 | CheckThreatLevel(ThreatLevel.VeryLow, "osTerrainFlush"); |
||
492 | m_host.AddScriptLPS(1); |
||
493 | |||
494 | ITerrainModule terrainModule = World.RequestModuleInterface<ITerrainModule>(); |
||
495 | if (terrainModule != null) terrainModule.TaintTerrain(); |
||
496 | } |
||
497 | |||
498 | public int osRegionRestart(double seconds) |
||
499 | { |
||
500 | // This is High here because region restart is not reliable |
||
501 | // it may result in the region staying down or becoming |
||
502 | // unstable. This should be changed to Low or VeryLow once |
||
503 | // The underlying functionality is fixed, since the security |
||
504 | // as such is sound |
||
505 | // |
||
506 | CheckThreatLevel(ThreatLevel.High, "osRegionRestart"); |
||
507 | |||
508 | IRestartModule restartModule = World.RequestModuleInterface<IRestartModule>(); |
||
509 | m_host.AddScriptLPS(1); |
||
510 | if (World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false) && (restartModule != null)) |
||
511 | { |
||
512 | if (seconds < 15) |
||
513 | { |
||
514 | restartModule.AbortRestart("Restart aborted"); |
||
515 | return 1; |
||
516 | } |
||
517 | |||
518 | List<int> times = new List<int>(); |
||
519 | while (seconds > 0) |
||
520 | { |
||
521 | times.Add((int)seconds); |
||
522 | if (seconds > 300) |
||
523 | seconds -= 120; |
||
524 | else if (seconds > 30) |
||
525 | seconds -= 30; |
||
526 | else |
||
527 | seconds -= 15; |
||
528 | } |
||
529 | |||
530 | restartModule.ScheduleRestart(UUID.Zero, "Region will restart in {0}", times.ToArray(), true); |
||
531 | return 1; |
||
532 | } |
||
533 | else |
||
534 | { |
||
535 | return 0; |
||
536 | } |
||
537 | } |
||
538 | |||
539 | public void osRegionNotice(string msg) |
||
540 | { |
||
541 | // This implementation provides absolutely no security |
||
542 | // It's high griefing potential makes this classification |
||
543 | // necessary |
||
544 | // |
||
545 | CheckThreatLevel(ThreatLevel.VeryHigh, "osRegionNotice"); |
||
546 | |||
547 | m_host.AddScriptLPS(1); |
||
548 | |||
549 | IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); |
||
550 | |||
551 | if (dm != null) |
||
552 | dm.SendGeneralAlert(msg); |
||
553 | } |
||
554 | |||
555 | public void osSetRot(UUID target, Quaternion rotation) |
||
556 | { |
||
557 | // This function has no security. It can be used to destroy |
||
558 | // arbitrary builds the user would normally have no rights to |
||
559 | // |
||
560 | CheckThreatLevel(ThreatLevel.VeryHigh, "osSetRot"); |
||
561 | |||
562 | m_host.AddScriptLPS(1); |
||
563 | if (World.Entities.ContainsKey(target)) |
||
564 | { |
||
565 | EntityBase entity; |
||
566 | if (World.Entities.TryGetValue(target, out entity)) |
||
567 | { |
||
568 | if (entity is SceneObjectGroup) |
||
569 | ((SceneObjectGroup)entity).UpdateGroupRotationR(rotation); |
||
570 | else if (entity is ScenePresence) |
||
571 | ((ScenePresence)entity).Rotation = rotation; |
||
572 | } |
||
573 | } |
||
574 | else |
||
575 | { |
||
576 | OSSLError("osSetRot: Invalid target"); |
||
577 | } |
||
578 | } |
||
579 | |||
580 | public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, |
||
581 | int timer) |
||
582 | { |
||
583 | // This may be upgraded depending on the griefing or DOS |
||
584 | // potential, or guarded with a delay |
||
585 | // |
||
586 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURL"); |
||
587 | |||
588 | m_host.AddScriptLPS(1); |
||
589 | if (dynamicID == String.Empty) |
||
590 | { |
||
591 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); |
||
592 | UUID createdTexture = |
||
593 | textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, |
||
594 | extraParams, timer); |
||
595 | return createdTexture.ToString(); |
||
596 | } |
||
597 | else |
||
598 | { |
||
599 | //TODO update existing dynamic textures |
||
600 | } |
||
601 | |||
602 | return UUID.Zero.ToString(); |
||
603 | } |
||
604 | |||
605 | public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, |
||
606 | int timer, int alpha) |
||
607 | { |
||
608 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlend"); |
||
609 | |||
610 | m_host.AddScriptLPS(1); |
||
611 | if (dynamicID == String.Empty) |
||
612 | { |
||
613 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); |
||
614 | UUID createdTexture = |
||
615 | textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, |
||
616 | extraParams, timer, true, (byte) alpha); |
||
617 | return createdTexture.ToString(); |
||
618 | } |
||
619 | else |
||
620 | { |
||
621 | //TODO update existing dynamic textures |
||
622 | } |
||
623 | |||
624 | return UUID.Zero.ToString(); |
||
625 | } |
||
626 | |||
627 | public string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams, |
||
628 | bool blend, int disp, int timer, int alpha, int face) |
||
629 | { |
||
630 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlendFace"); |
||
631 | |||
632 | m_host.AddScriptLPS(1); |
||
633 | if (dynamicID == String.Empty) |
||
634 | { |
||
635 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); |
||
636 | UUID createdTexture = |
||
637 | textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, |
||
638 | extraParams, timer, blend, disp, (byte) alpha, face); |
||
639 | return createdTexture.ToString(); |
||
640 | } |
||
641 | else |
||
642 | { |
||
643 | //TODO update existing dynamic textures |
||
644 | } |
||
645 | |||
646 | return UUID.Zero.ToString(); |
||
647 | } |
||
648 | |||
649 | public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, |
||
650 | int timer) |
||
651 | { |
||
652 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureData"); |
||
653 | |||
654 | m_host.AddScriptLPS(1); |
||
655 | if (dynamicID == String.Empty) |
||
656 | { |
||
657 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); |
||
658 | if (textureManager != null) |
||
659 | { |
||
660 | if (extraParams == String.Empty) |
||
661 | { |
||
662 | extraParams = "256"; |
||
663 | } |
||
664 | UUID createdTexture = |
||
665 | textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, |
||
666 | extraParams, timer); |
||
667 | return createdTexture.ToString(); |
||
668 | } |
||
669 | } |
||
670 | else |
||
671 | { |
||
672 | //TODO update existing dynamic textures |
||
673 | } |
||
674 | |||
675 | return UUID.Zero.ToString(); |
||
676 | } |
||
677 | |||
678 | public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, |
||
679 | int timer, int alpha) |
||
680 | { |
||
681 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlend"); |
||
682 | |||
683 | m_host.AddScriptLPS(1); |
||
684 | if (dynamicID == String.Empty) |
||
685 | { |
||
686 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); |
||
687 | if (textureManager != null) |
||
688 | { |
||
689 | if (extraParams == String.Empty) |
||
690 | { |
||
691 | extraParams = "256"; |
||
692 | } |
||
693 | UUID createdTexture = |
||
694 | textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, |
||
695 | extraParams, timer, true, (byte) alpha); |
||
696 | return createdTexture.ToString(); |
||
697 | } |
||
698 | } |
||
699 | else |
||
700 | { |
||
701 | //TODO update existing dynamic textures |
||
702 | } |
||
703 | |||
704 | return UUID.Zero.ToString(); |
||
705 | } |
||
706 | |||
707 | public string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams, |
||
708 | bool blend, int disp, int timer, int alpha, int face) |
||
709 | { |
||
710 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlendFace"); |
||
711 | |||
712 | m_host.AddScriptLPS(1); |
||
713 | if (dynamicID == String.Empty) |
||
714 | { |
||
715 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); |
||
716 | if (textureManager != null) |
||
717 | { |
||
718 | if (extraParams == String.Empty) |
||
719 | { |
||
720 | extraParams = "256"; |
||
721 | } |
||
722 | UUID createdTexture = |
||
723 | textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, |
||
724 | extraParams, timer, blend, disp, (byte) alpha, face); |
||
725 | return createdTexture.ToString(); |
||
726 | } |
||
727 | } |
||
728 | else |
||
729 | { |
||
730 | //TODO update existing dynamic textures |
||
731 | } |
||
732 | |||
733 | return UUID.Zero.ToString(); |
||
734 | } |
||
735 | |||
736 | public bool osConsoleCommand(string command) |
||
737 | { |
||
738 | CheckThreatLevel(ThreatLevel.Severe, "osConsoleCommand"); |
||
739 | |||
740 | m_host.AddScriptLPS(1); |
||
741 | |||
742 | // For safety, we add another permission check here, and don't rely only on the standard OSSL permissions |
||
743 | if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) |
||
744 | { |
||
745 | MainConsole.Instance.RunCommand(command); |
||
746 | return true; |
||
747 | } |
||
748 | |||
749 | return false; |
||
750 | } |
||
751 | |||
752 | public void osSetPrimFloatOnWater(int floatYN) |
||
753 | { |
||
754 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetPrimFloatOnWater"); |
||
755 | |||
756 | m_host.AddScriptLPS(1); |
||
757 | |||
758 | m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN); |
||
759 | } |
||
760 | |||
761 | // Teleport functions |
||
762 | public void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) |
||
763 | { |
||
764 | // High because there is no security check. High griefer potential |
||
765 | // |
||
766 | CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent"); |
||
767 | |||
768 | TeleportAgent(agent, regionName, position, lookat, false); |
||
769 | } |
||
770 | |||
771 | private void TeleportAgent(string agent, string regionName, |
||
772 | LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) |
||
773 | { |
||
774 | m_host.AddScriptLPS(1); |
||
775 | UUID agentId = new UUID(); |
||
776 | if (UUID.TryParse(agent, out agentId)) |
||
777 | { |
||
778 | ScenePresence presence = World.GetScenePresence(agentId); |
||
779 | if (presence != null) |
||
780 | { |
||
781 | // For osTeleportAgent, agent must be over owners land to avoid abuse |
||
782 | // For osTeleportOwner, this restriction isn't necessary |
||
783 | |||
784 | // commented out because its redundant and uneeded please remove eventually. |
||
785 | // if (relaxRestrictions || |
||
786 | // m_host.OwnerID |
||
787 | // == World.LandChannel.GetLandObject( |
||
788 | // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) |
||
789 | // { |
||
790 | |||
791 | // We will launch the teleport on a new thread so that when the script threads are terminated |
||
792 | // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. |
||
793 | Util.FireAndForget(o => World.RequestTeleportLocation( |
||
794 | presence.ControllingClient, regionName, position, |
||
795 | lookat, (uint)TPFlags.ViaLocation)); |
||
796 | |||
797 | ScriptSleep(5000); |
||
798 | |||
799 | // } |
||
800 | |||
801 | } |
||
802 | } |
||
803 | } |
||
804 | |||
805 | public void osTeleportAgent(string agent, int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) |
||
806 | { |
||
807 | // High because there is no security check. High griefer potential |
||
808 | // |
||
809 | CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent"); |
||
810 | |||
811 | TeleportAgent(agent, regionX, regionY, position, lookat, false); |
||
812 | } |
||
813 | |||
814 | private void TeleportAgent(string agent, int regionX, int regionY, |
||
815 | LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) |
||
816 | { |
||
817 | // ulong regionHandle = Util.UIntsToLong(((uint)regionX * (uint)Constants.RegionSize), ((uint)regionY * (uint)Constants.RegionSize)); |
||
818 | ulong regionHandle = Util.RegionLocToHandle((uint)regionX, (uint)regionY); |
||
819 | |||
820 | m_host.AddScriptLPS(1); |
||
821 | UUID agentId = new UUID(); |
||
822 | if (UUID.TryParse(agent, out agentId)) |
||
823 | { |
||
824 | ScenePresence presence = World.GetScenePresence(agentId); |
||
825 | if (presence != null) |
||
826 | { |
||
827 | // For osTeleportAgent, agent must be over owners land to avoid abuse |
||
828 | // For osTeleportOwner, this restriction isn't necessary |
||
829 | |||
830 | // commented out because its redundant and uneeded please remove eventually. |
||
831 | // if (relaxRestrictions || |
||
832 | // m_host.OwnerID |
||
833 | // == World.LandChannel.GetLandObject( |
||
834 | // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) |
||
835 | // { |
||
836 | |||
837 | // We will launch the teleport on a new thread so that when the script threads are terminated |
||
838 | // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. |
||
839 | Util.FireAndForget(o => World.RequestTeleportLocation( |
||
840 | presence.ControllingClient, regionHandle, |
||
841 | position, lookat, (uint)TPFlags.ViaLocation)); |
||
842 | |||
843 | ScriptSleep(5000); |
||
844 | |||
845 | // } |
||
846 | |||
847 | } |
||
848 | } |
||
849 | } |
||
850 | |||
851 | public void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) |
||
852 | { |
||
853 | osTeleportAgent(agent, World.RegionInfo.RegionName, position, lookat); |
||
854 | } |
||
855 | |||
856 | public void osTeleportOwner(string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) |
||
857 | { |
||
858 | // Threat level None because this is what can already be done with the World Map in the viewer |
||
859 | CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); |
||
860 | |||
861 | TeleportAgent(m_host.OwnerID.ToString(), regionName, position, lookat, true); |
||
862 | } |
||
863 | |||
864 | public void osTeleportOwner(LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) |
||
865 | { |
||
866 | osTeleportOwner(World.RegionInfo.RegionName, position, lookat); |
||
867 | } |
||
868 | |||
869 | public void osTeleportOwner(int regionX, int regionY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) |
||
870 | { |
||
871 | CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); |
||
872 | |||
873 | TeleportAgent(m_host.OwnerID.ToString(), regionX, regionY, position, lookat, true); |
||
874 | } |
||
875 | |||
876 | // Functions that get information from the agent itself. |
||
877 | // |
||
878 | // osGetAgentIP - this is used to determine the IP address of |
||
879 | //the client. This is needed to help configure other in world |
||
880 | //resources based on the IP address of the clients connected. |
||
881 | //I think High is a good risk level for this, as it is an |
||
882 | //information leak. |
||
883 | public string osGetAgentIP(string agent) |
||
884 | { |
||
885 | CheckThreatLevel(ThreatLevel.High, "osGetAgentIP"); |
||
886 | |||
887 | UUID avatarID = (UUID)agent; |
||
888 | |||
889 | m_host.AddScriptLPS(1); |
||
890 | if (World.Entities.ContainsKey((UUID)agent) && World.Entities[avatarID] is ScenePresence) |
||
891 | { |
||
892 | ScenePresence target = (ScenePresence)World.Entities[avatarID]; |
||
893 | return target.ControllingClient.RemoteEndPoint.Address.ToString(); |
||
894 | } |
||
895 | |||
896 | // fall through case, just return nothing |
||
897 | return ""; |
||
898 | } |
||
899 | |||
900 | // Get a list of all the avatars/agents in the region |
||
901 | public LSL_List osGetAgents() |
||
902 | { |
||
903 | // threat level is None as we could get this information with an |
||
904 | // in-world script as well, just not as efficient |
||
905 | CheckThreatLevel(ThreatLevel.None, "osGetAgents"); |
||
906 | m_host.AddScriptLPS(1); |
||
907 | |||
908 | LSL_List result = new LSL_List(); |
||
909 | World.ForEachRootScenePresence(delegate(ScenePresence sp) |
||
910 | { |
||
911 | result.Add(new LSL_String(sp.Name)); |
||
912 | }); |
||
913 | return result; |
||
914 | } |
||
915 | |||
916 | // Adam's super super custom animation functions |
||
917 | public void osAvatarPlayAnimation(string avatar, string animation) |
||
918 | { |
||
919 | CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarPlayAnimation"); |
||
920 | |||
921 | AvatarPlayAnimation(avatar, animation); |
||
922 | } |
||
923 | |||
924 | private void AvatarPlayAnimation(string avatar, string animation) |
||
925 | { |
||
926 | UUID avatarID = (UUID)avatar; |
||
927 | |||
928 | m_host.AddScriptLPS(1); |
||
929 | if (World.Entities.ContainsKey((UUID)avatar) && World.Entities[avatarID] is ScenePresence) |
||
930 | { |
||
931 | ScenePresence target = (ScenePresence)World.Entities[avatarID]; |
||
932 | if (target != null) |
||
933 | { |
||
934 | UUID animID=UUID.Zero; |
||
935 | lock (m_host.TaskInventory) |
||
936 | { |
||
937 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) |
||
938 | { |
||
939 | if (inv.Value.Name == animation) |
||
940 | { |
||
941 | if (inv.Value.Type == (int)AssetType.Animation) |
||
942 | animID = inv.Value.AssetID; |
||
943 | continue; |
||
944 | } |
||
945 | } |
||
946 | } |
||
947 | if (animID == UUID.Zero) |
||
948 | target.Animator.AddAnimation(animation, m_host.UUID); |
||
949 | else |
||
950 | target.Animator.AddAnimation(animID, m_host.UUID); |
||
951 | } |
||
952 | } |
||
953 | } |
||
954 | |||
955 | public void osAvatarStopAnimation(string avatar, string animation) |
||
956 | { |
||
957 | CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarStopAnimation"); |
||
958 | |||
959 | AvatarStopAnimation(avatar, animation); |
||
960 | } |
||
961 | |||
962 | private void AvatarStopAnimation(string avatar, string animation) |
||
963 | { |
||
964 | UUID avatarID = (UUID)avatar; |
||
965 | |||
966 | m_host.AddScriptLPS(1); |
||
967 | |||
968 | // FIXME: What we really want to do here is factor out the similar code in llStopAnimation() to a common |
||
969 | // method (though see that doesn't do the is animation check, which is probably a bug) and have both |
||
970 | // these functions call that common code. However, this does mean navigating the brain-dead requirement |
||
971 | // of calling InitLSL() |
||
972 | if (World.Entities.ContainsKey(avatarID) && World.Entities[avatarID] is ScenePresence) |
||
973 | { |
||
974 | ScenePresence target = (ScenePresence)World.Entities[avatarID]; |
||
975 | if (target != null) |
||
976 | { |
||
977 | UUID animID; |
||
978 | |||
979 | if (!UUID.TryParse(animation, out animID)) |
||
980 | { |
||
981 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(animation); |
||
982 | if (item != null && item.Type == (int)AssetType.Animation) |
||
983 | animID = item.AssetID; |
||
984 | else |
||
985 | animID = UUID.Zero; |
||
986 | } |
||
987 | |||
988 | if (animID == UUID.Zero) |
||
989 | target.Animator.RemoveAnimation(animation); |
||
990 | else |
||
991 | target.Animator.RemoveAnimation(animID, true); |
||
992 | } |
||
993 | } |
||
994 | } |
||
995 | |||
996 | //Texture draw functions |
||
997 | public string osMovePen(string drawList, int x, int y) |
||
998 | { |
||
999 | CheckThreatLevel(ThreatLevel.None, "osMovePen"); |
||
1000 | |||
1001 | m_host.AddScriptLPS(1); |
||
1002 | drawList += "MoveTo " + x + "," + y + ";"; |
||
1003 | return drawList; |
||
1004 | } |
||
1005 | |||
1006 | public string osDrawLine(string drawList, int startX, int startY, int endX, int endY) |
||
1007 | { |
||
1008 | CheckThreatLevel(ThreatLevel.None, "osDrawLine"); |
||
1009 | |||
1010 | m_host.AddScriptLPS(1); |
||
1011 | drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; "; |
||
1012 | return drawList; |
||
1013 | } |
||
1014 | |||
1015 | public string osDrawLine(string drawList, int endX, int endY) |
||
1016 | { |
||
1017 | CheckThreatLevel(ThreatLevel.None, "osDrawLine"); |
||
1018 | |||
1019 | m_host.AddScriptLPS(1); |
||
1020 | drawList += "LineTo " + endX + "," + endY + "; "; |
||
1021 | return drawList; |
||
1022 | } |
||
1023 | |||
1024 | public string osDrawText(string drawList, string text) |
||
1025 | { |
||
1026 | CheckThreatLevel(ThreatLevel.None, "osDrawText"); |
||
1027 | |||
1028 | m_host.AddScriptLPS(1); |
||
1029 | drawList += "Text " + text + "; "; |
||
1030 | return drawList; |
||
1031 | } |
||
1032 | |||
1033 | public string osDrawEllipse(string drawList, int width, int height) |
||
1034 | { |
||
1035 | CheckThreatLevel(ThreatLevel.None, "osDrawEllipse"); |
||
1036 | |||
1037 | m_host.AddScriptLPS(1); |
||
1038 | drawList += "Ellipse " + width + "," + height + "; "; |
||
1039 | return drawList; |
||
1040 | } |
||
1041 | |||
1042 | public string osDrawRectangle(string drawList, int width, int height) |
||
1043 | { |
||
1044 | CheckThreatLevel(ThreatLevel.None, "osDrawRectangle"); |
||
1045 | |||
1046 | m_host.AddScriptLPS(1); |
||
1047 | drawList += "Rectangle " + width + "," + height + "; "; |
||
1048 | return drawList; |
||
1049 | } |
||
1050 | |||
1051 | public string osDrawFilledRectangle(string drawList, int width, int height) |
||
1052 | { |
||
1053 | CheckThreatLevel(ThreatLevel.None, "osDrawFilledRectangle"); |
||
1054 | |||
1055 | m_host.AddScriptLPS(1); |
||
1056 | drawList += "FillRectangle " + width + "," + height + "; "; |
||
1057 | return drawList; |
||
1058 | } |
||
1059 | |||
1060 | public string osDrawFilledPolygon(string drawList, LSL_List x, LSL_List y) |
||
1061 | { |
||
1062 | CheckThreatLevel(ThreatLevel.None, "osDrawFilledPolygon"); |
||
1063 | |||
1064 | m_host.AddScriptLPS(1); |
||
1065 | |||
1066 | if (x.Length != y.Length || x.Length < 3) |
||
1067 | { |
||
1068 | return ""; |
||
1069 | } |
||
1070 | drawList += "FillPolygon " + x.GetLSLStringItem(0) + "," + y.GetLSLStringItem(0); |
||
1071 | for (int i = 1; i < x.Length; i++) |
||
1072 | { |
||
1073 | drawList += "," + x.GetLSLStringItem(i) + "," + y.GetLSLStringItem(i); |
||
1074 | } |
||
1075 | drawList += "; "; |
||
1076 | return drawList; |
||
1077 | } |
||
1078 | |||
1079 | public string osDrawPolygon(string drawList, LSL_List x, LSL_List y) |
||
1080 | { |
||
1081 | CheckThreatLevel(ThreatLevel.None, "osDrawPolygon"); |
||
1082 | |||
1083 | m_host.AddScriptLPS(1); |
||
1084 | |||
1085 | if (x.Length != y.Length || x.Length < 3) |
||
1086 | { |
||
1087 | return ""; |
||
1088 | } |
||
1089 | drawList += "Polygon " + x.GetLSLStringItem(0) + "," + y.GetLSLStringItem(0); |
||
1090 | for (int i = 1; i < x.Length; i++) |
||
1091 | { |
||
1092 | drawList += "," + x.GetLSLStringItem(i) + "," + y.GetLSLStringItem(i); |
||
1093 | } |
||
1094 | drawList += "; "; |
||
1095 | return drawList; |
||
1096 | } |
||
1097 | |||
1098 | public string osSetFontSize(string drawList, int fontSize) |
||
1099 | { |
||
1100 | CheckThreatLevel(ThreatLevel.None, "osSetFontSize"); |
||
1101 | |||
1102 | m_host.AddScriptLPS(1); |
||
1103 | drawList += "FontSize "+ fontSize +"; "; |
||
1104 | return drawList; |
||
1105 | } |
||
1106 | |||
1107 | public string osSetFontName(string drawList, string fontName) |
||
1108 | { |
||
1109 | CheckThreatLevel(ThreatLevel.None, "osSetFontName"); |
||
1110 | |||
1111 | m_host.AddScriptLPS(1); |
||
1112 | drawList += "FontName "+ fontName +"; "; |
||
1113 | return drawList; |
||
1114 | } |
||
1115 | |||
1116 | public string osSetPenSize(string drawList, int penSize) |
||
1117 | { |
||
1118 | CheckThreatLevel(ThreatLevel.None, "osSetPenSize"); |
||
1119 | |||
1120 | m_host.AddScriptLPS(1); |
||
1121 | drawList += "PenSize " + penSize + "; "; |
||
1122 | return drawList; |
||
1123 | } |
||
1124 | |||
1125 | public string osSetPenColor(string drawList, string color) |
||
1126 | { |
||
1127 | CheckThreatLevel(ThreatLevel.None, "osSetPenColor"); |
||
1128 | |||
1129 | m_host.AddScriptLPS(1); |
||
1130 | drawList += "PenColor " + color + "; "; |
||
1131 | return drawList; |
||
1132 | } |
||
1133 | |||
1134 | // Deprecated |
||
1135 | public string osSetPenColour(string drawList, string colour) |
||
1136 | { |
||
1137 | CheckThreatLevel(ThreatLevel.None, "osSetPenColour"); |
||
1138 | OSSLDeprecated("osSetPenColour", "osSetPenColor"); |
||
1139 | |||
1140 | m_host.AddScriptLPS(1); |
||
1141 | drawList += "PenColour " + colour + "; "; |
||
1142 | return drawList; |
||
1143 | } |
||
1144 | |||
1145 | public string osSetPenCap(string drawList, string direction, string type) |
||
1146 | { |
||
1147 | CheckThreatLevel(ThreatLevel.None, "osSetPenCap"); |
||
1148 | |||
1149 | m_host.AddScriptLPS(1); |
||
1150 | drawList += "PenCap " + direction + "," + type + "; "; |
||
1151 | return drawList; |
||
1152 | } |
||
1153 | |||
1154 | public string osDrawImage(string drawList, int width, int height, string imageUrl) |
||
1155 | { |
||
1156 | CheckThreatLevel(ThreatLevel.None, "osDrawImage"); |
||
1157 | |||
1158 | m_host.AddScriptLPS(1); |
||
1159 | drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ; |
||
1160 | return drawList; |
||
1161 | } |
||
1162 | |||
1163 | public LSL_Vector osGetDrawStringSize(string contentType, string text, string fontName, int fontSize) |
||
1164 | { |
||
1165 | CheckThreatLevel(ThreatLevel.VeryLow, "osGetDrawStringSize"); |
||
1166 | m_host.AddScriptLPS(1); |
||
1167 | |||
1168 | LSL_Vector vec = new LSL_Vector(0,0,0); |
||
1169 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); |
||
1170 | if (textureManager != null) |
||
1171 | { |
||
1172 | double xSize, ySize; |
||
1173 | textureManager.GetDrawStringSize(contentType, text, fontName, fontSize, |
||
1174 | out xSize, out ySize); |
||
1175 | vec.x = xSize; |
||
1176 | vec.y = ySize; |
||
1177 | } |
||
1178 | return vec; |
||
1179 | } |
||
1180 | |||
1181 | public void osSetStateEvents(int events) |
||
1182 | { |
||
1183 | // This function is a hack. There is no reason for it's existence |
||
1184 | // anymore, since state events now work properly. |
||
1185 | // It was probably added as a crutch or debugging aid, and |
||
1186 | // should be removed |
||
1187 | // |
||
1188 | CheckThreatLevel(ThreatLevel.High, "osSetStateEvents"); |
||
1189 | m_host.AddScriptLPS(1); |
||
1190 | |||
1191 | m_host.SetScriptEvents(m_item.ItemID, events); |
||
1192 | } |
||
1193 | |||
1194 | public void osSetRegionWaterHeight(double height) |
||
1195 | { |
||
1196 | CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight"); |
||
1197 | |||
1198 | m_host.AddScriptLPS(1); |
||
1199 | |||
1200 | World.EventManager.TriggerRequestChangeWaterHeight((float)height); |
||
1201 | } |
||
1202 | |||
1203 | /// <summary> |
||
1204 | /// Changes the Region Sun Settings, then Triggers a Sun Update |
||
1205 | /// </summary> |
||
1206 | /// <param name="useEstateSun">True to use Estate Sun instead of Region Sun</param> |
||
1207 | /// <param name="sunFixed">True to keep the sun stationary</param> |
||
1208 | /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param> |
||
1209 | public void osSetRegionSunSettings(bool useEstateSun, bool sunFixed, double sunHour) |
||
1210 | { |
||
1211 | CheckThreatLevel(ThreatLevel.High, "osSetRegionSunSettings"); |
||
1212 | |||
1213 | m_host.AddScriptLPS(1); |
||
1214 | |||
1215 | while (sunHour > 24.0) |
||
1216 | sunHour -= 24.0; |
||
1217 | |||
1218 | while (sunHour < 0) |
||
1219 | sunHour += 24.0; |
||
1220 | |||
1221 | World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun; |
||
1222 | World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30 |
||
1223 | World.RegionInfo.RegionSettings.FixedSun = sunFixed; |
||
1224 | World.RegionInfo.RegionSettings.Save(); |
||
1225 | |||
1226 | World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle); |
||
1227 | } |
||
1228 | |||
1229 | /// <summary> |
||
1230 | /// Changes the Estate Sun Settings, then Triggers a Sun Update |
||
1231 | /// </summary> |
||
1232 | /// <param name="sunFixed">True to keep the sun stationary, false to use global time</param> |
||
1233 | /// <param name="sunHour">The "Sun Hour" that is desired, 0...24, with 0 just after SunRise</param> |
||
1234 | public void osSetEstateSunSettings(bool sunFixed, double sunHour) |
||
1235 | { |
||
1236 | CheckThreatLevel(ThreatLevel.High, "osSetEstateSunSettings"); |
||
1237 | |||
1238 | m_host.AddScriptLPS(1); |
||
1239 | |||
1240 | while (sunHour > 24.0) |
||
1241 | sunHour -= 24.0; |
||
1242 | |||
1243 | while (sunHour < 0) |
||
1244 | sunHour += 24.0; |
||
1245 | |||
1246 | World.RegionInfo.EstateSettings.UseGlobalTime = !sunFixed; |
||
1247 | World.RegionInfo.EstateSettings.SunPosition = sunHour; |
||
1248 | World.RegionInfo.EstateSettings.FixedSun = sunFixed; |
||
1249 | World.RegionInfo.EstateSettings.Save(); |
||
1250 | |||
1251 | World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle); |
||
1252 | } |
||
1253 | |||
1254 | /// <summary> |
||
1255 | /// Return the current Sun Hour 0...24, with 0 being roughly sun-rise |
||
1256 | /// </summary> |
||
1257 | /// <returns></returns> |
||
1258 | public double osGetCurrentSunHour() |
||
1259 | { |
||
1260 | CheckThreatLevel(ThreatLevel.None, "osGetCurrentSunHour"); |
||
1261 | |||
1262 | m_host.AddScriptLPS(1); |
||
1263 | |||
1264 | // Must adjust for the fact that Region Sun Settings are still LL offset |
||
1265 | double sunHour = World.RegionInfo.RegionSettings.SunPosition - 6; |
||
1266 | |||
1267 | // See if the sun module has registered itself, if so it's authoritative |
||
1268 | ISunModule module = World.RequestModuleInterface<ISunModule>(); |
||
1269 | if (module != null) |
||
1270 | { |
||
1271 | sunHour = module.GetCurrentSunHour(); |
||
1272 | } |
||
1273 | |||
1274 | return sunHour; |
||
1275 | } |
||
1276 | |||
1277 | public double osSunGetParam(string param) |
||
1278 | { |
||
1279 | CheckThreatLevel(ThreatLevel.None, "osSunGetParam"); |
||
1280 | OSSLDeprecated("osSunGetParam", "osGetSunParam"); |
||
1281 | return GetSunParam(param); |
||
1282 | } |
||
1283 | |||
1284 | public double osGetSunParam(string param) |
||
1285 | { |
||
1286 | CheckThreatLevel(ThreatLevel.None, "osGetSunParam"); |
||
1287 | return GetSunParam(param); |
||
1288 | } |
||
1289 | |||
1290 | private double GetSunParam(string param) |
||
1291 | { |
||
1292 | m_host.AddScriptLPS(1); |
||
1293 | |||
1294 | double value = 0.0; |
||
1295 | |||
1296 | ISunModule module = World.RequestModuleInterface<ISunModule>(); |
||
1297 | if (module != null) |
||
1298 | { |
||
1299 | value = module.GetSunParameter(param); |
||
1300 | } |
||
1301 | |||
1302 | return value; |
||
1303 | } |
||
1304 | |||
1305 | public void osSunSetParam(string param, double value) |
||
1306 | { |
||
1307 | CheckThreatLevel(ThreatLevel.None, "osSunSetParam"); |
||
1308 | OSSLDeprecated("osSunSetParam", "osSetSunParam"); |
||
1309 | SetSunParam(param, value); |
||
1310 | } |
||
1311 | |||
1312 | public void osSetSunParam(string param, double value) |
||
1313 | { |
||
1314 | CheckThreatLevel(ThreatLevel.None, "osSetSunParam"); |
||
1315 | SetSunParam(param, value); |
||
1316 | } |
||
1317 | |||
1318 | private void SetSunParam(string param, double value) |
||
1319 | { |
||
1320 | m_host.AddScriptLPS(1); |
||
1321 | |||
1322 | ISunModule module = World.RequestModuleInterface<ISunModule>(); |
||
1323 | if (module != null) |
||
1324 | { |
||
1325 | module.SetSunParameter(param, value); |
||
1326 | } |
||
1327 | } |
||
1328 | |||
1329 | public string osWindActiveModelPluginName() |
||
1330 | { |
||
1331 | CheckThreatLevel(ThreatLevel.None, "osWindActiveModelPluginName"); |
||
1332 | m_host.AddScriptLPS(1); |
||
1333 | |||
1334 | IWindModule module = World.RequestModuleInterface<IWindModule>(); |
||
1335 | if (module != null) |
||
1336 | { |
||
1337 | return module.WindActiveModelPluginName; |
||
1338 | } |
||
1339 | |||
1340 | return String.Empty; |
||
1341 | } |
||
1342 | |||
1343 | public void osSetWindParam(string plugin, string param, LSL_Float value) |
||
1344 | { |
||
1345 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetWindParam"); |
||
1346 | m_host.AddScriptLPS(1); |
||
1347 | |||
1348 | IWindModule module = World.RequestModuleInterface<IWindModule>(); |
||
1349 | if (module != null) |
||
1350 | { |
||
1351 | try |
||
1352 | { |
||
1353 | module.WindParamSet(plugin, param, (float)value); |
||
1354 | } |
||
1355 | catch (Exception) { } |
||
1356 | } |
||
1357 | } |
||
1358 | |||
1359 | public LSL_Float osGetWindParam(string plugin, string param) |
||
1360 | { |
||
1361 | CheckThreatLevel(ThreatLevel.VeryLow, "osGetWindParam"); |
||
1362 | m_host.AddScriptLPS(1); |
||
1363 | |||
1364 | IWindModule module = World.RequestModuleInterface<IWindModule>(); |
||
1365 | if (module != null) |
||
1366 | { |
||
1367 | return module.WindParamGet(plugin, param); |
||
1368 | } |
||
1369 | |||
1370 | return 0.0f; |
||
1371 | } |
||
1372 | |||
1373 | // Routines for creating and managing parcels programmatically |
||
1374 | public void osParcelJoin(LSL_Vector pos1, LSL_Vector pos2) |
||
1375 | { |
||
1376 | CheckThreatLevel(ThreatLevel.High, "osParcelJoin"); |
||
1377 | m_host.AddScriptLPS(1); |
||
1378 | |||
1379 | int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x); |
||
1380 | int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y); |
||
1381 | int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x); |
||
1382 | int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y); |
||
1383 | |||
1384 | World.LandChannel.Join(startx,starty,endx,endy,m_host.OwnerID); |
||
1385 | } |
||
1386 | |||
1387 | public void osParcelSubdivide(LSL_Vector pos1, LSL_Vector pos2) |
||
1388 | { |
||
1389 | CheckThreatLevel(ThreatLevel.High, "osParcelSubdivide"); |
||
1390 | m_host.AddScriptLPS(1); |
||
1391 | |||
1392 | int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x); |
||
1393 | int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y); |
||
1394 | int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x); |
||
1395 | int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y); |
||
1396 | |||
1397 | World.LandChannel.Subdivide(startx,starty,endx,endy,m_host.OwnerID); |
||
1398 | } |
||
1399 | |||
1400 | public void osParcelSetDetails(LSL_Vector pos, LSL_List rules) |
||
1401 | { |
||
1402 | const string functionName = "osParcelSetDetails"; |
||
1403 | CheckThreatLevel(ThreatLevel.High, functionName); |
||
1404 | OSSLDeprecated(functionName, "osSetParcelDetails"); |
||
1405 | SetParcelDetails(pos, rules, functionName); |
||
1406 | } |
||
1407 | |||
1408 | public void osSetParcelDetails(LSL_Vector pos, LSL_List rules) |
||
1409 | { |
||
1410 | const string functionName = "osSetParcelDetails"; |
||
1411 | CheckThreatLevel(ThreatLevel.High, functionName); |
||
1412 | SetParcelDetails(pos, rules, functionName); |
||
1413 | } |
||
1414 | |||
1415 | private void SetParcelDetails(LSL_Vector pos, LSL_List rules, string functionName) |
||
1416 | { |
||
1417 | m_host.AddScriptLPS(1); |
||
1418 | |||
1419 | // Get a reference to the land data and make sure the owner of the script |
||
1420 | // can modify it |
||
1421 | |||
1422 | ILandObject startLandObject = World.LandChannel.GetLandObject((int)pos.x, (int)pos.y); |
||
1423 | if (startLandObject == null) |
||
1424 | { |
||
1425 | OSSLShoutError("There is no land at that location"); |
||
1426 | return; |
||
1427 | } |
||
1428 | |||
1429 | if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, startLandObject, GroupPowers.LandOptions)) |
||
1430 | { |
||
1431 | OSSLShoutError("You do not have permission to modify the parcel"); |
||
1432 | return; |
||
1433 | } |
||
1434 | |||
1435 | // Create a new land data object we can modify |
||
1436 | LandData newLand = startLandObject.LandData.Copy(); |
||
1437 | UUID uuid; |
||
1438 | |||
1439 | // Process the rules, not sure what the impact would be of changing owner or group |
||
1440 | for (int idx = 0; idx < rules.Length;) |
||
1441 | { |
||
1442 | int code = rules.GetLSLIntegerItem(idx++); |
||
1443 | string arg = rules.GetLSLStringItem(idx++); |
||
1444 | switch (code) |
||
1445 | { |
||
1446 | case ScriptBaseClass.PARCEL_DETAILS_NAME: |
||
1447 | newLand.Name = arg; |
||
1448 | break; |
||
1449 | |||
1450 | case ScriptBaseClass.PARCEL_DETAILS_DESC: |
||
1451 | newLand.Description = arg; |
||
1452 | break; |
||
1453 | |||
1454 | case ScriptBaseClass.PARCEL_DETAILS_OWNER: |
||
1455 | CheckThreatLevel(ThreatLevel.VeryHigh, functionName); |
||
1456 | if (UUID.TryParse(arg, out uuid)) |
||
1457 | newLand.OwnerID = uuid; |
||
1458 | break; |
||
1459 | |||
1460 | case ScriptBaseClass.PARCEL_DETAILS_GROUP: |
||
1461 | CheckThreatLevel(ThreatLevel.VeryHigh, functionName); |
||
1462 | if (UUID.TryParse(arg, out uuid)) |
||
1463 | newLand.GroupID = uuid; |
||
1464 | break; |
||
1465 | |||
1466 | case ScriptBaseClass.PARCEL_DETAILS_CLAIMDATE: |
||
1467 | CheckThreatLevel(ThreatLevel.VeryHigh, functionName); |
||
1468 | newLand.ClaimDate = Convert.ToInt32(arg); |
||
1469 | if (newLand.ClaimDate == 0) |
||
1470 | newLand.ClaimDate = Util.UnixTimeSinceEpoch(); |
||
1471 | break; |
||
1472 | } |
||
1473 | } |
||
1474 | |||
1475 | World.LandChannel.UpdateLandObject(newLand.LocalID,newLand); |
||
1476 | } |
||
1477 | |||
1478 | public double osList2Double(LSL_Types.list src, int index) |
||
1479 | { |
||
1480 | // There is really no double type in OSSL. C# and other |
||
1481 | // have one, but the current implementation of LSL_Types.list |
||
1482 | // is not allowed to contain any. |
||
1483 | // This really should be removed. |
||
1484 | // |
||
1485 | CheckThreatLevel(ThreatLevel.None, "osList2Double"); |
||
1486 | |||
1487 | m_host.AddScriptLPS(1); |
||
1488 | if (index < 0) |
||
1489 | { |
||
1490 | index = src.Length + index; |
||
1491 | } |
||
1492 | if (index >= src.Length) |
||
1493 | { |
||
1494 | return 0.0; |
||
1495 | } |
||
1496 | return Convert.ToDouble(src.Data[index]); |
||
1497 | } |
||
1498 | |||
1499 | public void osSetParcelMediaURL(string url) |
||
1500 | { |
||
1501 | // What actually is the difference to the LL function? |
||
1502 | // |
||
1503 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelMediaURL"); |
||
1504 | |||
1505 | m_host.AddScriptLPS(1); |
||
1506 | |||
1507 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
||
1508 | |||
1509 | if (land.LandData.OwnerID != m_host.OwnerID) |
||
1510 | return; |
||
1511 | |||
1512 | land.SetMediaUrl(url); |
||
1513 | } |
||
1514 | |||
1515 | public void osSetParcelSIPAddress(string SIPAddress) |
||
1516 | { |
||
1517 | // What actually is the difference to the LL function? |
||
1518 | // |
||
1519 | CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelSIPAddress"); |
||
1520 | |||
1521 | m_host.AddScriptLPS(1); |
||
1522 | |||
1523 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
||
1524 | |||
1525 | if (land.LandData.OwnerID != m_host.OwnerID) |
||
1526 | { |
||
1527 | OSSLError("osSetParcelSIPAddress: Sorry, you need to own the land to use this function"); |
||
1528 | return; |
||
1529 | } |
||
1530 | |||
1531 | // get the voice module |
||
1532 | IVoiceModule voiceModule = World.RequestModuleInterface<IVoiceModule>(); |
||
1533 | |||
1534 | if (voiceModule != null) |
||
1535 | voiceModule.setLandSIPAddress(SIPAddress,land.LandData.GlobalID); |
||
1536 | else |
||
1537 | OSSLError("osSetParcelSIPAddress: No voice module enabled for this land"); |
||
1538 | } |
||
1539 | |||
1540 | public string osGetScriptEngineName() |
||
1541 | { |
||
1542 | // This gets a "high" because knowing the engine may be used |
||
1543 | // to exploit engine-specific bugs or induce usage patterns |
||
1544 | // that trigger engine-specific failures. |
||
1545 | // Besides, public grid users aren't supposed to know. |
||
1546 | // |
||
1547 | CheckThreatLevel(ThreatLevel.High, "osGetScriptEngineName"); |
||
1548 | |||
1549 | m_host.AddScriptLPS(1); |
||
1550 | |||
1551 | int scriptEngineNameIndex = 0; |
||
1552 | |||
1553 | if (!String.IsNullOrEmpty(m_ScriptEngine.ScriptEngineName)) |
||
1554 | { |
||
1555 | // parse off the "ScriptEngine." |
||
1556 | scriptEngineNameIndex = m_ScriptEngine.ScriptEngineName.IndexOf(".", scriptEngineNameIndex); |
||
1557 | scriptEngineNameIndex++; // get past delimiter |
||
1558 | |||
1559 | int scriptEngineNameLength = m_ScriptEngine.ScriptEngineName.Length - scriptEngineNameIndex; |
||
1560 | |||
1561 | // create char array then a string that is only the script engine name |
||
1562 | Char[] scriptEngineNameCharArray = m_ScriptEngine.ScriptEngineName.ToCharArray(scriptEngineNameIndex, scriptEngineNameLength); |
||
1563 | String scriptEngineName = new String(scriptEngineNameCharArray); |
||
1564 | |||
1565 | return scriptEngineName; |
||
1566 | } |
||
1567 | else |
||
1568 | { |
||
1569 | return String.Empty; |
||
1570 | } |
||
1571 | } |
||
1572 | |||
1573 | public string osGetPhysicsEngineType() |
||
1574 | { |
||
1575 | // High because it can be used to target attacks to known weaknesses |
||
1576 | // This would allow a new class of griefer scripts that don't even |
||
1577 | // require their user to know what they are doing (see script |
||
1578 | // kiddie) |
||
1579 | // Because it would be nice if scripts didn't blow up if the information |
||
1580 | // about the physics engine, this function returns an empty string if |
||
1581 | // the user does not have permission to see it. This as opposed to |
||
1582 | // throwing an exception. |
||
1583 | m_host.AddScriptLPS(1); |
||
1584 | string ret = String.Empty; |
||
1585 | if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType"))) |
||
1586 | { |
||
1587 | if (m_ScriptEngine.World.PhysicsScene != null) |
||
1588 | { |
||
1589 | ret = m_ScriptEngine.World.PhysicsScene.EngineType; |
||
1590 | // An old physics engine might have an uninitialized engine type |
||
1591 | if (ret == null) |
||
1592 | ret = "unknown"; |
||
1593 | } |
||
1594 | } |
||
1595 | |||
1596 | return ret; |
||
1597 | } |
||
1598 | |||
1599 | public string osGetSimulatorVersion() |
||
1600 | { |
||
1601 | // High because it can be used to target attacks to known weaknesses |
||
1602 | // This would allow a new class of griefer scripts that don't even |
||
1603 | // require their user to know what they are doing (see script |
||
1604 | // kiddie) |
||
1605 | // |
||
1606 | CheckThreatLevel(ThreatLevel.High,"osGetSimulatorVersion"); |
||
1607 | m_host.AddScriptLPS(1); |
||
1608 | |||
1609 | return m_ScriptEngine.World.GetSimulatorVersion(); |
||
1610 | } |
||
1611 | |||
1612 | private Hashtable osdToHashtable(OSDMap map) |
||
1613 | { |
||
1614 | Hashtable result = new Hashtable(); |
||
1615 | foreach (KeyValuePair<string, OSD> item in map) { |
||
1616 | result.Add(item.Key, osdToObject(item.Value)); |
||
1617 | } |
||
1618 | return result; |
||
1619 | } |
||
1620 | |||
1621 | private ArrayList osdToArray(OSDArray list) |
||
1622 | { |
||
1623 | ArrayList result = new ArrayList(); |
||
1624 | foreach ( OSD item in list ) { |
||
1625 | result.Add(osdToObject(item)); |
||
1626 | } |
||
1627 | return result; |
||
1628 | } |
||
1629 | |||
1630 | private Object osdToObject(OSD decoded) |
||
1631 | { |
||
1632 | if ( decoded is OSDString ) { |
||
1633 | return (string) decoded.AsString(); |
||
1634 | } else if ( decoded is OSDInteger ) { |
||
1635 | return (int) decoded.AsInteger(); |
||
1636 | } else if ( decoded is OSDReal ) { |
||
1637 | return (float) decoded.AsReal(); |
||
1638 | } else if ( decoded is OSDBoolean ) { |
||
1639 | return (bool) decoded.AsBoolean(); |
||
1640 | } else if ( decoded is OSDMap ) { |
||
1641 | return osdToHashtable((OSDMap) decoded); |
||
1642 | } else if ( decoded is OSDArray ) { |
||
1643 | return osdToArray((OSDArray) decoded); |
||
1644 | } else { |
||
1645 | return null; |
||
1646 | } |
||
1647 | } |
||
1648 | |||
1649 | public Object osParseJSONNew(string JSON) |
||
1650 | { |
||
1651 | CheckThreatLevel(ThreatLevel.None, "osParseJSONNew"); |
||
1652 | |||
1653 | m_host.AddScriptLPS(1); |
||
1654 | |||
1655 | try |
||
1656 | { |
||
1657 | OSD decoded = OSDParser.DeserializeJson(JSON); |
||
1658 | return osdToObject(decoded); |
||
1659 | } |
||
1660 | catch(Exception e) |
||
1661 | { |
||
1662 | OSSLError("osParseJSONNew: Problems decoding JSON string " + JSON + " : " + e.Message) ; |
||
1663 | return null; |
||
1664 | } |
||
1665 | } |
||
1666 | |||
1667 | public Hashtable osParseJSON(string JSON) |
||
1668 | { |
||
1669 | CheckThreatLevel(ThreatLevel.None, "osParseJSON"); |
||
1670 | |||
1671 | m_host.AddScriptLPS(1); |
||
1672 | |||
1673 | Object decoded = osParseJSONNew(JSON); |
||
1674 | |||
1675 | if ( decoded is Hashtable ) { |
||
1676 | return (Hashtable) decoded; |
||
1677 | } else if ( decoded is ArrayList ) { |
||
1678 | ArrayList decoded_list = (ArrayList) decoded; |
||
1679 | Hashtable fakearray = new Hashtable(); |
||
1680 | int i = 0; |
||
1681 | for ( i = 0; i < decoded_list.Count ; i++ ) { |
||
1682 | fakearray.Add(i, decoded_list[i]); |
||
1683 | } |
||
1684 | return fakearray; |
||
1685 | } else { |
||
1686 | OSSLError("osParseJSON: unable to parse JSON string " + JSON); |
||
1687 | return null; |
||
1688 | } |
||
1689 | } |
||
1690 | |||
1691 | /// <summary> |
||
1692 | /// Send a message to to object identified by the given UUID |
||
1693 | /// </summary> |
||
1694 | /// <remarks> |
||
1695 | /// A script in the object must implement the dataserver function |
||
1696 | /// the dataserver function is passed the ID of the calling function and a string message |
||
1697 | /// </remarks> |
||
1698 | /// <param name="objectUUID"></param> |
||
1699 | /// <param name="message"></param> |
||
1700 | public void osMessageObject(LSL_Key objectUUID, string message) |
||
1701 | { |
||
1702 | CheckThreatLevel(ThreatLevel.Low, "osMessageObject"); |
||
1703 | m_host.AddScriptLPS(1); |
||
1704 | |||
1705 | UUID objUUID; |
||
1706 | if (!UUID.TryParse(objectUUID, out objUUID)) // prior to patching, a thrown exception regarding invalid GUID format would be shouted instead. |
||
1707 | { |
||
1708 | OSSLShoutError("osMessageObject() cannot send messages to objects with invalid UUIDs"); |
||
1709 | return; |
||
1710 | } |
||
1711 | |||
1712 | MessageObject(objUUID, message); |
||
1713 | } |
||
1714 | |||
1715 | private void MessageObject(UUID objUUID, string message) |
||
1716 | { |
||
1717 | object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; |
||
1718 | |||
1719 | SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); |
||
1720 | |||
1721 | if (sceneOP == null) // prior to patching, PostObjectEvent() would cause a throw exception to be shouted instead. |
||
1722 | { |
||
1723 | OSSLShoutError("osMessageObject() cannot send message to " + objUUID.ToString() + ", object was not found in scene."); |
||
1724 | return; |
||
1725 | } |
||
1726 | |||
1727 | m_ScriptEngine.PostObjectEvent( |
||
1728 | sceneOP.LocalId, new EventParams( |
||
1729 | "dataserver", resobj, new DetectParams[0])); |
||
1730 | } |
||
1731 | |||
1732 | /// <summary> |
||
1733 | /// Write a notecard directly to the prim's inventory. |
||
1734 | /// </summary> |
||
1735 | /// <remarks> |
||
1736 | /// This needs ThreatLevel high. It is an excellent griefer tool, |
||
1737 | /// In a loop, it can cause asset bloat and DOS levels of asset |
||
1738 | /// writes. |
||
1739 | /// </remarks> |
||
1740 | /// <param name="notecardName">The name of the notecard to write.</param> |
||
1741 | /// <param name="contents">The contents of the notecard.</param> |
||
1742 | public void osMakeNotecard(string notecardName, LSL_Types.list contents) |
||
1743 | { |
||
1744 | CheckThreatLevel(ThreatLevel.High, "osMakeNotecard"); |
||
1745 | m_host.AddScriptLPS(1); |
||
1746 | |||
1747 | StringBuilder notecardData = new StringBuilder(); |
||
1748 | |||
1749 | for (int i = 0; i < contents.Length; i++) |
||
1750 | notecardData.Append((string)(contents.GetLSLStringItem(i) + "\n")); |
||
1751 | |||
1752 | SaveNotecard(notecardName, "Script generated notecard", notecardData.ToString(), false); |
||
1753 | } |
||
1754 | |||
1755 | /// <summary> |
||
1756 | /// Save a notecard to prim inventory. |
||
1757 | /// </summary> |
||
1758 | /// <param name="name"></param> |
||
1759 | /// <param name="description">Description of notecard</param> |
||
1760 | /// <param name="notecardData"></param> |
||
1761 | /// <param name="forceSameName"> |
||
1762 | /// If true, then if an item exists with the same name, it is replaced. |
||
1763 | /// If false, then a new item is created witha slightly different name (e.g. name 1) |
||
1764 | /// </param> |
||
1765 | /// <returns>Prim inventory item created.</returns> |
||
1766 | protected TaskInventoryItem SaveNotecard(string name, string description, string data, bool forceSameName) |
||
1767 | { |
||
1768 | // Create new asset |
||
1769 | AssetBase asset = new AssetBase(UUID.Random(), name, (sbyte)AssetType.Notecard, m_host.OwnerID.ToString()); |
||
1770 | asset.Description = description; |
||
1771 | |||
1772 | int textLength = data.Length; |
||
1773 | data |
||
1774 | = "Linden text version 2\n{\nLLEmbeddedItems version 1\n{\ncount 0\n}\nText length " |
||
1775 | + textLength.ToString() + "\n" + data + "}\n"; |
||
1776 | |||
1777 | asset.Data = Util.UTF8.GetBytes(data); |
||
1778 | World.AssetService.Store(asset); |
||
1779 | |||
1780 | // Create Task Entry |
||
1781 | TaskInventoryItem taskItem = new TaskInventoryItem(); |
||
1782 | |||
1783 | taskItem.ResetIDs(m_host.UUID); |
||
1784 | taskItem.ParentID = m_host.UUID; |
||
1785 | taskItem.CreationDate = (uint)Util.UnixTimeSinceEpoch(); |
||
1786 | taskItem.Name = asset.Name; |
||
1787 | taskItem.Description = asset.Description; |
||
1788 | taskItem.Type = (int)AssetType.Notecard; |
||
1789 | taskItem.InvType = (int)InventoryType.Notecard; |
||
1790 | taskItem.OwnerID = m_host.OwnerID; |
||
1791 | taskItem.CreatorID = m_host.OwnerID; |
||
1792 | taskItem.BasePermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; |
||
1793 | taskItem.CurrentPermissions = (uint)PermissionMask.All | (uint)PermissionMask.Export; |
||
1794 | taskItem.EveryonePermissions = 0; |
||
1795 | taskItem.NextPermissions = (uint)PermissionMask.All; |
||
1796 | taskItem.GroupID = m_host.GroupID; |
||
1797 | taskItem.GroupPermissions = 0; |
||
1798 | taskItem.Flags = 0; |
||
1799 | taskItem.PermsGranter = UUID.Zero; |
||
1800 | taskItem.PermsMask = 0; |
||
1801 | taskItem.AssetID = asset.FullID; |
||
1802 | |||
1803 | if (forceSameName) |
||
1804 | m_host.Inventory.AddInventoryItemExclusive(taskItem, false); |
||
1805 | else |
||
1806 | m_host.Inventory.AddInventoryItem(taskItem, false); |
||
1807 | |||
1808 | return taskItem; |
||
1809 | } |
||
1810 | |||
1811 | /// <summary> |
||
1812 | /// Load the notecard data found at the given prim inventory item name or asset uuid. |
||
1813 | /// </summary> |
||
1814 | /// <param name="notecardNameOrUuid"></param> |
||
1815 | /// <returns>The text loaded. Null if no notecard was found.</returns> |
||
1816 | protected string LoadNotecard(string notecardNameOrUuid) |
||
1817 | { |
||
1818 | UUID assetID = CacheNotecard(notecardNameOrUuid); |
||
1819 | |||
1820 | if (assetID != UUID.Zero) |
||
1821 | { |
||
1822 | StringBuilder notecardData = new StringBuilder(); |
||
1823 | |||
1824 | for (int count = 0; count < NotecardCache.GetLines(assetID); count++) |
||
1825 | { |
||
1826 | string line = NotecardCache.GetLine(assetID, count) + "\n"; |
||
1827 | |||
1828 | // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); |
||
1829 | |||
1830 | notecardData.Append(line); |
||
1831 | } |
||
1832 | |||
1833 | return notecardData.ToString(); |
||
1834 | } |
||
1835 | |||
1836 | return null; |
||
1837 | } |
||
1838 | |||
1839 | /// <summary> |
||
1840 | /// Cache a notecard's contents. |
||
1841 | /// </summary> |
||
1842 | /// <param name="notecardNameOrUuid"></param> |
||
1843 | /// <returns> |
||
1844 | /// The asset id of the notecard, which is used for retrieving the cached data. |
||
1845 | /// UUID.Zero if no asset could be found. |
||
1846 | /// </returns> |
||
1847 | protected UUID CacheNotecard(string notecardNameOrUuid) |
||
1848 | { |
||
1849 | UUID assetID = UUID.Zero; |
||
1850 | |||
1851 | if (!UUID.TryParse(notecardNameOrUuid, out assetID)) |
||
1852 | { |
||
1853 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) |
||
1854 | { |
||
1855 | if (item.Type == 7 && item.Name == notecardNameOrUuid) |
||
1856 | { |
||
1857 | assetID = item.AssetID; |
||
1858 | } |
||
1859 | } |
||
1860 | } |
||
1861 | |||
1862 | if (assetID == UUID.Zero) |
||
1863 | return UUID.Zero; |
||
1864 | |||
1865 | if (!NotecardCache.IsCached(assetID)) |
||
1866 | { |
||
1867 | AssetBase a = World.AssetService.Get(assetID.ToString()); |
||
1868 | |||
1869 | if (a == null) |
||
1870 | return UUID.Zero; |
||
1871 | |||
1872 | string data = Encoding.UTF8.GetString(a.Data); |
||
1873 | NotecardCache.Cache(assetID, data); |
||
1874 | }; |
||
1875 | |||
1876 | return assetID; |
||
1877 | } |
||
1878 | |||
1879 | /// <summary> |
||
1880 | /// Directly get an entire notecard at once. |
||
1881 | /// </summary> |
||
1882 | /// <remarks> |
||
1883 | /// Instead of using the LSL Dataserver event to pull notecard data |
||
1884 | /// this will simply read the entire notecard and return its data as a string. |
||
1885 | /// |
||
1886 | /// Warning - due to the synchronous method this function uses to fetch assets, its use |
||
1887 | /// may be dangerous and unreliable while running in grid mode. |
||
1888 | /// </remarks> |
||
1889 | /// <param name="name">Name of the notecard or its asset id</param> |
||
1890 | /// <param name="line">The line number to read. The first line is line 0</param> |
||
1891 | /// <returns>Notecard line</returns> |
||
1892 | public string osGetNotecardLine(string name, int line) |
||
1893 | { |
||
1894 | CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNotecardLine"); |
||
1895 | m_host.AddScriptLPS(1); |
||
1896 | |||
1897 | UUID assetID = CacheNotecard(name); |
||
1898 | |||
1899 | if (assetID == UUID.Zero) |
||
1900 | { |
||
1901 | OSSLShoutError("Notecard '" + name + "' could not be found."); |
||
1902 | return "ERROR!"; |
||
1903 | } |
||
1904 | |||
1905 | return NotecardCache.GetLine(assetID, line); |
||
1906 | } |
||
1907 | |||
1908 | /// <summary> |
||
1909 | /// Get an entire notecard at once. |
||
1910 | /// </summary> |
||
1911 | /// <remarks> |
||
1912 | /// Instead of using the LSL Dataserver event to pull notecard data line by line, |
||
1913 | /// this will simply read the entire notecard and return its data as a string. |
||
1914 | /// |
||
1915 | /// Warning - due to the synchronous method this function uses to fetch assets, its use |
||
1916 | /// may be dangerous and unreliable while running in grid mode. |
||
1917 | /// </remarks> |
||
1918 | /// <param name="name">Name of the notecard or its asset id</param> |
||
1919 | /// <returns>Notecard text</returns> |
||
1920 | public string osGetNotecard(string name) |
||
1921 | { |
||
1922 | CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNotecard"); |
||
1923 | m_host.AddScriptLPS(1); |
||
1924 | |||
1925 | string text = LoadNotecard(name); |
||
1926 | |||
1927 | if (text == null) |
||
1928 | { |
||
1929 | OSSLShoutError("Notecard '" + name + "' could not be found."); |
||
1930 | return "ERROR!"; |
||
1931 | } |
||
1932 | else |
||
1933 | { |
||
1934 | return text; |
||
1935 | } |
||
1936 | } |
||
1937 | |||
1938 | /// <summary> |
||
1939 | /// Get the number of lines in the given notecard. |
||
1940 | /// </summary> |
||
1941 | /// <remarks> |
||
1942 | /// Instead of using the LSL Dataserver event to pull notecard data, |
||
1943 | /// this will simply read the number of note card lines and return this data as an integer. |
||
1944 | /// |
||
1945 | /// Warning - due to the synchronous method this function uses to fetch assets, its use |
||
1946 | /// may be dangerous and unreliable while running in grid mode. |
||
1947 | /// </remarks> |
||
1948 | /// <param name="name">Name of the notecard or its asset id</param> |
||
1949 | /// <returns></returns> |
||
1950 | public int osGetNumberOfNotecardLines(string name) |
||
1951 | { |
||
1952 | CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNumberOfNotecardLines"); |
||
1953 | m_host.AddScriptLPS(1); |
||
1954 | |||
1955 | UUID assetID = CacheNotecard(name); |
||
1956 | |||
1957 | if (assetID == UUID.Zero) |
||
1958 | { |
||
1959 | OSSLShoutError("Notecard '" + name + "' could not be found."); |
||
1960 | return -1; |
||
1961 | } |
||
1962 | |||
1963 | return NotecardCache.GetLines(assetID); |
||
1964 | } |
||
1965 | |||
1966 | public string osAvatarName2Key(string firstname, string lastname) |
||
1967 | { |
||
1968 | CheckThreatLevel(ThreatLevel.Low, "osAvatarName2Key"); |
||
1969 | m_host.AddScriptLPS(1); |
||
1970 | |||
1971 | UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, firstname, lastname); |
||
1972 | if (null == account) |
||
1973 | { |
||
1974 | return UUID.Zero.ToString(); |
||
1975 | } |
||
1976 | else |
||
1977 | { |
||
1978 | return account.PrincipalID.ToString(); |
||
1979 | } |
||
1980 | } |
||
1981 | |||
1982 | public string osKey2Name(string id) |
||
1983 | { |
||
1984 | CheckThreatLevel(ThreatLevel.Low, "osKey2Name"); |
||
1985 | m_host.AddScriptLPS(1); |
||
1986 | |||
1987 | UUID key = new UUID(); |
||
1988 | |||
1989 | if (UUID.TryParse(id, out key)) |
||
1990 | { |
||
1991 | UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, key); |
||
1992 | if (null == account) |
||
1993 | { |
||
1994 | return ""; |
||
1995 | } |
||
1996 | else |
||
1997 | { |
||
1998 | return account.Name; |
||
1999 | } |
||
2000 | } |
||
2001 | else |
||
2002 | { |
||
2003 | return ""; |
||
2004 | } |
||
2005 | } |
||
2006 | |||
2007 | private enum InfoType |
||
2008 | { |
||
2009 | Nick, |
||
2010 | Name, |
||
2011 | Login, |
||
2012 | Home, |
||
2013 | Custom |
||
2014 | }; |
||
2015 | |||
2016 | private string GridUserInfo(InfoType type) |
||
2017 | { |
||
2018 | return GridUserInfo(type, ""); |
||
2019 | } |
||
2020 | |||
2021 | private string GridUserInfo(InfoType type, string key) |
||
2022 | { |
||
2023 | string retval = String.Empty; |
||
2024 | IConfigSource config = m_ScriptEngine.ConfigSource; |
||
2025 | string url = null; |
||
2026 | |||
2027 | IConfig gridInfoConfig = config.Configs["GridInfo"]; |
||
2028 | |||
2029 | if (gridInfoConfig != null) |
||
2030 | url = gridInfoConfig.GetString("GridInfoURI", String.Empty); |
||
2031 | |||
2032 | if (String.IsNullOrEmpty(url)) |
||
2033 | return "Configuration Error!"; |
||
2034 | |||
2035 | string verb ="/json_grid_info"; |
||
2036 | OSDMap json = new OSDMap(); |
||
2037 | |||
2038 | OSDMap info = WebUtil.GetFromService(String.Format("{0}{1}",url,verb), 3000); |
||
2039 | |||
2040 | if (info["Success"] != true) |
||
2041 | return "Get GridInfo Failed!"; |
||
2042 | |||
2043 | json = (OSDMap)OSDParser.DeserializeJson(info["_RawResult"].AsString()); |
||
2044 | |||
2045 | switch (type) |
||
2046 | { |
||
2047 | case InfoType.Nick: |
||
2048 | retval = json["gridnick"]; |
||
2049 | break; |
||
2050 | |||
2051 | case InfoType.Name: |
||
2052 | retval = json["gridname"]; |
||
2053 | break; |
||
2054 | |||
2055 | case InfoType.Login: |
||
2056 | retval = json["login"]; |
||
2057 | break; |
||
2058 | |||
2059 | case InfoType.Home: |
||
2060 | retval = json["home"]; |
||
2061 | break; |
||
2062 | |||
2063 | case InfoType.Custom: |
||
2064 | retval = json[key]; |
||
2065 | break; |
||
2066 | |||
2067 | default: |
||
2068 | retval = "error"; |
||
2069 | break; |
||
2070 | } |
||
2071 | |||
2072 | return retval; |
||
2073 | } |
||
2074 | |||
2075 | /// <summary> |
||
2076 | /// Get the nickname of this grid, as set in the [GridInfo] config section. |
||
2077 | /// </summary> |
||
2078 | /// <remarks> |
||
2079 | /// Threat level is Moderate because intentional abuse, for instance |
||
2080 | /// scripts that are written to be malicious only on one grid, |
||
2081 | /// for instance in a HG scenario, are a distinct possibility. |
||
2082 | /// </remarks> |
||
2083 | /// <returns></returns> |
||
2084 | public string osGetGridNick() |
||
2085 | { |
||
2086 | CheckThreatLevel(ThreatLevel.Moderate, "osGetGridNick"); |
||
2087 | m_host.AddScriptLPS(1); |
||
2088 | |||
2089 | string nick = String.Empty; |
||
2090 | IConfigSource config = m_ScriptEngine.ConfigSource; |
||
2091 | |||
2092 | if (config.Configs[GridInfoServiceConfigSectionName] != null) |
||
2093 | nick = config.Configs[GridInfoServiceConfigSectionName].GetString("gridnick", nick); |
||
2094 | |||
2095 | if (String.IsNullOrEmpty(nick)) |
||
2096 | nick = GridUserInfo(InfoType.Nick); |
||
2097 | |||
2098 | return nick; |
||
2099 | } |
||
2100 | |||
2101 | public string osGetGridName() |
||
2102 | { |
||
2103 | CheckThreatLevel(ThreatLevel.Moderate, "osGetGridName"); |
||
2104 | m_host.AddScriptLPS(1); |
||
2105 | |||
2106 | string name = String.Empty; |
||
2107 | IConfigSource config = m_ScriptEngine.ConfigSource; |
||
2108 | |||
2109 | if (config.Configs[GridInfoServiceConfigSectionName] != null) |
||
2110 | name = config.Configs[GridInfoServiceConfigSectionName].GetString("gridname", name); |
||
2111 | |||
2112 | if (String.IsNullOrEmpty(name)) |
||
2113 | name = GridUserInfo(InfoType.Name); |
||
2114 | |||
2115 | return name; |
||
2116 | } |
||
2117 | |||
2118 | public string osGetGridLoginURI() |
||
2119 | { |
||
2120 | CheckThreatLevel(ThreatLevel.Moderate, "osGetGridLoginURI"); |
||
2121 | m_host.AddScriptLPS(1); |
||
2122 | |||
2123 | string loginURI = String.Empty; |
||
2124 | IConfigSource config = m_ScriptEngine.ConfigSource; |
||
2125 | |||
2126 | if (config.Configs[GridInfoServiceConfigSectionName] != null) |
||
2127 | loginURI = config.Configs[GridInfoServiceConfigSectionName].GetString("login", loginURI); |
||
2128 | |||
2129 | if (String.IsNullOrEmpty(loginURI)) |
||
2130 | loginURI = GridUserInfo(InfoType.Login); |
||
2131 | |||
2132 | return loginURI; |
||
2133 | } |
||
2134 | |||
2135 | public string osGetGridHomeURI() |
||
2136 | { |
||
2137 | CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI"); |
||
2138 | m_host.AddScriptLPS(1); |
||
2139 | |||
2140 | IConfigSource config = m_ScriptEngine.ConfigSource; |
||
2141 | string HomeURI = Util.GetConfigVarFromSections<string>(config, "HomeURI", |
||
2142 | new string[] { "Startup", "Hypergrid" }, String.Empty); |
||
2143 | |||
2144 | if (!string.IsNullOrEmpty(HomeURI)) |
||
2145 | return HomeURI; |
||
2146 | |||
2147 | // Legacy. Remove soon! |
||
2148 | if (config.Configs["LoginService"] != null) |
||
2149 | HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI); |
||
2150 | |||
2151 | if (String.IsNullOrEmpty(HomeURI)) |
||
2152 | HomeURI = GridUserInfo(InfoType.Home); |
||
2153 | |||
2154 | return HomeURI; |
||
2155 | } |
||
2156 | |||
2157 | public string osGetGridGatekeeperURI() |
||
2158 | { |
||
2159 | CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI"); |
||
2160 | m_host.AddScriptLPS(1); |
||
2161 | |||
2162 | IConfigSource config = m_ScriptEngine.ConfigSource; |
||
2163 | string gatekeeperURI = Util.GetConfigVarFromSections<string>(config, "GatekeeperURI", |
||
2164 | new string[] { "Startup", "Hypergrid" }, String.Empty); |
||
2165 | |||
2166 | if (!string.IsNullOrEmpty(gatekeeperURI)) |
||
2167 | return gatekeeperURI; |
||
2168 | |||
2169 | // Legacy. Remove soon! |
||
2170 | if (config.Configs["GridService"] != null) |
||
2171 | gatekeeperURI = config.Configs["GridService"].GetString("Gatekeeper", gatekeeperURI); |
||
2172 | |||
2173 | return gatekeeperURI; |
||
2174 | } |
||
2175 | |||
2176 | public string osGetGridCustom(string key) |
||
2177 | { |
||
2178 | CheckThreatLevel(ThreatLevel.Moderate, "osGetGridCustom"); |
||
2179 | m_host.AddScriptLPS(1); |
||
2180 | |||
2181 | string retval = String.Empty; |
||
2182 | IConfigSource config = m_ScriptEngine.ConfigSource; |
||
2183 | |||
2184 | if (config.Configs[GridInfoServiceConfigSectionName] != null) |
||
2185 | retval = config.Configs[GridInfoServiceConfigSectionName].GetString(key, retval); |
||
2186 | |||
2187 | if (String.IsNullOrEmpty(retval)) |
||
2188 | retval = GridUserInfo(InfoType.Custom, key); |
||
2189 | |||
2190 | return retval; |
||
2191 | } |
||
2192 | |||
2193 | public LSL_String osFormatString(string str, LSL_List strings) |
||
2194 | { |
||
2195 | CheckThreatLevel(ThreatLevel.VeryLow, "osFormatString"); |
||
2196 | m_host.AddScriptLPS(1); |
||
2197 | |||
2198 | return String.Format(str, strings.Data); |
||
2199 | } |
||
2200 | |||
2201 | public LSL_List osMatchString(string src, string pattern, int start) |
||
2202 | { |
||
2203 | CheckThreatLevel(ThreatLevel.VeryLow, "osMatchString"); |
||
2204 | m_host.AddScriptLPS(1); |
||
2205 | |||
2206 | LSL_List result = new LSL_List(); |
||
2207 | |||
2208 | // Normalize indices (if negative). |
||
2209 | // After normlaization they may still be |
||
2210 | // negative, but that is now relative to |
||
2211 | // the start, rather than the end, of the |
||
2212 | // sequence. |
||
2213 | if (start < 0) |
||
2214 | { |
||
2215 | start = src.Length + start; |
||
2216 | } |
||
2217 | |||
2218 | if (start < 0 || start >= src.Length) |
||
2219 | { |
||
2220 | return result; // empty list |
||
2221 | } |
||
2222 | |||
2223 | // Find matches beginning at start position |
||
2224 | Regex matcher = new Regex(pattern); |
||
2225 | Match match = matcher.Match(src, start); |
||
2226 | while (match.Success) |
||
2227 | { |
||
2228 | foreach (System.Text.RegularExpressions.Group g in match.Groups) |
||
2229 | { |
||
2230 | if (g.Success) |
||
2231 | { |
||
2232 | result.Add(new LSL_String(g.Value)); |
||
2233 | result.Add(new LSL_Integer(g.Index)); |
||
2234 | } |
||
2235 | } |
||
2236 | |||
2237 | match = match.NextMatch(); |
||
2238 | } |
||
2239 | |||
2240 | return result; |
||
2241 | } |
||
2242 | |||
2243 | public LSL_String osReplaceString(string src, string pattern, string replace, int count, int start) |
||
2244 | { |
||
2245 | CheckThreatLevel(ThreatLevel.VeryLow, "osReplaceString"); |
||
2246 | m_host.AddScriptLPS(1); |
||
2247 | |||
2248 | // Normalize indices (if negative). |
||
2249 | // After normlaization they may still be |
||
2250 | // negative, but that is now relative to |
||
2251 | // the start, rather than the end, of the |
||
2252 | // sequence. |
||
2253 | if (start < 0) |
||
2254 | { |
||
2255 | start = src.Length + start; |
||
2256 | } |
||
2257 | |||
2258 | if (start < 0 || start >= src.Length) |
||
2259 | { |
||
2260 | return src; |
||
2261 | } |
||
2262 | |||
2263 | // Find matches beginning at start position |
||
2264 | Regex matcher = new Regex(pattern); |
||
2265 | return matcher.Replace(src,replace,count,start); |
||
2266 | } |
||
2267 | |||
2268 | public string osLoadedCreationDate() |
||
2269 | { |
||
2270 | CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationDate"); |
||
2271 | m_host.AddScriptLPS(1); |
||
2272 | |||
2273 | return World.RegionInfo.RegionSettings.LoadedCreationDate; |
||
2274 | } |
||
2275 | |||
2276 | public string osLoadedCreationTime() |
||
2277 | { |
||
2278 | CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationTime"); |
||
2279 | m_host.AddScriptLPS(1); |
||
2280 | |||
2281 | return World.RegionInfo.RegionSettings.LoadedCreationTime; |
||
2282 | } |
||
2283 | |||
2284 | public string osLoadedCreationID() |
||
2285 | { |
||
2286 | CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationID"); |
||
2287 | m_host.AddScriptLPS(1); |
||
2288 | |||
2289 | return World.RegionInfo.RegionSettings.LoadedCreationID; |
||
2290 | } |
||
2291 | |||
2292 | /// <summary> |
||
2293 | /// Get the primitive parameters of a linked prim. |
||
2294 | /// </summary> |
||
2295 | /// <remarks> |
||
2296 | /// Threat level is 'Low' because certain users could possibly be tricked into |
||
2297 | /// dropping an unverified script into one of their own objects, which could |
||
2298 | /// then gather the physical construction details of the object and transmit it |
||
2299 | /// to an unscrupulous third party, thus permitting unauthorized duplication of |
||
2300 | /// the object's form. |
||
2301 | /// </remarks> |
||
2302 | /// <param name="linknumber"></param> |
||
2303 | /// <param name="rules"></param> |
||
2304 | /// <returns></returns> |
||
2305 | public LSL_List osGetLinkPrimitiveParams(int linknumber, LSL_List rules) |
||
2306 | { |
||
2307 | CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); |
||
2308 | m_host.AddScriptLPS(1); |
||
2309 | InitLSL(); |
||
2310 | // One needs to cast m_LSL_Api because we're using functions not |
||
2311 | // on the ILSL_Api interface. |
||
2312 | LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; |
||
2313 | LSL_List retVal = new LSL_List(); |
||
2314 | LSL_List remaining = null; |
||
2315 | List<SceneObjectPart> parts = LSL_Api.GetLinkParts(linknumber); |
||
2316 | foreach (SceneObjectPart part in parts) |
||
2317 | { |
||
2318 | remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); |
||
2319 | } |
||
2320 | |||
2321 | while (remaining != null && remaining.Length > 2) |
||
2322 | { |
||
2323 | linknumber = remaining.GetLSLIntegerItem(0); |
||
2324 | rules = remaining.GetSublist(1, -1); |
||
2325 | parts = LSL_Api.GetLinkParts(linknumber); |
||
2326 | |||
2327 | foreach (SceneObjectPart part in parts) |
||
2328 | remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); |
||
2329 | } |
||
2330 | return retVal; |
||
2331 | } |
||
2332 | |||
2333 | public LSL_Integer osIsNpc(LSL_Key npc) |
||
2334 | { |
||
2335 | CheckThreatLevel(ThreatLevel.None, "osIsNpc"); |
||
2336 | m_host.AddScriptLPS(1); |
||
2337 | |||
2338 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2339 | if (module != null) |
||
2340 | { |
||
2341 | UUID npcId; |
||
2342 | if (UUID.TryParse(npc.m_string, out npcId)) |
||
2343 | if (module.IsNPC(npcId, World)) |
||
2344 | return ScriptBaseClass.TRUE; |
||
2345 | } |
||
2346 | |||
2347 | return ScriptBaseClass.FALSE; |
||
2348 | } |
||
2349 | |||
2350 | public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard) |
||
2351 | { |
||
2352 | CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); |
||
2353 | m_host.AddScriptLPS(1); |
||
2354 | |||
2355 | return NpcCreate(firstname, lastname, position, notecard, false, false); |
||
2356 | } |
||
2357 | |||
2358 | public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) |
||
2359 | { |
||
2360 | CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); |
||
2361 | m_host.AddScriptLPS(1); |
||
2362 | |||
2363 | return NpcCreate( |
||
2364 | firstname, lastname, position, notecard, |
||
2365 | (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, |
||
2366 | (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) != 0); |
||
2367 | } |
||
2368 | |||
2369 | private LSL_Key NpcCreate( |
||
2370 | string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) |
||
2371 | { |
||
2372 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2373 | if (module != null) |
||
2374 | { |
||
2375 | AvatarAppearance appearance = null; |
||
2376 | |||
2377 | UUID id; |
||
2378 | if (UUID.TryParse(notecard, out id)) |
||
2379 | { |
||
2380 | ScenePresence clonePresence = World.GetScenePresence(id); |
||
2381 | if (clonePresence != null) |
||
2382 | appearance = clonePresence.Appearance; |
||
2383 | } |
||
2384 | |||
2385 | if (appearance == null) |
||
2386 | { |
||
2387 | string appearanceSerialized = LoadNotecard(notecard); |
||
2388 | |||
2389 | if (appearanceSerialized != null) |
||
2390 | { |
||
2391 | OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); |
||
2392 | appearance = new AvatarAppearance(); |
||
2393 | appearance.Unpack(appearanceOsd); |
||
2394 | } |
||
2395 | else |
||
2396 | { |
||
2397 | OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); |
||
2398 | } |
||
2399 | } |
||
2400 | |||
2401 | UUID ownerID = UUID.Zero; |
||
2402 | if (owned) |
||
2403 | ownerID = m_host.OwnerID; |
||
2404 | UUID x = module.CreateNPC(firstname, |
||
2405 | lastname, |
||
2406 | position, |
||
2407 | ownerID, |
||
2408 | senseAsAgent, |
||
2409 | World, |
||
2410 | appearance); |
||
2411 | |||
2412 | return new LSL_Key(x.ToString()); |
||
2413 | } |
||
2414 | |||
2415 | return new LSL_Key(UUID.Zero.ToString()); |
||
2416 | } |
||
2417 | |||
2418 | /// <summary> |
||
2419 | /// Save the current appearance of the NPC permanently to the named notecard. |
||
2420 | /// </summary> |
||
2421 | /// <param name="avatar"></param> |
||
2422 | /// <param name="notecard">The name of the notecard to which to save the appearance.</param> |
||
2423 | /// <returns>The asset ID of the notecard saved.</returns> |
||
2424 | public LSL_Key osNpcSaveAppearance(LSL_Key npc, string notecard) |
||
2425 | { |
||
2426 | CheckThreatLevel(ThreatLevel.High, "osNpcSaveAppearance"); |
||
2427 | m_host.AddScriptLPS(1); |
||
2428 | |||
2429 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
||
2430 | |||
2431 | if (npcModule != null) |
||
2432 | { |
||
2433 | UUID npcId; |
||
2434 | if (!UUID.TryParse(npc.m_string, out npcId)) |
||
2435 | return new LSL_Key(UUID.Zero.ToString()); |
||
2436 | |||
2437 | if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) |
||
2438 | return new LSL_Key(UUID.Zero.ToString()); |
||
2439 | |||
2440 | return SaveAppearanceToNotecard(npcId, notecard); |
||
2441 | } |
||
2442 | |||
2443 | return new LSL_Key(UUID.Zero.ToString()); |
||
2444 | } |
||
2445 | |||
2446 | public void osNpcLoadAppearance(LSL_Key npc, string notecard) |
||
2447 | { |
||
2448 | CheckThreatLevel(ThreatLevel.High, "osNpcLoadAppearance"); |
||
2449 | m_host.AddScriptLPS(1); |
||
2450 | |||
2451 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
||
2452 | |||
2453 | if (npcModule != null) |
||
2454 | { |
||
2455 | UUID npcId; |
||
2456 | if (!UUID.TryParse(npc.m_string, out npcId)) |
||
2457 | return; |
||
2458 | |||
2459 | if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) |
||
2460 | return; |
||
2461 | |||
2462 | string appearanceSerialized = LoadNotecard(notecard); |
||
2463 | |||
2464 | if (appearanceSerialized == null) |
||
2465 | OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); |
||
2466 | |||
2467 | OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); |
||
2468 | // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); |
||
2469 | // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); |
||
2470 | // Console.WriteLine("a.Type {0}, a.ToString() {1}", a.Type, a); |
||
2471 | AvatarAppearance appearance = new AvatarAppearance(); |
||
2472 | appearance.Unpack(appearanceOsd); |
||
2473 | |||
2474 | npcModule.SetNPCAppearance(npcId, appearance, m_host.ParentGroup.Scene); |
||
2475 | } |
||
2476 | } |
||
2477 | |||
2478 | public LSL_Key osNpcGetOwner(LSL_Key npc) |
||
2479 | { |
||
2480 | CheckThreatLevel(ThreatLevel.None, "osNpcGetOwner"); |
||
2481 | m_host.AddScriptLPS(1); |
||
2482 | |||
2483 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
||
2484 | if (npcModule != null) |
||
2485 | { |
||
2486 | UUID npcId; |
||
2487 | if (UUID.TryParse(npc.m_string, out npcId)) |
||
2488 | { |
||
2489 | UUID owner = npcModule.GetOwner(npcId); |
||
2490 | if (owner != UUID.Zero) |
||
2491 | return new LSL_Key(owner.ToString()); |
||
2492 | else |
||
2493 | return npc; |
||
2494 | } |
||
2495 | } |
||
2496 | |||
2497 | return new LSL_Key(UUID.Zero.ToString()); |
||
2498 | } |
||
2499 | |||
2500 | public LSL_Vector osNpcGetPos(LSL_Key npc) |
||
2501 | { |
||
2502 | CheckThreatLevel(ThreatLevel.High, "osNpcGetPos"); |
||
2503 | m_host.AddScriptLPS(1); |
||
2504 | |||
2505 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
||
2506 | if (npcModule != null) |
||
2507 | { |
||
2508 | UUID npcId; |
||
2509 | if (!UUID.TryParse(npc.m_string, out npcId)) |
||
2510 | return new LSL_Vector(0, 0, 0); |
||
2511 | |||
2512 | if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) |
||
2513 | return new LSL_Vector(0, 0, 0); |
||
2514 | |||
2515 | ScenePresence sp = World.GetScenePresence(npcId); |
||
2516 | |||
2517 | if (sp != null) |
||
2518 | return new LSL_Vector(sp.AbsolutePosition); |
||
2519 | } |
||
2520 | |||
2521 | return Vector3.Zero; |
||
2522 | } |
||
2523 | |||
2524 | public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) |
||
2525 | { |
||
2526 | CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); |
||
2527 | m_host.AddScriptLPS(1); |
||
2528 | |||
2529 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2530 | if (module != null) |
||
2531 | { |
||
2532 | UUID npcId; |
||
2533 | if (!UUID.TryParse(npc.m_string, out npcId)) |
||
2534 | return; |
||
2535 | |||
2536 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2537 | return; |
||
2538 | |||
2539 | module.MoveToTarget(npcId, World, pos, false, true, false); |
||
2540 | } |
||
2541 | } |
||
2542 | |||
2543 | public void osNpcMoveToTarget(LSL_Key npc, LSL_Vector target, int options) |
||
2544 | { |
||
2545 | CheckThreatLevel(ThreatLevel.High, "osNpcMoveToTarget"); |
||
2546 | m_host.AddScriptLPS(1); |
||
2547 | |||
2548 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2549 | if (module != null) |
||
2550 | { |
||
2551 | UUID npcId; |
||
2552 | if (!UUID.TryParse(npc.m_string, out npcId)) |
||
2553 | return; |
||
2554 | |||
2555 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2556 | return; |
||
2557 | |||
2558 | module.MoveToTarget( |
||
2559 | new UUID(npc.m_string), |
||
2560 | World, |
||
2561 | target, |
||
2562 | (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, |
||
2563 | (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, |
||
2564 | (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); |
||
2565 | } |
||
2566 | } |
||
2567 | |||
2568 | public LSL_Rotation osNpcGetRot(LSL_Key npc) |
||
2569 | { |
||
2570 | CheckThreatLevel(ThreatLevel.High, "osNpcGetRot"); |
||
2571 | m_host.AddScriptLPS(1); |
||
2572 | |||
2573 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
||
2574 | if (npcModule != null) |
||
2575 | { |
||
2576 | UUID npcId; |
||
2577 | if (!UUID.TryParse(npc.m_string, out npcId)) |
||
2578 | return new LSL_Rotation(Quaternion.Identity); |
||
2579 | |||
2580 | if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) |
||
2581 | return new LSL_Rotation(Quaternion.Identity); |
||
2582 | |||
2583 | ScenePresence sp = World.GetScenePresence(npcId); |
||
2584 | |||
2585 | if (sp != null) |
||
2586 | return new LSL_Rotation(sp.GetWorldRotation()); |
||
2587 | } |
||
2588 | |||
2589 | return Quaternion.Identity; |
||
2590 | } |
||
2591 | |||
2592 | public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation) |
||
2593 | { |
||
2594 | CheckThreatLevel(ThreatLevel.High, "osNpcSetRot"); |
||
2595 | m_host.AddScriptLPS(1); |
||
2596 | |||
2597 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
||
2598 | if (npcModule != null) |
||
2599 | { |
||
2600 | UUID npcId; |
||
2601 | if (!UUID.TryParse(npc.m_string, out npcId)) |
||
2602 | return; |
||
2603 | |||
2604 | if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) |
||
2605 | return; |
||
2606 | |||
2607 | ScenePresence sp = World.GetScenePresence(npcId); |
||
2608 | |||
2609 | if (sp != null) |
||
2610 | sp.Rotation = rotation; |
||
2611 | } |
||
2612 | } |
||
2613 | |||
2614 | public void osNpcStopMoveToTarget(LSL_Key npc) |
||
2615 | { |
||
2616 | CheckThreatLevel(ThreatLevel.High, "osNpcStopMoveToTarget"); |
||
2617 | m_host.AddScriptLPS(1); |
||
2618 | |||
2619 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2620 | if (module != null) |
||
2621 | { |
||
2622 | UUID npcId = new UUID(npc.m_string); |
||
2623 | |||
2624 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2625 | return; |
||
2626 | |||
2627 | module.StopMoveToTarget(npcId, World); |
||
2628 | } |
||
2629 | } |
||
2630 | |||
2631 | public void osNpcSay(LSL_Key npc, string message) |
||
2632 | { |
||
2633 | osNpcSay(npc, 0, message); |
||
2634 | } |
||
2635 | |||
2636 | public void osNpcSay(LSL_Key npc, int channel, string message) |
||
2637 | { |
||
2638 | CheckThreatLevel(ThreatLevel.High, "osNpcSay"); |
||
2639 | m_host.AddScriptLPS(1); |
||
2640 | |||
2641 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2642 | if (module != null) |
||
2643 | { |
||
2644 | UUID npcId = new UUID(npc.m_string); |
||
2645 | |||
2646 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2647 | return; |
||
2648 | |||
2649 | module.Say(npcId, World, message, channel); |
||
2650 | } |
||
2651 | } |
||
2652 | |||
2653 | public void osNpcShout(LSL_Key npc, int channel, string message) |
||
2654 | { |
||
2655 | CheckThreatLevel(ThreatLevel.High, "osNpcShout"); |
||
2656 | m_host.AddScriptLPS(1); |
||
2657 | |||
2658 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2659 | if (module != null) |
||
2660 | { |
||
2661 | UUID npcId = new UUID(npc.m_string); |
||
2662 | |||
2663 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2664 | return; |
||
2665 | |||
2666 | module.Shout(npcId, World, message, channel); |
||
2667 | } |
||
2668 | } |
||
2669 | |||
2670 | public void osNpcSit(LSL_Key npc, LSL_Key target, int options) |
||
2671 | { |
||
2672 | CheckThreatLevel(ThreatLevel.High, "osNpcSit"); |
||
2673 | m_host.AddScriptLPS(1); |
||
2674 | |||
2675 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2676 | if (module != null) |
||
2677 | { |
||
2678 | UUID npcId = new UUID(npc.m_string); |
||
2679 | |||
2680 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2681 | return; |
||
2682 | |||
2683 | module.Sit(npcId, new UUID(target.m_string), World); |
||
2684 | } |
||
2685 | } |
||
2686 | |||
2687 | public void osNpcStand(LSL_Key npc) |
||
2688 | { |
||
2689 | CheckThreatLevel(ThreatLevel.High, "osNpcStand"); |
||
2690 | m_host.AddScriptLPS(1); |
||
2691 | |||
2692 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2693 | if (module != null) |
||
2694 | { |
||
2695 | UUID npcId = new UUID(npc.m_string); |
||
2696 | |||
2697 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2698 | return; |
||
2699 | |||
2700 | module.Stand(npcId, World); |
||
2701 | } |
||
2702 | } |
||
2703 | |||
2704 | public void osNpcRemove(LSL_Key npc) |
||
2705 | { |
||
2706 | CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); |
||
2707 | m_host.AddScriptLPS(1); |
||
2708 | |||
2709 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2710 | if (module != null) |
||
2711 | { |
||
2712 | UUID npcId = new UUID(npc.m_string); |
||
2713 | |||
2714 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2715 | return; |
||
2716 | |||
2717 | module.DeleteNPC(npcId, World); |
||
2718 | } |
||
2719 | } |
||
2720 | |||
2721 | public void osNpcPlayAnimation(LSL_Key npc, string animation) |
||
2722 | { |
||
2723 | CheckThreatLevel(ThreatLevel.High, "osNpcPlayAnimation"); |
||
2724 | m_host.AddScriptLPS(1); |
||
2725 | |||
2726 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2727 | if (module != null) |
||
2728 | { |
||
2729 | UUID npcID = new UUID(npc.m_string); |
||
2730 | |||
2731 | if (module.CheckPermissions(npcID, m_host.OwnerID)) |
||
2732 | AvatarPlayAnimation(npcID.ToString(), animation); |
||
2733 | } |
||
2734 | } |
||
2735 | |||
2736 | public void osNpcStopAnimation(LSL_Key npc, string animation) |
||
2737 | { |
||
2738 | CheckThreatLevel(ThreatLevel.High, "osNpcStopAnimation"); |
||
2739 | m_host.AddScriptLPS(1); |
||
2740 | |||
2741 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2742 | if (module != null) |
||
2743 | { |
||
2744 | UUID npcID = new UUID(npc.m_string); |
||
2745 | |||
2746 | if (module.CheckPermissions(npcID, m_host.OwnerID)) |
||
2747 | AvatarStopAnimation(npcID.ToString(), animation); |
||
2748 | } |
||
2749 | } |
||
2750 | |||
2751 | public void osNpcWhisper(LSL_Key npc, int channel, string message) |
||
2752 | { |
||
2753 | CheckThreatLevel(ThreatLevel.High, "osNpcWhisper"); |
||
2754 | m_host.AddScriptLPS(1); |
||
2755 | |||
2756 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2757 | if (module != null) |
||
2758 | { |
||
2759 | UUID npcId = new UUID(npc.m_string); |
||
2760 | |||
2761 | if (!module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2762 | return; |
||
2763 | |||
2764 | module.Whisper(npcId, World, message, channel); |
||
2765 | } |
||
2766 | } |
||
2767 | |||
2768 | public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num) |
||
2769 | { |
||
2770 | CheckThreatLevel(ThreatLevel.High, "osNpcTouch"); |
||
2771 | m_host.AddScriptLPS(1); |
||
2772 | |||
2773 | INPCModule module = World.RequestModuleInterface<INPCModule>(); |
||
2774 | int linkNum = link_num.value; |
||
2775 | if (module != null || (linkNum < 0 && linkNum != ScriptBaseClass.LINK_THIS)) |
||
2776 | { |
||
2777 | UUID npcId; |
||
2778 | if (!UUID.TryParse(npcLSL_Key, out npcId) || !module.CheckPermissions(npcId, m_host.OwnerID)) |
||
2779 | return; |
||
2780 | |||
2781 | SceneObjectPart part = null; |
||
2782 | UUID objectId; |
||
2783 | if (UUID.TryParse(LSL_String.ToString(object_key), out objectId)) |
||
2784 | part = World.GetSceneObjectPart(objectId); |
||
2785 | |||
2786 | if (part == null) |
||
2787 | return; |
||
2788 | |||
2789 | if (linkNum != ScriptBaseClass.LINK_THIS) |
||
2790 | { |
||
2791 | if (linkNum == 0 || linkNum == ScriptBaseClass.LINK_ROOT) |
||
2792 | { // 0 and 1 are treated as root, find the root if the current part isnt it |
||
2793 | if (!part.IsRoot) |
||
2794 | part = part.ParentGroup.RootPart; |
||
2795 | } |
||
2796 | else |
||
2797 | { // Find the prim with the given link number if not found then fail silently |
||
2798 | part = part.ParentGroup.GetLinkNumPart(linkNum); |
||
2799 | if (part == null) |
||
2800 | return; |
||
2801 | } |
||
2802 | } |
||
2803 | |||
2804 | module.Touch(npcId, part.UUID); |
||
2805 | } |
||
2806 | } |
||
2807 | |||
2808 | /// <summary> |
||
2809 | /// Save the current appearance of the script owner permanently to the named notecard. |
||
2810 | /// </summary> |
||
2811 | /// <param name="notecard">The name of the notecard to which to save the appearance.</param> |
||
2812 | /// <returns>The asset ID of the notecard saved.</returns> |
||
2813 | public LSL_Key osOwnerSaveAppearance(string notecard) |
||
2814 | { |
||
2815 | CheckThreatLevel(ThreatLevel.High, "osOwnerSaveAppearance"); |
||
2816 | m_host.AddScriptLPS(1); |
||
2817 | |||
2818 | return SaveAppearanceToNotecard(m_host.OwnerID, notecard); |
||
2819 | } |
||
2820 | |||
2821 | public LSL_Key osAgentSaveAppearance(LSL_Key avatarId, string notecard) |
||
2822 | { |
||
2823 | CheckThreatLevel(ThreatLevel.VeryHigh, "osAgentSaveAppearance"); |
||
2824 | m_host.AddScriptLPS(1); |
||
2825 | |||
2826 | return SaveAppearanceToNotecard(avatarId, notecard); |
||
2827 | } |
||
2828 | |||
2829 | protected LSL_Key SaveAppearanceToNotecard(ScenePresence sp, string notecard) |
||
2830 | { |
||
2831 | IAvatarFactoryModule appearanceModule = World.RequestModuleInterface<IAvatarFactoryModule>(); |
||
2832 | |||
2833 | if (appearanceModule != null) |
||
2834 | { |
||
2835 | appearanceModule.SaveBakedTextures(sp.UUID); |
||
2836 | OSDMap appearancePacked = sp.Appearance.Pack(); |
||
2837 | |||
2838 | TaskInventoryItem item |
||
2839 | = SaveNotecard(notecard, "Avatar Appearance", Util.GetFormattedXml(appearancePacked as OSD), true); |
||
2840 | |||
2841 | return new LSL_Key(item.AssetID.ToString()); |
||
2842 | } |
||
2843 | else |
||
2844 | { |
||
2845 | return new LSL_Key(UUID.Zero.ToString()); |
||
2846 | } |
||
2847 | } |
||
2848 | |||
2849 | protected LSL_Key SaveAppearanceToNotecard(UUID avatarId, string notecard) |
||
2850 | { |
||
2851 | ScenePresence sp = World.GetScenePresence(avatarId); |
||
2852 | |||
2853 | if (sp == null || sp.IsChildAgent) |
||
2854 | return new LSL_Key(UUID.Zero.ToString()); |
||
2855 | |||
2856 | return SaveAppearanceToNotecard(sp, notecard); |
||
2857 | } |
||
2858 | |||
2859 | protected LSL_Key SaveAppearanceToNotecard(LSL_Key rawAvatarId, string notecard) |
||
2860 | { |
||
2861 | UUID avatarId; |
||
2862 | if (!UUID.TryParse(rawAvatarId, out avatarId)) |
||
2863 | return new LSL_Key(UUID.Zero.ToString()); |
||
2864 | |||
2865 | return SaveAppearanceToNotecard(avatarId, notecard); |
||
2866 | } |
||
2867 | |||
2868 | /// <summary> |
||
2869 | /// Get current region's map texture UUID |
||
2870 | /// </summary> |
||
2871 | /// <returns></returns> |
||
2872 | public LSL_Key osGetMapTexture() |
||
2873 | { |
||
2874 | CheckThreatLevel(ThreatLevel.None, "osGetMapTexture"); |
||
2875 | m_host.AddScriptLPS(1); |
||
2876 | |||
2877 | return m_ScriptEngine.World.RegionInfo.RegionSettings.TerrainImageID.ToString(); |
||
2878 | } |
||
2879 | |||
2880 | /// <summary> |
||
2881 | /// Get a region's map texture UUID by region UUID or name. |
||
2882 | /// </summary> |
||
2883 | /// <param name="regionName"></param> |
||
2884 | /// <returns></returns> |
||
2885 | public LSL_Key osGetRegionMapTexture(string regionName) |
||
2886 | { |
||
2887 | CheckThreatLevel(ThreatLevel.High, "osGetRegionMapTexture"); |
||
2888 | m_host.AddScriptLPS(1); |
||
2889 | |||
2890 | Scene scene = m_ScriptEngine.World; |
||
2891 | UUID key = UUID.Zero; |
||
2892 | GridRegion region; |
||
2893 | |||
2894 | //If string is a key, use it. Otherwise, try to locate region by name. |
||
2895 | if (UUID.TryParse(regionName, out key)) |
||
2896 | region = scene.GridService.GetRegionByUUID(UUID.Zero, key); |
||
2897 | else |
||
2898 | region = scene.GridService.GetRegionByName(UUID.Zero, regionName); |
||
2899 | |||
2900 | // If region was found, return the regions map texture key. |
||
2901 | if (region != null) |
||
2902 | key = region.TerrainImage; |
||
2903 | |||
2904 | ScriptSleep(1000); |
||
2905 | |||
2906 | return key.ToString(); |
||
2907 | } |
||
2908 | |||
2909 | /// <summary> |
||
2910 | /// Return information regarding various simulator statistics (sim fps, physics fps, time |
||
2911 | /// dilation, total number of prims, total number of active scripts, script lps, various |
||
2912 | /// timing data, packets in/out, etc. Basically much the information that's shown in the |
||
2913 | /// client's Statistics Bar (Ctrl-Shift-1) |
||
2914 | /// </summary> |
||
2915 | /// <returns>List of floats</returns> |
||
2916 | public LSL_List osGetRegionStats() |
||
2917 | { |
||
2918 | CheckThreatLevel(ThreatLevel.Moderate, "osGetRegionStats"); |
||
2919 | m_host.AddScriptLPS(1); |
||
2920 | LSL_List ret = new LSL_List(); |
||
2921 | float[] stats = World.StatsReporter.LastReportedSimStats; |
||
2922 | |||
2923 | for (int i = 0; i < 21; i++) |
||
2924 | { |
||
2925 | ret.Add(new LSL_Float(stats[i])); |
||
2926 | } |
||
2927 | return ret; |
||
2928 | } |
||
2929 | |||
2930 | public LSL_Vector osGetRegionSize() |
||
2931 | { |
||
2932 | CheckThreatLevel(ThreatLevel.None, "osGetRegionSize"); |
||
2933 | m_host.AddScriptLPS(1); |
||
2934 | |||
2935 | bool isMegaregion; |
||
2936 | IRegionCombinerModule rcMod = World.RequestModuleInterface<IRegionCombinerModule>(); |
||
2937 | if (rcMod != null) |
||
2938 | isMegaregion = rcMod.IsRootForMegaregion(World.RegionInfo.RegionID); |
||
2939 | else |
||
2940 | isMegaregion = false; |
||
2941 | |||
2942 | if (isMegaregion) |
||
2943 | { |
||
2944 | Vector2 size = rcMod.GetSizeOfMegaregion(World.RegionInfo.RegionID); |
||
2945 | return new LSL_Vector(size.X, size.Y, Constants.RegionHeight); |
||
2946 | } |
||
2947 | else |
||
2948 | { |
||
2949 | return new LSL_Vector((float)Constants.RegionSize, (float)Constants.RegionSize, Constants.RegionHeight); |
||
2950 | } |
||
2951 | } |
||
2952 | |||
2953 | public int osGetSimulatorMemory() |
||
2954 | { |
||
2955 | CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory"); |
||
2956 | m_host.AddScriptLPS(1); |
||
2957 | long pws = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64; |
||
2958 | |||
2959 | if (pws > Int32.MaxValue) |
||
2960 | return Int32.MaxValue; |
||
2961 | if (pws < 0) |
||
2962 | return 0; |
||
2963 | |||
2964 | return (int)pws; |
||
2965 | } |
||
2966 | |||
2967 | public void osSetSpeed(string UUID, LSL_Float SpeedModifier) |
||
2968 | { |
||
2969 | CheckThreatLevel(ThreatLevel.Moderate, "osSetSpeed"); |
||
2970 | m_host.AddScriptLPS(1); |
||
2971 | ScenePresence avatar = World.GetScenePresence(new UUID(UUID)); |
||
2972 | |||
2973 | if (avatar != null) |
||
2974 | avatar.SpeedModifier = (float)SpeedModifier; |
||
2975 | } |
||
2976 | |||
2977 | public void osKickAvatar(string FirstName, string SurName, string alert) |
||
2978 | { |
||
2979 | CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); |
||
2980 | m_host.AddScriptLPS(1); |
||
2981 | |||
2982 | World.ForEachRootScenePresence(delegate(ScenePresence sp) |
||
2983 | { |
||
2984 | if (sp.Firstname == FirstName && sp.Lastname == SurName) |
||
2985 | { |
||
2986 | // kick client... |
||
2987 | if (alert != null) |
||
2988 | sp.ControllingClient.Kick(alert); |
||
2989 | |||
2990 | // ...and close on our side |
||
2991 | sp.Scene.CloseAgent(sp.UUID, false); |
||
2992 | } |
||
2993 | }); |
||
2994 | } |
||
2995 | |||
2996 | public LSL_Float osGetHealth(string avatar) |
||
2997 | { |
||
2998 | CheckThreatLevel(ThreatLevel.None, "osGetHealth"); |
||
2999 | m_host.AddScriptLPS(1); |
||
3000 | |||
3001 | LSL_Float health = new LSL_Float(-1); |
||
3002 | ScenePresence presence = World.GetScenePresence(new UUID(avatar)); |
||
3003 | if (presence != null) health = presence.Health; |
||
3004 | return health; |
||
3005 | } |
||
3006 | |||
3007 | public void osCauseDamage(string avatar, double damage) |
||
3008 | { |
||
3009 | CheckThreatLevel(ThreatLevel.High, "osCauseDamage"); |
||
3010 | m_host.AddScriptLPS(1); |
||
3011 | |||
3012 | UUID avatarId = new UUID(avatar); |
||
3013 | Vector3 pos = m_host.GetWorldPosition(); |
||
3014 | |||
3015 | ScenePresence presence = World.GetScenePresence(avatarId); |
||
3016 | if (presence != null) |
||
3017 | { |
||
3018 | LandData land = World.GetLandData(pos); |
||
3019 | if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) |
||
3020 | { |
||
3021 | float health = presence.Health; |
||
3022 | health -= (float)damage; |
||
3023 | presence.setHealthWithUpdate(health); |
||
3024 | if (health <= 0) |
||
3025 | { |
||
3026 | float healthliveagain = 100; |
||
3027 | presence.ControllingClient.SendAgentAlertMessage("You died!", true); |
||
3028 | presence.setHealthWithUpdate(healthliveagain); |
||
3029 | presence.Scene.TeleportClientHome(presence.UUID, presence.ControllingClient); |
||
3030 | } |
||
3031 | } |
||
3032 | } |
||
3033 | } |
||
3034 | |||
3035 | public void osCauseHealing(string avatar, double healing) |
||
3036 | { |
||
3037 | CheckThreatLevel(ThreatLevel.High, "osCauseHealing"); |
||
3038 | m_host.AddScriptLPS(1); |
||
3039 | |||
3040 | UUID avatarId = new UUID(avatar); |
||
3041 | ScenePresence presence = World.GetScenePresence(avatarId); |
||
3042 | |||
3043 | if (presence != null && World.ScriptDanger(m_host.LocalId, m_host.GetWorldPosition())) |
||
3044 | { |
||
3045 | float health = presence.Health; |
||
3046 | health += (float)healing; |
||
3047 | |||
3048 | if (health >= 100) |
||
3049 | health = 100; |
||
3050 | |||
3051 | presence.setHealthWithUpdate(health); |
||
3052 | } |
||
3053 | } |
||
3054 | |||
3055 | public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) |
||
3056 | { |
||
3057 | CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); |
||
3058 | m_host.AddScriptLPS(1); |
||
3059 | InitLSL(); |
||
3060 | |||
3061 | return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); |
||
3062 | } |
||
3063 | |||
3064 | public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) |
||
3065 | { |
||
3066 | CheckThreatLevel(ThreatLevel.High, "osSetPrimitiveParams"); |
||
3067 | m_host.AddScriptLPS(1); |
||
3068 | InitLSL(); |
||
3069 | |||
3070 | m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); |
||
3071 | } |
||
3072 | |||
3073 | /// <summary> |
||
3074 | /// Set parameters for light projection in host prim |
||
3075 | /// </summary> |
||
3076 | public void osSetProjectionParams(bool projection, LSL_Key texture, double fov, double focus, double amb) |
||
3077 | { |
||
3078 | CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams"); |
||
3079 | |||
3080 | osSetProjectionParams(UUID.Zero.ToString(), projection, texture, fov, focus, amb); |
||
3081 | } |
||
3082 | |||
3083 | /// <summary> |
||
3084 | /// Set parameters for light projection with uuid of target prim |
||
3085 | /// </summary> |
||
3086 | public void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb) |
||
3087 | { |
||
3088 | CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams"); |
||
3089 | m_host.AddScriptLPS(1); |
||
3090 | |||
3091 | SceneObjectPart obj = null; |
||
3092 | if (prim == UUID.Zero.ToString()) |
||
3093 | { |
||
3094 | obj = m_host; |
||
3095 | } |
||
3096 | else |
||
3097 | { |
||
3098 | obj = World.GetSceneObjectPart(new UUID(prim)); |
||
3099 | if (obj == null) |
||
3100 | return; |
||
3101 | } |
||
3102 | |||
3103 | obj.Shape.ProjectionEntry = projection; |
||
3104 | obj.Shape.ProjectionTextureUUID = new UUID(texture); |
||
3105 | obj.Shape.ProjectionFOV = (float)fov; |
||
3106 | obj.Shape.ProjectionFocus = (float)focus; |
||
3107 | obj.Shape.ProjectionAmbiance = (float)amb; |
||
3108 | |||
3109 | obj.ParentGroup.HasGroupChanged = true; |
||
3110 | obj.ScheduleFullUpdate(); |
||
3111 | } |
||
3112 | |||
3113 | /// <summary> |
||
3114 | /// Like osGetAgents but returns enough info for a radar |
||
3115 | /// </summary> |
||
3116 | /// <returns>Strided list of the UUID, position and name of each avatar in the region</returns> |
||
3117 | public LSL_List osGetAvatarList() |
||
3118 | { |
||
3119 | CheckThreatLevel(ThreatLevel.None, "osGetAvatarList"); |
||
3120 | m_host.AddScriptLPS(1); |
||
3121 | |||
3122 | LSL_List result = new LSL_List(); |
||
3123 | World.ForEachRootScenePresence(delegate (ScenePresence avatar) |
||
3124 | { |
||
3125 | if (avatar != null && avatar.UUID != m_host.OwnerID) |
||
3126 | { |
||
3127 | result.Add(new LSL_String(avatar.UUID.ToString())); |
||
3128 | result.Add(new LSL_Vector(avatar.AbsolutePosition)); |
||
3129 | result.Add(new LSL_String(avatar.Name)); |
||
3130 | } |
||
3131 | }); |
||
3132 | |||
3133 | return result; |
||
3134 | } |
||
3135 | |||
3136 | /// <summary> |
||
3137 | /// Convert a unix time to a llGetTimestamp() like string |
||
3138 | /// </summary> |
||
3139 | /// <param name="unixTime"></param> |
||
3140 | /// <returns></returns> |
||
3141 | public LSL_String osUnixTimeToTimestamp(long time) |
||
3142 | { |
||
3143 | CheckThreatLevel(ThreatLevel.VeryLow, "osUnixTimeToTimestamp"); |
||
3144 | m_host.AddScriptLPS(1); |
||
3145 | |||
3146 | long baseTicks = 621355968000000000; |
||
3147 | long tickResolution = 10000000; |
||
3148 | long epochTicks = (time * tickResolution) + baseTicks; |
||
3149 | DateTime date = new DateTime(epochTicks); |
||
3150 | |||
3151 | return date.ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); |
||
3152 | } |
||
3153 | |||
3154 | /// <summary> |
||
3155 | /// Get the description from an inventory item |
||
3156 | /// </summary> |
||
3157 | /// <param name="inventoryName"></param> |
||
3158 | /// <returns>Item description</returns> |
||
3159 | public LSL_String osGetInventoryDesc(string item) |
||
3160 | { |
||
3161 | m_host.AddScriptLPS(1); |
||
3162 | |||
3163 | lock (m_host.TaskInventory) |
||
3164 | { |
||
3165 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) |
||
3166 | { |
||
3167 | if (inv.Value.Name == item) |
||
3168 | { |
||
3169 | return inv.Value.Description.ToString(); |
||
3170 | } |
||
3171 | } |
||
3172 | } |
||
3173 | |||
3174 | return String.Empty; |
||
3175 | } |
||
3176 | |||
3177 | /// <summary> |
||
3178 | /// Invite user to the group this object is set to |
||
3179 | /// </summary> |
||
3180 | /// <param name="agentId"></param> |
||
3181 | /// <returns></returns> |
||
3182 | public LSL_Integer osInviteToGroup(LSL_Key agentId) |
||
3183 | { |
||
3184 | CheckThreatLevel(ThreatLevel.VeryLow, "osInviteToGroup"); |
||
3185 | m_host.AddScriptLPS(1); |
||
3186 | |||
3187 | UUID agent = new UUID(agentId); |
||
3188 | |||
3189 | // groups module is required |
||
3190 | IGroupsModule groupsModule = m_ScriptEngine.World.RequestModuleInterface<IGroupsModule>(); |
||
3191 | if (groupsModule == null) return ScriptBaseClass.FALSE; |
||
3192 | |||
3193 | // object has to be set to a group, but not group owned |
||
3194 | if (m_host.GroupID == UUID.Zero || m_host.GroupID == m_host.OwnerID) return ScriptBaseClass.FALSE; |
||
3195 | |||
3196 | // object owner has to be in that group and required permissions |
||
3197 | GroupMembershipData member = groupsModule.GetMembershipData(m_host.GroupID, m_host.OwnerID); |
||
3198 | if (member == null || (member.GroupPowers & (ulong)GroupPowers.Invite) == 0) return ScriptBaseClass.FALSE; |
||
3199 | |||
3200 | // check if agent is in that group already |
||
3201 | //member = groupsModule.GetMembershipData(agent, m_host.GroupID, agent); |
||
3202 | //if (member != null) return ScriptBaseClass.FALSE; |
||
3203 | |||
3204 | // invited agent has to be present in this scene |
||
3205 | if (World.GetScenePresence(agent) == null) return ScriptBaseClass.FALSE; |
||
3206 | |||
3207 | groupsModule.InviteGroup(null, m_host.OwnerID, m_host.GroupID, agent, UUID.Zero); |
||
3208 | |||
3209 | return ScriptBaseClass.TRUE; |
||
3210 | } |
||
3211 | |||
3212 | /// <summary> |
||
3213 | /// Eject user from the group this object is set to |
||
3214 | /// </summary> |
||
3215 | /// <param name="agentId"></param> |
||
3216 | /// <returns></returns> |
||
3217 | public LSL_Integer osEjectFromGroup(LSL_Key agentId) |
||
3218 | { |
||
3219 | CheckThreatLevel(ThreatLevel.VeryLow, "osEjectFromGroup"); |
||
3220 | m_host.AddScriptLPS(1); |
||
3221 | |||
3222 | UUID agent = new UUID(agentId); |
||
3223 | |||
3224 | // groups module is required |
||
3225 | IGroupsModule groupsModule = m_ScriptEngine.World.RequestModuleInterface<IGroupsModule>(); |
||
3226 | if (groupsModule == null) return ScriptBaseClass.FALSE; |
||
3227 | |||
3228 | // object has to be set to a group, but not group owned |
||
3229 | if (m_host.GroupID == UUID.Zero || m_host.GroupID == m_host.OwnerID) return ScriptBaseClass.FALSE; |
||
3230 | |||
3231 | // object owner has to be in that group and required permissions |
||
3232 | GroupMembershipData member = groupsModule.GetMembershipData(m_host.GroupID, m_host.OwnerID); |
||
3233 | if (member == null || (member.GroupPowers & (ulong)GroupPowers.Eject) == 0) return ScriptBaseClass.FALSE; |
||
3234 | |||
3235 | // agent has to be in that group |
||
3236 | //member = groupsModule.GetMembershipData(agent, m_host.GroupID, agent); |
||
3237 | //if (member == null) return ScriptBaseClass.FALSE; |
||
3238 | |||
3239 | // ejectee can be offline |
||
3240 | |||
3241 | groupsModule.EjectGroupMember(null, m_host.OwnerID, m_host.GroupID, agent); |
||
3242 | |||
3243 | return ScriptBaseClass.TRUE; |
||
3244 | } |
||
3245 | |||
3246 | /// <summary> |
||
3247 | /// Sets terrain estate texture |
||
3248 | /// </summary> |
||
3249 | /// <param name="level"></param> |
||
3250 | /// <param name="texture"></param> |
||
3251 | /// <returns></returns> |
||
3252 | public void osSetTerrainTexture(int level, LSL_Key texture) |
||
3253 | { |
||
3254 | CheckThreatLevel(ThreatLevel.High, "osSetTerrainTexture"); |
||
3255 | |||
3256 | m_host.AddScriptLPS(1); |
||
3257 | //Check to make sure that the script's owner is the estate manager/master |
||
3258 | //World.Permissions.GenericEstatePermission( |
||
3259 | if (World.Permissions.IsGod(m_host.OwnerID)) |
||
3260 | { |
||
3261 | if (level < 0 || level > 3) |
||
3262 | return; |
||
3263 | |||
3264 | UUID textureID = new UUID(); |
||
3265 | if (!UUID.TryParse(texture, out textureID)) |
||
3266 | return; |
||
3267 | |||
3268 | // estate module is required |
||
3269 | IEstateModule estate = World.RequestModuleInterface<IEstateModule>(); |
||
3270 | if (estate != null) |
||
3271 | estate.setEstateTerrainBaseTexture(level, textureID); |
||
3272 | } |
||
3273 | } |
||
3274 | |||
3275 | /// <summary> |
||
3276 | /// Sets terrain heights of estate |
||
3277 | /// </summary> |
||
3278 | /// <param name="corner"></param> |
||
3279 | /// <param name="low"></param> |
||
3280 | /// <param name="high"></param> |
||
3281 | /// <returns></returns> |
||
3282 | public void osSetTerrainTextureHeight(int corner, double low, double high) |
||
3283 | { |
||
3284 | CheckThreatLevel(ThreatLevel.High, "osSetTerrainTextureHeight"); |
||
3285 | |||
3286 | m_host.AddScriptLPS(1); |
||
3287 | //Check to make sure that the script's owner is the estate manager/master |
||
3288 | //World.Permissions.GenericEstatePermission( |
||
3289 | if (World.Permissions.IsGod(m_host.OwnerID)) |
||
3290 | { |
||
3291 | if (corner < 0 || corner > 3) |
||
3292 | return; |
||
3293 | |||
3294 | // estate module is required |
||
3295 | IEstateModule estate = World.RequestModuleInterface<IEstateModule>(); |
||
3296 | if (estate != null) |
||
3297 | estate.setEstateTerrainTextureHeights(corner, (float)low, (float)high); |
||
3298 | } |
||
3299 | } |
||
3300 | |||
3301 | #region Attachment commands |
||
3302 | |||
3303 | public void osForceAttachToAvatar(int attachmentPoint) |
||
3304 | { |
||
3305 | CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); |
||
3306 | |||
3307 | m_host.AddScriptLPS(1); |
||
3308 | |||
3309 | InitLSL(); |
||
3310 | ((LSL_Api)m_LSL_Api).AttachToAvatar(attachmentPoint); |
||
3311 | } |
||
3312 | |||
3313 | public void osForceAttachToAvatarFromInventory(string itemName, int attachmentPoint) |
||
3314 | { |
||
3315 | CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory"); |
||
3316 | |||
3317 | m_host.AddScriptLPS(1); |
||
3318 | |||
3319 | ForceAttachToAvatarFromInventory(m_host.OwnerID, itemName, attachmentPoint); |
||
3320 | } |
||
3321 | |||
3322 | public void osForceAttachToOtherAvatarFromInventory(string rawAvatarId, string itemName, int attachmentPoint) |
||
3323 | { |
||
3324 | CheckThreatLevel(ThreatLevel.Severe, "osForceAttachToOtherAvatarFromInventory"); |
||
3325 | |||
3326 | m_host.AddScriptLPS(1); |
||
3327 | |||
3328 | UUID avatarId; |
||
3329 | |||
3330 | if (!UUID.TryParse(rawAvatarId, out avatarId)) |
||
3331 | return; |
||
3332 | |||
3333 | ForceAttachToAvatarFromInventory(avatarId, itemName, attachmentPoint); |
||
3334 | } |
||
3335 | |||
3336 | public void ForceAttachToAvatarFromInventory(UUID avatarId, string itemName, int attachmentPoint) |
||
3337 | { |
||
3338 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; |
||
3339 | |||
3340 | if (attachmentsModule == null) |
||
3341 | return; |
||
3342 | |||
3343 | InitLSL(); |
||
3344 | |||
3345 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); |
||
3346 | |||
3347 | if (item == null) |
||
3348 | { |
||
3349 | ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Could not find object '{0}'", itemName)); |
||
3350 | throw new Exception(String.Format("The inventory item '{0}' could not be found", itemName)); |
||
3351 | } |
||
3352 | |||
3353 | if (item.InvType != (int)InventoryType.Object) |
||
3354 | { |
||
3355 | // FIXME: Temporary null check for regression tests since they dont' have the infrastructure to set |
||
3356 | // up the api reference. |
||
3357 | if (m_LSL_Api != null) |
||
3358 | ((LSL_Api)m_LSL_Api).llSay(0, string.Format("Unable to attach, item '{0}' is not an object.", itemName)); |
||
3359 | |||
3360 | throw new Exception(String.Format("The inventory item '{0}' is not an object", itemName)); |
||
3361 | } |
||
3362 | |||
3363 | ScenePresence sp = World.GetScenePresence(avatarId); |
||
3364 | |||
3365 | if (sp == null) |
||
3366 | return; |
||
3367 | |||
3368 | InventoryItemBase newItem = World.MoveTaskInventoryItem(sp.UUID, UUID.Zero, m_host, item.ItemID); |
||
3369 | |||
3370 | if (newItem == null) |
||
3371 | { |
||
3372 | m_log.ErrorFormat( |
||
3373 | "[OSSL API]: Could not create user inventory item {0} for {1}, attach point {2} in {3}", |
||
3374 | itemName, m_host.Name, attachmentPoint, World.Name); |
||
3375 | |||
3376 | return; |
||
3377 | } |
||
3378 | |||
3379 | attachmentsModule.RezSingleAttachmentFromInventory(sp, newItem.ID, (uint)attachmentPoint); |
||
3380 | } |
||
3381 | |||
3382 | public void osForceDetachFromAvatar() |
||
3383 | { |
||
3384 | CheckThreatLevel(ThreatLevel.High, "osForceDetachFromAvatar"); |
||
3385 | |||
3386 | m_host.AddScriptLPS(1); |
||
3387 | |||
3388 | InitLSL(); |
||
3389 | ((LSL_Api)m_LSL_Api).DetachFromAvatar(); |
||
3390 | } |
||
3391 | |||
3392 | public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) |
||
3393 | { |
||
3394 | CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments"); |
||
3395 | |||
3396 | m_host.AddScriptLPS(1); |
||
3397 | |||
3398 | UUID targetUUID; |
||
3399 | ScenePresence target; |
||
3400 | LSL_List resp = new LSL_List(); |
||
3401 | |||
3402 | if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) |
||
3403 | { |
||
3404 | foreach (object point in attachmentPoints.Data) |
||
3405 | { |
||
3406 | LSL_Integer ipoint = new LSL_Integer( |
||
3407 | (point is LSL_Integer || point is int || point is uint) ? |
||
3408 | (int)point : |
||
3409 | |||
3410 | ); |
||
3411 | resp.Add(ipoint); |
||
3412 | if (ipoint == 0) |
||
3413 | { |
||
3414 | // indicates zero attachments |
||
3415 | resp.Add(new LSL_Integer(0)); |
||
3416 | } |
||
3417 | else |
||
3418 | { |
||
3419 | // gets the number of attachments on the attachment point |
||
3420 | resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count)); |
||
3421 | } |
||
3422 | } |
||
3423 | } |
||
3424 | |||
3425 | return resp; |
||
3426 | } |
||
3427 | |||
3428 | public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options) |
||
3429 | { |
||
3430 | CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments"); |
||
3431 | m_host.AddScriptLPS(1); |
||
3432 | |||
3433 | UUID targetUUID; |
||
3434 | ScenePresence target; |
||
3435 | |||
3436 | if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) |
||
3437 | { |
||
3438 | List<int> aps = new List<int>(); |
||
3439 | foreach (object point in attachmentPoints.Data) |
||
3440 | { |
||
3441 | int ipoint; |
||
3442 | if (int.TryParse(point.ToString(), out ipoint)) |
||
3443 | { |
||
3444 | aps.Add(ipoint); |
||
3445 | } |
||
3446 | } |
||
3447 | |||
3448 | List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(); |
||
3449 | |||
3450 | bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL); |
||
3451 | bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0; |
||
3452 | |||
3453 | if (msgAll && invertPoints) |
||
3454 | { |
||
3455 | return; |
||
3456 | } |
||
3457 | else if (msgAll || invertPoints) |
||
3458 | { |
||
3459 | attachments = target.GetAttachments(); |
||
3460 | } |
||
3461 | else |
||
3462 | { |
||
3463 | foreach (int point in aps) |
||
3464 | { |
||
3465 | if (point > 0) |
||
3466 | { |
||
3467 | attachments.AddRange(target.GetAttachments((uint)point)); |
||
3468 | } |
||
3469 | } |
||
3470 | } |
||
3471 | |||
3472 | // if we have no attachments at this point, exit now |
||
3473 | if (attachments.Count == 0) |
||
3474 | { |
||
3475 | return; |
||
3476 | } |
||
3477 | |||
3478 | List<SceneObjectGroup> ignoreThese = new List<SceneObjectGroup>(); |
||
3479 | |||
3480 | if (invertPoints) |
||
3481 | { |
||
3482 | foreach (SceneObjectGroup attachment in attachments) |
||
3483 | { |
||
3484 | if (aps.Contains((int)attachment.AttachmentPoint)) |
||
3485 | { |
||
3486 | ignoreThese.Add(attachment); |
||
3487 | } |
||
3488 | } |
||
3489 | } |
||
3490 | |||
3491 | foreach (SceneObjectGroup attachment in ignoreThese) |
||
3492 | { |
||
3493 | attachments.Remove(attachment); |
||
3494 | } |
||
3495 | ignoreThese.Clear(); |
||
3496 | |||
3497 | // if inverting removed all attachments to check, exit now |
||
3498 | if (attachments.Count < 1) |
||
3499 | { |
||
3500 | return; |
||
3501 | } |
||
3502 | |||
3503 | if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0) |
||
3504 | { |
||
3505 | foreach (SceneObjectGroup attachment in attachments) |
||
3506 | { |
||
3507 | if (attachment.RootPart.CreatorID != m_host.CreatorID) |
||
3508 | { |
||
3509 | ignoreThese.Add(attachment); |
||
3510 | } |
||
3511 | } |
||
3512 | |||
3513 | foreach (SceneObjectGroup attachment in ignoreThese) |
||
3514 | { |
||
3515 | attachments.Remove(attachment); |
||
3516 | } |
||
3517 | ignoreThese.Clear(); |
||
3518 | |||
3519 | // if filtering by same object creator removed all |
||
3520 | // attachments to check, exit now |
||
3521 | if (attachments.Count == 0) |
||
3522 | { |
||
3523 | return; |
||
3524 | } |
||
3525 | } |
||
3526 | |||
3527 | if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0) |
||
3528 | { |
||
3529 | foreach (SceneObjectGroup attachment in attachments) |
||
3530 | { |
||
3531 | if (attachment.RootPart.CreatorID != m_item.CreatorID) |
||
3532 | { |
||
3533 | ignoreThese.Add(attachment); |
||
3534 | } |
||
3535 | } |
||
3536 | |||
3537 | foreach (SceneObjectGroup attachment in ignoreThese) |
||
3538 | { |
||
3539 | attachments.Remove(attachment); |
||
3540 | } |
||
3541 | ignoreThese.Clear(); |
||
3542 | |||
3543 | // if filtering by object creator must match originating |
||
3544 | // script creator removed all attachments to check, |
||
3545 | // exit now |
||
3546 | if (attachments.Count == 0) |
||
3547 | { |
||
3548 | return; |
||
3549 | } |
||
3550 | } |
||
3551 | |||
3552 | foreach (SceneObjectGroup attachment in attachments) |
||
3553 | { |
||
3554 | MessageObject(attachment.RootPart.UUID, message); |
||
3555 | } |
||
3556 | } |
||
3557 | } |
||
3558 | |||
3559 | #endregion |
||
3560 | |||
3561 | /// <summary> |
||
3562 | /// Checks if thing is a UUID. |
||
3563 | /// </summary> |
||
3564 | /// <param name="thing"></param> |
||
3565 | /// <returns>1 if thing is a valid UUID, 0 otherwise</returns> |
||
3566 | public LSL_Integer osIsUUID(string thing) |
||
3567 | { |
||
3568 | CheckThreatLevel(ThreatLevel.None, "osIsUUID"); |
||
3569 | m_host.AddScriptLPS(1); |
||
3570 | |||
3571 | UUID test; |
||
3572 | return UUID.TryParse(thing, out test) ? 1 : 0; |
||
3573 | } |
||
3574 | |||
3575 | /// <summary> |
||
3576 | /// Wraps to Math.Min() |
||
3577 | /// </summary> |
||
3578 | /// <param name="a"></param> |
||
3579 | /// <param name="b"></param> |
||
3580 | /// <returns></returns> |
||
3581 | public LSL_Float osMin(double a, double b) |
||
3582 | { |
||
3583 | CheckThreatLevel(ThreatLevel.None, "osMin"); |
||
3584 | m_host.AddScriptLPS(1); |
||
3585 | |||
3586 | return Math.Min(a, b); |
||
3587 | } |
||
3588 | |||
3589 | /// <summary> |
||
3590 | /// Wraps to Math.max() |
||
3591 | /// </summary> |
||
3592 | /// <param name="a"></param> |
||
3593 | /// <param name="b"></param> |
||
3594 | /// <returns></returns> |
||
3595 | public LSL_Float osMax(double a, double b) |
||
3596 | { |
||
3597 | CheckThreatLevel(ThreatLevel.None, "osMax"); |
||
3598 | m_host.AddScriptLPS(1); |
||
3599 | |||
3600 | return Math.Max(a, b); |
||
3601 | } |
||
3602 | |||
3603 | public LSL_Key osGetRezzingObject() |
||
3604 | { |
||
3605 | CheckThreatLevel(ThreatLevel.None, "osGetRezzingObject"); |
||
3606 | m_host.AddScriptLPS(1); |
||
3607 | |||
3608 | return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); |
||
3609 | } |
||
3610 | |||
3611 | /// <summary> |
||
3612 | /// Sets the response type for an HTTP request/response |
||
3613 | /// </summary> |
||
3614 | /// <returns></returns> |
||
3615 | public void osSetContentType(LSL_Key id, string type) |
||
3616 | { |
||
3617 | CheckThreatLevel(ThreatLevel.High, "osSetContentType"); |
||
3618 | |||
3619 | if (m_UrlModule != null) |
||
3620 | m_UrlModule.HttpContentType(new UUID(id),type); |
||
3621 | } |
||
3622 | |||
3623 | /// Shout an error if the object owner did not grant the script the specified permissions. |
||
3624 | /// </summary> |
||
3625 | /// <param name="perms"></param> |
||
3626 | /// <returns>boolean indicating whether an error was shouted.</returns> |
||
3627 | protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) |
||
3628 | { |
||
3629 | m_host.AddScriptLPS(1); |
||
3630 | bool fail = false; |
||
3631 | if (m_item.PermsGranter != m_host.OwnerID) |
||
3632 | { |
||
3633 | fail = true; |
||
3634 | OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix)); |
||
3635 | } |
||
3636 | else if ((m_item.PermsMask & perms) == 0) |
||
3637 | { |
||
3638 | fail = true; |
||
3639 | OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix)); |
||
3640 | } |
||
3641 | |||
3642 | return fail; |
||
3643 | } |
||
3644 | |||
3645 | protected void DropAttachment(bool checkPerms) |
||
3646 | { |
||
3647 | if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) |
||
3648 | { |
||
3649 | return; |
||
3650 | } |
||
3651 | |||
3652 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; |
||
3653 | ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); |
||
3654 | |||
3655 | if (attachmentsModule != null && sp != null) |
||
3656 | { |
||
3657 | attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId); |
||
3658 | } |
||
3659 | } |
||
3660 | |||
3661 | protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) |
||
3662 | { |
||
3663 | if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) |
||
3664 | { |
||
3665 | return; |
||
3666 | } |
||
3667 | |||
3668 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; |
||
3669 | ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); |
||
3670 | |||
3671 | if (attachmentsModule != null && sp != null) |
||
3672 | { |
||
3673 | attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot); |
||
3674 | } |
||
3675 | } |
||
3676 | |||
3677 | public void osDropAttachment() |
||
3678 | { |
||
3679 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); |
||
3680 | m_host.AddScriptLPS(1); |
||
3681 | |||
3682 | DropAttachment(true); |
||
3683 | } |
||
3684 | |||
3685 | public void osForceDropAttachment() |
||
3686 | { |
||
3687 | CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment"); |
||
3688 | m_host.AddScriptLPS(1); |
||
3689 | |||
3690 | DropAttachment(false); |
||
3691 | } |
||
3692 | |||
3693 | public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) |
||
3694 | { |
||
3695 | CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); |
||
3696 | m_host.AddScriptLPS(1); |
||
3697 | |||
3698 | DropAttachmentAt(true, pos, rot); |
||
3699 | } |
||
3700 | |||
3701 | public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) |
||
3702 | { |
||
3703 | CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); |
||
3704 | m_host.AddScriptLPS(1); |
||
3705 | |||
3706 | DropAttachmentAt(false, pos, rot); |
||
3707 | } |
||
3708 | |||
3709 | public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) |
||
3710 | { |
||
3711 | CheckThreatLevel(ThreatLevel.Low, "osListenRegex"); |
||
3712 | m_host.AddScriptLPS(1); |
||
3713 | UUID keyID; |
||
3714 | UUID.TryParse(ID, out keyID); |
||
3715 | |||
3716 | // if we want the name to be used as a regular expression, ensure it is valid first. |
||
3717 | if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME) |
||
3718 | { |
||
3719 | try |
||
3720 | { |
||
3721 | Regex.IsMatch("", name); |
||
3722 | } |
||
3723 | catch (Exception) |
||
3724 | { |
||
3725 | OSSLShoutError("Name regex is invalid."); |
||
3726 | return -1; |
||
3727 | } |
||
3728 | } |
||
3729 | |||
3730 | // if we want the msg to be used as a regular expression, ensure it is valid first. |
||
3731 | if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) |
||
3732 | { |
||
3733 | try |
||
3734 | { |
||
3735 | Regex.IsMatch("", msg); |
||
3736 | } |
||
3737 | catch (Exception) |
||
3738 | { |
||
3739 | OSSLShoutError("Message regex is invalid."); |
||
3740 | return -1; |
||
3741 | } |
||
3742 | } |
||
3743 | |||
3744 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
||
3745 | return (wComm == null) ? -1 : wComm.Listen( |
||
3746 | m_host.LocalId, |
||
3747 | m_item.ItemID, |
||
3748 | m_host.UUID, |
||
3749 | channelID, |
||
3750 | name, |
||
3751 | keyID, |
||
3752 | msg, |
||
3753 | regexBitfield |
||
3754 | ); |
||
3755 | } |
||
3756 | |||
3757 | public LSL_Integer osRegexIsMatch(string input, string pattern) |
||
3758 | { |
||
3759 | CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch"); |
||
3760 | m_host.AddScriptLPS(1); |
||
3761 | try |
||
3762 | { |
||
3763 | return Regex.IsMatch(input, pattern) ? 1 : 0; |
||
3764 | } |
||
3765 | catch (Exception) |
||
3766 | { |
||
3767 | OSSLShoutError("Possible invalid regular expression detected."); |
||
3768 | return 0; |
||
3769 | } |
||
3770 | } |
||
3771 | } |
||
3772 | } |