aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs30556
1 files changed, 15278 insertions, 15278 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index afc4393..b4a8620 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -1,15278 +1,15278 @@
1/* 1/*
2 * Copyright (c) Contributors, http://opensimulator.org/ 2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders. 3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 * 4 *
5 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met: 6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright 7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer. 8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright 9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the 10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution. 11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the 12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products 13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission. 14 * derived from this software without specific prior written permission.
15 * 15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY 16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY 19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 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 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 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 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. 25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections; 29using System.Collections;
30using System.Collections.Generic; 30using System.Collections.Generic;
31using System.Diagnostics; 31using System.Diagnostics;
32using System.Drawing; 32using System.Drawing;
33using System.Drawing.Imaging; 33using System.Drawing.Imaging;
34using System.Runtime.Remoting.Lifetime; 34using System.Runtime.Remoting.Lifetime;
35using System.Text; 35using System.Text;
36using System.Threading; 36using System.Threading;
37using System.Text.RegularExpressions; 37using System.Text.RegularExpressions;
38using Nini.Config; 38using Nini.Config;
39using log4net; 39using log4net;
40using OpenMetaverse; 40using OpenMetaverse;
41using OpenMetaverse.Assets; 41using OpenMetaverse.Assets;
42using OpenMetaverse.Packets; 42using OpenMetaverse.Packets;
43using OpenMetaverse.Rendering; 43using OpenMetaverse.Rendering;
44using OpenSim; 44using OpenSim;
45using OpenSim.Framework; 45using OpenSim.Framework;
46 46
47using OpenSim.Region.CoreModules; 47using OpenSim.Region.CoreModules;
48using OpenSim.Region.CoreModules.World.Land; 48using OpenSim.Region.CoreModules.World.Land;
49using OpenSim.Region.CoreModules.World.Terrain; 49using OpenSim.Region.CoreModules.World.Terrain;
50using OpenSim.Region.Framework.Interfaces; 50using OpenSim.Region.Framework.Interfaces;
51using OpenSim.Region.Framework.Scenes; 51using OpenSim.Region.Framework.Scenes;
52using OpenSim.Region.Framework.Scenes.Animation; 52using OpenSim.Region.Framework.Scenes.Animation;
53using OpenSim.Region.Framework.Scenes.Scripting; 53using OpenSim.Region.Framework.Scenes.Scripting;
54using OpenSim.Region.Physics.Manager; 54using OpenSim.Region.Physics.Manager;
55using OpenSim.Region.ScriptEngine.Shared; 55using OpenSim.Region.ScriptEngine.Shared;
56using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; 56using OpenSim.Region.ScriptEngine.Shared.Api.Plugins;
57using OpenSim.Region.ScriptEngine.Shared.ScriptBase; 57using OpenSim.Region.ScriptEngine.Shared.ScriptBase;
58using OpenSim.Region.ScriptEngine.Interfaces; 58using OpenSim.Region.ScriptEngine.Interfaces;
59using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; 59using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces;
60using OpenSim.Services.Interfaces; 60using OpenSim.Services.Interfaces;
61using GridRegion = OpenSim.Services.Interfaces.GridRegion; 61using GridRegion = OpenSim.Services.Interfaces.GridRegion;
62using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; 62using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo;
63using PrimType = OpenSim.Region.Framework.Scenes.PrimType; 63using PrimType = OpenSim.Region.Framework.Scenes.PrimType;
64using AssetLandmark = OpenSim.Framework.AssetLandmark; 64using AssetLandmark = OpenSim.Framework.AssetLandmark;
65using RegionFlags = OpenSim.Framework.RegionFlags; 65using RegionFlags = OpenSim.Framework.RegionFlags;
66 66
67using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; 67using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat;
68using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; 68using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger;
69using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 69using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
70using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; 70using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list;
71using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; 71using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion;
72using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; 72using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
73using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; 73using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3;
74using System.Reflection; 74using System.Reflection;
75using System.Linq; 75using System.Linq;
76using PermissionMask = OpenSim.Framework.PermissionMask; 76using PermissionMask = OpenSim.Framework.PermissionMask;
77 77
78namespace OpenSim.Region.ScriptEngine.Shared.Api 78namespace OpenSim.Region.ScriptEngine.Shared.Api
79{ 79{
80 // MUST be a ref type 80 // MUST be a ref type
81 public class UserInfoCacheEntry 81 public class UserInfoCacheEntry
82 { 82 {
83 public int time; 83 public int time;
84 public UserAccount account; 84 public UserAccount account;
85 public PresenceInfo pinfo; 85 public PresenceInfo pinfo;
86 } 86 }
87 87
88 /// <summary> 88 /// <summary>
89 /// Contains all LSL ll-functions. This class will be in Default AppDomain. 89 /// Contains all LSL ll-functions. This class will be in Default AppDomain.
90 /// </summary> 90 /// </summary>
91 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi 91 public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi
92 { 92 {
93 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 93 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
94 94
95 public int LlRequestAgentDataCacheTimeoutMs { get; set; } 95 public int LlRequestAgentDataCacheTimeoutMs { get; set; }
96 96
97 protected IScriptEngine m_ScriptEngine; 97 protected IScriptEngine m_ScriptEngine;
98 protected SceneObjectPart m_host; 98 protected SceneObjectPart m_host;
99 99
100 /// <summary> 100 /// <summary>
101 /// Used for script sleeps when we are using co-operative script termination. 101 /// Used for script sleeps when we are using co-operative script termination.
102 /// </summary> 102 /// </summary>
103 /// <remarks>null if co-operative script termination is not active</remarks> 103 /// <remarks>null if co-operative script termination is not active</remarks>
104 WaitHandle m_coopSleepHandle; 104 WaitHandle m_coopSleepHandle;
105 105
106 /// <summary> 106 /// <summary>
107 /// The timer used by the ScriptInstance to measure how long the script has executed. 107 /// The timer used by the ScriptInstance to measure how long the script has executed.
108 /// </summary> 108 /// </summary>
109 private Stopwatch m_executionTimer; 109 private Stopwatch m_executionTimer;
110 110
111 /// <summary> 111 /// <summary>
112 /// The item that hosts this script 112 /// The item that hosts this script
113 /// </summary> 113 /// </summary>
114 protected TaskInventoryItem m_item; 114 protected TaskInventoryItem m_item;
115 115
116 protected bool throwErrorOnNotImplemented = false; 116 protected bool throwErrorOnNotImplemented = false;
117 protected AsyncCommandManager AsyncCommands = null; 117 protected AsyncCommandManager AsyncCommands = null;
118 protected float m_ScriptDelayFactor = 1.0f; 118 protected float m_ScriptDelayFactor = 1.0f;
119 protected float m_ScriptDistanceFactor = 1.0f; 119 protected float m_ScriptDistanceFactor = 1.0f;
120 protected float m_MinTimerInterval = 0.5f; 120 protected float m_MinTimerInterval = 0.5f;
121 protected float m_recoilScaleFactor = 0.0f; 121 protected float m_recoilScaleFactor = 0.0f;
122 122
123 protected DateTime m_timer = DateTime.Now; 123 protected DateTime m_timer = DateTime.Now;
124 protected bool m_waitingForScriptAnswer = false; 124 protected bool m_waitingForScriptAnswer = false;
125 protected bool m_automaticLinkPermission = false; 125 protected bool m_automaticLinkPermission = false;
126 protected IMessageTransferModule m_TransferModule = null; 126 protected IMessageTransferModule m_TransferModule = null;
127 protected int m_notecardLineReadCharsMax = 255; 127 protected int m_notecardLineReadCharsMax = 255;
128 protected int m_scriptConsoleChannel = 0; 128 protected int m_scriptConsoleChannel = 0;
129 protected bool m_scriptConsoleChannelEnabled = false; 129 protected bool m_scriptConsoleChannelEnabled = false;
130 protected IUrlModule m_UrlModule = null; 130 protected IUrlModule m_UrlModule = null;
131 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); 131 protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>();
132 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. 132 protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp.
133 protected int m_sleepMsOnSetTexture = 200; 133 protected int m_sleepMsOnSetTexture = 200;
134 protected int m_sleepMsOnSetLinkTexture = 200; 134 protected int m_sleepMsOnSetLinkTexture = 200;
135 protected int m_sleepMsOnScaleTexture = 200; 135 protected int m_sleepMsOnScaleTexture = 200;
136 protected int m_sleepMsOnOffsetTexture = 200; 136 protected int m_sleepMsOnOffsetTexture = 200;
137 protected int m_sleepMsOnRotateTexture = 200; 137 protected int m_sleepMsOnRotateTexture = 200;
138 protected int m_sleepMsOnSetPos = 200; 138 protected int m_sleepMsOnSetPos = 200;
139 protected int m_sleepMsOnSetRot = 200; 139 protected int m_sleepMsOnSetRot = 200;
140 protected int m_sleepMsOnSetLocalRot = 200; 140 protected int m_sleepMsOnSetLocalRot = 200;
141 protected int m_sleepMsOnPreloadSound = 1000; 141 protected int m_sleepMsOnPreloadSound = 1000;
142 protected int m_sleepMsOnMakeExplosion = 100; 142 protected int m_sleepMsOnMakeExplosion = 100;
143 protected int m_sleepMsOnMakeFountain = 100; 143 protected int m_sleepMsOnMakeFountain = 100;
144 protected int m_sleepMsOnMakeSmoke = 100; 144 protected int m_sleepMsOnMakeSmoke = 100;
145 protected int m_sleepMsOnMakeFire = 100; 145 protected int m_sleepMsOnMakeFire = 100;
146 protected int m_sleepMsOnRezAtRoot = 100; 146 protected int m_sleepMsOnRezAtRoot = 100;
147 protected int m_sleepMsOnInstantMessage = 2000; 147 protected int m_sleepMsOnInstantMessage = 2000;
148 protected int m_sleepMsOnEmail = 20000; 148 protected int m_sleepMsOnEmail = 20000;
149 protected int m_sleepMsOnCreateLink = 1000; 149 protected int m_sleepMsOnCreateLink = 1000;
150 protected int m_sleepMsOnGiveInventory = 3000; 150 protected int m_sleepMsOnGiveInventory = 3000;
151 protected int m_sleepMsOnRequestAgentData = 100; 151 protected int m_sleepMsOnRequestAgentData = 100;
152 protected int m_sleepMsOnRequestInventoryData = 1000; 152 protected int m_sleepMsOnRequestInventoryData = 1000;
153 protected int m_sleepMsOnSetDamage = 5000; 153 protected int m_sleepMsOnSetDamage = 5000;
154 protected int m_sleepMsOnTextBox = 1000; 154 protected int m_sleepMsOnTextBox = 1000;
155 protected int m_sleepMsOnAdjustSoundVolume = 100; 155 protected int m_sleepMsOnAdjustSoundVolume = 100;
156 protected int m_sleepMsOnEjectFromLand = 5000; 156 protected int m_sleepMsOnEjectFromLand = 5000;
157 protected int m_sleepMsOnAddToLandPassList = 100; 157 protected int m_sleepMsOnAddToLandPassList = 100;
158 protected int m_sleepMsOnDialog = 1000; 158 protected int m_sleepMsOnDialog = 1000;
159 protected int m_sleepMsOnRemoteLoadScript = 3000; 159 protected int m_sleepMsOnRemoteLoadScript = 3000;
160 protected int m_sleepMsOnRemoteLoadScriptPin = 3000; 160 protected int m_sleepMsOnRemoteLoadScriptPin = 3000;
161 protected int m_sleepMsOnOpenRemoteDataChannel = 1000; 161 protected int m_sleepMsOnOpenRemoteDataChannel = 1000;
162 protected int m_sleepMsOnSendRemoteData = 3000; 162 protected int m_sleepMsOnSendRemoteData = 3000;
163 protected int m_sleepMsOnRemoteDataReply = 3000; 163 protected int m_sleepMsOnRemoteDataReply = 3000;
164 protected int m_sleepMsOnCloseRemoteDataChannel = 1000; 164 protected int m_sleepMsOnCloseRemoteDataChannel = 1000;
165 protected int m_sleepMsOnSetPrimitiveParams = 200; 165 protected int m_sleepMsOnSetPrimitiveParams = 200;
166 protected int m_sleepMsOnSetLinkPrimitiveParams = 200; 166 protected int m_sleepMsOnSetLinkPrimitiveParams = 200;
167 protected int m_sleepMsOnXorBase64Strings = 300; 167 protected int m_sleepMsOnXorBase64Strings = 300;
168 protected int m_sleepMsOnSetParcelMusicURL = 2000; 168 protected int m_sleepMsOnSetParcelMusicURL = 2000;
169 protected int m_sleepMsOnGetPrimMediaParams = 1000; 169 protected int m_sleepMsOnGetPrimMediaParams = 1000;
170 protected int m_sleepMsOnGetLinkMedia = 1000; 170 protected int m_sleepMsOnGetLinkMedia = 1000;
171 protected int m_sleepMsOnSetPrimMediaParams = 1000; 171 protected int m_sleepMsOnSetPrimMediaParams = 1000;
172 protected int m_sleepMsOnSetLinkMedia = 1000; 172 protected int m_sleepMsOnSetLinkMedia = 1000;
173 protected int m_sleepMsOnClearPrimMedia = 1000; 173 protected int m_sleepMsOnClearPrimMedia = 1000;
174 protected int m_sleepMsOnClearLinkMedia = 1000; 174 protected int m_sleepMsOnClearLinkMedia = 1000;
175 protected int m_sleepMsOnRequestSimulatorData = 1000; 175 protected int m_sleepMsOnRequestSimulatorData = 1000;
176 protected int m_sleepMsOnLoadURL = 10000; 176 protected int m_sleepMsOnLoadURL = 10000;
177 protected int m_sleepMsOnParcelMediaCommandList = 2000; 177 protected int m_sleepMsOnParcelMediaCommandList = 2000;
178 protected int m_sleepMsOnParcelMediaQuery = 2000; 178 protected int m_sleepMsOnParcelMediaQuery = 2000;
179 protected int m_sleepMsOnModPow = 1000; 179 protected int m_sleepMsOnModPow = 1000;
180 protected int m_sleepMsOnSetPrimURL = 2000; 180 protected int m_sleepMsOnSetPrimURL = 2000;
181 protected int m_sleepMsOnRefreshPrimURL = 20000; 181 protected int m_sleepMsOnRefreshPrimURL = 20000;
182 protected int m_sleepMsOnMapDestination = 1000; 182 protected int m_sleepMsOnMapDestination = 1000;
183 protected int m_sleepMsOnAddToLandBanList = 100; 183 protected int m_sleepMsOnAddToLandBanList = 100;
184 protected int m_sleepMsOnRemoveFromLandPassList = 100; 184 protected int m_sleepMsOnRemoveFromLandPassList = 100;
185 protected int m_sleepMsOnRemoveFromLandBanList = 100; 185 protected int m_sleepMsOnRemoveFromLandBanList = 100;
186 protected int m_sleepMsOnResetLandBanList = 100; 186 protected int m_sleepMsOnResetLandBanList = 100;
187 protected int m_sleepMsOnResetLandPassList = 100; 187 protected int m_sleepMsOnResetLandPassList = 100;
188 protected int m_sleepMsOnGetParcelPrimOwners = 2000; 188 protected int m_sleepMsOnGetParcelPrimOwners = 2000;
189 protected int m_sleepMsOnGetNumberOfNotecardLines = 100; 189 protected int m_sleepMsOnGetNumberOfNotecardLines = 100;
190 protected int m_sleepMsOnGetNotecardLine = 100; 190 protected int m_sleepMsOnGetNotecardLine = 100;
191 protected string m_internalObjectHost = "lsl.opensim.local"; 191 protected string m_internalObjectHost = "lsl.opensim.local";
192 protected bool m_restrictEmail = false; 192 protected bool m_restrictEmail = false;
193 protected ISoundModule m_SoundModule = null; 193 protected ISoundModule m_SoundModule = null;
194 194
195 protected float m_avatarHeightCorrection = 0.2f; 195 protected float m_avatarHeightCorrection = 0.2f;
196 protected bool m_useSimpleBoxesInGetBoundingBox = false; 196 protected bool m_useSimpleBoxesInGetBoundingBox = false;
197 protected bool m_addStatsInGetBoundingBox = false; 197 protected bool m_addStatsInGetBoundingBox = false;
198 198
199 //LSL Avatar Bounding Box (lABB), lower (1) and upper (2), 199 //LSL Avatar Bounding Box (lABB), lower (1) and upper (2),
200 //standing (Std), Groundsitting (Grs), Sitting (Sit), 200 //standing (Std), Groundsitting (Grs), Sitting (Sit),
201 //along X, Y and Z axes, constants (0) and coefficients (1) 201 //along X, Y and Z axes, constants (0) and coefficients (1)
202 protected float m_lABB1StdX0 = -0.275f; 202 protected float m_lABB1StdX0 = -0.275f;
203 protected float m_lABB2StdX0 = 0.275f; 203 protected float m_lABB2StdX0 = 0.275f;
204 protected float m_lABB1StdY0 = -0.35f; 204 protected float m_lABB1StdY0 = -0.35f;
205 protected float m_lABB2StdY0 = 0.35f; 205 protected float m_lABB2StdY0 = 0.35f;
206 protected float m_lABB1StdZ0 = -0.1f; 206 protected float m_lABB1StdZ0 = -0.1f;
207 protected float m_lABB1StdZ1 = -0.5f; 207 protected float m_lABB1StdZ1 = -0.5f;
208 protected float m_lABB2StdZ0 = 0.1f; 208 protected float m_lABB2StdZ0 = 0.1f;
209 protected float m_lABB2StdZ1 = 0.5f; 209 protected float m_lABB2StdZ1 = 0.5f;
210 protected float m_lABB1GrsX0 = -0.3875f; 210 protected float m_lABB1GrsX0 = -0.3875f;
211 protected float m_lABB2GrsX0 = 0.3875f; 211 protected float m_lABB2GrsX0 = 0.3875f;
212 protected float m_lABB1GrsY0 = -0.5f; 212 protected float m_lABB1GrsY0 = -0.5f;
213 protected float m_lABB2GrsY0 = 0.5f; 213 protected float m_lABB2GrsY0 = 0.5f;
214 protected float m_lABB1GrsZ0 = -0.05f; 214 protected float m_lABB1GrsZ0 = -0.05f;
215 protected float m_lABB1GrsZ1 = -0.375f; 215 protected float m_lABB1GrsZ1 = -0.375f;
216 protected float m_lABB2GrsZ0 = 0.5f; 216 protected float m_lABB2GrsZ0 = 0.5f;
217 protected float m_lABB2GrsZ1 = 0.0f; 217 protected float m_lABB2GrsZ1 = 0.0f;
218 protected float m_lABB1SitX0 = -0.5875f; 218 protected float m_lABB1SitX0 = -0.5875f;
219 protected float m_lABB2SitX0 = 0.1875f; 219 protected float m_lABB2SitX0 = 0.1875f;
220 protected float m_lABB1SitY0 = -0.35f; 220 protected float m_lABB1SitY0 = -0.35f;
221 protected float m_lABB2SitY0 = 0.35f; 221 protected float m_lABB2SitY0 = 0.35f;
222 protected float m_lABB1SitZ0 = -0.35f; 222 protected float m_lABB1SitZ0 = -0.35f;
223 protected float m_lABB1SitZ1 = -0.375f; 223 protected float m_lABB1SitZ1 = -0.375f;
224 protected float m_lABB2SitZ0 = -0.25f; 224 protected float m_lABB2SitZ0 = -0.25f;
225 protected float m_lABB2SitZ1 = 0.25f; 225 protected float m_lABB2SitZ1 = 0.25f;
226 226
227 protected float m_primSafetyCoeffX = 2.414214f; 227 protected float m_primSafetyCoeffX = 2.414214f;
228 protected float m_primSafetyCoeffY = 2.414214f; 228 protected float m_primSafetyCoeffY = 2.414214f;
229 protected float m_primSafetyCoeffZ = 1.618034f; 229 protected float m_primSafetyCoeffZ = 1.618034f;
230 protected bool m_useCastRayV3 = false; 230 protected bool m_useCastRayV3 = false;
231 protected float m_floatToleranceInCastRay = 0.00001f; 231 protected float m_floatToleranceInCastRay = 0.00001f;
232 protected float m_floatTolerance2InCastRay = 0.001f; 232 protected float m_floatTolerance2InCastRay = 0.001f;
233 protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; 233 protected DetailLevel m_primLodInCastRay = DetailLevel.Medium;
234 protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; 234 protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium;
235 protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; 235 protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest;
236 protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium; 236 protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium;
237 protected int m_maxHitsInCastRay = 16; 237 protected int m_maxHitsInCastRay = 16;
238 protected int m_maxHitsPerPrimInCastRay = 16; 238 protected int m_maxHitsPerPrimInCastRay = 16;
239 protected int m_maxHitsPerObjectInCastRay = 16; 239 protected int m_maxHitsPerObjectInCastRay = 16;
240 protected bool m_detectExitsInCastRay = false; 240 protected bool m_detectExitsInCastRay = false;
241 protected bool m_filterPartsInCastRay = false; 241 protected bool m_filterPartsInCastRay = false;
242 protected bool m_doAttachmentsInCastRay = false; 242 protected bool m_doAttachmentsInCastRay = false;
243 protected int m_msThrottleInCastRay = 200; 243 protected int m_msThrottleInCastRay = 200;
244 protected int m_msPerRegionInCastRay = 40; 244 protected int m_msPerRegionInCastRay = 40;
245 protected int m_msPerAvatarInCastRay = 10; 245 protected int m_msPerAvatarInCastRay = 10;
246 protected int m_msMinInCastRay = 2; 246 protected int m_msMinInCastRay = 2;
247 protected int m_msMaxInCastRay = 40; 247 protected int m_msMaxInCastRay = 40;
248 protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>(); 248 protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>();
249 protected bool m_useMeshCacheInCastRay = true; 249 protected bool m_useMeshCacheInCastRay = true;
250 protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); 250 protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>();
251 251
252 //An array of HTTP/1.1 headers that are not allowed to be used 252 //An array of HTTP/1.1 headers that are not allowed to be used
253 //as custom headers by llHTTPRequest. 253 //as custom headers by llHTTPRequest.
254 private string[] HttpStandardHeaders = 254 private string[] HttpStandardHeaders =
255 { 255 {
256 "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", 256 "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language",
257 "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control", 257 "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control",
258 "Connection", "Content-Encoding", "Content-Language", 258 "Connection", "Content-Encoding", "Content-Language",
259 "Content-Length", "Content-Location", "Content-MD5", 259 "Content-Length", "Content-Location", "Content-MD5",
260 "Content-Range", "Content-Type", "Date", "ETag", "Expect", 260 "Content-Range", "Content-Type", "Date", "ETag", "Expect",
261 "Expires", "From", "Host", "If-Match", "If-Modified-Since", 261 "Expires", "From", "Host", "If-Match", "If-Modified-Since",
262 "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", 262 "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified",
263 "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate", 263 "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate",
264 "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server", 264 "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server",
265 "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent", 265 "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent",
266 "Vary", "Via", "Warning", "WWW-Authenticate" 266 "Vary", "Via", "Warning", "WWW-Authenticate"
267 }; 267 };
268 268
269 public void Initialize( 269 public void Initialize(
270 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle, 270 IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle,
271 Stopwatch executionTimer) 271 Stopwatch executionTimer)
272 { 272 {
273 m_ScriptEngine = scriptEngine; 273 m_ScriptEngine = scriptEngine;
274 m_host = host; 274 m_host = host;
275 m_item = item; 275 m_item = item;
276 m_coopSleepHandle = coopSleepHandle; 276 m_coopSleepHandle = coopSleepHandle;
277 m_executionTimer = executionTimer; 277 m_executionTimer = executionTimer;
278 278
279 LoadConfig(); 279 LoadConfig();
280 280
281 m_TransferModule = 281 m_TransferModule =
282 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); 282 m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>();
283 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); 283 m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>();
284 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); 284 m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>();
285 285
286 AsyncCommands = new AsyncCommandManager(m_ScriptEngine); 286 AsyncCommands = new AsyncCommandManager(m_ScriptEngine);
287 } 287 }
288 288
289 /// <summary> 289 /// <summary>
290 /// Load configuration items that affect script, object and run-time behavior. */ 290 /// Load configuration items that affect script, object and run-time behavior. */
291 /// </summary> 291 /// </summary>
292 private void LoadConfig() 292 private void LoadConfig()
293 { 293 {
294 LlRequestAgentDataCacheTimeoutMs = 20000; 294 LlRequestAgentDataCacheTimeoutMs = 20000;
295 295
296 IConfig seConfig = m_ScriptEngine.Config; 296 IConfig seConfig = m_ScriptEngine.Config;
297 297
298 if (seConfig != null) 298 if (seConfig != null)
299 { 299 {
300 m_ScriptDelayFactor = 300 m_ScriptDelayFactor =
301 seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor); 301 seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor);
302 m_ScriptDistanceFactor = 302 m_ScriptDistanceFactor =
303 seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor); 303 seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor);
304 m_MinTimerInterval = 304 m_MinTimerInterval =
305 seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval); 305 seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval);
306 m_automaticLinkPermission = 306 m_automaticLinkPermission =
307 seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission); 307 seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission);
308 m_notecardLineReadCharsMax = 308 m_notecardLineReadCharsMax =
309 seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax); 309 seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax);
310 310
311 // Rezzing an object with a velocity can create recoil. This feature seems to have been 311 // Rezzing an object with a velocity can create recoil. This feature seems to have been
312 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales 312 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
313 // it by this factor. May be zero to turn off recoil all together. 313 // it by this factor. May be zero to turn off recoil all together.
314 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor); 314 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
315 } 315 }
316 316
317 if (m_notecardLineReadCharsMax > 65535) 317 if (m_notecardLineReadCharsMax > 65535)
318 m_notecardLineReadCharsMax = 65535; 318 m_notecardLineReadCharsMax = 65535;
319 319
320 // load limits for particular subsystems. 320 // load limits for particular subsystems.
321 IConfigSource seConfigSource = m_ScriptEngine.ConfigSource; 321 IConfigSource seConfigSource = m_ScriptEngine.ConfigSource;
322 322
323 if (seConfigSource != null) 323 if (seConfigSource != null)
324 { 324 {
325 IConfig lslConfig = seConfigSource.Configs["LL-Functions"]; 325 IConfig lslConfig = seConfigSource.Configs["LL-Functions"];
326 if (lslConfig != null) 326 if (lslConfig != null)
327 { 327 {
328 m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); 328 m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail);
329 m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection); 329 m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection);
330 m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox); 330 m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox);
331 m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox); 331 m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox);
332 m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0); 332 m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0);
333 m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0); 333 m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0);
334 m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0); 334 m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0);
335 m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0); 335 m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0);
336 m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0); 336 m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0);
337 m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1); 337 m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1);
338 m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0); 338 m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0);
339 m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1); 339 m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1);
340 m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0); 340 m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0);
341 m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0); 341 m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0);
342 m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0); 342 m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0);
343 m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0); 343 m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0);
344 m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0); 344 m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0);
345 m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1); 345 m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1);
346 m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0); 346 m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0);
347 m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1); 347 m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1);
348 m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0); 348 m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0);
349 m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0); 349 m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0);
350 m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0); 350 m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0);
351 m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0); 351 m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0);
352 m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0); 352 m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0);
353 m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1); 353 m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1);
354 m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0); 354 m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0);
355 m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1); 355 m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1);
356 m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); 356 m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX);
357 m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); 357 m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY);
358 m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); 358 m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ);
359 m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3); 359 m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3);
360 m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); 360 m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay);
361 m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); 361 m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay);
362 m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay); 362 m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay);
363 m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay); 363 m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay);
364 m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay); 364 m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay);
365 m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay); 365 m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay);
366 m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); 366 m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay);
367 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); 367 m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay);
368 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); 368 m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay);
369 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); 369 m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay);
370 m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); 370 m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay);
371 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); 371 m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay);
372 m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay); 372 m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay);
373 m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay); 373 m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay);
374 m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay); 374 m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay);
375 m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay); 375 m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay);
376 m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay); 376 m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay);
377 m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay); 377 m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay);
378 } 378 }
379 379
380 IConfig smtpConfig = seConfigSource.Configs["SMTP"]; 380 IConfig smtpConfig = seConfigSource.Configs["SMTP"];
381 if (smtpConfig != null) 381 if (smtpConfig != null)
382 { 382 {
383 // there's an smtp config, so load in the snooze time. 383 // there's an smtp config, so load in the snooze time.
384 EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); 384 EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
385 385
386 m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost); 386 m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost);
387 } 387 }
388 } 388 }
389 m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000; 389 m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000;
390 } 390 }
391 391
392 public override Object InitializeLifetimeService() 392 public override Object InitializeLifetimeService()
393 { 393 {
394 ILease lease = (ILease)base.InitializeLifetimeService(); 394 ILease lease = (ILease)base.InitializeLifetimeService();
395 395
396 if (lease.CurrentState == LeaseState.Initial) 396 if (lease.CurrentState == LeaseState.Initial)
397 { 397 {
398 lease.InitialLeaseTime = TimeSpan.FromMinutes(0); 398 lease.InitialLeaseTime = TimeSpan.FromMinutes(0);
399// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); 399// lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0);
400// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); 400// lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0);
401 } 401 }
402 return lease; 402 return lease;
403 } 403 }
404 404
405 protected virtual void ScriptSleep(int delay) 405 protected virtual void ScriptSleep(int delay)
406 { 406 {
407 delay = (int)((float)delay * m_ScriptDelayFactor); 407 delay = (int)((float)delay * m_ScriptDelayFactor);
408 if (delay == 0) 408 if (delay == 0)
409 return; 409 return;
410 410
411 Sleep(delay); 411 Sleep(delay);
412 } 412 }
413 413
414 protected virtual void Sleep(int delay) 414 protected virtual void Sleep(int delay)
415 { 415 {
416 if (m_executionTimer != null) 416 if (m_executionTimer != null)
417 m_executionTimer.Stop(); // sleep time doesn't count as execution time, since it doesn't use the CPU 417 m_executionTimer.Stop(); // sleep time doesn't count as execution time, since it doesn't use the CPU
418 418
419 try 419 try
420 { 420 {
421 if (m_coopSleepHandle == null) 421 if (m_coopSleepHandle == null)
422 System.Threading.Thread.Sleep(delay); 422 System.Threading.Thread.Sleep(delay);
423 else 423 else
424 CheckForCoopTermination(delay); 424 CheckForCoopTermination(delay);
425 } 425 }
426 finally 426 finally
427 { 427 {
428 if (m_executionTimer != null) 428 if (m_executionTimer != null)
429 m_executionTimer.Start(); 429 m_executionTimer.Start();
430 } 430 }
431 } 431 }
432 432
433 /// <summary> 433 /// <summary>
434 /// Check for co-operative termination. 434 /// Check for co-operative termination.
435 /// </summary> 435 /// </summary>
436 /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param> 436 /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param>
437 protected virtual void CheckForCoopTermination(int delay) 437 protected virtual void CheckForCoopTermination(int delay)
438 { 438 {
439 if (m_coopSleepHandle.WaitOne(delay)) 439 if (m_coopSleepHandle.WaitOne(delay))
440 throw new ScriptCoopStopException(); 440 throw new ScriptCoopStopException();
441 } 441 }
442 442
443 public Scene World 443 public Scene World
444 { 444 {
445 get { return m_ScriptEngine.World; } 445 get { return m_ScriptEngine.World; }
446 } 446 }
447 447
448 public void state(string newState) 448 public void state(string newState)
449 { 449 {
450 m_ScriptEngine.SetState(m_item.ItemID, newState); 450 m_ScriptEngine.SetState(m_item.ItemID, newState);
451 } 451 }
452 452
453 /// <summary> 453 /// <summary>
454 /// Reset the named script. The script must be present 454 /// Reset the named script. The script must be present
455 /// in the same prim. 455 /// in the same prim.
456 /// </summary> 456 /// </summary>
457 public void llResetScript() 457 public void llResetScript()
458 { 458 {
459 m_host.AddScriptLPS(1); 459 m_host.AddScriptLPS(1);
460 460
461 // We need to tell the URL module, if we hav one, to release 461 // We need to tell the URL module, if we hav one, to release
462 // the allocated URLs 462 // the allocated URLs
463 if (m_UrlModule != null) 463 if (m_UrlModule != null)
464 m_UrlModule.ScriptRemoved(m_item.ItemID); 464 m_UrlModule.ScriptRemoved(m_item.ItemID);
465 465
466 m_ScriptEngine.ApiResetScript(m_item.ItemID); 466 m_ScriptEngine.ApiResetScript(m_item.ItemID);
467 } 467 }
468 468
469 public void llResetOtherScript(string name) 469 public void llResetOtherScript(string name)
470 { 470 {
471 UUID item; 471 UUID item;
472 472
473 m_host.AddScriptLPS(1); 473 m_host.AddScriptLPS(1);
474 474
475 if ((item = GetScriptByName(name)) != UUID.Zero) 475 if ((item = GetScriptByName(name)) != UUID.Zero)
476 m_ScriptEngine.ResetScript(item); 476 m_ScriptEngine.ResetScript(item);
477 else 477 else
478 Error("llResetOtherScript", "Can't find script '" + name + "'"); 478 Error("llResetOtherScript", "Can't find script '" + name + "'");
479 } 479 }
480 480
481 public LSL_Integer llGetScriptState(string name) 481 public LSL_Integer llGetScriptState(string name)
482 { 482 {
483 UUID item; 483 UUID item;
484 484
485 m_host.AddScriptLPS(1); 485 m_host.AddScriptLPS(1);
486 486
487 if ((item = GetScriptByName(name)) != UUID.Zero) 487 if ((item = GetScriptByName(name)) != UUID.Zero)
488 { 488 {
489 return m_ScriptEngine.GetScriptState(item) ?1:0; 489 return m_ScriptEngine.GetScriptState(item) ?1:0;
490 } 490 }
491 491
492 Error("llGetScriptState", "Can't find script '" + name + "'"); 492 Error("llGetScriptState", "Can't find script '" + name + "'");
493 493
494 // If we didn't find it, then it's safe to 494 // If we didn't find it, then it's safe to
495 // assume it is not running. 495 // assume it is not running.
496 496
497 return 0; 497 return 0;
498 } 498 }
499 499
500 public void llSetScriptState(string name, int run) 500 public void llSetScriptState(string name, int run)
501 { 501 {
502 UUID item; 502 UUID item;
503 503
504 m_host.AddScriptLPS(1); 504 m_host.AddScriptLPS(1);
505 505
506 // These functions are supposed to be robust, 506 // These functions are supposed to be robust,
507 // so get the state one step at a time. 507 // so get the state one step at a time.
508 508
509 if ((item = GetScriptByName(name)) != UUID.Zero) 509 if ((item = GetScriptByName(name)) != UUID.Zero)
510 { 510 {
511 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true); 511 m_ScriptEngine.SetScriptState(item, run == 0 ? false : true);
512 } 512 }
513 else 513 else
514 { 514 {
515 Error("llSetScriptState", "Can't find script '" + name + "'"); 515 Error("llSetScriptState", "Can't find script '" + name + "'");
516 } 516 }
517 } 517 }
518 518
519 /// <summary> 519 /// <summary>
520 /// Get a given link entity from a linkset (linked objects and any sitting avatars). 520 /// Get a given link entity from a linkset (linked objects and any sitting avatars).
521 /// </summary> 521 /// </summary>
522 /// <remarks> 522 /// <remarks>
523 /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then 523 /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then
524 /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset. 524 /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset.
525 /// The ScenePresences receive linknums in the order in which they sat. 525 /// The ScenePresences receive linknums in the order in which they sat.
526 /// </remarks> 526 /// </remarks>
527 /// <returns> 527 /// <returns>
528 /// The link entity. null if not found. 528 /// The link entity. null if not found.
529 /// </returns> 529 /// </returns>
530 /// <param name='part'></param> 530 /// <param name='part'></param>
531 /// <param name='linknum'> 531 /// <param name='linknum'>
532 /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4). 532 /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4).
533 /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned. 533 /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned.
534 /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned. If any 534 /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned. If any
535 /// positive integer is given in this case then null is returned. 535 /// positive integer is given in this case then null is returned.
536 /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number 536 /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number
537 /// of entities, then the entity which corresponds to that linknum is returned. 537 /// of entities, then the entity which corresponds to that linknum is returned.
538 /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then 538 /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then
539 /// null is returned. 539 /// null is returned.
540 /// </param> 540 /// </param>
541 public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum) 541 public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum)
542 { 542 {
543 if (linknum < 0) 543 if (linknum < 0)
544 { 544 {
545 if (linknum == ScriptBaseClass.LINK_THIS) 545 if (linknum == ScriptBaseClass.LINK_THIS)
546 return part; 546 return part;
547 else 547 else
548 return null; 548 return null;
549 } 549 }
550 550
551 int actualPrimCount = part.ParentGroup.PrimCount; 551 int actualPrimCount = part.ParentGroup.PrimCount;
552 List<ScenePresence> sittingAvatars = part.ParentGroup.GetSittingAvatars(); 552 List<ScenePresence> sittingAvatars = part.ParentGroup.GetSittingAvatars();
553 int adjustedPrimCount = actualPrimCount + sittingAvatars.Count; 553 int adjustedPrimCount = actualPrimCount + sittingAvatars.Count;
554 554
555 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single 555 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
556 // prim that has any avatars sat upon it (in which case the root prim is link 1). 556 // prim that has any avatars sat upon it (in which case the root prim is link 1).
557 if (linknum == 0) 557 if (linknum == 0)
558 { 558 {
559 if (actualPrimCount == 1 && sittingAvatars.Count == 0) 559 if (actualPrimCount == 1 && sittingAvatars.Count == 0)
560 return part; 560 return part;
561 561
562 return null; 562 return null;
563 } 563 }
564 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but 564 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
565 // here we must match 1 (ScriptBaseClass.LINK_ROOT). 565 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
566 else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1) 566 else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1)
567 { 567 {
568 if (sittingAvatars.Count > 0) 568 if (sittingAvatars.Count > 0)
569 return part.ParentGroup.RootPart; 569 return part.ParentGroup.RootPart;
570 else 570 else
571 return null; 571 return null;
572 } 572 }
573 else if (linknum <= adjustedPrimCount) 573 else if (linknum <= adjustedPrimCount)
574 { 574 {
575 if (linknum <= actualPrimCount) 575 if (linknum <= actualPrimCount)
576 { 576 {
577 return part.ParentGroup.GetLinkNumPart(linknum); 577 return part.ParentGroup.GetLinkNumPart(linknum);
578 } 578 }
579 else 579 else
580 { 580 {
581 return sittingAvatars[linknum - actualPrimCount - 1]; 581 return sittingAvatars[linknum - actualPrimCount - 1];
582 } 582 }
583 } 583 }
584 else 584 else
585 { 585 {
586 return null; 586 return null;
587 } 587 }
588 } 588 }
589 589
590 public List<SceneObjectPart> GetLinkParts(int linkType) 590 public List<SceneObjectPart> GetLinkParts(int linkType)
591 { 591 {
592 return GetLinkParts(m_host, linkType); 592 return GetLinkParts(m_host, linkType);
593 } 593 }
594 594
595 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) 595 public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType)
596 { 596 {
597 List<SceneObjectPart> ret = new List<SceneObjectPart>(); 597 List<SceneObjectPart> ret = new List<SceneObjectPart>();
598 ret.Add(part); 598 ret.Add(part);
599 599
600 switch (linkType) 600 switch (linkType)
601 { 601 {
602 case ScriptBaseClass.LINK_SET: 602 case ScriptBaseClass.LINK_SET:
603 return new List<SceneObjectPart>(part.ParentGroup.Parts); 603 return new List<SceneObjectPart>(part.ParentGroup.Parts);
604 604
605 case ScriptBaseClass.LINK_ROOT: 605 case ScriptBaseClass.LINK_ROOT:
606 ret = new List<SceneObjectPart>(); 606 ret = new List<SceneObjectPart>();
607 ret.Add(part.ParentGroup.RootPart); 607 ret.Add(part.ParentGroup.RootPart);
608 return ret; 608 return ret;
609 609
610 case ScriptBaseClass.LINK_ALL_OTHERS: 610 case ScriptBaseClass.LINK_ALL_OTHERS:
611 ret = new List<SceneObjectPart>(part.ParentGroup.Parts); 611 ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
612 612
613 if (ret.Contains(part)) 613 if (ret.Contains(part))
614 ret.Remove(part); 614 ret.Remove(part);
615 615
616 return ret; 616 return ret;
617 617
618 case ScriptBaseClass.LINK_ALL_CHILDREN: 618 case ScriptBaseClass.LINK_ALL_CHILDREN:
619 ret = new List<SceneObjectPart>(part.ParentGroup.Parts); 619 ret = new List<SceneObjectPart>(part.ParentGroup.Parts);
620 620
621 if (ret.Contains(part.ParentGroup.RootPart)) 621 if (ret.Contains(part.ParentGroup.RootPart))
622 ret.Remove(part.ParentGroup.RootPart); 622 ret.Remove(part.ParentGroup.RootPart);
623 return ret; 623 return ret;
624 624
625 case ScriptBaseClass.LINK_THIS: 625 case ScriptBaseClass.LINK_THIS:
626 return ret; 626 return ret;
627 627
628 default: 628 default:
629 if (linkType < 0) 629 if (linkType < 0)
630 return new List<SceneObjectPart>(); 630 return new List<SceneObjectPart>();
631 631
632 SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType); 632 SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType);
633 if (target == null) 633 if (target == null)
634 return new List<SceneObjectPart>(); 634 return new List<SceneObjectPart>();
635 ret = new List<SceneObjectPart>(); 635 ret = new List<SceneObjectPart>();
636 ret.Add(target); 636 ret.Add(target);
637 return ret; 637 return ret;
638 } 638 }
639 } 639 }
640 640
641 public List<ISceneEntity> GetLinkEntities(int linkType) 641 public List<ISceneEntity> GetLinkEntities(int linkType)
642 { 642 {
643 return GetLinkEntities(m_host, linkType); 643 return GetLinkEntities(m_host, linkType);
644 } 644 }
645 645
646 public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType) 646 public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType)
647 { 647 {
648 List<ISceneEntity> ret; 648 List<ISceneEntity> ret;
649 649
650 switch (linkType) 650 switch (linkType)
651 { 651 {
652 case ScriptBaseClass.LINK_SET: 652 case ScriptBaseClass.LINK_SET:
653 return new List<ISceneEntity>(part.ParentGroup.Parts); 653 return new List<ISceneEntity>(part.ParentGroup.Parts);
654 654
655 case ScriptBaseClass.LINK_ROOT: 655 case ScriptBaseClass.LINK_ROOT:
656 return new List<ISceneEntity>() { part.ParentGroup.RootPart }; 656 return new List<ISceneEntity>() { part.ParentGroup.RootPart };
657 657
658 case ScriptBaseClass.LINK_ALL_OTHERS: 658 case ScriptBaseClass.LINK_ALL_OTHERS:
659 ret = new List<ISceneEntity>(part.ParentGroup.Parts); 659 ret = new List<ISceneEntity>(part.ParentGroup.Parts);
660 660
661 if (ret.Contains(part)) 661 if (ret.Contains(part))
662 ret.Remove(part); 662 ret.Remove(part);
663 663
664 return ret; 664 return ret;
665 665
666 case ScriptBaseClass.LINK_ALL_CHILDREN: 666 case ScriptBaseClass.LINK_ALL_CHILDREN:
667 ret = new List<ISceneEntity>(part.ParentGroup.Parts); 667 ret = new List<ISceneEntity>(part.ParentGroup.Parts);
668 668
669 if (ret.Contains(part.ParentGroup.RootPart)) 669 if (ret.Contains(part.ParentGroup.RootPart))
670 ret.Remove(part.ParentGroup.RootPart); 670 ret.Remove(part.ParentGroup.RootPart);
671 671
672 return ret; 672 return ret;
673 673
674 case ScriptBaseClass.LINK_THIS: 674 case ScriptBaseClass.LINK_THIS:
675 return new List<ISceneEntity>() { part }; 675 return new List<ISceneEntity>() { part };
676 676
677 default: 677 default:
678 if (linkType < 0) 678 if (linkType < 0)
679 return new List<ISceneEntity>(); 679 return new List<ISceneEntity>();
680 680
681 ISceneEntity target = GetLinkEntity(part, linkType); 681 ISceneEntity target = GetLinkEntity(part, linkType);
682 if (target == null) 682 if (target == null)
683 return new List<ISceneEntity>(); 683 return new List<ISceneEntity>();
684 684
685 return new List<ISceneEntity>() { target }; 685 return new List<ISceneEntity>() { target };
686 } 686 }
687 } 687 }
688 688
689 //These are the implementations of the various ll-functions used by the LSL scripts. 689 //These are the implementations of the various ll-functions used by the LSL scripts.
690 public LSL_Float llSin(double f) 690 public LSL_Float llSin(double f)
691 { 691 {
692 m_host.AddScriptLPS(1); 692 m_host.AddScriptLPS(1);
693 return (double)Math.Sin(f); 693 return (double)Math.Sin(f);
694 } 694 }
695 695
696 public LSL_Float llCos(double f) 696 public LSL_Float llCos(double f)
697 { 697 {
698 m_host.AddScriptLPS(1); 698 m_host.AddScriptLPS(1);
699 return (double)Math.Cos(f); 699 return (double)Math.Cos(f);
700 } 700 }
701 701
702 public LSL_Float llTan(double f) 702 public LSL_Float llTan(double f)
703 { 703 {
704 m_host.AddScriptLPS(1); 704 m_host.AddScriptLPS(1);
705 return (double)Math.Tan(f); 705 return (double)Math.Tan(f);
706 } 706 }
707 707
708 public LSL_Float llAtan2(double x, double y) 708 public LSL_Float llAtan2(double x, double y)
709 { 709 {
710 m_host.AddScriptLPS(1); 710 m_host.AddScriptLPS(1);
711 return (double)Math.Atan2(x, y); 711 return (double)Math.Atan2(x, y);
712 } 712 }
713 713
714 public LSL_Float llSqrt(double f) 714 public LSL_Float llSqrt(double f)
715 { 715 {
716 m_host.AddScriptLPS(1); 716 m_host.AddScriptLPS(1);
717 return (double)Math.Sqrt(f); 717 return (double)Math.Sqrt(f);
718 } 718 }
719 719
720 public LSL_Float llPow(double fbase, double fexponent) 720 public LSL_Float llPow(double fbase, double fexponent)
721 { 721 {
722 m_host.AddScriptLPS(1); 722 m_host.AddScriptLPS(1);
723 return (double)Math.Pow(fbase, fexponent); 723 return (double)Math.Pow(fbase, fexponent);
724 } 724 }
725 725
726 public LSL_Integer llAbs(int i) 726 public LSL_Integer llAbs(int i)
727 { 727 {
728 // changed to replicate LSL behaviour whereby minimum int value is returned untouched. 728 // changed to replicate LSL behaviour whereby minimum int value is returned untouched.
729 m_host.AddScriptLPS(1); 729 m_host.AddScriptLPS(1);
730 if (i == Int32.MinValue) 730 if (i == Int32.MinValue)
731 return i; 731 return i;
732 else 732 else
733 return (int)Math.Abs(i); 733 return (int)Math.Abs(i);
734 } 734 }
735 735
736 public LSL_Float llFabs(double f) 736 public LSL_Float llFabs(double f)
737 { 737 {
738 m_host.AddScriptLPS(1); 738 m_host.AddScriptLPS(1);
739 return (double)Math.Abs(f); 739 return (double)Math.Abs(f);
740 } 740 }
741 741
742 public LSL_Float llFrand(double mag) 742 public LSL_Float llFrand(double mag)
743 { 743 {
744 m_host.AddScriptLPS(1); 744 m_host.AddScriptLPS(1);
745 745
746 return Util.RandomClass.NextDouble() * mag; 746 return Util.RandomClass.NextDouble() * mag;
747 } 747 }
748 748
749 public LSL_Integer llFloor(double f) 749 public LSL_Integer llFloor(double f)
750 { 750 {
751 m_host.AddScriptLPS(1); 751 m_host.AddScriptLPS(1);
752 return (int)Math.Floor(f); 752 return (int)Math.Floor(f);
753 } 753 }
754 754
755 public LSL_Integer llCeil(double f) 755 public LSL_Integer llCeil(double f)
756 { 756 {
757 m_host.AddScriptLPS(1); 757 m_host.AddScriptLPS(1);
758 return (int)Math.Ceiling(f); 758 return (int)Math.Ceiling(f);
759 } 759 }
760 760
761 // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven) 761 // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven)
762 public LSL_Integer llRound(double f) 762 public LSL_Integer llRound(double f)
763 { 763 {
764 m_host.AddScriptLPS(1); 764 m_host.AddScriptLPS(1);
765 return (int)Math.Round(f, MidpointRounding.AwayFromZero); 765 return (int)Math.Round(f, MidpointRounding.AwayFromZero);
766 } 766 }
767 767
768 //This next group are vector operations involving squaring and square root. ckrinke 768 //This next group are vector operations involving squaring and square root. ckrinke
769 public LSL_Float llVecMag(LSL_Vector v) 769 public LSL_Float llVecMag(LSL_Vector v)
770 { 770 {
771 m_host.AddScriptLPS(1); 771 m_host.AddScriptLPS(1);
772 return LSL_Vector.Mag(v); 772 return LSL_Vector.Mag(v);
773 } 773 }
774 774
775 public LSL_Vector llVecNorm(LSL_Vector v) 775 public LSL_Vector llVecNorm(LSL_Vector v)
776 { 776 {
777 m_host.AddScriptLPS(1); 777 m_host.AddScriptLPS(1);
778 return LSL_Vector.Norm(v); 778 return LSL_Vector.Norm(v);
779 } 779 }
780 780
781 private double VecDist(LSL_Vector a, LSL_Vector b) 781 private double VecDist(LSL_Vector a, LSL_Vector b)
782 { 782 {
783 double dx = a.x - b.x; 783 double dx = a.x - b.x;
784 double dy = a.y - b.y; 784 double dy = a.y - b.y;
785 double dz = a.z - b.z; 785 double dz = a.z - b.z;
786 return Math.Sqrt(dx * dx + dy * dy + dz * dz); 786 return Math.Sqrt(dx * dx + dy * dy + dz * dz);
787 } 787 }
788 788
789 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) 789 public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b)
790 { 790 {
791 m_host.AddScriptLPS(1); 791 m_host.AddScriptLPS(1);
792 return VecDist(a, b); 792 return VecDist(a, b);
793 } 793 }
794 794
795 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke 795 //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke
796 796
797 /// <summary> 797 /// <summary>
798 /// Convert an LSL rotation to a Euler vector. 798 /// Convert an LSL rotation to a Euler vector.
799 /// </summary> 799 /// </summary>
800 /// <remarks> 800 /// <remarks>
801 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf 801 /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf
802 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2 802 /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2
803 /// </remarks> 803 /// </remarks>
804 /// <param name="r"></param> 804 /// <param name="r"></param>
805 /// <returns></returns> 805 /// <returns></returns>
806 public LSL_Vector llRot2Euler(LSL_Rotation r) 806 public LSL_Vector llRot2Euler(LSL_Rotation r)
807 { 807 {
808 m_host.AddScriptLPS(1); 808 m_host.AddScriptLPS(1);
809 809
810 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. 810 LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r.
811 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. 811 double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later.
812 if (m == 0.0) return new LSL_Vector(); 812 if (m == 0.0) return new LSL_Vector();
813 double x = Math.Atan2(-v.y, v.z); 813 double x = Math.Atan2(-v.y, v.z);
814 double sin = v.x / m; 814 double sin = v.x / m;
815 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. 815 if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities.
816 double y = Math.Asin(sin); 816 double y = Math.Asin(sin);
817 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation 817 // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation
818 v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); 818 v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0)));
819 double z = Math.Atan2(v.y, v.x); 819 double z = Math.Atan2(v.y, v.x);
820 820
821 return new LSL_Vector(x, y, z); 821 return new LSL_Vector(x, y, z);
822 } 822 }
823 823
824 /* From wiki: 824 /* From wiki:
825 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes 825 The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes
826 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, 826 in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation,
827 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting 827 a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting
828 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. 828 vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis.
829 */ 829 */
830 830
831 /* How we arrived at this llEuler2Rot 831 /* How we arrived at this llEuler2Rot
832 * 832 *
833 * Experiment in SL to determine conventions: 833 * Experiment in SL to determine conventions:
834 * llEuler2Rot(<PI,0,0>)=<1,0,0,0> 834 * llEuler2Rot(<PI,0,0>)=<1,0,0,0>
835 * llEuler2Rot(<0,PI,0>)=<0,1,0,0> 835 * llEuler2Rot(<0,PI,0>)=<0,1,0,0>
836 * llEuler2Rot(<0,0,PI>)=<0,0,1,0> 836 * llEuler2Rot(<0,0,PI>)=<0,0,1,0>
837 * 837 *
838 * Important facts about Quaternions 838 * Important facts about Quaternions
839 * - multiplication is non-commutative (a*b != b*a) 839 * - multiplication is non-commutative (a*b != b*a)
840 * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication 840 * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication
841 * 841 *
842 * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot): 842 * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot):
843 * Qx = c1+i*s1 843 * Qx = c1+i*s1
844 * Qy = c2+j*s2; 844 * Qy = c2+j*s2;
845 * Qz = c3+k*s3; 845 * Qz = c3+k*s3;
846 * 846 *
847 * Rotations applied in order (from above) Z, Y, X 847 * Rotations applied in order (from above) Z, Y, X
848 * Q = (Qz * Qy) * Qx 848 * Q = (Qz * Qy) * Qx
849 * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3) 849 * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3)
850 * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3) 850 * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3)
851 * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3) 851 * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3)
852 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3 852 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3
853 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3 853 * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3
854 * regroup: x=i*(s1*c2*c3+c1*s2*s3) 854 * regroup: x=i*(s1*c2*c3+c1*s2*s3)
855 * y=j*(c1*s2*c3-s1*c2*s3) 855 * y=j*(c1*s2*c3-s1*c2*s3)
856 * z=k*(s1*s2*c3+c1*c2*s3) 856 * z=k*(s1*s2*c3+c1*c2*s3)
857 * s= c1*c2*c3-s1*s2*s3 857 * s= c1*c2*c3-s1*s2*s3
858 * 858 *
859 * This implementation agrees with the functions found here: 859 * This implementation agrees with the functions found here:
860 * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions 860 * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions
861 * And with the results in SL. 861 * And with the results in SL.
862 * 862 *
863 * It's also possible to calculate llEuler2Rot by direct multiplication of 863 * It's also possible to calculate llEuler2Rot by direct multiplication of
864 * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function 864 * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function
865 * from the wiki). 865 * from the wiki).
866 * Apparently in some cases this is better from a numerical precision perspective? 866 * Apparently in some cases this is better from a numerical precision perspective?
867 */ 867 */
868 868
869 public LSL_Rotation llEuler2Rot(LSL_Vector v) 869 public LSL_Rotation llEuler2Rot(LSL_Vector v)
870 { 870 {
871 m_host.AddScriptLPS(1); 871 m_host.AddScriptLPS(1);
872 872
873 double x,y,z,s; 873 double x,y,z,s;
874 874
875 double c1 = Math.Cos(v.x * 0.5); 875 double c1 = Math.Cos(v.x * 0.5);
876 double c2 = Math.Cos(v.y * 0.5); 876 double c2 = Math.Cos(v.y * 0.5);
877 double c3 = Math.Cos(v.z * 0.5); 877 double c3 = Math.Cos(v.z * 0.5);
878 double s1 = Math.Sin(v.x * 0.5); 878 double s1 = Math.Sin(v.x * 0.5);
879 double s2 = Math.Sin(v.y * 0.5); 879 double s2 = Math.Sin(v.y * 0.5);
880 double s3 = Math.Sin(v.z * 0.5); 880 double s3 = Math.Sin(v.z * 0.5);
881 881
882 x = s1 * c2 * c3 + c1 * s2 * s3; 882 x = s1 * c2 * c3 + c1 * s2 * s3;
883 y = c1 * s2 * c3 - s1 * c2 * s3; 883 y = c1 * s2 * c3 - s1 * c2 * s3;
884 z = s1 * s2 * c3 + c1 * c2 * s3; 884 z = s1 * s2 * c3 + c1 * c2 * s3;
885 s = c1 * c2 * c3 - s1 * s2 * s3; 885 s = c1 * c2 * c3 - s1 * s2 * s3;
886 886
887 return new LSL_Rotation(x, y, z, s); 887 return new LSL_Rotation(x, y, z, s);
888 } 888 }
889 889
890 public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up) 890 public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up)
891 { 891 {
892 m_host.AddScriptLPS(1); 892 m_host.AddScriptLPS(1);
893 double s; 893 double s;
894 double tr = fwd.x + left.y + up.z + 1.0; 894 double tr = fwd.x + left.y + up.z + 1.0;
895 895
896 if (tr >= 1.0) 896 if (tr >= 1.0)
897 { 897 {
898 s = 0.5 / Math.Sqrt(tr); 898 s = 0.5 / Math.Sqrt(tr);
899 return new LSL_Rotation( 899 return new LSL_Rotation(
900 (left.z - up.y) * s, 900 (left.z - up.y) * s,
901 (up.x - fwd.z) * s, 901 (up.x - fwd.z) * s,
902 (fwd.y - left.x) * s, 902 (fwd.y - left.x) * s,
903 0.25 / s); 903 0.25 / s);
904 } 904 }
905 else 905 else
906 { 906 {
907 double max = (left.y > up.z) ? left.y : up.z; 907 double max = (left.y > up.z) ? left.y : up.z;
908 908
909 if (max < fwd.x) 909 if (max < fwd.x)
910 { 910 {
911 s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0); 911 s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0);
912 double x = s * 0.5; 912 double x = s * 0.5;
913 s = 0.5 / s; 913 s = 0.5 / s;
914 return new LSL_Rotation( 914 return new LSL_Rotation(
915 x, 915 x,
916 (fwd.y + left.x) * s, 916 (fwd.y + left.x) * s,
917 (up.x + fwd.z) * s, 917 (up.x + fwd.z) * s,
918 (left.z - up.y) * s); 918 (left.z - up.y) * s);
919 } 919 }
920 else if (max == left.y) 920 else if (max == left.y)
921 { 921 {
922 s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0); 922 s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0);
923 double y = s * 0.5; 923 double y = s * 0.5;
924 s = 0.5 / s; 924 s = 0.5 / s;
925 return new LSL_Rotation( 925 return new LSL_Rotation(
926 (fwd.y + left.x) * s, 926 (fwd.y + left.x) * s,
927 y, 927 y,
928 (left.z + up.y) * s, 928 (left.z + up.y) * s,
929 (up.x - fwd.z) * s); 929 (up.x - fwd.z) * s);
930 } 930 }
931 else 931 else
932 { 932 {
933 s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0); 933 s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0);
934 double z = s * 0.5; 934 double z = s * 0.5;
935 s = 0.5 / s; 935 s = 0.5 / s;
936 return new LSL_Rotation( 936 return new LSL_Rotation(
937 (up.x + fwd.z) * s, 937 (up.x + fwd.z) * s,
938 (left.z + up.y) * s, 938 (left.z + up.y) * s,
939 z, 939 z,
940 (fwd.y - left.x) * s); 940 (fwd.y - left.x) * s);
941 } 941 }
942 } 942 }
943 } 943 }
944 944
945 public LSL_Vector llRot2Fwd(LSL_Rotation r) 945 public LSL_Vector llRot2Fwd(LSL_Rotation r)
946 { 946 {
947 m_host.AddScriptLPS(1); 947 m_host.AddScriptLPS(1);
948 948
949 double x, y, z, m; 949 double x, y, z, m;
950 950
951 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; 951 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
952 // m is always greater than zero 952 // m is always greater than zero
953 // if m is not equal to 1 then Rotation needs to be normalized 953 // if m is not equal to 1 then Rotation needs to be normalized
954 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision 954 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
955 { 955 {
956 m = 1.0 / Math.Sqrt(m); 956 m = 1.0 / Math.Sqrt(m);
957 r.x *= m; 957 r.x *= m;
958 r.y *= m; 958 r.y *= m;
959 r.z *= m; 959 r.z *= m;
960 r.s *= m; 960 r.s *= m;
961 } 961 }
962 962
963 // Fast Algebric Calculations instead of Vectors & Quaternions Product 963 // Fast Algebric Calculations instead of Vectors & Quaternions Product
964 x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s; 964 x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s;
965 y = 2 * (r.x * r.y + r.z * r.s); 965 y = 2 * (r.x * r.y + r.z * r.s);
966 z = 2 * (r.x * r.z - r.y * r.s); 966 z = 2 * (r.x * r.z - r.y * r.s);
967 return (new LSL_Vector(x, y, z)); 967 return (new LSL_Vector(x, y, z));
968 } 968 }
969 969
970 public LSL_Vector llRot2Left(LSL_Rotation r) 970 public LSL_Vector llRot2Left(LSL_Rotation r)
971 { 971 {
972 m_host.AddScriptLPS(1); 972 m_host.AddScriptLPS(1);
973 973
974 double x, y, z, m; 974 double x, y, z, m;
975 975
976 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; 976 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
977 // m is always greater than zero 977 // m is always greater than zero
978 // if m is not equal to 1 then Rotation needs to be normalized 978 // if m is not equal to 1 then Rotation needs to be normalized
979 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision 979 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
980 { 980 {
981 m = 1.0 / Math.Sqrt(m); 981 m = 1.0 / Math.Sqrt(m);
982 r.x *= m; 982 r.x *= m;
983 r.y *= m; 983 r.y *= m;
984 r.z *= m; 984 r.z *= m;
985 r.s *= m; 985 r.s *= m;
986 } 986 }
987 987
988 // Fast Algebric Calculations instead of Vectors & Quaternions Product 988 // Fast Algebric Calculations instead of Vectors & Quaternions Product
989 x = 2 * (r.x * r.y - r.z * r.s); 989 x = 2 * (r.x * r.y - r.z * r.s);
990 y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s; 990 y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s;
991 z = 2 * (r.x * r.s + r.y * r.z); 991 z = 2 * (r.x * r.s + r.y * r.z);
992 return (new LSL_Vector(x, y, z)); 992 return (new LSL_Vector(x, y, z));
993 } 993 }
994 994
995 public LSL_Vector llRot2Up(LSL_Rotation r) 995 public LSL_Vector llRot2Up(LSL_Rotation r)
996 { 996 {
997 m_host.AddScriptLPS(1); 997 m_host.AddScriptLPS(1);
998 double x, y, z, m; 998 double x, y, z, m;
999 999
1000 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; 1000 m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s;
1001 // m is always greater than zero 1001 // m is always greater than zero
1002 // if m is not equal to 1 then Rotation needs to be normalized 1002 // if m is not equal to 1 then Rotation needs to be normalized
1003 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision 1003 if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision
1004 { 1004 {
1005 m = 1.0 / Math.Sqrt(m); 1005 m = 1.0 / Math.Sqrt(m);
1006 r.x *= m; 1006 r.x *= m;
1007 r.y *= m; 1007 r.y *= m;
1008 r.z *= m; 1008 r.z *= m;
1009 r.s *= m; 1009 r.s *= m;
1010 } 1010 }
1011 1011
1012 // Fast Algebric Calculations instead of Vectors & Quaternions Product 1012 // Fast Algebric Calculations instead of Vectors & Quaternions Product
1013 x = 2 * (r.x * r.z + r.y * r.s); 1013 x = 2 * (r.x * r.z + r.y * r.s);
1014 y = 2 * (-r.x * r.s + r.y * r.z); 1014 y = 2 * (-r.x * r.s + r.y * r.z);
1015 z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s; 1015 z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s;
1016 return (new LSL_Vector(x, y, z)); 1016 return (new LSL_Vector(x, y, z));
1017 } 1017 }
1018 1018
1019 public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b) 1019 public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b)
1020 { 1020 {
1021 //A and B should both be normalized 1021 //A and B should both be normalized
1022 m_host.AddScriptLPS(1); 1022 m_host.AddScriptLPS(1);
1023 LSL_Rotation rotBetween; 1023 LSL_Rotation rotBetween;
1024 // Check for zero vectors. If either is zero, return zero rotation. Otherwise, 1024 // Check for zero vectors. If either is zero, return zero rotation. Otherwise,
1025 // continue calculation. 1025 // continue calculation.
1026 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) 1026 if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f))
1027 { 1027 {
1028 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 1028 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1029 } 1029 }
1030 else 1030 else
1031 { 1031 {
1032 a = LSL_Vector.Norm(a); 1032 a = LSL_Vector.Norm(a);
1033 b = LSL_Vector.Norm(b); 1033 b = LSL_Vector.Norm(b);
1034 double dotProduct = LSL_Vector.Dot(a, b); 1034 double dotProduct = LSL_Vector.Dot(a, b);
1035 // There are two degenerate cases possible. These are for vectors 180 or 1035 // There are two degenerate cases possible. These are for vectors 180 or
1036 // 0 degrees apart. These have to be detected and handled individually. 1036 // 0 degrees apart. These have to be detected and handled individually.
1037 // 1037 //
1038 // Check for vectors 180 degrees apart. 1038 // Check for vectors 180 degrees apart.
1039 // A dot product of -1 would mean the angle between vectors is 180 degrees. 1039 // A dot product of -1 would mean the angle between vectors is 180 degrees.
1040 if (dotProduct < -0.9999999f) 1040 if (dotProduct < -0.9999999f)
1041 { 1041 {
1042 // First assume X axis is orthogonal to the vectors. 1042 // First assume X axis is orthogonal to the vectors.
1043 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); 1043 LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f);
1044 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); 1044 orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a));
1045 // Check for near zero vector. A very small non-zero number here will create 1045 // Check for near zero vector. A very small non-zero number here will create
1046 // a rotation in an undesired direction. 1046 // a rotation in an undesired direction.
1047 if (LSL_Vector.Mag(orthoVector) > 0.0001) 1047 if (LSL_Vector.Mag(orthoVector) > 0.0001)
1048 { 1048 {
1049 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); 1049 rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f);
1050 } 1050 }
1051 // If the magnitude of the vector was near zero, then assume the X axis is not 1051 // If the magnitude of the vector was near zero, then assume the X axis is not
1052 // orthogonal and use the Z axis instead. 1052 // orthogonal and use the Z axis instead.
1053 else 1053 else
1054 { 1054 {
1055 // Set 180 z rotation. 1055 // Set 180 z rotation.
1056 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f); 1056 rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f);
1057 } 1057 }
1058 } 1058 }
1059 // Check for parallel vectors. 1059 // Check for parallel vectors.
1060 // A dot product of 1 would mean the angle between vectors is 0 degrees. 1060 // A dot product of 1 would mean the angle between vectors is 0 degrees.
1061 else if (dotProduct > 0.9999999f) 1061 else if (dotProduct > 0.9999999f)
1062 { 1062 {
1063 // Set zero rotation. 1063 // Set zero rotation.
1064 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 1064 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1065 } 1065 }
1066 else 1066 else
1067 { 1067 {
1068 // All special checks have been performed so get the axis of rotation. 1068 // All special checks have been performed so get the axis of rotation.
1069 LSL_Vector crossProduct = LSL_Vector.Cross(a, b); 1069 LSL_Vector crossProduct = LSL_Vector.Cross(a, b);
1070 // Quarternion s value is the length of the unit vector + dot product. 1070 // Quarternion s value is the length of the unit vector + dot product.
1071 double qs = 1.0 + dotProduct; 1071 double qs = 1.0 + dotProduct;
1072 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs); 1072 rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs);
1073 // Normalize the rotation. 1073 // Normalize the rotation.
1074 double mag = LSL_Rotation.Mag(rotBetween); 1074 double mag = LSL_Rotation.Mag(rotBetween);
1075 // We shouldn't have to worry about a divide by zero here. The qs value will be 1075 // We shouldn't have to worry about a divide by zero here. The qs value will be
1076 // non-zero because we already know if we're here, then the dotProduct is not -1 so 1076 // non-zero because we already know if we're here, then the dotProduct is not -1 so
1077 // qs will not be zero. Also, we've already handled the input vectors being zero so the 1077 // qs will not be zero. Also, we've already handled the input vectors being zero so the
1078 // crossProduct vector should also not be zero. 1078 // crossProduct vector should also not be zero.
1079 rotBetween.x = rotBetween.x / mag; 1079 rotBetween.x = rotBetween.x / mag;
1080 rotBetween.y = rotBetween.y / mag; 1080 rotBetween.y = rotBetween.y / mag;
1081 rotBetween.z = rotBetween.z / mag; 1081 rotBetween.z = rotBetween.z / mag;
1082 rotBetween.s = rotBetween.s / mag; 1082 rotBetween.s = rotBetween.s / mag;
1083 // Check for undefined values and set zero rotation if any found. This code might not actually be required 1083 // Check for undefined values and set zero rotation if any found. This code might not actually be required
1084 // any longer since zero vectors are checked for at the top. 1084 // any longer since zero vectors are checked for at the top.
1085 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s)) 1085 if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s))
1086 { 1086 {
1087 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); 1087 rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f);
1088 } 1088 }
1089 } 1089 }
1090 } 1090 }
1091 return rotBetween; 1091 return rotBetween;
1092 } 1092 }
1093 1093
1094 public void llWhisper(int channelID, string text) 1094 public void llWhisper(int channelID, string text)
1095 { 1095 {
1096 m_host.AddScriptLPS(1); 1096 m_host.AddScriptLPS(1);
1097 1097
1098 if (text.Length > 1023) 1098 if (text.Length > 1023)
1099 text = text.Substring(0, 1023); 1099 text = text.Substring(0, 1023);
1100 1100
1101 World.SimChat(Utils.StringToBytes(text), 1101 World.SimChat(Utils.StringToBytes(text),
1102 ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); 1102 ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
1103 1103
1104 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1104 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1105 if (wComm != null) 1105 if (wComm != null)
1106 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); 1106 wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text);
1107 } 1107 }
1108 1108
1109 public void llSay(int channelID, string text) 1109 public void llSay(int channelID, string text)
1110 { 1110 {
1111 m_host.AddScriptLPS(1); 1111 m_host.AddScriptLPS(1);
1112 1112
1113 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) 1113 if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel))
1114 { 1114 {
1115 Console.WriteLine(text); 1115 Console.WriteLine(text);
1116 } 1116 }
1117 else 1117 else
1118 { 1118 {
1119 if (text.Length > 1023) 1119 if (text.Length > 1023)
1120 text = text.Substring(0, 1023); 1120 text = text.Substring(0, 1023);
1121 1121
1122 World.SimChat(Utils.StringToBytes(text), 1122 World.SimChat(Utils.StringToBytes(text),
1123 ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); 1123 ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
1124 1124
1125 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1125 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1126 if (wComm != null) 1126 if (wComm != null)
1127 wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text); 1127 wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text);
1128 } 1128 }
1129 } 1129 }
1130 1130
1131 public void llShout(int channelID, string text) 1131 public void llShout(int channelID, string text)
1132 { 1132 {
1133 m_host.AddScriptLPS(1); 1133 m_host.AddScriptLPS(1);
1134 1134
1135 if (text.Length > 1023) 1135 if (text.Length > 1023)
1136 text = text.Substring(0, 1023); 1136 text = text.Substring(0, 1023);
1137 1137
1138 World.SimChat(Utils.StringToBytes(text), 1138 World.SimChat(Utils.StringToBytes(text),
1139 ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); 1139 ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
1140 1140
1141 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1141 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1142 if (wComm != null) 1142 if (wComm != null)
1143 wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text); 1143 wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text);
1144 } 1144 }
1145 1145
1146 public void llRegionSay(int channelID, string text) 1146 public void llRegionSay(int channelID, string text)
1147 { 1147 {
1148 if (channelID == 0) 1148 if (channelID == 0)
1149 { 1149 {
1150 Error("llRegionSay", "Cannot use on channel 0"); 1150 Error("llRegionSay", "Cannot use on channel 0");
1151 return; 1151 return;
1152 } 1152 }
1153 1153
1154 if (text.Length > 1023) 1154 if (text.Length > 1023)
1155 text = text.Substring(0, 1023); 1155 text = text.Substring(0, 1023);
1156 1156
1157 m_host.AddScriptLPS(1); 1157 m_host.AddScriptLPS(1);
1158 1158
1159 World.SimChat(Utils.StringToBytes(text), 1159 World.SimChat(Utils.StringToBytes(text),
1160 ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); 1160 ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
1161 1161
1162 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1162 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1163 if (wComm != null) 1163 if (wComm != null)
1164 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); 1164 wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text);
1165 } 1165 }
1166 1166
1167 public void llRegionSayTo(string target, int channel, string msg) 1167 public void llRegionSayTo(string target, int channel, string msg)
1168 { 1168 {
1169 if (msg.Length > 1023) 1169 if (msg.Length > 1023)
1170 msg = msg.Substring(0, 1023); 1170 msg = msg.Substring(0, 1023);
1171 1171
1172 m_host.AddScriptLPS(1); 1172 m_host.AddScriptLPS(1);
1173 1173
1174 if (channel == ScriptBaseClass.DEBUG_CHANNEL) 1174 if (channel == ScriptBaseClass.DEBUG_CHANNEL)
1175 { 1175 {
1176 return; 1176 return;
1177 } 1177 }
1178 1178
1179 UUID TargetID; 1179 UUID TargetID;
1180 UUID.TryParse(target, out TargetID); 1180 UUID.TryParse(target, out TargetID);
1181 1181
1182 World.SimChatToAgent(TargetID, Utils.StringToBytes(msg), 1182 World.SimChatToAgent(TargetID, Utils.StringToBytes(msg),
1183 channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); 1183 channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true);
1184 1184
1185 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1185 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1186 if (wComm != null) 1186 if (wComm != null)
1187 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); 1187 wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg);
1188 } 1188 }
1189 1189
1190 public LSL_Integer llListen(int channelID, string name, string ID, string msg) 1190 public LSL_Integer llListen(int channelID, string name, string ID, string msg)
1191 { 1191 {
1192 m_host.AddScriptLPS(1); 1192 m_host.AddScriptLPS(1);
1193 UUID keyID; 1193 UUID keyID;
1194 UUID.TryParse(ID, out keyID); 1194 UUID.TryParse(ID, out keyID);
1195 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1195 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1196 if (wComm != null) 1196 if (wComm != null)
1197 return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg); 1197 return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg);
1198 else 1198 else
1199 return -1; 1199 return -1;
1200 } 1200 }
1201 1201
1202 public void llListenControl(int number, int active) 1202 public void llListenControl(int number, int active)
1203 { 1203 {
1204 m_host.AddScriptLPS(1); 1204 m_host.AddScriptLPS(1);
1205 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1205 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1206 if (wComm != null) 1206 if (wComm != null)
1207 wComm.ListenControl(m_item.ItemID, number, active); 1207 wComm.ListenControl(m_item.ItemID, number, active);
1208 } 1208 }
1209 1209
1210 public void llListenRemove(int number) 1210 public void llListenRemove(int number)
1211 { 1211 {
1212 m_host.AddScriptLPS(1); 1212 m_host.AddScriptLPS(1);
1213 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 1213 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
1214 if (wComm != null) 1214 if (wComm != null)
1215 wComm.ListenRemove(m_item.ItemID, number); 1215 wComm.ListenRemove(m_item.ItemID, number);
1216 } 1216 }
1217 1217
1218 public void llSensor(string name, string id, int type, double range, double arc) 1218 public void llSensor(string name, string id, int type, double range, double arc)
1219 { 1219 {
1220 m_host.AddScriptLPS(1); 1220 m_host.AddScriptLPS(1);
1221 UUID keyID = UUID.Zero; 1221 UUID keyID = UUID.Zero;
1222 UUID.TryParse(id, out keyID); 1222 UUID.TryParse(id, out keyID);
1223 1223
1224 AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host); 1224 AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host);
1225 } 1225 }
1226 1226
1227 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) 1227 public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate)
1228 { 1228 {
1229 m_host.AddScriptLPS(1); 1229 m_host.AddScriptLPS(1);
1230 UUID keyID = UUID.Zero; 1230 UUID keyID = UUID.Zero;
1231 UUID.TryParse(id, out keyID); 1231 UUID.TryParse(id, out keyID);
1232 1232
1233 AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host); 1233 AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host);
1234 } 1234 }
1235 1235
1236 public void llSensorRemove() 1236 public void llSensorRemove()
1237 { 1237 {
1238 m_host.AddScriptLPS(1); 1238 m_host.AddScriptLPS(1);
1239 AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID); 1239 AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID);
1240 } 1240 }
1241 1241
1242 public string resolveName(UUID objecUUID) 1242 public string resolveName(UUID objecUUID)
1243 { 1243 {
1244 // try avatar username surname 1244 // try avatar username surname
1245 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID); 1245 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID);
1246 if (account != null) 1246 if (account != null)
1247 { 1247 {
1248 string avatarname = account.Name; 1248 string avatarname = account.Name;
1249 return avatarname; 1249 return avatarname;
1250 } 1250 }
1251 // try an scene object 1251 // try an scene object
1252 SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID); 1252 SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID);
1253 if (SOP != null) 1253 if (SOP != null)
1254 { 1254 {
1255 string objectname = SOP.Name; 1255 string objectname = SOP.Name;
1256 return objectname; 1256 return objectname;
1257 } 1257 }
1258 1258
1259 EntityBase SensedObject; 1259 EntityBase SensedObject;
1260 World.Entities.TryGetValue(objecUUID, out SensedObject); 1260 World.Entities.TryGetValue(objecUUID, out SensedObject);
1261 1261
1262 if (SensedObject == null) 1262 if (SensedObject == null)
1263 { 1263 {
1264 IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>(); 1264 IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
1265 if (groups != null) 1265 if (groups != null)
1266 { 1266 {
1267 GroupRecord gr = groups.GetGroupRecord(objecUUID); 1267 GroupRecord gr = groups.GetGroupRecord(objecUUID);
1268 if (gr != null) 1268 if (gr != null)
1269 return gr.GroupName; 1269 return gr.GroupName;
1270 } 1270 }
1271 return String.Empty; 1271 return String.Empty;
1272 } 1272 }
1273 1273
1274 return SensedObject.Name; 1274 return SensedObject.Name;
1275 } 1275 }
1276 1276
1277 public LSL_String llDetectedName(int number) 1277 public LSL_String llDetectedName(int number)
1278 { 1278 {
1279 m_host.AddScriptLPS(1); 1279 m_host.AddScriptLPS(1);
1280 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1280 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1281 if (detectedParams == null) 1281 if (detectedParams == null)
1282 return String.Empty; 1282 return String.Empty;
1283 return detectedParams.Name; 1283 return detectedParams.Name;
1284 } 1284 }
1285 1285
1286 public LSL_String llDetectedKey(int number) 1286 public LSL_String llDetectedKey(int number)
1287 { 1287 {
1288 m_host.AddScriptLPS(1); 1288 m_host.AddScriptLPS(1);
1289 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1289 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1290 if (detectedParams == null) 1290 if (detectedParams == null)
1291 return String.Empty; 1291 return String.Empty;
1292 return detectedParams.Key.ToString(); 1292 return detectedParams.Key.ToString();
1293 } 1293 }
1294 1294
1295 public LSL_String llDetectedOwner(int number) 1295 public LSL_String llDetectedOwner(int number)
1296 { 1296 {
1297 m_host.AddScriptLPS(1); 1297 m_host.AddScriptLPS(1);
1298 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1298 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1299 if (detectedParams == null) 1299 if (detectedParams == null)
1300 return String.Empty; 1300 return String.Empty;
1301 return detectedParams.Owner.ToString(); 1301 return detectedParams.Owner.ToString();
1302 } 1302 }
1303 1303
1304 public LSL_Integer llDetectedType(int number) 1304 public LSL_Integer llDetectedType(int number)
1305 { 1305 {
1306 m_host.AddScriptLPS(1); 1306 m_host.AddScriptLPS(1);
1307 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1307 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1308 if (detectedParams == null) 1308 if (detectedParams == null)
1309 return 0; 1309 return 0;
1310 return new LSL_Integer(detectedParams.Type); 1310 return new LSL_Integer(detectedParams.Type);
1311 } 1311 }
1312 1312
1313 public LSL_Vector llDetectedPos(int number) 1313 public LSL_Vector llDetectedPos(int number)
1314 { 1314 {
1315 m_host.AddScriptLPS(1); 1315 m_host.AddScriptLPS(1);
1316 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1316 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1317 if (detectedParams == null) 1317 if (detectedParams == null)
1318 return new LSL_Vector(); 1318 return new LSL_Vector();
1319 return detectedParams.Position; 1319 return detectedParams.Position;
1320 } 1320 }
1321 1321
1322 public LSL_Vector llDetectedVel(int number) 1322 public LSL_Vector llDetectedVel(int number)
1323 { 1323 {
1324 m_host.AddScriptLPS(1); 1324 m_host.AddScriptLPS(1);
1325 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1325 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1326 if (detectedParams == null) 1326 if (detectedParams == null)
1327 return new LSL_Vector(); 1327 return new LSL_Vector();
1328 return detectedParams.Velocity; 1328 return detectedParams.Velocity;
1329 } 1329 }
1330 1330
1331 public LSL_Vector llDetectedGrab(int number) 1331 public LSL_Vector llDetectedGrab(int number)
1332 { 1332 {
1333 m_host.AddScriptLPS(1); 1333 m_host.AddScriptLPS(1);
1334 DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1334 DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1335 if (parms == null) 1335 if (parms == null)
1336 return new LSL_Vector(0, 0, 0); 1336 return new LSL_Vector(0, 0, 0);
1337 1337
1338 return parms.OffsetPos; 1338 return parms.OffsetPos;
1339 } 1339 }
1340 1340
1341 public LSL_Rotation llDetectedRot(int number) 1341 public LSL_Rotation llDetectedRot(int number)
1342 { 1342 {
1343 m_host.AddScriptLPS(1); 1343 m_host.AddScriptLPS(1);
1344 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1344 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1345 if (detectedParams == null) 1345 if (detectedParams == null)
1346 return new LSL_Rotation(); 1346 return new LSL_Rotation();
1347 return detectedParams.Rotation; 1347 return detectedParams.Rotation;
1348 } 1348 }
1349 1349
1350 public LSL_Integer llDetectedGroup(int number) 1350 public LSL_Integer llDetectedGroup(int number)
1351 { 1351 {
1352 m_host.AddScriptLPS(1); 1352 m_host.AddScriptLPS(1);
1353 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1353 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1354 if (detectedParams == null) 1354 if (detectedParams == null)
1355 return new LSL_Integer(0); 1355 return new LSL_Integer(0);
1356 if (m_host.GroupID == detectedParams.Group) 1356 if (m_host.GroupID == detectedParams.Group)
1357 return new LSL_Integer(1); 1357 return new LSL_Integer(1);
1358 return new LSL_Integer(0); 1358 return new LSL_Integer(0);
1359 } 1359 }
1360 1360
1361 public LSL_Integer llDetectedLinkNumber(int number) 1361 public LSL_Integer llDetectedLinkNumber(int number)
1362 { 1362 {
1363 m_host.AddScriptLPS(1); 1363 m_host.AddScriptLPS(1);
1364 DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); 1364 DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number);
1365 if (parms == null) 1365 if (parms == null)
1366 return new LSL_Integer(0); 1366 return new LSL_Integer(0);
1367 1367
1368 return new LSL_Integer(parms.LinkNum); 1368 return new LSL_Integer(parms.LinkNum);
1369 } 1369 }
1370 1370
1371 /// <summary> 1371 /// <summary>
1372 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details 1372 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details
1373 /// </summary> 1373 /// </summary>
1374 public LSL_Vector llDetectedTouchBinormal(int index) 1374 public LSL_Vector llDetectedTouchBinormal(int index)
1375 { 1375 {
1376 m_host.AddScriptLPS(1); 1376 m_host.AddScriptLPS(1);
1377 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); 1377 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1378 if (detectedParams == null) 1378 if (detectedParams == null)
1379 return new LSL_Vector(); 1379 return new LSL_Vector();
1380 return detectedParams.TouchBinormal; 1380 return detectedParams.TouchBinormal;
1381 } 1381 }
1382 1382
1383 /// <summary> 1383 /// <summary>
1384 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details 1384 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details
1385 /// </summary> 1385 /// </summary>
1386 public LSL_Integer llDetectedTouchFace(int index) 1386 public LSL_Integer llDetectedTouchFace(int index)
1387 { 1387 {
1388 m_host.AddScriptLPS(1); 1388 m_host.AddScriptLPS(1);
1389 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); 1389 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1390 if (detectedParams == null) 1390 if (detectedParams == null)
1391 return new LSL_Integer(-1); 1391 return new LSL_Integer(-1);
1392 return new LSL_Integer(detectedParams.TouchFace); 1392 return new LSL_Integer(detectedParams.TouchFace);
1393 } 1393 }
1394 1394
1395 /// <summary> 1395 /// <summary>
1396 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details 1396 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details
1397 /// </summary> 1397 /// </summary>
1398 public LSL_Vector llDetectedTouchNormal(int index) 1398 public LSL_Vector llDetectedTouchNormal(int index)
1399 { 1399 {
1400 m_host.AddScriptLPS(1); 1400 m_host.AddScriptLPS(1);
1401 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); 1401 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1402 if (detectedParams == null) 1402 if (detectedParams == null)
1403 return new LSL_Vector(); 1403 return new LSL_Vector();
1404 return detectedParams.TouchNormal; 1404 return detectedParams.TouchNormal;
1405 } 1405 }
1406 1406
1407 /// <summary> 1407 /// <summary>
1408 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details 1408 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details
1409 /// </summary> 1409 /// </summary>
1410 public LSL_Vector llDetectedTouchPos(int index) 1410 public LSL_Vector llDetectedTouchPos(int index)
1411 { 1411 {
1412 m_host.AddScriptLPS(1); 1412 m_host.AddScriptLPS(1);
1413 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); 1413 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1414 if (detectedParams == null) 1414 if (detectedParams == null)
1415 return new LSL_Vector(); 1415 return new LSL_Vector();
1416 return detectedParams.TouchPos; 1416 return detectedParams.TouchPos;
1417 } 1417 }
1418 1418
1419 /// <summary> 1419 /// <summary>
1420 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details 1420 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details
1421 /// </summary> 1421 /// </summary>
1422 public LSL_Vector llDetectedTouchST(int index) 1422 public LSL_Vector llDetectedTouchST(int index)
1423 { 1423 {
1424 m_host.AddScriptLPS(1); 1424 m_host.AddScriptLPS(1);
1425 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); 1425 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1426 if (detectedParams == null) 1426 if (detectedParams == null)
1427 return new LSL_Vector(-1.0, -1.0, 0.0); 1427 return new LSL_Vector(-1.0, -1.0, 0.0);
1428 return detectedParams.TouchST; 1428 return detectedParams.TouchST;
1429 } 1429 }
1430 1430
1431 /// <summary> 1431 /// <summary>
1432 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details 1432 /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details
1433 /// </summary> 1433 /// </summary>
1434 public LSL_Vector llDetectedTouchUV(int index) 1434 public LSL_Vector llDetectedTouchUV(int index)
1435 { 1435 {
1436 m_host.AddScriptLPS(1); 1436 m_host.AddScriptLPS(1);
1437 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); 1437 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index);
1438 if (detectedParams == null) 1438 if (detectedParams == null)
1439 return new LSL_Vector(-1.0, -1.0, 0.0); 1439 return new LSL_Vector(-1.0, -1.0, 0.0);
1440 return detectedParams.TouchUV; 1440 return detectedParams.TouchUV;
1441 } 1441 }
1442 1442
1443 public virtual void llDie() 1443 public virtual void llDie()
1444 { 1444 {
1445 m_host.AddScriptLPS(1); 1445 m_host.AddScriptLPS(1);
1446 throw new SelfDeleteException(); 1446 throw new SelfDeleteException();
1447 } 1447 }
1448 1448
1449 public LSL_Float llGround(LSL_Vector offset) 1449 public LSL_Float llGround(LSL_Vector offset)
1450 { 1450 {
1451 m_host.AddScriptLPS(1); 1451 m_host.AddScriptLPS(1);
1452 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; 1452 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
1453 1453
1454 //Get the slope normal. This gives us the equation of the plane tangent to the slope. 1454 //Get the slope normal. This gives us the equation of the plane tangent to the slope.
1455 LSL_Vector vsn = llGroundNormal(offset); 1455 LSL_Vector vsn = llGroundNormal(offset);
1456 1456
1457 // Clamp to valid position 1457 // Clamp to valid position
1458 if (pos.X < 0) 1458 if (pos.X < 0)
1459 pos.X = 0; 1459 pos.X = 0;
1460 else if (pos.X >= World.Heightmap.Width) 1460 else if (pos.X >= World.Heightmap.Width)
1461 pos.X = World.Heightmap.Width - 1; 1461 pos.X = World.Heightmap.Width - 1;
1462 if (pos.Y < 0) 1462 if (pos.Y < 0)
1463 pos.Y = 0; 1463 pos.Y = 0;
1464 else if (pos.Y >= World.Heightmap.Height) 1464 else if (pos.Y >= World.Heightmap.Height)
1465 pos.Y = World.Heightmap.Height - 1; 1465 pos.Y = World.Heightmap.Height - 1;
1466 1466
1467 //Get the height for the integer coordinates from the Heightmap 1467 //Get the height for the integer coordinates from the Heightmap
1468 float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y]; 1468 float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y];
1469 1469
1470 //Calculate the difference between the actual coordinates and the integer coordinates 1470 //Calculate the difference between the actual coordinates and the integer coordinates
1471 float xdiff = pos.X - (float)((int)pos.X); 1471 float xdiff = pos.X - (float)((int)pos.X);
1472 float ydiff = pos.Y - (float)((int)pos.Y); 1472 float ydiff = pos.Y - (float)((int)pos.Y);
1473 1473
1474 //Use the equation of the tangent plane to adjust the height to account for slope 1474 //Use the equation of the tangent plane to adjust the height to account for slope
1475 1475
1476 return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight; 1476 return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight;
1477 } 1477 }
1478 1478
1479 public LSL_Float llCloud(LSL_Vector offset) 1479 public LSL_Float llCloud(LSL_Vector offset)
1480 { 1480 {
1481 m_host.AddScriptLPS(1); 1481 m_host.AddScriptLPS(1);
1482 float cloudCover = 0f; 1482 float cloudCover = 0f;
1483 ICloudModule module = World.RequestModuleInterface<ICloudModule>(); 1483 ICloudModule module = World.RequestModuleInterface<ICloudModule>();
1484 if (module != null) 1484 if (module != null)
1485 { 1485 {
1486 Vector3 pos = m_host.GetWorldPosition(); 1486 Vector3 pos = m_host.GetWorldPosition();
1487 int x = (int)(pos.X + offset.x); 1487 int x = (int)(pos.X + offset.x);
1488 int y = (int)(pos.Y + offset.y); 1488 int y = (int)(pos.Y + offset.y);
1489 1489
1490 cloudCover = module.CloudCover(x, y, 0); 1490 cloudCover = module.CloudCover(x, y, 0);
1491 1491
1492 } 1492 }
1493 return cloudCover; 1493 return cloudCover;
1494 } 1494 }
1495 1495
1496 public LSL_Vector llWind(LSL_Vector offset) 1496 public LSL_Vector llWind(LSL_Vector offset)
1497 { 1497 {
1498 m_host.AddScriptLPS(1); 1498 m_host.AddScriptLPS(1);
1499 LSL_Vector wind = new LSL_Vector(0, 0, 0); 1499 LSL_Vector wind = new LSL_Vector(0, 0, 0);
1500 IWindModule module = World.RequestModuleInterface<IWindModule>(); 1500 IWindModule module = World.RequestModuleInterface<IWindModule>();
1501 if (module != null) 1501 if (module != null)
1502 { 1502 {
1503 Vector3 pos = m_host.GetWorldPosition(); 1503 Vector3 pos = m_host.GetWorldPosition();
1504 int x = (int)(pos.X + offset.x); 1504 int x = (int)(pos.X + offset.x);
1505 int y = (int)(pos.Y + offset.y); 1505 int y = (int)(pos.Y + offset.y);
1506 1506
1507 Vector3 windSpeed = module.WindSpeed(x, y, 0); 1507 Vector3 windSpeed = module.WindSpeed(x, y, 0);
1508 1508
1509 wind.x = windSpeed.X; 1509 wind.x = windSpeed.X;
1510 wind.y = windSpeed.Y; 1510 wind.y = windSpeed.Y;
1511 } 1511 }
1512 return wind; 1512 return wind;
1513 } 1513 }
1514 1514
1515 public void llSetStatus(int status, int value) 1515 public void llSetStatus(int status, int value)
1516 { 1516 {
1517 m_host.AddScriptLPS(1); 1517 m_host.AddScriptLPS(1);
1518 1518
1519 int statusrotationaxis = 0; 1519 int statusrotationaxis = 0;
1520 1520
1521 if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS) 1521 if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS)
1522 { 1522 {
1523 if (value != 0) 1523 if (value != 0)
1524 { 1524 {
1525 SceneObjectGroup group = m_host.ParentGroup; 1525 SceneObjectGroup group = m_host.ParentGroup;
1526 bool allow = true; 1526 bool allow = true;
1527 1527
1528 foreach (SceneObjectPart part in group.Parts) 1528 foreach (SceneObjectPart part in group.Parts)
1529 { 1529 {
1530 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) 1530 if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys)
1531 { 1531 {
1532 allow = false; 1532 allow = false;
1533 break; 1533 break;
1534 } 1534 }
1535 } 1535 }
1536 1536
1537 if (!allow) 1537 if (!allow)
1538 return; 1538 return;
1539 1539
1540 m_host.ScriptSetPhysicsStatus(true); 1540 m_host.ScriptSetPhysicsStatus(true);
1541 } 1541 }
1542 else 1542 else
1543 { 1543 {
1544 m_host.ScriptSetPhysicsStatus(false); 1544 m_host.ScriptSetPhysicsStatus(false);
1545 } 1545 }
1546 } 1546 }
1547 1547
1548 if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM) 1548 if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM)
1549 { 1549 {
1550 m_host.ParentGroup.ScriptSetPhantomStatus(value != 0); 1550 m_host.ParentGroup.ScriptSetPhantomStatus(value != 0);
1551 } 1551 }
1552 1552
1553 if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS) 1553 if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS)
1554 { 1554 {
1555 m_host.AddFlag(PrimFlags.CastShadows); 1555 m_host.AddFlag(PrimFlags.CastShadows);
1556 } 1556 }
1557 1557
1558 if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X) 1558 if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X)
1559 { 1559 {
1560 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X; 1560 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X;
1561 } 1561 }
1562 1562
1563 if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y) 1563 if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y)
1564 { 1564 {
1565 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y; 1565 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y;
1566 } 1566 }
1567 1567
1568 if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z) 1568 if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z)
1569 { 1569 {
1570 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z; 1570 statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z;
1571 } 1571 }
1572 1572
1573 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) 1573 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB)
1574 m_host.BlockGrab = value != 0; 1574 m_host.BlockGrab = value != 0;
1575 1575
1576 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) 1576 if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT)
1577 m_host.ParentGroup.BlockGrabOverride = value != 0; 1577 m_host.ParentGroup.BlockGrabOverride = value != 0;
1578 1578
1579 if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) 1579 if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE)
1580 { 1580 {
1581 if (value != 0) 1581 if (value != 0)
1582 m_host.SetDieAtEdge(true); 1582 m_host.SetDieAtEdge(true);
1583 else 1583 else
1584 m_host.SetDieAtEdge(false); 1584 m_host.SetDieAtEdge(false);
1585 } 1585 }
1586 1586
1587 if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE) 1587 if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE)
1588 { 1588 {
1589 if (value != 0) 1589 if (value != 0)
1590 m_host.SetReturnAtEdge(true); 1590 m_host.SetReturnAtEdge(true);
1591 else 1591 else
1592 m_host.SetReturnAtEdge(false); 1592 m_host.SetReturnAtEdge(false);
1593 } 1593 }
1594 1594
1595 if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX) 1595 if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX)
1596 { 1596 {
1597 if (value != 0) 1597 if (value != 0)
1598 m_host.SetStatusSandbox(true); 1598 m_host.SetStatusSandbox(true);
1599 else 1599 else
1600 m_host.SetStatusSandbox(false); 1600 m_host.SetStatusSandbox(false);
1601 } 1601 }
1602 1602
1603 if (statusrotationaxis != 0) 1603 if (statusrotationaxis != 0)
1604 { 1604 {
1605 m_host.SetAxisRotation(statusrotationaxis, value); 1605 m_host.SetAxisRotation(statusrotationaxis, value);
1606 } 1606 }
1607 } 1607 }
1608 1608
1609 private bool IsPhysical() 1609 private bool IsPhysical()
1610 { 1610 {
1611 return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics); 1611 return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics);
1612 } 1612 }
1613 1613
1614 public LSL_Integer llGetStatus(int status) 1614 public LSL_Integer llGetStatus(int status)
1615 { 1615 {
1616 m_host.AddScriptLPS(1); 1616 m_host.AddScriptLPS(1);
1617 // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString()); 1617 // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString());
1618 switch (status) 1618 switch (status)
1619 { 1619 {
1620 case ScriptBaseClass.STATUS_PHYSICS: 1620 case ScriptBaseClass.STATUS_PHYSICS:
1621 return IsPhysical() ? 1 : 0; 1621 return IsPhysical() ? 1 : 0;
1622 1622
1623 case ScriptBaseClass.STATUS_PHANTOM: 1623 case ScriptBaseClass.STATUS_PHANTOM:
1624 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) 1624 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom)
1625 { 1625 {
1626 return 1; 1626 return 1;
1627 } 1627 }
1628 return 0; 1628 return 0;
1629 1629
1630 case ScriptBaseClass.STATUS_CAST_SHADOWS: 1630 case ScriptBaseClass.STATUS_CAST_SHADOWS:
1631 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows) 1631 if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows)
1632 { 1632 {
1633 return 1; 1633 return 1;
1634 } 1634 }
1635 return 0; 1635 return 0;
1636 1636
1637 case ScriptBaseClass.STATUS_BLOCK_GRAB: 1637 case ScriptBaseClass.STATUS_BLOCK_GRAB:
1638 return m_host.BlockGrab ? 1 : 0; 1638 return m_host.BlockGrab ? 1 : 0;
1639 1639
1640 case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT: 1640 case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT:
1641 return m_host.ParentGroup.BlockGrabOverride ? 1 : 0; 1641 return m_host.ParentGroup.BlockGrabOverride ? 1 : 0;
1642 1642
1643 case ScriptBaseClass.STATUS_DIE_AT_EDGE: 1643 case ScriptBaseClass.STATUS_DIE_AT_EDGE:
1644 if (m_host.GetDieAtEdge()) 1644 if (m_host.GetDieAtEdge())
1645 return 1; 1645 return 1;
1646 else 1646 else
1647 return 0; 1647 return 0;
1648 1648
1649 case ScriptBaseClass.STATUS_RETURN_AT_EDGE: 1649 case ScriptBaseClass.STATUS_RETURN_AT_EDGE:
1650 if (m_host.GetReturnAtEdge()) 1650 if (m_host.GetReturnAtEdge())
1651 return 1; 1651 return 1;
1652 else 1652 else
1653 return 0; 1653 return 0;
1654 1654
1655 case ScriptBaseClass.STATUS_ROTATE_X: 1655 case ScriptBaseClass.STATUS_ROTATE_X:
1656 // if (m_host.GetAxisRotation(2) != 0) 1656 // if (m_host.GetAxisRotation(2) != 0)
1657 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0) 1657 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
1658 return 1; 1658 return 1;
1659 else 1659 else
1660 return 0; 1660 return 0;
1661 1661
1662 case ScriptBaseClass.STATUS_ROTATE_Y: 1662 case ScriptBaseClass.STATUS_ROTATE_Y:
1663 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0) 1663 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
1664 return 1; 1664 return 1;
1665 else 1665 else
1666 return 0; 1666 return 0;
1667 1667
1668 case ScriptBaseClass.STATUS_ROTATE_Z: 1668 case ScriptBaseClass.STATUS_ROTATE_Z:
1669 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0) 1669 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
1670 return 1; 1670 return 1;
1671 else 1671 else
1672 return 0; 1672 return 0;
1673 1673
1674 case ScriptBaseClass.STATUS_SANDBOX: 1674 case ScriptBaseClass.STATUS_SANDBOX:
1675 if (m_host.GetStatusSandbox()) 1675 if (m_host.GetStatusSandbox())
1676 return 1; 1676 return 1;
1677 else 1677 else
1678 return 0; 1678 return 0;
1679 } 1679 }
1680 return 0; 1680 return 0;
1681 } 1681 }
1682 1682
1683 public void llSetScale(LSL_Vector scale) 1683 public void llSetScale(LSL_Vector scale)
1684 { 1684 {
1685 m_host.AddScriptLPS(1); 1685 m_host.AddScriptLPS(1);
1686 SetScale(m_host, scale); 1686 SetScale(m_host, scale);
1687 } 1687 }
1688 1688
1689 protected void SetScale(SceneObjectPart part, LSL_Vector scale) 1689 protected void SetScale(SceneObjectPart part, LSL_Vector scale)
1690 { 1690 {
1691 // TODO: this needs to trigger a persistance save as well 1691 // TODO: this needs to trigger a persistance save as well
1692 if (part == null || part.ParentGroup.IsDeleted) 1692 if (part == null || part.ParentGroup.IsDeleted)
1693 return; 1693 return;
1694 1694
1695 // First we need to check whether or not we need to clamp the size of a physics-enabled prim 1695 // First we need to check whether or not we need to clamp the size of a physics-enabled prim
1696 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; 1696 PhysicsActor pa = part.ParentGroup.RootPart.PhysActor;
1697 if (pa != null && pa.IsPhysical) 1697 if (pa != null && pa.IsPhysical)
1698 { 1698 {
1699 scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); 1699 scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x));
1700 scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); 1700 scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y));
1701 scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); 1701 scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z));
1702 } 1702 }
1703 else 1703 else
1704 { 1704 {
1705 // If not physical, then we clamp the scale to the non-physical min/max 1705 // If not physical, then we clamp the scale to the non-physical min/max
1706 scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); 1706 scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x));
1707 scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); 1707 scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y));
1708 scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); 1708 scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z));
1709 } 1709 }
1710 1710
1711 Vector3 tmp = part.Scale; 1711 Vector3 tmp = part.Scale;
1712 tmp.X = (float)scale.x; 1712 tmp.X = (float)scale.x;
1713 tmp.Y = (float)scale.y; 1713 tmp.Y = (float)scale.y;
1714 tmp.Z = (float)scale.z; 1714 tmp.Z = (float)scale.z;
1715 part.Scale = tmp; 1715 part.Scale = tmp;
1716 part.SendFullUpdateToAllClients(); 1716 part.SendFullUpdateToAllClients();
1717 } 1717 }
1718 1718
1719 public LSL_Vector llGetScale() 1719 public LSL_Vector llGetScale()
1720 { 1720 {
1721 m_host.AddScriptLPS(1); 1721 m_host.AddScriptLPS(1);
1722 return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); 1722 return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z);
1723 } 1723 }
1724 1724
1725 public void llSetClickAction(int action) 1725 public void llSetClickAction(int action)
1726 { 1726 {
1727 m_host.AddScriptLPS(1); 1727 m_host.AddScriptLPS(1);
1728 m_host.ClickAction = (byte)action; 1728 m_host.ClickAction = (byte)action;
1729 m_host.ParentGroup.HasGroupChanged = true; 1729 m_host.ParentGroup.HasGroupChanged = true;
1730 m_host.ScheduleFullUpdate(); 1730 m_host.ScheduleFullUpdate();
1731 return; 1731 return;
1732 } 1732 }
1733 1733
1734 public void llSetColor(LSL_Vector color, int face) 1734 public void llSetColor(LSL_Vector color, int face)
1735 { 1735 {
1736 m_host.AddScriptLPS(1); 1736 m_host.AddScriptLPS(1);
1737 1737
1738 if (face == ScriptBaseClass.ALL_SIDES) 1738 if (face == ScriptBaseClass.ALL_SIDES)
1739 face = SceneObjectPart.ALL_SIDES; 1739 face = SceneObjectPart.ALL_SIDES;
1740 1740
1741 m_host.SetFaceColorAlpha(face, color, null); 1741 m_host.SetFaceColorAlpha(face, color, null);
1742 } 1742 }
1743 1743
1744 public void llSetContentType(LSL_Key id, LSL_Integer type) 1744 public void llSetContentType(LSL_Key id, LSL_Integer type)
1745 { 1745 {
1746 m_host.AddScriptLPS(1); 1746 m_host.AddScriptLPS(1);
1747 1747
1748 if (m_UrlModule == null) 1748 if (m_UrlModule == null)
1749 return; 1749 return;
1750 1750
1751 // Make sure the content type is text/plain to start with 1751 // Make sure the content type is text/plain to start with
1752 m_UrlModule.HttpContentType(new UUID(id), "text/plain"); 1752 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1753 1753
1754 // Is the object owner online and in the region 1754 // Is the object owner online and in the region
1755 ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID); 1755 ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID);
1756 if (agent == null || agent.IsChildAgent) 1756 if (agent == null || agent.IsChildAgent)
1757 return; // Fail if the owner is not in the same region 1757 return; // Fail if the owner is not in the same region
1758 1758
1759 // Is it the embeded browser? 1759 // Is it the embeded browser?
1760 string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent"); 1760 string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent");
1761 if (userAgent.IndexOf("SecondLife") < 0) 1761 if (userAgent.IndexOf("SecondLife") < 0)
1762 return; // Not the embedded browser. Is this check good enough? 1762 return; // Not the embedded browser. Is this check good enough?
1763 1763
1764 // Use the IP address of the client and check against the request 1764 // Use the IP address of the client and check against the request
1765 // seperate logins from the same IP will allow all of them to get non-text/plain as long 1765 // seperate logins from the same IP will allow all of them to get non-text/plain as long
1766 // as the owner is in the region. Same as SL! 1766 // as the owner is in the region. Same as SL!
1767 string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString(); 1767 string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString();
1768 string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr"); 1768 string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr");
1769 //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'"); 1769 //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'");
1770 if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "") 1770 if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "")
1771 return; 1771 return;
1772 if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "") 1772 if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "")
1773 return; 1773 return;
1774 1774
1775 // If the request isnt from the same IP address then the request cannot be from the owner 1775 // If the request isnt from the same IP address then the request cannot be from the owner
1776 if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim())) 1776 if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim()))
1777 return; 1777 return;
1778 1778
1779 switch (type) 1779 switch (type)
1780 { 1780 {
1781 case ScriptBaseClass.CONTENT_TYPE_HTML: 1781 case ScriptBaseClass.CONTENT_TYPE_HTML:
1782 m_UrlModule.HttpContentType(new UUID(id), "text/html"); 1782 m_UrlModule.HttpContentType(new UUID(id), "text/html");
1783 break; 1783 break;
1784 case ScriptBaseClass.CONTENT_TYPE_XML: 1784 case ScriptBaseClass.CONTENT_TYPE_XML:
1785 m_UrlModule.HttpContentType(new UUID(id), "application/xml"); 1785 m_UrlModule.HttpContentType(new UUID(id), "application/xml");
1786 break; 1786 break;
1787 case ScriptBaseClass.CONTENT_TYPE_XHTML: 1787 case ScriptBaseClass.CONTENT_TYPE_XHTML:
1788 m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml"); 1788 m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml");
1789 break; 1789 break;
1790 case ScriptBaseClass.CONTENT_TYPE_ATOM: 1790 case ScriptBaseClass.CONTENT_TYPE_ATOM:
1791 m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml"); 1791 m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml");
1792 break; 1792 break;
1793 case ScriptBaseClass.CONTENT_TYPE_JSON: 1793 case ScriptBaseClass.CONTENT_TYPE_JSON:
1794 m_UrlModule.HttpContentType(new UUID(id), "application/json"); 1794 m_UrlModule.HttpContentType(new UUID(id), "application/json");
1795 break; 1795 break;
1796 case ScriptBaseClass.CONTENT_TYPE_LLSD: 1796 case ScriptBaseClass.CONTENT_TYPE_LLSD:
1797 m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml"); 1797 m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml");
1798 break; 1798 break;
1799 case ScriptBaseClass.CONTENT_TYPE_FORM: 1799 case ScriptBaseClass.CONTENT_TYPE_FORM:
1800 m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded"); 1800 m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded");
1801 break; 1801 break;
1802 case ScriptBaseClass.CONTENT_TYPE_RSS: 1802 case ScriptBaseClass.CONTENT_TYPE_RSS:
1803 m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml"); 1803 m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml");
1804 break; 1804 break;
1805 default: 1805 default:
1806 m_UrlModule.HttpContentType(new UUID(id), "text/plain"); 1806 m_UrlModule.HttpContentType(new UUID(id), "text/plain");
1807 break; 1807 break;
1808 } 1808 }
1809 } 1809 }
1810 1810
1811 public void SetTexGen(SceneObjectPart part, int face,int style) 1811 public void SetTexGen(SceneObjectPart part, int face,int style)
1812 { 1812 {
1813 Primitive.TextureEntry tex = part.Shape.Textures; 1813 Primitive.TextureEntry tex = part.Shape.Textures;
1814 MappingType textype; 1814 MappingType textype;
1815 textype = MappingType.Default; 1815 textype = MappingType.Default;
1816 if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR) 1816 if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR)
1817 textype = MappingType.Planar; 1817 textype = MappingType.Planar;
1818 1818
1819 if (face >= 0 && face < GetNumberOfSides(part)) 1819 if (face >= 0 && face < GetNumberOfSides(part))
1820 { 1820 {
1821 tex.CreateFace((uint) face); 1821 tex.CreateFace((uint) face);
1822 tex.FaceTextures[face].TexMapType = textype; 1822 tex.FaceTextures[face].TexMapType = textype;
1823 part.UpdateTextureEntry(tex.GetBytes()); 1823 part.UpdateTextureEntry(tex.GetBytes());
1824 return; 1824 return;
1825 } 1825 }
1826 else if (face == ScriptBaseClass.ALL_SIDES) 1826 else if (face == ScriptBaseClass.ALL_SIDES)
1827 { 1827 {
1828 for (uint i = 0; i < GetNumberOfSides(part); i++) 1828 for (uint i = 0; i < GetNumberOfSides(part); i++)
1829 { 1829 {
1830 if (tex.FaceTextures[i] != null) 1830 if (tex.FaceTextures[i] != null)
1831 { 1831 {
1832 tex.FaceTextures[i].TexMapType = textype; 1832 tex.FaceTextures[i].TexMapType = textype;
1833 } 1833 }
1834 tex.DefaultTexture.TexMapType = textype; 1834 tex.DefaultTexture.TexMapType = textype;
1835 } 1835 }
1836 part.UpdateTextureEntry(tex.GetBytes()); 1836 part.UpdateTextureEntry(tex.GetBytes());
1837 return; 1837 return;
1838 } 1838 }
1839 } 1839 }
1840 1840
1841 public void SetGlow(SceneObjectPart part, int face, float glow) 1841 public void SetGlow(SceneObjectPart part, int face, float glow)
1842 { 1842 {
1843 Primitive.TextureEntry tex = part.Shape.Textures; 1843 Primitive.TextureEntry tex = part.Shape.Textures;
1844 if (face >= 0 && face < GetNumberOfSides(part)) 1844 if (face >= 0 && face < GetNumberOfSides(part))
1845 { 1845 {
1846 tex.CreateFace((uint) face); 1846 tex.CreateFace((uint) face);
1847 tex.FaceTextures[face].Glow = glow; 1847 tex.FaceTextures[face].Glow = glow;
1848 part.UpdateTextureEntry(tex.GetBytes()); 1848 part.UpdateTextureEntry(tex.GetBytes());
1849 return; 1849 return;
1850 } 1850 }
1851 else if (face == ScriptBaseClass.ALL_SIDES) 1851 else if (face == ScriptBaseClass.ALL_SIDES)
1852 { 1852 {
1853 for (uint i = 0; i < GetNumberOfSides(part); i++) 1853 for (uint i = 0; i < GetNumberOfSides(part); i++)
1854 { 1854 {
1855 if (tex.FaceTextures[i] != null) 1855 if (tex.FaceTextures[i] != null)
1856 { 1856 {
1857 tex.FaceTextures[i].Glow = glow; 1857 tex.FaceTextures[i].Glow = glow;
1858 } 1858 }
1859 tex.DefaultTexture.Glow = glow; 1859 tex.DefaultTexture.Glow = glow;
1860 } 1860 }
1861 part.UpdateTextureEntry(tex.GetBytes()); 1861 part.UpdateTextureEntry(tex.GetBytes());
1862 return; 1862 return;
1863 } 1863 }
1864 } 1864 }
1865 1865
1866 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) 1866 public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump)
1867 { 1867 {
1868 1868
1869 Shininess sval = new Shininess(); 1869 Shininess sval = new Shininess();
1870 1870
1871 switch (shiny) 1871 switch (shiny)
1872 { 1872 {
1873 case 0: 1873 case 0:
1874 sval = Shininess.None; 1874 sval = Shininess.None;
1875 break; 1875 break;
1876 case 1: 1876 case 1:
1877 sval = Shininess.Low; 1877 sval = Shininess.Low;
1878 break; 1878 break;
1879 case 2: 1879 case 2:
1880 sval = Shininess.Medium; 1880 sval = Shininess.Medium;
1881 break; 1881 break;
1882 case 3: 1882 case 3:
1883 sval = Shininess.High; 1883 sval = Shininess.High;
1884 break; 1884 break;
1885 default: 1885 default:
1886 sval = Shininess.None; 1886 sval = Shininess.None;
1887 break; 1887 break;
1888 } 1888 }
1889 1889
1890 Primitive.TextureEntry tex = part.Shape.Textures; 1890 Primitive.TextureEntry tex = part.Shape.Textures;
1891 if (face >= 0 && face < GetNumberOfSides(part)) 1891 if (face >= 0 && face < GetNumberOfSides(part))
1892 { 1892 {
1893 tex.CreateFace((uint) face); 1893 tex.CreateFace((uint) face);
1894 tex.FaceTextures[face].Shiny = sval; 1894 tex.FaceTextures[face].Shiny = sval;
1895 tex.FaceTextures[face].Bump = bump; 1895 tex.FaceTextures[face].Bump = bump;
1896 part.UpdateTextureEntry(tex.GetBytes()); 1896 part.UpdateTextureEntry(tex.GetBytes());
1897 return; 1897 return;
1898 } 1898 }
1899 else if (face == ScriptBaseClass.ALL_SIDES) 1899 else if (face == ScriptBaseClass.ALL_SIDES)
1900 { 1900 {
1901 for (uint i = 0; i < GetNumberOfSides(part); i++) 1901 for (uint i = 0; i < GetNumberOfSides(part); i++)
1902 { 1902 {
1903 if (tex.FaceTextures[i] != null) 1903 if (tex.FaceTextures[i] != null)
1904 { 1904 {
1905 tex.FaceTextures[i].Shiny = sval; 1905 tex.FaceTextures[i].Shiny = sval;
1906 tex.FaceTextures[i].Bump = bump; 1906 tex.FaceTextures[i].Bump = bump;
1907 } 1907 }
1908 tex.DefaultTexture.Shiny = sval; 1908 tex.DefaultTexture.Shiny = sval;
1909 tex.DefaultTexture.Bump = bump; 1909 tex.DefaultTexture.Bump = bump;
1910 } 1910 }
1911 part.UpdateTextureEntry(tex.GetBytes()); 1911 part.UpdateTextureEntry(tex.GetBytes());
1912 return; 1912 return;
1913 } 1913 }
1914 } 1914 }
1915 1915
1916 public void SetFullBright(SceneObjectPart part, int face, bool bright) 1916 public void SetFullBright(SceneObjectPart part, int face, bool bright)
1917 { 1917 {
1918 Primitive.TextureEntry tex = part.Shape.Textures; 1918 Primitive.TextureEntry tex = part.Shape.Textures;
1919 if (face >= 0 && face < GetNumberOfSides(part)) 1919 if (face >= 0 && face < GetNumberOfSides(part))
1920 { 1920 {
1921 tex.CreateFace((uint) face); 1921 tex.CreateFace((uint) face);
1922 tex.FaceTextures[face].Fullbright = bright; 1922 tex.FaceTextures[face].Fullbright = bright;
1923 part.UpdateTextureEntry(tex.GetBytes()); 1923 part.UpdateTextureEntry(tex.GetBytes());
1924 return; 1924 return;
1925 } 1925 }
1926 else if (face == ScriptBaseClass.ALL_SIDES) 1926 else if (face == ScriptBaseClass.ALL_SIDES)
1927 { 1927 {
1928 for (uint i = 0; i < GetNumberOfSides(part); i++) 1928 for (uint i = 0; i < GetNumberOfSides(part); i++)
1929 { 1929 {
1930 if (tex.FaceTextures[i] != null) 1930 if (tex.FaceTextures[i] != null)
1931 { 1931 {
1932 tex.FaceTextures[i].Fullbright = bright; 1932 tex.FaceTextures[i].Fullbright = bright;
1933 } 1933 }
1934 } 1934 }
1935 tex.DefaultTexture.Fullbright = bright; 1935 tex.DefaultTexture.Fullbright = bright;
1936 part.UpdateTextureEntry(tex.GetBytes()); 1936 part.UpdateTextureEntry(tex.GetBytes());
1937 return; 1937 return;
1938 } 1938 }
1939 } 1939 }
1940 1940
1941 public LSL_Float llGetAlpha(int face) 1941 public LSL_Float llGetAlpha(int face)
1942 { 1942 {
1943 m_host.AddScriptLPS(1); 1943 m_host.AddScriptLPS(1);
1944 1944
1945 return GetAlpha(m_host, face); 1945 return GetAlpha(m_host, face);
1946 } 1946 }
1947 1947
1948 protected LSL_Float GetAlpha(SceneObjectPart part, int face) 1948 protected LSL_Float GetAlpha(SceneObjectPart part, int face)
1949 { 1949 {
1950 Primitive.TextureEntry tex = part.Shape.Textures; 1950 Primitive.TextureEntry tex = part.Shape.Textures;
1951 if (face == ScriptBaseClass.ALL_SIDES) 1951 if (face == ScriptBaseClass.ALL_SIDES)
1952 { 1952 {
1953 int i; 1953 int i;
1954 double sum = 0.0; 1954 double sum = 0.0;
1955 for (i = 0 ; i < GetNumberOfSides(part); i++) 1955 for (i = 0 ; i < GetNumberOfSides(part); i++)
1956 sum += (double)tex.GetFace((uint)i).RGBA.A; 1956 sum += (double)tex.GetFace((uint)i).RGBA.A;
1957 return sum; 1957 return sum;
1958 } 1958 }
1959 if (face >= 0 && face < GetNumberOfSides(part)) 1959 if (face >= 0 && face < GetNumberOfSides(part))
1960 { 1960 {
1961 return (double)tex.GetFace((uint)face).RGBA.A; 1961 return (double)tex.GetFace((uint)face).RGBA.A;
1962 } 1962 }
1963 return 0.0; 1963 return 0.0;
1964 } 1964 }
1965 1965
1966 public void llSetAlpha(double alpha, int face) 1966 public void llSetAlpha(double alpha, int face)
1967 { 1967 {
1968 m_host.AddScriptLPS(1); 1968 m_host.AddScriptLPS(1);
1969 1969
1970 SetAlpha(m_host, alpha, face); 1970 SetAlpha(m_host, alpha, face);
1971 } 1971 }
1972 1972
1973 public void llSetLinkAlpha(int linknumber, double alpha, int face) 1973 public void llSetLinkAlpha(int linknumber, double alpha, int face)
1974 { 1974 {
1975 m_host.AddScriptLPS(1); 1975 m_host.AddScriptLPS(1);
1976 1976
1977 List<SceneObjectPart> parts = GetLinkParts(linknumber); 1977 List<SceneObjectPart> parts = GetLinkParts(linknumber);
1978 1978
1979 foreach (SceneObjectPart part in parts) 1979 foreach (SceneObjectPart part in parts)
1980 SetAlpha(part, alpha, face); 1980 SetAlpha(part, alpha, face);
1981 } 1981 }
1982 1982
1983 protected void SetAlpha(SceneObjectPart part, double alpha, int face) 1983 protected void SetAlpha(SceneObjectPart part, double alpha, int face)
1984 { 1984 {
1985 Primitive.TextureEntry tex = part.Shape.Textures; 1985 Primitive.TextureEntry tex = part.Shape.Textures;
1986 Color4 texcolor; 1986 Color4 texcolor;
1987 if (face >= 0 && face < GetNumberOfSides(part)) 1987 if (face >= 0 && face < GetNumberOfSides(part))
1988 { 1988 {
1989 texcolor = tex.CreateFace((uint)face).RGBA; 1989 texcolor = tex.CreateFace((uint)face).RGBA;
1990 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); 1990 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
1991 tex.FaceTextures[face].RGBA = texcolor; 1991 tex.FaceTextures[face].RGBA = texcolor;
1992 part.UpdateTextureEntry(tex.GetBytes()); 1992 part.UpdateTextureEntry(tex.GetBytes());
1993 return; 1993 return;
1994 } 1994 }
1995 else if (face == ScriptBaseClass.ALL_SIDES) 1995 else if (face == ScriptBaseClass.ALL_SIDES)
1996 { 1996 {
1997 for (int i = 0; i < GetNumberOfSides(part); i++) 1997 for (int i = 0; i < GetNumberOfSides(part); i++)
1998 { 1998 {
1999 if (tex.FaceTextures[i] != null) 1999 if (tex.FaceTextures[i] != null)
2000 { 2000 {
2001 texcolor = tex.FaceTextures[i].RGBA; 2001 texcolor = tex.FaceTextures[i].RGBA;
2002 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); 2002 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
2003 tex.FaceTextures[i].RGBA = texcolor; 2003 tex.FaceTextures[i].RGBA = texcolor;
2004 } 2004 }
2005 } 2005 }
2006 2006
2007 // In some cases, the default texture can be null, eg when every face 2007 // In some cases, the default texture can be null, eg when every face
2008 // has a unique texture 2008 // has a unique texture
2009 if (tex.DefaultTexture != null) 2009 if (tex.DefaultTexture != null)
2010 { 2010 {
2011 texcolor = tex.DefaultTexture.RGBA; 2011 texcolor = tex.DefaultTexture.RGBA;
2012 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); 2012 texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f);
2013 tex.DefaultTexture.RGBA = texcolor; 2013 tex.DefaultTexture.RGBA = texcolor;
2014 } 2014 }
2015 2015
2016 part.UpdateTextureEntry(tex.GetBytes()); 2016 part.UpdateTextureEntry(tex.GetBytes());
2017 return; 2017 return;
2018 } 2018 }
2019 } 2019 }
2020 2020
2021 /// <summary> 2021 /// <summary>
2022 /// Set flexi parameters of a part. 2022 /// Set flexi parameters of a part.
2023 /// 2023 ///
2024 /// FIXME: Much of this code should probably be within the part itself. 2024 /// FIXME: Much of this code should probably be within the part itself.
2025 /// </summary> 2025 /// </summary>
2026 /// <param name="part"></param> 2026 /// <param name="part"></param>
2027 /// <param name="flexi"></param> 2027 /// <param name="flexi"></param>
2028 /// <param name="softness"></param> 2028 /// <param name="softness"></param>
2029 /// <param name="gravity"></param> 2029 /// <param name="gravity"></param>
2030 /// <param name="friction"></param> 2030 /// <param name="friction"></param>
2031 /// <param name="wind"></param> 2031 /// <param name="wind"></param>
2032 /// <param name="tension"></param> 2032 /// <param name="tension"></param>
2033 /// <param name="Force"></param> 2033 /// <param name="Force"></param>
2034 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, 2034 protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction,
2035 float wind, float tension, LSL_Vector Force) 2035 float wind, float tension, LSL_Vector Force)
2036 { 2036 {
2037 if (part == null) 2037 if (part == null)
2038 return; 2038 return;
2039 2039
2040 if (flexi) 2040 if (flexi)
2041 { 2041 {
2042 part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do 2042 part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do
2043 // work once the prim is already flexi 2043 // work once the prim is already flexi
2044 part.Shape.FlexiSoftness = softness; 2044 part.Shape.FlexiSoftness = softness;
2045 part.Shape.FlexiGravity = gravity; 2045 part.Shape.FlexiGravity = gravity;
2046 part.Shape.FlexiDrag = friction; 2046 part.Shape.FlexiDrag = friction;
2047 part.Shape.FlexiWind = wind; 2047 part.Shape.FlexiWind = wind;
2048 part.Shape.FlexiTension = tension; 2048 part.Shape.FlexiTension = tension;
2049 part.Shape.FlexiForceX = (float)Force.x; 2049 part.Shape.FlexiForceX = (float)Force.x;
2050 part.Shape.FlexiForceY = (float)Force.y; 2050 part.Shape.FlexiForceY = (float)Force.y;
2051 part.Shape.FlexiForceZ = (float)Force.z; 2051 part.Shape.FlexiForceZ = (float)Force.z;
2052 part.Shape.PathCurve = (byte)Extrusion.Flexible; 2052 part.Shape.PathCurve = (byte)Extrusion.Flexible;
2053 } 2053 }
2054 else 2054 else
2055 { 2055 {
2056 // Other values not set, they do not seem to be sent to the viewer 2056 // Other values not set, they do not seem to be sent to the viewer
2057 // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off 2057 // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off
2058 part.Shape.PathCurve = (byte)Extrusion.Straight; 2058 part.Shape.PathCurve = (byte)Extrusion.Straight;
2059 part.Shape.FlexiEntry = false; 2059 part.Shape.FlexiEntry = false;
2060 } 2060 }
2061 part.ParentGroup.HasGroupChanged = true; 2061 part.ParentGroup.HasGroupChanged = true;
2062 part.ScheduleFullUpdate(); 2062 part.ScheduleFullUpdate();
2063 } 2063 }
2064 2064
2065 /// <summary> 2065 /// <summary>
2066 /// Set a light point on a part 2066 /// Set a light point on a part
2067 /// </summary> 2067 /// </summary>
2068 /// FIXME: Much of this code should probably be in SceneObjectGroup 2068 /// FIXME: Much of this code should probably be in SceneObjectGroup
2069 /// 2069 ///
2070 /// <param name="part"></param> 2070 /// <param name="part"></param>
2071 /// <param name="light"></param> 2071 /// <param name="light"></param>
2072 /// <param name="color"></param> 2072 /// <param name="color"></param>
2073 /// <param name="intensity"></param> 2073 /// <param name="intensity"></param>
2074 /// <param name="radius"></param> 2074 /// <param name="radius"></param>
2075 /// <param name="falloff"></param> 2075 /// <param name="falloff"></param>
2076 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) 2076 protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff)
2077 { 2077 {
2078 if (part == null) 2078 if (part == null)
2079 return; 2079 return;
2080 2080
2081 if (light) 2081 if (light)
2082 { 2082 {
2083 part.Shape.LightEntry = true; 2083 part.Shape.LightEntry = true;
2084 part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); 2084 part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f);
2085 part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); 2085 part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f);
2086 part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); 2086 part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f);
2087 part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f); 2087 part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f);
2088 part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f); 2088 part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f);
2089 part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f); 2089 part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f);
2090 } 2090 }
2091 else 2091 else
2092 { 2092 {
2093 part.Shape.LightEntry = false; 2093 part.Shape.LightEntry = false;
2094 } 2094 }
2095 2095
2096 part.ParentGroup.HasGroupChanged = true; 2096 part.ParentGroup.HasGroupChanged = true;
2097 part.ScheduleFullUpdate(); 2097 part.ScheduleFullUpdate();
2098 } 2098 }
2099 2099
2100 public LSL_Vector llGetColor(int face) 2100 public LSL_Vector llGetColor(int face)
2101 { 2101 {
2102 m_host.AddScriptLPS(1); 2102 m_host.AddScriptLPS(1);
2103 return GetColor(m_host, face); 2103 return GetColor(m_host, face);
2104 } 2104 }
2105 2105
2106 protected LSL_Vector GetColor(SceneObjectPart part, int face) 2106 protected LSL_Vector GetColor(SceneObjectPart part, int face)
2107 { 2107 {
2108 Primitive.TextureEntry tex = part.Shape.Textures; 2108 Primitive.TextureEntry tex = part.Shape.Textures;
2109 Color4 texcolor; 2109 Color4 texcolor;
2110 LSL_Vector rgb = new LSL_Vector(); 2110 LSL_Vector rgb = new LSL_Vector();
2111 if (face == ScriptBaseClass.ALL_SIDES) 2111 if (face == ScriptBaseClass.ALL_SIDES)
2112 { 2112 {
2113 int i; 2113 int i;
2114 2114
2115 for (i = 0 ; i < GetNumberOfSides(part); i++) 2115 for (i = 0 ; i < GetNumberOfSides(part); i++)
2116 { 2116 {
2117 texcolor = tex.GetFace((uint)i).RGBA; 2117 texcolor = tex.GetFace((uint)i).RGBA;
2118 rgb.x += texcolor.R; 2118 rgb.x += texcolor.R;
2119 rgb.y += texcolor.G; 2119 rgb.y += texcolor.G;
2120 rgb.z += texcolor.B; 2120 rgb.z += texcolor.B;
2121 } 2121 }
2122 2122
2123 rgb.x /= (float)GetNumberOfSides(part); 2123 rgb.x /= (float)GetNumberOfSides(part);
2124 rgb.y /= (float)GetNumberOfSides(part); 2124 rgb.y /= (float)GetNumberOfSides(part);
2125 rgb.z /= (float)GetNumberOfSides(part); 2125 rgb.z /= (float)GetNumberOfSides(part);
2126 2126
2127 return rgb; 2127 return rgb;
2128 } 2128 }
2129 2129
2130 if (face >= 0 && face < GetNumberOfSides(part)) 2130 if (face >= 0 && face < GetNumberOfSides(part))
2131 { 2131 {
2132 texcolor = tex.GetFace((uint)face).RGBA; 2132 texcolor = tex.GetFace((uint)face).RGBA;
2133 rgb.x = texcolor.R; 2133 rgb.x = texcolor.R;
2134 rgb.y = texcolor.G; 2134 rgb.y = texcolor.G;
2135 rgb.z = texcolor.B; 2135 rgb.z = texcolor.B;
2136 2136
2137 return rgb; 2137 return rgb;
2138 } 2138 }
2139 else 2139 else
2140 { 2140 {
2141 return new LSL_Vector(); 2141 return new LSL_Vector();
2142 } 2142 }
2143 } 2143 }
2144 2144
2145 public void llSetTexture(string texture, int face) 2145 public void llSetTexture(string texture, int face)
2146 { 2146 {
2147 m_host.AddScriptLPS(1); 2147 m_host.AddScriptLPS(1);
2148 SetTexture(m_host, texture, face); 2148 SetTexture(m_host, texture, face);
2149 ScriptSleep(m_sleepMsOnSetTexture); 2149 ScriptSleep(m_sleepMsOnSetTexture);
2150 } 2150 }
2151 2151
2152 public void llSetLinkTexture(int linknumber, string texture, int face) 2152 public void llSetLinkTexture(int linknumber, string texture, int face)
2153 { 2153 {
2154 m_host.AddScriptLPS(1); 2154 m_host.AddScriptLPS(1);
2155 2155
2156 List<SceneObjectPart> parts = GetLinkParts(linknumber); 2156 List<SceneObjectPart> parts = GetLinkParts(linknumber);
2157 2157
2158 foreach (SceneObjectPart part in parts) 2158 foreach (SceneObjectPart part in parts)
2159 SetTexture(part, texture, face); 2159 SetTexture(part, texture, face);
2160 2160
2161 ScriptSleep(m_sleepMsOnSetLinkTexture); 2161 ScriptSleep(m_sleepMsOnSetLinkTexture);
2162 } 2162 }
2163 2163
2164 protected void SetTexture(SceneObjectPart part, string texture, int face) 2164 protected void SetTexture(SceneObjectPart part, string texture, int face)
2165 { 2165 {
2166 UUID textureID = new UUID(); 2166 UUID textureID = new UUID();
2167 2167
2168 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); 2168 textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture);
2169 if (textureID == UUID.Zero) 2169 if (textureID == UUID.Zero)
2170 { 2170 {
2171 if (!UUID.TryParse(texture, out textureID)) 2171 if (!UUID.TryParse(texture, out textureID))
2172 return; 2172 return;
2173 } 2173 }
2174 2174
2175 Primitive.TextureEntry tex = part.Shape.Textures; 2175 Primitive.TextureEntry tex = part.Shape.Textures;
2176 2176
2177 if (face >= 0 && face < GetNumberOfSides(part)) 2177 if (face >= 0 && face < GetNumberOfSides(part))
2178 { 2178 {
2179 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2179 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2180 texface.TextureID = textureID; 2180 texface.TextureID = textureID;
2181 tex.FaceTextures[face] = texface; 2181 tex.FaceTextures[face] = texface;
2182 part.UpdateTextureEntry(tex.GetBytes()); 2182 part.UpdateTextureEntry(tex.GetBytes());
2183 return; 2183 return;
2184 } 2184 }
2185 else if (face == ScriptBaseClass.ALL_SIDES) 2185 else if (face == ScriptBaseClass.ALL_SIDES)
2186 { 2186 {
2187 for (uint i = 0; i < GetNumberOfSides(part); i++) 2187 for (uint i = 0; i < GetNumberOfSides(part); i++)
2188 { 2188 {
2189 if (tex.FaceTextures[i] != null) 2189 if (tex.FaceTextures[i] != null)
2190 { 2190 {
2191 tex.FaceTextures[i].TextureID = textureID; 2191 tex.FaceTextures[i].TextureID = textureID;
2192 } 2192 }
2193 } 2193 }
2194 tex.DefaultTexture.TextureID = textureID; 2194 tex.DefaultTexture.TextureID = textureID;
2195 part.UpdateTextureEntry(tex.GetBytes()); 2195 part.UpdateTextureEntry(tex.GetBytes());
2196 return; 2196 return;
2197 } 2197 }
2198 } 2198 }
2199 2199
2200 public void llScaleTexture(double u, double v, int face) 2200 public void llScaleTexture(double u, double v, int face)
2201 { 2201 {
2202 m_host.AddScriptLPS(1); 2202 m_host.AddScriptLPS(1);
2203 2203
2204 ScaleTexture(m_host, u, v, face); 2204 ScaleTexture(m_host, u, v, face);
2205 ScriptSleep(m_sleepMsOnScaleTexture); 2205 ScriptSleep(m_sleepMsOnScaleTexture);
2206 } 2206 }
2207 2207
2208 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) 2208 protected void ScaleTexture(SceneObjectPart part, double u, double v, int face)
2209 { 2209 {
2210 Primitive.TextureEntry tex = part.Shape.Textures; 2210 Primitive.TextureEntry tex = part.Shape.Textures;
2211 if (face >= 0 && face < GetNumberOfSides(part)) 2211 if (face >= 0 && face < GetNumberOfSides(part))
2212 { 2212 {
2213 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2213 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2214 texface.RepeatU = (float)u; 2214 texface.RepeatU = (float)u;
2215 texface.RepeatV = (float)v; 2215 texface.RepeatV = (float)v;
2216 tex.FaceTextures[face] = texface; 2216 tex.FaceTextures[face] = texface;
2217 part.UpdateTextureEntry(tex.GetBytes()); 2217 part.UpdateTextureEntry(tex.GetBytes());
2218 return; 2218 return;
2219 } 2219 }
2220 if (face == ScriptBaseClass.ALL_SIDES) 2220 if (face == ScriptBaseClass.ALL_SIDES)
2221 { 2221 {
2222 for (int i = 0; i < GetNumberOfSides(part); i++) 2222 for (int i = 0; i < GetNumberOfSides(part); i++)
2223 { 2223 {
2224 if (tex.FaceTextures[i] != null) 2224 if (tex.FaceTextures[i] != null)
2225 { 2225 {
2226 tex.FaceTextures[i].RepeatU = (float)u; 2226 tex.FaceTextures[i].RepeatU = (float)u;
2227 tex.FaceTextures[i].RepeatV = (float)v; 2227 tex.FaceTextures[i].RepeatV = (float)v;
2228 } 2228 }
2229 } 2229 }
2230 tex.DefaultTexture.RepeatU = (float)u; 2230 tex.DefaultTexture.RepeatU = (float)u;
2231 tex.DefaultTexture.RepeatV = (float)v; 2231 tex.DefaultTexture.RepeatV = (float)v;
2232 part.UpdateTextureEntry(tex.GetBytes()); 2232 part.UpdateTextureEntry(tex.GetBytes());
2233 return; 2233 return;
2234 } 2234 }
2235 } 2235 }
2236 2236
2237 public void llOffsetTexture(double u, double v, int face) 2237 public void llOffsetTexture(double u, double v, int face)
2238 { 2238 {
2239 m_host.AddScriptLPS(1); 2239 m_host.AddScriptLPS(1);
2240 OffsetTexture(m_host, u, v, face); 2240 OffsetTexture(m_host, u, v, face);
2241 ScriptSleep(m_sleepMsOnOffsetTexture); 2241 ScriptSleep(m_sleepMsOnOffsetTexture);
2242 } 2242 }
2243 2243
2244 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) 2244 protected void OffsetTexture(SceneObjectPart part, double u, double v, int face)
2245 { 2245 {
2246 Primitive.TextureEntry tex = part.Shape.Textures; 2246 Primitive.TextureEntry tex = part.Shape.Textures;
2247 if (face >= 0 && face < GetNumberOfSides(part)) 2247 if (face >= 0 && face < GetNumberOfSides(part))
2248 { 2248 {
2249 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2249 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2250 texface.OffsetU = (float)u; 2250 texface.OffsetU = (float)u;
2251 texface.OffsetV = (float)v; 2251 texface.OffsetV = (float)v;
2252 tex.FaceTextures[face] = texface; 2252 tex.FaceTextures[face] = texface;
2253 part.UpdateTextureEntry(tex.GetBytes()); 2253 part.UpdateTextureEntry(tex.GetBytes());
2254 return; 2254 return;
2255 } 2255 }
2256 if (face == ScriptBaseClass.ALL_SIDES) 2256 if (face == ScriptBaseClass.ALL_SIDES)
2257 { 2257 {
2258 for (int i = 0; i < GetNumberOfSides(part); i++) 2258 for (int i = 0; i < GetNumberOfSides(part); i++)
2259 { 2259 {
2260 if (tex.FaceTextures[i] != null) 2260 if (tex.FaceTextures[i] != null)
2261 { 2261 {
2262 tex.FaceTextures[i].OffsetU = (float)u; 2262 tex.FaceTextures[i].OffsetU = (float)u;
2263 tex.FaceTextures[i].OffsetV = (float)v; 2263 tex.FaceTextures[i].OffsetV = (float)v;
2264 } 2264 }
2265 } 2265 }
2266 tex.DefaultTexture.OffsetU = (float)u; 2266 tex.DefaultTexture.OffsetU = (float)u;
2267 tex.DefaultTexture.OffsetV = (float)v; 2267 tex.DefaultTexture.OffsetV = (float)v;
2268 part.UpdateTextureEntry(tex.GetBytes()); 2268 part.UpdateTextureEntry(tex.GetBytes());
2269 return; 2269 return;
2270 } 2270 }
2271 } 2271 }
2272 2272
2273 public void llRotateTexture(double rotation, int face) 2273 public void llRotateTexture(double rotation, int face)
2274 { 2274 {
2275 m_host.AddScriptLPS(1); 2275 m_host.AddScriptLPS(1);
2276 RotateTexture(m_host, rotation, face); 2276 RotateTexture(m_host, rotation, face);
2277 ScriptSleep(m_sleepMsOnRotateTexture); 2277 ScriptSleep(m_sleepMsOnRotateTexture);
2278 } 2278 }
2279 2279
2280 protected void RotateTexture(SceneObjectPart part, double rotation, int face) 2280 protected void RotateTexture(SceneObjectPart part, double rotation, int face)
2281 { 2281 {
2282 Primitive.TextureEntry tex = part.Shape.Textures; 2282 Primitive.TextureEntry tex = part.Shape.Textures;
2283 if (face >= 0 && face < GetNumberOfSides(part)) 2283 if (face >= 0 && face < GetNumberOfSides(part))
2284 { 2284 {
2285 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); 2285 Primitive.TextureEntryFace texface = tex.CreateFace((uint)face);
2286 texface.Rotation = (float)rotation; 2286 texface.Rotation = (float)rotation;
2287 tex.FaceTextures[face] = texface; 2287 tex.FaceTextures[face] = texface;
2288 part.UpdateTextureEntry(tex.GetBytes()); 2288 part.UpdateTextureEntry(tex.GetBytes());
2289 return; 2289 return;
2290 } 2290 }
2291 if (face == ScriptBaseClass.ALL_SIDES) 2291 if (face == ScriptBaseClass.ALL_SIDES)
2292 { 2292 {
2293 for (int i = 0; i < GetNumberOfSides(part); i++) 2293 for (int i = 0; i < GetNumberOfSides(part); i++)
2294 { 2294 {
2295 if (tex.FaceTextures[i] != null) 2295 if (tex.FaceTextures[i] != null)
2296 { 2296 {
2297 tex.FaceTextures[i].Rotation = (float)rotation; 2297 tex.FaceTextures[i].Rotation = (float)rotation;
2298 } 2298 }
2299 } 2299 }
2300 tex.DefaultTexture.Rotation = (float)rotation; 2300 tex.DefaultTexture.Rotation = (float)rotation;
2301 part.UpdateTextureEntry(tex.GetBytes()); 2301 part.UpdateTextureEntry(tex.GetBytes());
2302 return; 2302 return;
2303 } 2303 }
2304 } 2304 }
2305 2305
2306 public LSL_String llGetTexture(int face) 2306 public LSL_String llGetTexture(int face)
2307 { 2307 {
2308 m_host.AddScriptLPS(1); 2308 m_host.AddScriptLPS(1);
2309 return GetTexture(m_host, face); 2309 return GetTexture(m_host, face);
2310 } 2310 }
2311 2311
2312 protected LSL_String GetTexture(SceneObjectPart part, int face) 2312 protected LSL_String GetTexture(SceneObjectPart part, int face)
2313 { 2313 {
2314 Primitive.TextureEntry tex = part.Shape.Textures; 2314 Primitive.TextureEntry tex = part.Shape.Textures;
2315 if (face == ScriptBaseClass.ALL_SIDES) 2315 if (face == ScriptBaseClass.ALL_SIDES)
2316 { 2316 {
2317 face = 0; 2317 face = 0;
2318 } 2318 }
2319 2319
2320 if (face >= 0 && face < GetNumberOfSides(part)) 2320 if (face >= 0 && face < GetNumberOfSides(part))
2321 { 2321 {
2322 Primitive.TextureEntryFace texface; 2322 Primitive.TextureEntryFace texface;
2323 texface = tex.GetFace((uint)face); 2323 texface = tex.GetFace((uint)face);
2324 string texture = texface.TextureID.ToString(); 2324 string texture = texface.TextureID.ToString();
2325 2325
2326 lock (part.TaskInventory) 2326 lock (part.TaskInventory)
2327 { 2327 {
2328 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory) 2328 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory)
2329 { 2329 {
2330 if (inv.Value.AssetID == texface.TextureID) 2330 if (inv.Value.AssetID == texface.TextureID)
2331 { 2331 {
2332 texture = inv.Value.Name.ToString(); 2332 texture = inv.Value.Name.ToString();
2333 break; 2333 break;
2334 } 2334 }
2335 } 2335 }
2336 } 2336 }
2337 2337
2338 return texture; 2338 return texture;
2339 } 2339 }
2340 else 2340 else
2341 { 2341 {
2342 return UUID.Zero.ToString(); 2342 return UUID.Zero.ToString();
2343 } 2343 }
2344 } 2344 }
2345 2345
2346 public void llSetPos(LSL_Vector pos) 2346 public void llSetPos(LSL_Vector pos)
2347 { 2347 {
2348 m_host.AddScriptLPS(1); 2348 m_host.AddScriptLPS(1);
2349 2349
2350 SetPos(m_host, pos, true); 2350 SetPos(m_host, pos, true);
2351 2351
2352 ScriptSleep(m_sleepMsOnSetPos); 2352 ScriptSleep(m_sleepMsOnSetPos);
2353 } 2353 }
2354 2354
2355 /// <summary> 2355 /// <summary>
2356 /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos 2356 /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos
2357 /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into. 2357 /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into.
2358 /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking. 2358 /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking.
2359 /// </summary> 2359 /// </summary>
2360 /// <param name="pos"></param> 2360 /// <param name="pos"></param>
2361 /// <returns>1 if successful, 0 otherwise.</returns> 2361 /// <returns>1 if successful, 0 otherwise.</returns>
2362 public LSL_Integer llSetRegionPos(LSL_Vector pos) 2362 public LSL_Integer llSetRegionPos(LSL_Vector pos)
2363 { 2363 {
2364 m_host.AddScriptLPS(1); 2364 m_host.AddScriptLPS(1);
2365 2365
2366 // BEGIN WORKAROUND 2366 // BEGIN WORKAROUND
2367 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. 2367 // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND.
2368 // 2368 //
2369 // This workaround is to prevent silent failure of this function. 2369 // This workaround is to prevent silent failure of this function.
2370 // According to the specification on the SL Wiki, providing a position outside of the 2370 // According to the specification on the SL Wiki, providing a position outside of the
2371 if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY) 2371 if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY)
2372 { 2372 {
2373 return 0; 2373 return 0;
2374 } 2374 }
2375 // END WORK AROUND 2375 // END WORK AROUND
2376 else if ( // this is not part of the workaround if-block because it's not related to the workaround. 2376 else if ( // this is not part of the workaround if-block because it's not related to the workaround.
2377 IsPhysical() || 2377 IsPhysical() ||
2378 m_host.ParentGroup.IsAttachment || // return FALSE if attachment 2378 m_host.ParentGroup.IsAttachment || // return FALSE if attachment
2379 ( 2379 (
2380 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. 2380 pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region.
2381 pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region. 2381 pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region.
2382 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. 2382 pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region.
2383 pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region. 2383 pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region.
2384 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m 2384 pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m
2385 ) 2385 )
2386 ) 2386 )
2387 { 2387 {
2388 return 0; 2388 return 0;
2389 } 2389 }
2390 2390
2391 // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range. 2391 // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range.
2392 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. 2392 // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read.
2393 2393
2394 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; 2394 Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition;
2395 LandData here = World.GetLandData(objectPos); 2395 LandData here = World.GetLandData(objectPos);
2396 LandData there = World.GetLandData(pos); 2396 LandData there = World.GetLandData(pos);
2397 2397
2398 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. 2398 // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits.
2399 2399
2400 bool sameParcel = here.GlobalID == there.GlobalID; 2400 bool sameParcel = here.GlobalID == there.GlobalID;
2401 2401
2402 if (!sameParcel && !World.Permissions.CanRezObject( 2402 if (!sameParcel && !World.Permissions.CanRezObject(
2403 m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) 2403 m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos))
2404 { 2404 {
2405 return 0; 2405 return 0;
2406 } 2406 }
2407 2407
2408 SetPos(m_host.ParentGroup.RootPart, pos, false); 2408 SetPos(m_host.ParentGroup.RootPart, pos, false);
2409 2409
2410 return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0; 2410 return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0;
2411 } 2411 }
2412 2412
2413 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2413 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2414 // note linked setpos is capped "differently" 2414 // note linked setpos is capped "differently"
2415 private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end) 2415 private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end)
2416 { 2416 {
2417 if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor) 2417 if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor)
2418 return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start); 2418 return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start);
2419 else 2419 else
2420 return end; 2420 return end;
2421 } 2421 }
2422 2422
2423 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) 2423 protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos)
2424 { 2424 {
2425 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 2425 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
2426 return fromPos; 2426 return fromPos;
2427 2427
2428 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2428 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2429 2429
2430 2430
2431 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); 2431 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2432 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); 2432 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2433 2433
2434 if (part.ParentGroup.RootPart == part) 2434 if (part.ParentGroup.RootPart == part)
2435 { 2435 {
2436 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) 2436 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2437 targetPos.z = ground; 2437 targetPos.z = ground;
2438 } 2438 }
2439 LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); 2439 LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos);
2440 2440
2441 return real_vec; 2441 return real_vec;
2442 } 2442 }
2443 2443
2444 /// <summary> 2444 /// <summary>
2445 /// set object position, optionally capping the distance. 2445 /// set object position, optionally capping the distance.
2446 /// </summary> 2446 /// </summary>
2447 /// <param name="part"></param> 2447 /// <param name="part"></param>
2448 /// <param name="targetPos"></param> 2448 /// <param name="targetPos"></param>
2449 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> 2449 /// <param name="adjust">if TRUE, will cap the distance to 10m.</param>
2450 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) 2450 protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust)
2451 { 2451 {
2452 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) 2452 // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos)
2453 LSL_Vector currentPos = GetPartLocalPos(part); 2453 LSL_Vector currentPos = GetPartLocalPos(part);
2454 2454
2455 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); 2455 float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y);
2456 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); 2456 bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true);
2457 2457
2458 if (part.ParentGroup.RootPart == part) 2458 if (part.ParentGroup.RootPart == part)
2459 { 2459 {
2460 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) 2460 if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0)
2461 targetPos.z = ground; 2461 targetPos.z = ground;
2462 SceneObjectGroup parent = part.ParentGroup; 2462 SceneObjectGroup parent = part.ParentGroup;
2463 parent.UpdateGroupPosition(!adjust ? targetPos : 2463 parent.UpdateGroupPosition(!adjust ? targetPos :
2464 SetPosAdjust(currentPos, targetPos)); 2464 SetPosAdjust(currentPos, targetPos));
2465 } 2465 }
2466 else 2466 else
2467 { 2467 {
2468 part.OffsetPosition = !adjust ? targetPos : 2468 part.OffsetPosition = !adjust ? targetPos :
2469 SetPosAdjust(currentPos, targetPos); 2469 SetPosAdjust(currentPos, targetPos);
2470 SceneObjectGroup parent = part.ParentGroup; 2470 SceneObjectGroup parent = part.ParentGroup;
2471 parent.HasGroupChanged = true; 2471 parent.HasGroupChanged = true;
2472 parent.ScheduleGroupForTerseUpdate(); 2472 parent.ScheduleGroupForTerseUpdate();
2473 } 2473 }
2474 } 2474 }
2475 2475
2476 public LSL_Vector llGetPos() 2476 public LSL_Vector llGetPos()
2477 { 2477 {
2478 m_host.AddScriptLPS(1); 2478 m_host.AddScriptLPS(1);
2479 return m_host.GetWorldPosition(); 2479 return m_host.GetWorldPosition();
2480 } 2480 }
2481 2481
2482 public LSL_Vector llGetLocalPos() 2482 public LSL_Vector llGetLocalPos()
2483 { 2483 {
2484 m_host.AddScriptLPS(1); 2484 m_host.AddScriptLPS(1);
2485 return GetPartLocalPos(m_host); 2485 return GetPartLocalPos(m_host);
2486 } 2486 }
2487 2487
2488 protected LSL_Vector GetPartLocalPos(SceneObjectPart part) 2488 protected LSL_Vector GetPartLocalPos(SceneObjectPart part)
2489 { 2489 {
2490 m_host.AddScriptLPS(1); 2490 m_host.AddScriptLPS(1);
2491 2491
2492 Vector3 pos; 2492 Vector3 pos;
2493 2493
2494 if (!part.IsRoot) 2494 if (!part.IsRoot)
2495 { 2495 {
2496 pos = part.OffsetPosition; 2496 pos = part.OffsetPosition;
2497 } 2497 }
2498 else 2498 else
2499 { 2499 {
2500 if (part.ParentGroup.IsAttachment) 2500 if (part.ParentGroup.IsAttachment)
2501 { 2501 {
2502 pos = part.AttachedPos; 2502 pos = part.AttachedPos;
2503 } 2503 }
2504 else 2504 else
2505 { 2505 {
2506 pos = part.AbsolutePosition; 2506 pos = part.AbsolutePosition;
2507 } 2507 }
2508 } 2508 }
2509 2509
2510// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); 2510// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos);
2511 2511
2512 return new LSL_Vector(pos); 2512 return new LSL_Vector(pos);
2513 } 2513 }
2514 2514
2515 public void llSetRot(LSL_Rotation rot) 2515 public void llSetRot(LSL_Rotation rot)
2516 { 2516 {
2517 m_host.AddScriptLPS(1); 2517 m_host.AddScriptLPS(1);
2518 2518
2519 // try to let this work as in SL... 2519 // try to let this work as in SL...
2520 if (m_host.ParentID == 0) 2520 if (m_host.ParentID == 0)
2521 { 2521 {
2522 // special case: If we are root, rotate complete SOG to new rotation 2522 // special case: If we are root, rotate complete SOG to new rotation
2523 SetRot(m_host, rot); 2523 SetRot(m_host, rot);
2524 } 2524 }
2525 else 2525 else
2526 { 2526 {
2527 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 2527 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
2528 SceneObjectPart rootPart = m_host.ParentGroup.RootPart; 2528 SceneObjectPart rootPart = m_host.ParentGroup.RootPart;
2529 if (rootPart != null) // better safe than sorry 2529 if (rootPart != null) // better safe than sorry
2530 { 2530 {
2531 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); 2531 SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot);
2532 } 2532 }
2533 } 2533 }
2534 2534
2535 ScriptSleep(m_sleepMsOnSetRot); 2535 ScriptSleep(m_sleepMsOnSetRot);
2536 } 2536 }
2537 2537
2538 public void llSetLocalRot(LSL_Rotation rot) 2538 public void llSetLocalRot(LSL_Rotation rot)
2539 { 2539 {
2540 m_host.AddScriptLPS(1); 2540 m_host.AddScriptLPS(1);
2541 SetRot(m_host, rot); 2541 SetRot(m_host, rot);
2542 ScriptSleep(m_sleepMsOnSetLocalRot); 2542 ScriptSleep(m_sleepMsOnSetLocalRot);
2543 } 2543 }
2544 2544
2545 protected void SetRot(SceneObjectPart part, Quaternion rot) 2545 protected void SetRot(SceneObjectPart part, Quaternion rot)
2546 { 2546 {
2547 part.UpdateRotation(rot); 2547 part.UpdateRotation(rot);
2548 // Update rotation does not move the object in the physics scene if it's a linkset. 2548 // Update rotation does not move the object in the physics scene if it's a linkset.
2549 2549
2550//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type 2550//KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type
2551// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; 2551// part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition;
2552 2552
2553 // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line 2553 // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line
2554 // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt 2554 // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt
2555 // It's perfectly okay when the object is not an active physical body though. 2555 // It's perfectly okay when the object is not an active physical body though.
2556 // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against 2556 // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against
2557 // but only if the object is not physial and active. This is important for rotating doors. 2557 // but only if the object is not physial and active. This is important for rotating doors.
2558 // without the absoluteposition = absoluteposition happening, the doors do not move in the physics 2558 // without the absoluteposition = absoluteposition happening, the doors do not move in the physics
2559 // scene 2559 // scene
2560 PhysicsActor pa = part.PhysActor; 2560 PhysicsActor pa = part.PhysActor;
2561 2561
2562 if (pa != null && !pa.IsPhysical) 2562 if (pa != null && !pa.IsPhysical)
2563 { 2563 {
2564 part.ParentGroup.ResetChildPrimPhysicsPositions(); 2564 part.ParentGroup.ResetChildPrimPhysicsPositions();
2565 } 2565 }
2566 } 2566 }
2567 2567
2568 /// <summary> 2568 /// <summary>
2569 /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation 2569 /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
2570 /// </summary> 2570 /// </summary>
2571 public LSL_Rotation llGetRot() 2571 public LSL_Rotation llGetRot()
2572 { 2572 {
2573 // unlinked or root prim then use llRootRotation 2573 // unlinked or root prim then use llRootRotation
2574 // see llRootRotaion for references. 2574 // see llRootRotaion for references.
2575 if (m_host.LinkNum == 0 || m_host.LinkNum == 1) 2575 if (m_host.LinkNum == 0 || m_host.LinkNum == 1)
2576 { 2576 {
2577 return llGetRootRotation(); 2577 return llGetRootRotation();
2578 } 2578 }
2579 2579
2580 m_host.AddScriptLPS(1); 2580 m_host.AddScriptLPS(1);
2581 Quaternion q = m_host.GetWorldRotation(); 2581 Quaternion q = m_host.GetWorldRotation();
2582 return new LSL_Rotation(q.X, q.Y, q.Z, q.W); 2582 return new LSL_Rotation(q.X, q.Y, q.Z, q.W);
2583 } 2583 }
2584 2584
2585 private LSL_Rotation GetPartRot(SceneObjectPart part) 2585 private LSL_Rotation GetPartRot(SceneObjectPart part)
2586 { 2586 {
2587 Quaternion q; 2587 Quaternion q;
2588 if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim 2588 if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim
2589 { 2589 {
2590 if (part.ParentGroup.AttachmentPoint != 0) 2590 if (part.ParentGroup.AttachmentPoint != 0)
2591 { 2591 {
2592 ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar); 2592 ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar);
2593 if (avatar != null) 2593 if (avatar != null)
2594 { 2594 {
2595 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 2595 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
2596 q = avatar.CameraRotation; // Mouselook 2596 q = avatar.CameraRotation; // Mouselook
2597 else 2597 else
2598 q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate 2598 q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
2599 } 2599 }
2600 else 2600 else
2601 q = part.ParentGroup.GroupRotation; // Likely never get here but just in case 2601 q = part.ParentGroup.GroupRotation; // Likely never get here but just in case
2602 } 2602 }
2603 else 2603 else
2604 q = part.ParentGroup.GroupRotation; // just the group rotation 2604 q = part.ParentGroup.GroupRotation; // just the group rotation
2605 2605
2606 return new LSL_Rotation(q); 2606 return new LSL_Rotation(q);
2607 } 2607 }
2608 2608
2609 return new LSL_Rotation(part.GetWorldRotation()); 2609 return new LSL_Rotation(part.GetWorldRotation());
2610 } 2610 }
2611 2611
2612 public LSL_Rotation llGetLocalRot() 2612 public LSL_Rotation llGetLocalRot()
2613 { 2613 {
2614 m_host.AddScriptLPS(1); 2614 m_host.AddScriptLPS(1);
2615 2615
2616 return new LSL_Rotation(m_host.RotationOffset); 2616 return new LSL_Rotation(m_host.RotationOffset);
2617 } 2617 }
2618 2618
2619 public void llSetForce(LSL_Vector force, int local) 2619 public void llSetForce(LSL_Vector force, int local)
2620 { 2620 {
2621 m_host.AddScriptLPS(1); 2621 m_host.AddScriptLPS(1);
2622 2622
2623 if (!m_host.ParentGroup.IsDeleted) 2623 if (!m_host.ParentGroup.IsDeleted)
2624 { 2624 {
2625 if (local != 0) 2625 if (local != 0)
2626 force *= llGetRot(); 2626 force *= llGetRot();
2627 2627
2628 m_host.ParentGroup.RootPart.SetForce(force); 2628 m_host.ParentGroup.RootPart.SetForce(force);
2629 } 2629 }
2630 } 2630 }
2631 2631
2632 public LSL_Vector llGetForce() 2632 public LSL_Vector llGetForce()
2633 { 2633 {
2634 LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0); 2634 LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0);
2635 2635
2636 m_host.AddScriptLPS(1); 2636 m_host.AddScriptLPS(1);
2637 2637
2638 if (!m_host.ParentGroup.IsDeleted) 2638 if (!m_host.ParentGroup.IsDeleted)
2639 { 2639 {
2640 force = m_host.ParentGroup.RootPart.GetForce(); 2640 force = m_host.ParentGroup.RootPart.GetForce();
2641 } 2641 }
2642 2642
2643 return force; 2643 return force;
2644 } 2644 }
2645 2645
2646 public void llSetVelocity(LSL_Vector velocity, int local) 2646 public void llSetVelocity(LSL_Vector velocity, int local)
2647 { 2647 {
2648 m_host.AddScriptLPS(1); 2648 m_host.AddScriptLPS(1);
2649 2649
2650 if (!m_host.ParentGroup.IsDeleted) 2650 if (!m_host.ParentGroup.IsDeleted)
2651 { 2651 {
2652 if (local != 0) 2652 if (local != 0)
2653 velocity *= llGetRot(); 2653 velocity *= llGetRot();
2654 2654
2655 m_host.ParentGroup.RootPart.Velocity = velocity; 2655 m_host.ParentGroup.RootPart.Velocity = velocity;
2656 } 2656 }
2657 } 2657 }
2658 2658
2659 public void llSetAngularVelocity(LSL_Vector angularVelocity, int local) 2659 public void llSetAngularVelocity(LSL_Vector angularVelocity, int local)
2660 { 2660 {
2661 m_host.AddScriptLPS(1); 2661 m_host.AddScriptLPS(1);
2662 2662
2663 if (!m_host.ParentGroup.IsDeleted) 2663 if (!m_host.ParentGroup.IsDeleted)
2664 { 2664 {
2665 if (local != 0) 2665 if (local != 0)
2666 angularVelocity *= llGetRot(); 2666 angularVelocity *= llGetRot();
2667 2667
2668 m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity; 2668 m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity;
2669 } 2669 }
2670 } 2670 }
2671 2671
2672 public LSL_Integer llTarget(LSL_Vector position, double range) 2672 public LSL_Integer llTarget(LSL_Vector position, double range)
2673 { 2673 {
2674 m_host.AddScriptLPS(1); 2674 m_host.AddScriptLPS(1);
2675 return m_host.ParentGroup.registerTargetWaypoint(position, 2675 return m_host.ParentGroup.registerTargetWaypoint(position,
2676 (float)range); 2676 (float)range);
2677 } 2677 }
2678 2678
2679 public void llTargetRemove(int number) 2679 public void llTargetRemove(int number)
2680 { 2680 {
2681 m_host.AddScriptLPS(1); 2681 m_host.AddScriptLPS(1);
2682 m_host.ParentGroup.unregisterTargetWaypoint(number); 2682 m_host.ParentGroup.unregisterTargetWaypoint(number);
2683 } 2683 }
2684 2684
2685 public LSL_Integer llRotTarget(LSL_Rotation rot, double error) 2685 public LSL_Integer llRotTarget(LSL_Rotation rot, double error)
2686 { 2686 {
2687 m_host.AddScriptLPS(1); 2687 m_host.AddScriptLPS(1);
2688 return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); 2688 return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error);
2689 } 2689 }
2690 2690
2691 public void llRotTargetRemove(int number) 2691 public void llRotTargetRemove(int number)
2692 { 2692 {
2693 m_host.AddScriptLPS(1); 2693 m_host.AddScriptLPS(1);
2694 m_host.ParentGroup.unregisterRotTargetWaypoint(number); 2694 m_host.ParentGroup.unregisterRotTargetWaypoint(number);
2695 } 2695 }
2696 2696
2697 public void llMoveToTarget(LSL_Vector target, double tau) 2697 public void llMoveToTarget(LSL_Vector target, double tau)
2698 { 2698 {
2699 m_host.AddScriptLPS(1); 2699 m_host.AddScriptLPS(1);
2700 m_host.MoveToTarget(target, (float)tau); 2700 m_host.MoveToTarget(target, (float)tau);
2701 } 2701 }
2702 2702
2703 public void llStopMoveToTarget() 2703 public void llStopMoveToTarget()
2704 { 2704 {
2705 m_host.AddScriptLPS(1); 2705 m_host.AddScriptLPS(1);
2706 m_host.StopMoveToTarget(); 2706 m_host.StopMoveToTarget();
2707 } 2707 }
2708 2708
2709 public void llApplyImpulse(LSL_Vector force, int local) 2709 public void llApplyImpulse(LSL_Vector force, int local)
2710 { 2710 {
2711 m_host.AddScriptLPS(1); 2711 m_host.AddScriptLPS(1);
2712 //No energy force yet 2712 //No energy force yet
2713 Vector3 v = force; 2713 Vector3 v = force;
2714 if (v.Length() > 20000.0f) 2714 if (v.Length() > 20000.0f)
2715 { 2715 {
2716 v.Normalize(); 2716 v.Normalize();
2717 v = v * 20000.0f; 2717 v = v * 20000.0f;
2718 } 2718 }
2719 m_host.ApplyImpulse(v, local != 0); 2719 m_host.ApplyImpulse(v, local != 0);
2720 } 2720 }
2721 2721
2722 public void llApplyRotationalImpulse(LSL_Vector force, int local) 2722 public void llApplyRotationalImpulse(LSL_Vector force, int local)
2723 { 2723 {
2724 m_host.AddScriptLPS(1); 2724 m_host.AddScriptLPS(1);
2725 m_host.ApplyAngularImpulse(force, local != 0); 2725 m_host.ApplyAngularImpulse(force, local != 0);
2726 } 2726 }
2727 2727
2728 public void llSetTorque(LSL_Vector torque, int local) 2728 public void llSetTorque(LSL_Vector torque, int local)
2729 { 2729 {
2730 m_host.AddScriptLPS(1); 2730 m_host.AddScriptLPS(1);
2731 m_host.SetAngularImpulse(torque, local != 0); 2731 m_host.SetAngularImpulse(torque, local != 0);
2732 } 2732 }
2733 2733
2734 public LSL_Vector llGetTorque() 2734 public LSL_Vector llGetTorque()
2735 { 2735 {
2736 m_host.AddScriptLPS(1); 2736 m_host.AddScriptLPS(1);
2737 2737
2738 return new LSL_Vector(m_host.ParentGroup.GetTorque()); 2738 return new LSL_Vector(m_host.ParentGroup.GetTorque());
2739 } 2739 }
2740 2740
2741 public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) 2741 public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local)
2742 { 2742 {
2743 m_host.AddScriptLPS(1); 2743 m_host.AddScriptLPS(1);
2744 llSetForce(force, local); 2744 llSetForce(force, local);
2745 llSetTorque(torque, local); 2745 llSetTorque(torque, local);
2746 } 2746 }
2747 2747
2748 public LSL_Vector llGetVel() 2748 public LSL_Vector llGetVel()
2749 { 2749 {
2750 m_host.AddScriptLPS(1); 2750 m_host.AddScriptLPS(1);
2751 2751
2752 Vector3 vel; 2752 Vector3 vel;
2753 2753
2754 if (m_host.ParentGroup.IsAttachment) 2754 if (m_host.ParentGroup.IsAttachment)
2755 { 2755 {
2756 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 2756 ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
2757 vel = avatar.GetWorldVelocity(); 2757 vel = avatar.GetWorldVelocity();
2758 } 2758 }
2759 else 2759 else
2760 { 2760 {
2761 vel = m_host.Velocity; 2761 vel = m_host.Velocity;
2762 } 2762 }
2763 2763
2764 return new LSL_Vector(vel); 2764 return new LSL_Vector(vel);
2765 } 2765 }
2766 2766
2767 public LSL_Vector llGetAccel() 2767 public LSL_Vector llGetAccel()
2768 { 2768 {
2769 m_host.AddScriptLPS(1); 2769 m_host.AddScriptLPS(1);
2770 2770
2771 return new LSL_Vector(m_host.Acceleration); 2771 return new LSL_Vector(m_host.Acceleration);
2772 } 2772 }
2773 2773
2774 public LSL_Vector llGetOmega() 2774 public LSL_Vector llGetOmega()
2775 { 2775 {
2776 m_host.AddScriptLPS(1); 2776 m_host.AddScriptLPS(1);
2777 2777
2778 return new LSL_Vector(m_host.AngularVelocity); 2778 return new LSL_Vector(m_host.AngularVelocity);
2779 } 2779 }
2780 2780
2781 public LSL_Float llGetTimeOfDay() 2781 public LSL_Float llGetTimeOfDay()
2782 { 2782 {
2783 m_host.AddScriptLPS(1); 2783 m_host.AddScriptLPS(1);
2784 return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)); 2784 return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4));
2785 } 2785 }
2786 2786
2787 public LSL_Float llGetWallclock() 2787 public LSL_Float llGetWallclock()
2788 { 2788 {
2789 m_host.AddScriptLPS(1); 2789 m_host.AddScriptLPS(1);
2790 return DateTime.Now.TimeOfDay.TotalSeconds; 2790 return DateTime.Now.TimeOfDay.TotalSeconds;
2791 } 2791 }
2792 2792
2793 public LSL_Float llGetTime() 2793 public LSL_Float llGetTime()
2794 { 2794 {
2795 m_host.AddScriptLPS(1); 2795 m_host.AddScriptLPS(1);
2796 TimeSpan ScriptTime = DateTime.Now - m_timer; 2796 TimeSpan ScriptTime = DateTime.Now - m_timer;
2797 return (double)(ScriptTime.TotalMilliseconds / 1000); 2797 return (double)(ScriptTime.TotalMilliseconds / 1000);
2798 } 2798 }
2799 2799
2800 public void llResetTime() 2800 public void llResetTime()
2801 { 2801 {
2802 m_host.AddScriptLPS(1); 2802 m_host.AddScriptLPS(1);
2803 m_timer = DateTime.Now; 2803 m_timer = DateTime.Now;
2804 } 2804 }
2805 2805
2806 public LSL_Float llGetAndResetTime() 2806 public LSL_Float llGetAndResetTime()
2807 { 2807 {
2808 m_host.AddScriptLPS(1); 2808 m_host.AddScriptLPS(1);
2809 TimeSpan ScriptTime = DateTime.Now - m_timer; 2809 TimeSpan ScriptTime = DateTime.Now - m_timer;
2810 m_timer = DateTime.Now; 2810 m_timer = DateTime.Now;
2811 return (double)(ScriptTime.TotalMilliseconds / 1000); 2811 return (double)(ScriptTime.TotalMilliseconds / 1000);
2812 } 2812 }
2813 2813
2814 public void llSound(string sound, double volume, int queue, int loop) 2814 public void llSound(string sound, double volume, int queue, int loop)
2815 { 2815 {
2816 m_host.AddScriptLPS(1); 2816 m_host.AddScriptLPS(1);
2817 Deprecated("llSound", "Use llPlaySound instead"); 2817 Deprecated("llSound", "Use llPlaySound instead");
2818 } 2818 }
2819 2819
2820 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound 2820 // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound
2821 // 20080530 Updated to remove code duplication 2821 // 20080530 Updated to remove code duplication
2822 public void llPlaySound(string sound, double volume) 2822 public void llPlaySound(string sound, double volume)
2823 { 2823 {
2824 m_host.AddScriptLPS(1); 2824 m_host.AddScriptLPS(1);
2825 2825
2826 // send the sound, once, to all clients in range 2826 // send the sound, once, to all clients in range
2827 if (m_SoundModule != null) 2827 if (m_SoundModule != null)
2828 { 2828 {
2829 m_SoundModule.SendSound( 2829 m_SoundModule.SendSound(
2830 m_host.UUID, 2830 m_host.UUID,
2831 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), 2831 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound),
2832 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None, 2832 volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None,
2833 0, false, false); 2833 0, false, false);
2834 } 2834 }
2835 } 2835 }
2836 2836
2837 public void llLoopSound(string sound, double volume) 2837 public void llLoopSound(string sound, double volume)
2838 { 2838 {
2839 m_host.AddScriptLPS(1); 2839 m_host.AddScriptLPS(1);
2840 if (m_SoundModule != null) 2840 if (m_SoundModule != null)
2841 { 2841 {
2842 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 2842 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2843 volume, 20, false); 2843 volume, 20, false);
2844 } 2844 }
2845 } 2845 }
2846 2846
2847 public void llLoopSoundMaster(string sound, double volume) 2847 public void llLoopSoundMaster(string sound, double volume)
2848 { 2848 {
2849 m_host.AddScriptLPS(1); 2849 m_host.AddScriptLPS(1);
2850 if (m_SoundModule != null) 2850 if (m_SoundModule != null)
2851 { 2851 {
2852 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 2852 m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound),
2853 volume, 20, true); 2853 volume, 20, true);
2854 } 2854 }
2855 } 2855 }
2856 2856
2857 public void llLoopSoundSlave(string sound, double volume) 2857 public void llLoopSoundSlave(string sound, double volume)
2858 { 2858 {
2859 m_host.AddScriptLPS(1); 2859 m_host.AddScriptLPS(1);
2860 lock (m_host.ParentGroup.LoopSoundSlavePrims) 2860 lock (m_host.ParentGroup.LoopSoundSlavePrims)
2861 { 2861 {
2862 m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host); 2862 m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host);
2863 } 2863 }
2864 } 2864 }
2865 2865
2866 public void llPlaySoundSlave(string sound, double volume) 2866 public void llPlaySoundSlave(string sound, double volume)
2867 { 2867 {
2868 m_host.AddScriptLPS(1); 2868 m_host.AddScriptLPS(1);
2869 2869
2870 // send the sound, once, to all clients in range 2870 // send the sound, once, to all clients in range
2871 if (m_SoundModule != null) 2871 if (m_SoundModule != null)
2872 { 2872 {
2873 m_SoundModule.SendSound(m_host.UUID, 2873 m_SoundModule.SendSound(m_host.UUID,
2874 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, 2874 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0,
2875 0, true, false); 2875 0, true, false);
2876 } 2876 }
2877 } 2877 }
2878 2878
2879 public void llTriggerSound(string sound, double volume) 2879 public void llTriggerSound(string sound, double volume)
2880 { 2880 {
2881 m_host.AddScriptLPS(1); 2881 m_host.AddScriptLPS(1);
2882 // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. 2882 // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory.
2883 if (m_SoundModule != null) 2883 if (m_SoundModule != null)
2884 { 2884 {
2885 m_SoundModule.SendSound(m_host.UUID, 2885 m_SoundModule.SendSound(m_host.UUID,
2886 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0, 2886 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0,
2887 false, false); 2887 false, false);
2888 } 2888 }
2889 } 2889 }
2890 2890
2891 public void llStopSound() 2891 public void llStopSound()
2892 { 2892 {
2893 m_host.AddScriptLPS(1); 2893 m_host.AddScriptLPS(1);
2894 2894
2895 if (m_SoundModule != null) 2895 if (m_SoundModule != null)
2896 m_SoundModule.StopSound(m_host.UUID); 2896 m_SoundModule.StopSound(m_host.UUID);
2897 } 2897 }
2898 2898
2899 public void llPreloadSound(string sound) 2899 public void llPreloadSound(string sound)
2900 { 2900 {
2901 m_host.AddScriptLPS(1); 2901 m_host.AddScriptLPS(1);
2902 if (m_SoundModule != null) 2902 if (m_SoundModule != null)
2903 m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0); 2903 m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0);
2904 ScriptSleep(m_sleepMsOnPreloadSound); 2904 ScriptSleep(m_sleepMsOnPreloadSound);
2905 } 2905 }
2906 2906
2907 /// <summary> 2907 /// <summary>
2908 /// Return a portion of the designated string bounded by 2908 /// Return a portion of the designated string bounded by
2909 /// inclusive indices (start and end). As usual, the negative 2909 /// inclusive indices (start and end). As usual, the negative
2910 /// indices, and the tolerance for out-of-bound values, makes 2910 /// indices, and the tolerance for out-of-bound values, makes
2911 /// this more complicated than it might otherwise seem. 2911 /// this more complicated than it might otherwise seem.
2912 /// </summary> 2912 /// </summary>
2913 public LSL_String llGetSubString(string src, int start, int end) 2913 public LSL_String llGetSubString(string src, int start, int end)
2914 { 2914 {
2915 m_host.AddScriptLPS(1); 2915 m_host.AddScriptLPS(1);
2916 2916
2917 // Normalize indices (if negative). 2917 // Normalize indices (if negative).
2918 // After normlaization they may still be 2918 // After normlaization they may still be
2919 // negative, but that is now relative to 2919 // negative, but that is now relative to
2920 // the start, rather than the end, of the 2920 // the start, rather than the end, of the
2921 // sequence. 2921 // sequence.
2922 2922
2923 if (start < 0) 2923 if (start < 0)
2924 { 2924 {
2925 start = src.Length+start; 2925 start = src.Length+start;
2926 } 2926 }
2927 if (end < 0) 2927 if (end < 0)
2928 { 2928 {
2929 end = src.Length+end; 2929 end = src.Length+end;
2930 } 2930 }
2931 2931
2932 // Conventional substring 2932 // Conventional substring
2933 if (start <= end) 2933 if (start <= end)
2934 { 2934 {
2935 // Implies both bounds are out-of-range. 2935 // Implies both bounds are out-of-range.
2936 if (end < 0 || start >= src.Length) 2936 if (end < 0 || start >= src.Length)
2937 { 2937 {
2938 return String.Empty; 2938 return String.Empty;
2939 } 2939 }
2940 // If end is positive, then it directly 2940 // If end is positive, then it directly
2941 // corresponds to the lengt of the substring 2941 // corresponds to the lengt of the substring
2942 // needed (plus one of course). BUT, it 2942 // needed (plus one of course). BUT, it
2943 // must be within bounds. 2943 // must be within bounds.
2944 if (end >= src.Length) 2944 if (end >= src.Length)
2945 { 2945 {
2946 end = src.Length-1; 2946 end = src.Length-1;
2947 } 2947 }
2948 2948
2949 if (start < 0) 2949 if (start < 0)
2950 { 2950 {
2951 return src.Substring(0,end+1); 2951 return src.Substring(0,end+1);
2952 } 2952 }
2953 // Both indices are positive 2953 // Both indices are positive
2954 return src.Substring(start, (end+1) - start); 2954 return src.Substring(start, (end+1) - start);
2955 } 2955 }
2956 2956
2957 // Inverted substring (end < start) 2957 // Inverted substring (end < start)
2958 else 2958 else
2959 { 2959 {
2960 // Implies both indices are below the 2960 // Implies both indices are below the
2961 // lower bound. In the inverted case, that 2961 // lower bound. In the inverted case, that
2962 // means the entire string will be returned 2962 // means the entire string will be returned
2963 // unchanged. 2963 // unchanged.
2964 if (start < 0) 2964 if (start < 0)
2965 { 2965 {
2966 return src; 2966 return src;
2967 } 2967 }
2968 // If both indices are greater than the upper 2968 // If both indices are greater than the upper
2969 // bound the result may seem initially counter 2969 // bound the result may seem initially counter
2970 // intuitive. 2970 // intuitive.
2971 if (end >= src.Length) 2971 if (end >= src.Length)
2972 { 2972 {
2973 return src; 2973 return src;
2974 } 2974 }
2975 2975
2976 if (end < 0) 2976 if (end < 0)
2977 { 2977 {
2978 if (start < src.Length) 2978 if (start < src.Length)
2979 { 2979 {
2980 return src.Substring(start); 2980 return src.Substring(start);
2981 } 2981 }
2982 else 2982 else
2983 { 2983 {
2984 return String.Empty; 2984 return String.Empty;
2985 } 2985 }
2986 } 2986 }
2987 else 2987 else
2988 { 2988 {
2989 if (start < src.Length) 2989 if (start < src.Length)
2990 { 2990 {
2991 return src.Substring(0,end+1) + src.Substring(start); 2991 return src.Substring(0,end+1) + src.Substring(start);
2992 } 2992 }
2993 else 2993 else
2994 { 2994 {
2995 return src.Substring(0,end+1); 2995 return src.Substring(0,end+1);
2996 } 2996 }
2997 } 2997 }
2998 } 2998 }
2999 } 2999 }
3000 3000
3001 /// <summary> 3001 /// <summary>
3002 /// Delete substring removes the specified substring bounded 3002 /// Delete substring removes the specified substring bounded
3003 /// by the inclusive indices start and end. Indices may be 3003 /// by the inclusive indices start and end. Indices may be
3004 /// negative (indicating end-relative) and may be inverted, 3004 /// negative (indicating end-relative) and may be inverted,
3005 /// i.e. end < start. 3005 /// i.e. end < start.
3006 /// </summary> 3006 /// </summary>
3007 public LSL_String llDeleteSubString(string src, int start, int end) 3007 public LSL_String llDeleteSubString(string src, int start, int end)
3008 { 3008 {
3009 m_host.AddScriptLPS(1); 3009 m_host.AddScriptLPS(1);
3010 3010
3011 // Normalize indices (if negative). 3011 // Normalize indices (if negative).
3012 // After normlaization they may still be 3012 // After normlaization they may still be
3013 // negative, but that is now relative to 3013 // negative, but that is now relative to
3014 // the start, rather than the end, of the 3014 // the start, rather than the end, of the
3015 // sequence. 3015 // sequence.
3016 if (start < 0) 3016 if (start < 0)
3017 { 3017 {
3018 start = src.Length+start; 3018 start = src.Length+start;
3019 } 3019 }
3020 if (end < 0) 3020 if (end < 0)
3021 { 3021 {
3022 end = src.Length+end; 3022 end = src.Length+end;
3023 } 3023 }
3024 // Conventionally delimited substring 3024 // Conventionally delimited substring
3025 if (start <= end) 3025 if (start <= end)
3026 { 3026 {
3027 // If both bounds are outside of the existing 3027 // If both bounds are outside of the existing
3028 // string, then return unchanges. 3028 // string, then return unchanges.
3029 if (end < 0 || start >= src.Length) 3029 if (end < 0 || start >= src.Length)
3030 { 3030 {
3031 return src; 3031 return src;
3032 } 3032 }
3033 // At least one bound is in-range, so we 3033 // At least one bound is in-range, so we
3034 // need to clip the out-of-bound argument. 3034 // need to clip the out-of-bound argument.
3035 if (start < 0) 3035 if (start < 0)
3036 { 3036 {
3037 start = 0; 3037 start = 0;
3038 } 3038 }
3039 3039
3040 if (end >= src.Length) 3040 if (end >= src.Length)
3041 { 3041 {
3042 end = src.Length-1; 3042 end = src.Length-1;
3043 } 3043 }
3044 3044
3045 return src.Remove(start,end-start+1); 3045 return src.Remove(start,end-start+1);
3046 } 3046 }
3047 // Inverted substring 3047 // Inverted substring
3048 else 3048 else
3049 { 3049 {
3050 // In this case, out of bounds means that 3050 // In this case, out of bounds means that
3051 // the existing string is part of the cut. 3051 // the existing string is part of the cut.
3052 if (start < 0 || end >= src.Length) 3052 if (start < 0 || end >= src.Length)
3053 { 3053 {
3054 return String.Empty; 3054 return String.Empty;
3055 } 3055 }
3056 3056
3057 if (end > 0) 3057 if (end > 0)
3058 { 3058 {
3059 if (start < src.Length) 3059 if (start < src.Length)
3060 { 3060 {
3061 return src.Remove(start).Remove(0,end+1); 3061 return src.Remove(start).Remove(0,end+1);
3062 } 3062 }
3063 else 3063 else
3064 { 3064 {
3065 return src.Remove(0,end+1); 3065 return src.Remove(0,end+1);
3066 } 3066 }
3067 } 3067 }
3068 else 3068 else
3069 { 3069 {
3070 if (start < src.Length) 3070 if (start < src.Length)
3071 { 3071 {
3072 return src.Remove(start); 3072 return src.Remove(start);
3073 } 3073 }
3074 else 3074 else
3075 { 3075 {
3076 return src; 3076 return src;
3077 } 3077 }
3078 } 3078 }
3079 } 3079 }
3080 } 3080 }
3081 3081
3082 /// <summary> 3082 /// <summary>
3083 /// Insert string inserts the specified string identified by src 3083 /// Insert string inserts the specified string identified by src
3084 /// at the index indicated by index. Index may be negative, in 3084 /// at the index indicated by index. Index may be negative, in
3085 /// which case it is end-relative. The index may exceed either 3085 /// which case it is end-relative. The index may exceed either
3086 /// string bound, with the result being a concatenation. 3086 /// string bound, with the result being a concatenation.
3087 /// </summary> 3087 /// </summary>
3088 public LSL_String llInsertString(string dest, int index, string src) 3088 public LSL_String llInsertString(string dest, int index, string src)
3089 { 3089 {
3090 m_host.AddScriptLPS(1); 3090 m_host.AddScriptLPS(1);
3091 3091
3092 // Normalize indices (if negative). 3092 // Normalize indices (if negative).
3093 // After normlaization they may still be 3093 // After normlaization they may still be
3094 // negative, but that is now relative to 3094 // negative, but that is now relative to
3095 // the start, rather than the end, of the 3095 // the start, rather than the end, of the
3096 // sequence. 3096 // sequence.
3097 if (index < 0) 3097 if (index < 0)
3098 { 3098 {
3099 index = dest.Length+index; 3099 index = dest.Length+index;
3100 3100
3101 // Negative now means it is less than the lower 3101 // Negative now means it is less than the lower
3102 // bound of the string. 3102 // bound of the string.
3103 3103
3104 if (index < 0) 3104 if (index < 0)
3105 { 3105 {
3106 return src+dest; 3106 return src+dest;
3107 } 3107 }
3108 3108
3109 } 3109 }
3110 3110
3111 if (index >= dest.Length) 3111 if (index >= dest.Length)
3112 { 3112 {
3113 return dest+src; 3113 return dest+src;
3114 } 3114 }
3115 3115
3116 // The index is in bounds. 3116 // The index is in bounds.
3117 // In this case the index refers to the index that will 3117 // In this case the index refers to the index that will
3118 // be assigned to the first character of the inserted string. 3118 // be assigned to the first character of the inserted string.
3119 // So unlike the other string operations, we do not add one 3119 // So unlike the other string operations, we do not add one
3120 // to get the correct string length. 3120 // to get the correct string length.
3121 return dest.Substring(0,index)+src+dest.Substring(index); 3121 return dest.Substring(0,index)+src+dest.Substring(index);
3122 3122
3123 } 3123 }
3124 3124
3125 public LSL_String llToUpper(string src) 3125 public LSL_String llToUpper(string src)
3126 { 3126 {
3127 m_host.AddScriptLPS(1); 3127 m_host.AddScriptLPS(1);
3128 return src.ToUpper(); 3128 return src.ToUpper();
3129 } 3129 }
3130 3130
3131 public LSL_String llToLower(string src) 3131 public LSL_String llToLower(string src)
3132 { 3132 {
3133 m_host.AddScriptLPS(1); 3133 m_host.AddScriptLPS(1);
3134 return src.ToLower(); 3134 return src.ToLower();
3135 } 3135 }
3136 3136
3137 public void llGiveMoney(string destination, int amount) 3137 public void llGiveMoney(string destination, int amount)
3138 { 3138 {
3139 Util.FireAndForget(x => 3139 Util.FireAndForget(x =>
3140 { 3140 {
3141 m_host.AddScriptLPS(1); 3141 m_host.AddScriptLPS(1);
3142 3142
3143 if (m_item.PermsGranter == UUID.Zero) 3143 if (m_item.PermsGranter == UUID.Zero)
3144 return; 3144 return;
3145 3145
3146 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) 3146 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
3147 { 3147 {
3148 Error("llGiveMoney", "No permissions to give money"); 3148 Error("llGiveMoney", "No permissions to give money");
3149 return; 3149 return;
3150 } 3150 }
3151 3151
3152 UUID toID = new UUID(); 3152 UUID toID = new UUID();
3153 3153
3154 if (!UUID.TryParse(destination, out toID)) 3154 if (!UUID.TryParse(destination, out toID))
3155 { 3155 {
3156 Error("llGiveMoney", "Bad key in llGiveMoney"); 3156 Error("llGiveMoney", "Bad key in llGiveMoney");
3157 return; 3157 return;
3158 } 3158 }
3159 3159
3160 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); 3160 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
3161 3161
3162 if (money == null) 3162 if (money == null)
3163 { 3163 {
3164 NotImplemented("llGiveMoney"); 3164 NotImplemented("llGiveMoney");
3165 return; 3165 return;
3166 } 3166 }
3167 3167
3168 money.ObjectGiveMoney( 3168 money.ObjectGiveMoney(
3169 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 3169 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
3170 }, null, "LSL_Api.llGiveMoney"); 3170 }, null, "LSL_Api.llGiveMoney");
3171 } 3171 }
3172 3172
3173 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3173 public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3174 { 3174 {
3175 m_host.AddScriptLPS(1); 3175 m_host.AddScriptLPS(1);
3176 Deprecated("llMakeExplosion", "Use llParticleSystem instead"); 3176 Deprecated("llMakeExplosion", "Use llParticleSystem instead");
3177 ScriptSleep(m_sleepMsOnMakeExplosion); 3177 ScriptSleep(m_sleepMsOnMakeExplosion);
3178 } 3178 }
3179 3179
3180 public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset) 3180 public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset)
3181 { 3181 {
3182 m_host.AddScriptLPS(1); 3182 m_host.AddScriptLPS(1);
3183 Deprecated("llMakeFountain", "Use llParticleSystem instead"); 3183 Deprecated("llMakeFountain", "Use llParticleSystem instead");
3184 ScriptSleep(m_sleepMsOnMakeFountain); 3184 ScriptSleep(m_sleepMsOnMakeFountain);
3185 } 3185 }
3186 3186
3187 public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3187 public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3188 { 3188 {
3189 m_host.AddScriptLPS(1); 3189 m_host.AddScriptLPS(1);
3190 Deprecated("llMakeSmoke", "Use llParticleSystem instead"); 3190 Deprecated("llMakeSmoke", "Use llParticleSystem instead");
3191 ScriptSleep(m_sleepMsOnMakeSmoke); 3191 ScriptSleep(m_sleepMsOnMakeSmoke);
3192 } 3192 }
3193 3193
3194 public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) 3194 public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset)
3195 { 3195 {
3196 m_host.AddScriptLPS(1); 3196 m_host.AddScriptLPS(1);
3197 Deprecated("llMakeFire", "Use llParticleSystem instead"); 3197 Deprecated("llMakeFire", "Use llParticleSystem instead");
3198 ScriptSleep(m_sleepMsOnMakeFire); 3198 ScriptSleep(m_sleepMsOnMakeFire);
3199 } 3199 }
3200 3200
3201 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3201 public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3202 { 3202 {
3203 m_host.AddScriptLPS(1); 3203 m_host.AddScriptLPS(1);
3204 3204
3205 Util.FireAndForget(x => 3205 Util.FireAndForget(x =>
3206 { 3206 {
3207 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) 3207 if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s))
3208 return; 3208 return;
3209 3209
3210 float dist = (float)llVecDist(llGetPos(), pos); 3210 float dist = (float)llVecDist(llGetPos(), pos);
3211 3211
3212 if (dist > m_ScriptDistanceFactor * 10.0f) 3212 if (dist > m_ScriptDistanceFactor * 10.0f)
3213 return; 3213 return;
3214 3214
3215 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); 3215 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
3216 3216
3217 if (item == null) 3217 if (item == null)
3218 { 3218 {
3219 Error("llRezAtRoot", "Can't find object '" + inventory + "'"); 3219 Error("llRezAtRoot", "Can't find object '" + inventory + "'");
3220 return; 3220 return;
3221 } 3221 }
3222 3222
3223 if (item.InvType != (int)InventoryType.Object) 3223 if (item.InvType != (int)InventoryType.Object)
3224 { 3224 {
3225 Error("llRezAtRoot", "Can't create requested object; object is missing from database"); 3225 Error("llRezAtRoot", "Can't create requested object; object is missing from database");
3226 return; 3226 return;
3227 } 3227 }
3228 3228
3229 // need the magnitude later 3229 // need the magnitude later
3230 // float velmag = (float)Util.GetMagnitude(llvel); 3230 // float velmag = (float)Util.GetMagnitude(llvel);
3231 3231
3232 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param); 3232 List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param);
3233 3233
3234 // If either of these are null, then there was an unknown error. 3234 // If either of these are null, then there was an unknown error.
3235 if (new_groups == null) 3235 if (new_groups == null)
3236 return; 3236 return;
3237 3237
3238 foreach (SceneObjectGroup group in new_groups) 3238 foreach (SceneObjectGroup group in new_groups)
3239 { 3239 {
3240 // objects rezzed with this method are die_at_edge by default. 3240 // objects rezzed with this method are die_at_edge by default.
3241 group.RootPart.SetDieAtEdge(true); 3241 group.RootPart.SetDieAtEdge(true);
3242 3242
3243 group.ResumeScripts(); 3243 group.ResumeScripts();
3244 3244
3245 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( 3245 m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams(
3246 "object_rez", new Object[] { 3246 "object_rez", new Object[] {
3247 new LSL_String( 3247 new LSL_String(
3248 group.RootPart.UUID.ToString()) }, 3248 group.RootPart.UUID.ToString()) },
3249 new DetectParams[0])); 3249 new DetectParams[0]));
3250 3250
3251 float groupmass = group.GetMass(); 3251 float groupmass = group.GetMass();
3252 3252
3253 PhysicsActor pa = group.RootPart.PhysActor; 3253 PhysicsActor pa = group.RootPart.PhysActor;
3254 3254
3255 //Recoil. 3255 //Recoil.
3256 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3256 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3257 { 3257 {
3258 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; 3258 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3259 if (recoil != Vector3.Zero) 3259 if (recoil != Vector3.Zero)
3260 { 3260 {
3261 llApplyImpulse(recoil, 0); 3261 llApplyImpulse(recoil, 0);
3262 } 3262 }
3263 } 3263 }
3264 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3264 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3265 } 3265 }
3266 }, null, "LSL_Api.llRezAtRoot"); 3266 }, null, "LSL_Api.llRezAtRoot");
3267 3267
3268 //ScriptSleep((int)((groupmass * velmag) / 10)); 3268 //ScriptSleep((int)((groupmass * velmag) / 10));
3269 ScriptSleep(m_sleepMsOnRezAtRoot); 3269 ScriptSleep(m_sleepMsOnRezAtRoot);
3270 } 3270 }
3271 3271
3272 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) 3272 public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param)
3273 { 3273 {
3274 llRezAtRoot(inventory, pos, vel, rot, param); 3274 llRezAtRoot(inventory, pos, vel, rot, param);
3275 } 3275 }
3276 3276
3277 public void llLookAt(LSL_Vector target, double strength, double damping) 3277 public void llLookAt(LSL_Vector target, double strength, double damping)
3278 { 3278 {
3279 m_host.AddScriptLPS(1); 3279 m_host.AddScriptLPS(1);
3280 // Determine where we are looking from 3280 // Determine where we are looking from
3281 LSL_Vector from = llGetPos(); 3281 LSL_Vector from = llGetPos();
3282 3282
3283 // normalized direction to target 3283 // normalized direction to target
3284 LSL_Vector dir = llVecNorm(target - from); 3284 LSL_Vector dir = llVecNorm(target - from);
3285 // use vertical to help compute left axis 3285 // use vertical to help compute left axis
3286 LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0); 3286 LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0);
3287 // find normalized left axis parallel to horizon 3287 // find normalized left axis parallel to horizon
3288 LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir)); 3288 LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir));
3289 // make up orthogonal to left and dir 3289 // make up orthogonal to left and dir
3290 up = LSL_Vector.Cross(dir, left); 3290 up = LSL_Vector.Cross(dir, left);
3291 3291
3292 // compute rotation based on orthogonal axes 3292 // compute rotation based on orthogonal axes
3293 LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up); 3293 LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up);
3294 3294
3295 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3295 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
3296 // set the rotation of the object, copy that behavior 3296 // set the rotation of the object, copy that behavior
3297 PhysicsActor pa = m_host.PhysActor; 3297 PhysicsActor pa = m_host.PhysActor;
3298 3298
3299 if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical) 3299 if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical)
3300 { 3300 {
3301 llSetRot(rot); 3301 llSetRot(rot);
3302 } 3302 }
3303 else 3303 else
3304 { 3304 {
3305 m_host.StartLookAt(rot, (float)strength, (float)damping); 3305 m_host.StartLookAt(rot, (float)strength, (float)damping);
3306 } 3306 }
3307 } 3307 }
3308 3308
3309 public void llStopLookAt() 3309 public void llStopLookAt()
3310 { 3310 {
3311 m_host.AddScriptLPS(1); 3311 m_host.AddScriptLPS(1);
3312 m_host.StopLookAt(); 3312 m_host.StopLookAt();
3313 } 3313 }
3314 3314
3315 public void llSetTimerEvent(double sec) 3315 public void llSetTimerEvent(double sec)
3316 { 3316 {
3317 if (sec != 0.0 && sec < m_MinTimerInterval) 3317 if (sec != 0.0 && sec < m_MinTimerInterval)
3318 sec = m_MinTimerInterval; 3318 sec = m_MinTimerInterval;
3319 m_host.AddScriptLPS(1); 3319 m_host.AddScriptLPS(1);
3320 // Setting timer repeat 3320 // Setting timer repeat
3321 AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec); 3321 AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec);
3322 } 3322 }
3323 3323
3324 public virtual void llSleep(double sec) 3324 public virtual void llSleep(double sec)
3325 { 3325 {
3326// m_log.Info("llSleep snoozing " + sec + "s."); 3326// m_log.Info("llSleep snoozing " + sec + "s.");
3327 m_host.AddScriptLPS(1); 3327 m_host.AddScriptLPS(1);
3328 3328
3329 Sleep((int)(sec * 1000)); 3329 Sleep((int)(sec * 1000));
3330 } 3330 }
3331 3331
3332 public LSL_Float llGetMass() 3332 public LSL_Float llGetMass()
3333 { 3333 {
3334 m_host.AddScriptLPS(1); 3334 m_host.AddScriptLPS(1);
3335 3335
3336 if (m_host.ParentGroup.IsAttachment) 3336 if (m_host.ParentGroup.IsAttachment)
3337 { 3337 {
3338 ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 3338 ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
3339 3339
3340 if (attachedAvatar != null) 3340 if (attachedAvatar != null)
3341 { 3341 {
3342 return attachedAvatar.GetMass(); 3342 return attachedAvatar.GetMass();
3343 } 3343 }
3344 else 3344 else
3345 { 3345 {
3346 return 0; 3346 return 0;
3347 } 3347 }
3348 } 3348 }
3349 else 3349 else
3350 { 3350 {
3351 if (m_host.IsRoot) 3351 if (m_host.IsRoot)
3352 { 3352 {
3353 return m_host.ParentGroup.GetMass(); 3353 return m_host.ParentGroup.GetMass();
3354 } 3354 }
3355 else 3355 else
3356 { 3356 {
3357 return m_host.GetMass(); 3357 return m_host.GetMass();
3358 } 3358 }
3359 } 3359 }
3360 } 3360 }
3361 3361
3362 public LSL_Float llGetMassMKS() 3362 public LSL_Float llGetMassMKS()
3363 { 3363 {
3364 // this is what the wiki says it does! 3364 // this is what the wiki says it does!
3365 // http://wiki.secondlife.com/wiki/LlGetMassMKS 3365 // http://wiki.secondlife.com/wiki/LlGetMassMKS
3366 return llGetMass() * 100.0; 3366 return llGetMass() * 100.0;
3367 } 3367 }
3368 3368
3369 public void llCollisionFilter(string name, string id, int accept) 3369 public void llCollisionFilter(string name, string id, int accept)
3370 { 3370 {
3371 m_host.AddScriptLPS(1); 3371 m_host.AddScriptLPS(1);
3372 m_host.CollisionFilter.Clear(); 3372 m_host.CollisionFilter.Clear();
3373 UUID objectID; 3373 UUID objectID;
3374 3374
3375 if (!UUID.TryParse(id, out objectID)) 3375 if (!UUID.TryParse(id, out objectID))
3376 objectID = UUID.Zero; 3376 objectID = UUID.Zero;
3377 3377
3378 if (objectID == UUID.Zero && name == "") 3378 if (objectID == UUID.Zero && name == "")
3379 return; 3379 return;
3380 3380
3381 m_host.CollisionFilter.Add(accept,objectID.ToString() + name); 3381 m_host.CollisionFilter.Add(accept,objectID.ToString() + name);
3382 } 3382 }
3383 3383
3384 public void llTakeControls(int controls, int accept, int pass_on) 3384 public void llTakeControls(int controls, int accept, int pass_on)
3385 { 3385 {
3386 if (m_item.PermsGranter != UUID.Zero) 3386 if (m_item.PermsGranter != UUID.Zero)
3387 { 3387 {
3388 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); 3388 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3389 3389
3390 if (presence != null) 3390 if (presence != null)
3391 { 3391 {
3392 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 3392 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
3393 { 3393 {
3394 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID); 3394 presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID);
3395 } 3395 }
3396 } 3396 }
3397 } 3397 }
3398 3398
3399 m_host.AddScriptLPS(1); 3399 m_host.AddScriptLPS(1);
3400 } 3400 }
3401 3401
3402 public void llReleaseControls() 3402 public void llReleaseControls()
3403 { 3403 {
3404 m_host.AddScriptLPS(1); 3404 m_host.AddScriptLPS(1);
3405 3405
3406 if (m_item.PermsGranter != UUID.Zero) 3406 if (m_item.PermsGranter != UUID.Zero)
3407 { 3407 {
3408 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); 3408 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3409 3409
3410 if (presence != null) 3410 if (presence != null)
3411 { 3411 {
3412 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) 3412 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0)
3413 { 3413 {
3414 // Unregister controls from Presence 3414 // Unregister controls from Presence
3415 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); 3415 presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID);
3416 // Remove Take Control permission. 3416 // Remove Take Control permission.
3417 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3417 m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3418 } 3418 }
3419 } 3419 }
3420 } 3420 }
3421 } 3421 }
3422 3422
3423 public void llReleaseURL(string url) 3423 public void llReleaseURL(string url)
3424 { 3424 {
3425 m_host.AddScriptLPS(1); 3425 m_host.AddScriptLPS(1);
3426 if (m_UrlModule != null) 3426 if (m_UrlModule != null)
3427 m_UrlModule.ReleaseURL(url); 3427 m_UrlModule.ReleaseURL(url);
3428 } 3428 }
3429 3429
3430 /// <summary> 3430 /// <summary>
3431 /// Attach the object containing this script to the avatar that owns it. 3431 /// Attach the object containing this script to the avatar that owns it.
3432 /// </summary> 3432 /// </summary>
3433 /// <param name='attachmentPoint'> 3433 /// <param name='attachmentPoint'>
3434 /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>) 3434 /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>)
3435 /// </param> 3435 /// </param>
3436 /// <returns>true if the attach suceeded, false if it did not</returns> 3436 /// <returns>true if the attach suceeded, false if it did not</returns>
3437 public bool AttachToAvatar(int attachmentPoint) 3437 public bool AttachToAvatar(int attachmentPoint)
3438 { 3438 {
3439 SceneObjectGroup grp = m_host.ParentGroup; 3439 SceneObjectGroup grp = m_host.ParentGroup;
3440 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 3440 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
3441 3441
3442 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; 3442 IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule;
3443 3443
3444 if (attachmentsModule != null) 3444 if (attachmentsModule != null)
3445 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true); 3445 return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true);
3446 else 3446 else
3447 return false; 3447 return false;
3448 } 3448 }
3449 3449
3450 /// <summary> 3450 /// <summary>
3451 /// Detach the object containing this script from the avatar it is attached to. 3451 /// Detach the object containing this script from the avatar it is attached to.
3452 /// </summary> 3452 /// </summary>
3453 /// <remarks> 3453 /// <remarks>
3454 /// Nothing happens if the object is not attached. 3454 /// Nothing happens if the object is not attached.
3455 /// </remarks> 3455 /// </remarks>
3456 public void DetachFromAvatar() 3456 public void DetachFromAvatar()
3457 { 3457 {
3458 Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar"); 3458 Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar");
3459 } 3459 }
3460 3460
3461 private void DetachWrapper(object o) 3461 private void DetachWrapper(object o)
3462 { 3462 {
3463 if (World.AttachmentsModule != null) 3463 if (World.AttachmentsModule != null)
3464 { 3464 {
3465 SceneObjectPart host = (SceneObjectPart)o; 3465 SceneObjectPart host = (SceneObjectPart)o;
3466 ScenePresence presence = World.GetScenePresence(host.OwnerID); 3466 ScenePresence presence = World.GetScenePresence(host.OwnerID);
3467 World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup); 3467 World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup);
3468 } 3468 }
3469 } 3469 }
3470 3470
3471 public void llAttachToAvatar(int attachmentPoint) 3471 public void llAttachToAvatar(int attachmentPoint)
3472 { 3472 {
3473 m_host.AddScriptLPS(1); 3473 m_host.AddScriptLPS(1);
3474 3474
3475// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0) 3475// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
3476// return; 3476// return;
3477 3477
3478 if (m_item.PermsGranter != m_host.OwnerID) 3478 if (m_item.PermsGranter != m_host.OwnerID)
3479 return; 3479 return;
3480 3480
3481 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) 3481 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
3482 AttachToAvatar(attachmentPoint); 3482 AttachToAvatar(attachmentPoint);
3483 } 3483 }
3484 3484
3485 public void llDetachFromAvatar() 3485 public void llDetachFromAvatar()
3486 { 3486 {
3487 m_host.AddScriptLPS(1); 3487 m_host.AddScriptLPS(1);
3488 3488
3489 if (m_host.ParentGroup.AttachmentPoint == 0) 3489 if (m_host.ParentGroup.AttachmentPoint == 0)
3490 return; 3490 return;
3491 3491
3492 if (m_item.PermsGranter != m_host.OwnerID) 3492 if (m_item.PermsGranter != m_host.OwnerID)
3493 return; 3493 return;
3494 3494
3495 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) 3495 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0)
3496 DetachFromAvatar(); 3496 DetachFromAvatar();
3497 } 3497 }
3498 3498
3499 public void llTakeCamera(string avatar) 3499 public void llTakeCamera(string avatar)
3500 { 3500 {
3501 m_host.AddScriptLPS(1); 3501 m_host.AddScriptLPS(1);
3502 Deprecated("llTakeCamera", "Use llSetCameraParams instead"); 3502 Deprecated("llTakeCamera", "Use llSetCameraParams instead");
3503 } 3503 }
3504 3504
3505 public void llReleaseCamera(string avatar) 3505 public void llReleaseCamera(string avatar)
3506 { 3506 {
3507 m_host.AddScriptLPS(1); 3507 m_host.AddScriptLPS(1);
3508 Deprecated("llReleaseCamera", "Use llClearCameraParams instead"); 3508 Deprecated("llReleaseCamera", "Use llClearCameraParams instead");
3509 } 3509 }
3510 3510
3511 public LSL_String llGetOwner() 3511 public LSL_String llGetOwner()
3512 { 3512 {
3513 m_host.AddScriptLPS(1); 3513 m_host.AddScriptLPS(1);
3514 3514
3515 return m_host.OwnerID.ToString(); 3515 return m_host.OwnerID.ToString();
3516 } 3516 }
3517 3517
3518 public void llInstantMessage(string user, string message) 3518 public void llInstantMessage(string user, string message)
3519 { 3519 {
3520 m_host.AddScriptLPS(1); 3520 m_host.AddScriptLPS(1);
3521 3521
3522 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. 3522 // We may be able to use ClientView.SendInstantMessage here, but we need a client instance.
3523 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, 3523 // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent,
3524 // but I don't think we have a list of scenes available from here. 3524 // but I don't think we have a list of scenes available from here.
3525 // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.) 3525 // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.)
3526 3526
3527 // user is a UUID 3527 // user is a UUID
3528 3528
3529 // TODO: figure out values for client, fromSession, and imSessionID 3529 // TODO: figure out values for client, fromSession, and imSessionID
3530 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); 3530 // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch());
3531 3531
3532 GridInstantMessage msg = new GridInstantMessage(); 3532 GridInstantMessage msg = new GridInstantMessage();
3533 msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid; 3533 msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid;
3534 msg.toAgentID = new Guid(user); // toAgentID.Guid; 3534 msg.toAgentID = new Guid(user); // toAgentID.Guid;
3535 msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here 3535 msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here
3536// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); 3536// m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message);
3537// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); 3537// m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString());
3538 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; 3538 msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp;
3539 //if (client != null) 3539 //if (client != null)
3540 //{ 3540 //{
3541 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; 3541 msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName;
3542 //} 3542 //}
3543 //else 3543 //else
3544 //{ 3544 //{
3545 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it 3545 // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it
3546 //} 3546 //}
3547 // Cap the message length at 1024. 3547 // Cap the message length at 1024.
3548 if (message != null && message.Length > 1024) 3548 if (message != null && message.Length > 1024)
3549 msg.message = message.Substring(0, 1024); 3549 msg.message = message.Substring(0, 1024);
3550 else 3550 else
3551 msg.message = message; 3551 msg.message = message;
3552 msg.dialog = (byte)19; // messgage from script ??? // dialog; 3552 msg.dialog = (byte)19; // messgage from script ??? // dialog;
3553 msg.fromGroup = false;// fromGroup; 3553 msg.fromGroup = false;// fromGroup;
3554 msg.offline = (byte)0; //offline; 3554 msg.offline = (byte)0; //offline;
3555 msg.ParentEstateID = 0; //ParentEstateID; 3555 msg.ParentEstateID = 0; //ParentEstateID;
3556 msg.Position = new Vector3(m_host.AbsolutePosition); 3556 msg.Position = new Vector3(m_host.AbsolutePosition);
3557 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; 3557 msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid;
3558 3558
3559 Vector3 pos = m_host.AbsolutePosition; 3559 Vector3 pos = m_host.AbsolutePosition;
3560 msg.binaryBucket 3560 msg.binaryBucket
3561 = Util.StringToBytes256( 3561 = Util.StringToBytes256(
3562 "{0}/{1}/{2}/{3}", 3562 "{0}/{1}/{2}/{3}",
3563 World.RegionInfo.RegionName, 3563 World.RegionInfo.RegionName,
3564 (int)Math.Floor(pos.X), 3564 (int)Math.Floor(pos.X),
3565 (int)Math.Floor(pos.Y), 3565 (int)Math.Floor(pos.Y),
3566 (int)Math.Floor(pos.Z)); 3566 (int)Math.Floor(pos.Z));
3567 3567
3568 if (m_TransferModule != null) 3568 if (m_TransferModule != null)
3569 { 3569 {
3570 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 3570 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
3571 } 3571 }
3572 3572
3573 ScriptSleep(m_sleepMsOnInstantMessage); 3573 ScriptSleep(m_sleepMsOnInstantMessage);
3574 } 3574 }
3575 3575
3576 public void llEmail(string address, string subject, string message) 3576 public void llEmail(string address, string subject, string message)
3577 { 3577 {
3578 m_host.AddScriptLPS(1); 3578 m_host.AddScriptLPS(1);
3579 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); 3579 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
3580 if (emailModule == null) 3580 if (emailModule == null)
3581 { 3581 {
3582 Error("llEmail", "Email module not configured"); 3582 Error("llEmail", "Email module not configured");
3583 return; 3583 return;
3584 } 3584 }
3585 3585
3586 //Restrict email destination to the avatars registered email address? 3586 //Restrict email destination to the avatars registered email address?
3587 //The restriction only applies if the destination address is not local. 3587 //The restriction only applies if the destination address is not local.
3588 if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false) 3588 if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false)
3589 { 3589 {
3590 UserAccount account = 3590 UserAccount account =
3591 World.UserAccountService.GetUserAccount( 3591 World.UserAccountService.GetUserAccount(
3592 World.RegionInfo.ScopeID, 3592 World.RegionInfo.ScopeID,
3593 m_host.OwnerID); 3593 m_host.OwnerID);
3594 3594
3595 if (account == null) 3595 if (account == null)
3596 { 3596 {
3597 Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'"); 3597 Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'");
3598 return; 3598 return;
3599 } 3599 }
3600 3600
3601 if (String.IsNullOrEmpty(account.Email)) 3601 if (String.IsNullOrEmpty(account.Email))
3602 { 3602 {
3603 Error("llEmail", "User account has not registered an email address."); 3603 Error("llEmail", "User account has not registered an email address.");
3604 return; 3604 return;
3605 } 3605 }
3606 3606
3607 address = account.Email; 3607 address = account.Email;
3608 } 3608 }
3609 3609
3610 emailModule.SendEmail(m_host.UUID, address, subject, message); 3610 emailModule.SendEmail(m_host.UUID, address, subject, message);
3611 ScriptSleep(m_sleepMsOnEmail); 3611 ScriptSleep(m_sleepMsOnEmail);
3612 } 3612 }
3613 3613
3614 public void llGetNextEmail(string address, string subject) 3614 public void llGetNextEmail(string address, string subject)
3615 { 3615 {
3616 m_host.AddScriptLPS(1); 3616 m_host.AddScriptLPS(1);
3617 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); 3617 IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>();
3618 if (emailModule == null) 3618 if (emailModule == null)
3619 { 3619 {
3620 Error("llGetNextEmail", "Email module not configured"); 3620 Error("llGetNextEmail", "Email module not configured");
3621 return; 3621 return;
3622 } 3622 }
3623 Email email; 3623 Email email;
3624 3624
3625 email = emailModule.GetNextEmail(m_host.UUID, address, subject); 3625 email = emailModule.GetNextEmail(m_host.UUID, address, subject);
3626 3626
3627 if (email == null) 3627 if (email == null)
3628 return; 3628 return;
3629 3629
3630 m_ScriptEngine.PostObjectEvent(m_host.LocalId, 3630 m_ScriptEngine.PostObjectEvent(m_host.LocalId,
3631 new EventParams("email", 3631 new EventParams("email",
3632 new Object[] { 3632 new Object[] {
3633 new LSL_String(email.time), 3633 new LSL_String(email.time),
3634 new LSL_String(email.sender), 3634 new LSL_String(email.sender),
3635 new LSL_String(email.subject), 3635 new LSL_String(email.subject),
3636 new LSL_String(email.message), 3636 new LSL_String(email.message),
3637 new LSL_Integer(email.numLeft)}, 3637 new LSL_Integer(email.numLeft)},
3638 new DetectParams[0])); 3638 new DetectParams[0]));
3639 3639
3640 } 3640 }
3641 3641
3642 public LSL_String llGetKey() 3642 public LSL_String llGetKey()
3643 { 3643 {
3644 m_host.AddScriptLPS(1); 3644 m_host.AddScriptLPS(1);
3645 return m_host.UUID.ToString(); 3645 return m_host.UUID.ToString();
3646 } 3646 }
3647 3647
3648 public LSL_Key llGenerateKey() 3648 public LSL_Key llGenerateKey()
3649 { 3649 {
3650 m_host.AddScriptLPS(1); 3650 m_host.AddScriptLPS(1);
3651 return UUID.Random().ToString(); 3651 return UUID.Random().ToString();
3652 } 3652 }
3653 3653
3654 public void llSetBuoyancy(double buoyancy) 3654 public void llSetBuoyancy(double buoyancy)
3655 { 3655 {
3656 m_host.AddScriptLPS(1); 3656 m_host.AddScriptLPS(1);
3657 3657
3658 if (!m_host.ParentGroup.IsDeleted) 3658 if (!m_host.ParentGroup.IsDeleted)
3659 { 3659 {
3660 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy); 3660 m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy);
3661 } 3661 }
3662 } 3662 }
3663 3663
3664 /// <summary> 3664 /// <summary>
3665 /// Attempt to clamp the object on the Z axis at the given height over tau seconds. 3665 /// Attempt to clamp the object on the Z axis at the given height over tau seconds.
3666 /// </summary> 3666 /// </summary>
3667 /// <param name="height">Height to hover. Height of zero disables hover.</param> 3667 /// <param name="height">Height to hover. Height of zero disables hover.</param>
3668 /// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param> 3668 /// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param>
3669 /// <param name="tau">Number of seconds over which to reach target</param> 3669 /// <param name="tau">Number of seconds over which to reach target</param>
3670 public void llSetHoverHeight(double height, int water, double tau) 3670 public void llSetHoverHeight(double height, int water, double tau)
3671 { 3671 {
3672 m_host.AddScriptLPS(1); 3672 m_host.AddScriptLPS(1);
3673 3673
3674 if (m_host.PhysActor != null) 3674 if (m_host.PhysActor != null)
3675 { 3675 {
3676 PIDHoverType hoverType = PIDHoverType.Ground; 3676 PIDHoverType hoverType = PIDHoverType.Ground;
3677 if (water != 0) 3677 if (water != 0)
3678 { 3678 {
3679 hoverType = PIDHoverType.GroundAndWater; 3679 hoverType = PIDHoverType.GroundAndWater;
3680 } 3680 }
3681 3681
3682 m_host.SetHoverHeight((float)height, hoverType, (float)tau); 3682 m_host.SetHoverHeight((float)height, hoverType, (float)tau);
3683 } 3683 }
3684 } 3684 }
3685 3685
3686 public void llStopHover() 3686 public void llStopHover()
3687 { 3687 {
3688 m_host.AddScriptLPS(1); 3688 m_host.AddScriptLPS(1);
3689 if (m_host.PhysActor != null) 3689 if (m_host.PhysActor != null)
3690 { 3690 {
3691 m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f); 3691 m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
3692 } 3692 }
3693 } 3693 }
3694 3694
3695 public void llMinEventDelay(double delay) 3695 public void llMinEventDelay(double delay)
3696 { 3696 {
3697 m_host.AddScriptLPS(1); 3697 m_host.AddScriptLPS(1);
3698 try 3698 try
3699 { 3699 {
3700 m_ScriptEngine.SetMinEventDelay(m_item.ItemID, delay); 3700 m_ScriptEngine.SetMinEventDelay(m_item.ItemID, delay);
3701 } 3701 }
3702 catch (NotImplementedException) 3702 catch (NotImplementedException)
3703 { 3703 {
3704 // Currently not implemented in DotNetEngine only XEngine 3704 // Currently not implemented in DotNetEngine only XEngine
3705 NotImplemented("llMinEventDelay", "In DotNetEngine"); 3705 NotImplemented("llMinEventDelay", "In DotNetEngine");
3706 } 3706 }
3707 } 3707 }
3708 3708
3709 public void llSoundPreload(string sound) 3709 public void llSoundPreload(string sound)
3710 { 3710 {
3711 m_host.AddScriptLPS(1); 3711 m_host.AddScriptLPS(1);
3712 Deprecated("llSoundPreload", "Use llPreloadSound instead"); 3712 Deprecated("llSoundPreload", "Use llPreloadSound instead");
3713 } 3713 }
3714 3714
3715 public void llRotLookAt(LSL_Rotation target, double strength, double damping) 3715 public void llRotLookAt(LSL_Rotation target, double strength, double damping)
3716 { 3716 {
3717 m_host.AddScriptLPS(1); 3717 m_host.AddScriptLPS(1);
3718 3718
3719 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply 3719 // Per discussion with Melanie, for non-physical objects llLookAt appears to simply
3720 // set the rotation of the object, copy that behavior 3720 // set the rotation of the object, copy that behavior
3721 PhysicsActor pa = m_host.PhysActor; 3721 PhysicsActor pa = m_host.PhysActor;
3722 3722
3723 if (strength == 0 || pa == null || !pa.IsPhysical) 3723 if (strength == 0 || pa == null || !pa.IsPhysical)
3724 { 3724 {
3725 llSetLocalRot(target); 3725 llSetLocalRot(target);
3726 } 3726 }
3727 else 3727 else
3728 { 3728 {
3729 m_host.RotLookAt(target, (float)strength, (float)damping); 3729 m_host.RotLookAt(target, (float)strength, (float)damping);
3730 } 3730 }
3731 } 3731 }
3732 3732
3733 public LSL_Integer llStringLength(string str) 3733 public LSL_Integer llStringLength(string str)
3734 { 3734 {
3735 m_host.AddScriptLPS(1); 3735 m_host.AddScriptLPS(1);
3736 if (str.Length > 0) 3736 if (str.Length > 0)
3737 { 3737 {
3738 return str.Length; 3738 return str.Length;
3739 } 3739 }
3740 else 3740 else
3741 { 3741 {
3742 return 0; 3742 return 0;
3743 } 3743 }
3744 } 3744 }
3745 3745
3746 public void llStartAnimation(string anim) 3746 public void llStartAnimation(string anim)
3747 { 3747 {
3748 m_host.AddScriptLPS(1); 3748 m_host.AddScriptLPS(1);
3749 3749
3750 if (m_item.PermsGranter == UUID.Zero) 3750 if (m_item.PermsGranter == UUID.Zero)
3751 return; 3751 return;
3752 3752
3753 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) 3753 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
3754 { 3754 {
3755 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); 3755 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3756 3756
3757 if (presence != null) 3757 if (presence != null)
3758 { 3758 {
3759 // Do NOT try to parse UUID, animations cannot be triggered by ID 3759 // Do NOT try to parse UUID, animations cannot be triggered by ID
3760 UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation); 3760 UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation);
3761 if (animID == UUID.Zero) 3761 if (animID == UUID.Zero)
3762 presence.Animator.AddAnimation(anim, m_host.UUID); 3762 presence.Animator.AddAnimation(anim, m_host.UUID);
3763 else 3763 else
3764 presence.Animator.AddAnimation(animID, m_host.UUID); 3764 presence.Animator.AddAnimation(animID, m_host.UUID);
3765 } 3765 }
3766 } 3766 }
3767 } 3767 }
3768 3768
3769 public void llStopAnimation(string anim) 3769 public void llStopAnimation(string anim)
3770 { 3770 {
3771 m_host.AddScriptLPS(1); 3771 m_host.AddScriptLPS(1);
3772 3772
3773 if (m_item.PermsGranter == UUID.Zero) 3773 if (m_item.PermsGranter == UUID.Zero)
3774 return; 3774 return;
3775 3775
3776 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) 3776 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0)
3777 { 3777 {
3778 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); 3778 ScenePresence presence = World.GetScenePresence(m_item.PermsGranter);
3779 3779
3780 if (presence != null) 3780 if (presence != null)
3781 { 3781 {
3782 UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim); 3782 UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim);
3783 3783
3784 if (animID == UUID.Zero) 3784 if (animID == UUID.Zero)
3785 presence.Animator.RemoveAnimation(anim); 3785 presence.Animator.RemoveAnimation(anim);
3786 else 3786 else
3787 presence.Animator.RemoveAnimation(animID, true); 3787 presence.Animator.RemoveAnimation(animID, true);
3788 } 3788 }
3789 } 3789 }
3790 } 3790 }
3791 3791
3792 public void llPointAt(LSL_Vector pos) 3792 public void llPointAt(LSL_Vector pos)
3793 { 3793 {
3794 m_host.AddScriptLPS(1); 3794 m_host.AddScriptLPS(1);
3795 } 3795 }
3796 3796
3797 public void llStopPointAt() 3797 public void llStopPointAt()
3798 { 3798 {
3799 m_host.AddScriptLPS(1); 3799 m_host.AddScriptLPS(1);
3800 } 3800 }
3801 3801
3802 public void llTargetOmega(LSL_Vector axis, double spinrate, double gain) 3802 public void llTargetOmega(LSL_Vector axis, double spinrate, double gain)
3803 { 3803 {
3804 m_host.AddScriptLPS(1); 3804 m_host.AddScriptLPS(1);
3805 TargetOmega(m_host, axis, spinrate, gain); 3805 TargetOmega(m_host, axis, spinrate, gain);
3806 } 3806 }
3807 3807
3808 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) 3808 protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain)
3809 { 3809 {
3810 PhysicsActor pa = part.PhysActor; 3810 PhysicsActor pa = part.PhysActor;
3811 if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d ) 3811 if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d )
3812 spinrate = 0.0d; 3812 spinrate = 0.0d;
3813 part.UpdateAngularVelocity(axis * spinrate); 3813 part.UpdateAngularVelocity(axis * spinrate);
3814 } 3814 }
3815 3815
3816 public LSL_Integer llGetStartParameter() 3816 public LSL_Integer llGetStartParameter()
3817 { 3817 {
3818 m_host.AddScriptLPS(1); 3818 m_host.AddScriptLPS(1);
3819 return m_ScriptEngine.GetStartParameter(m_item.ItemID); 3819 return m_ScriptEngine.GetStartParameter(m_item.ItemID);
3820 } 3820 }
3821 3821
3822 public void llRequestPermissions(string agent, int perm) 3822 public void llRequestPermissions(string agent, int perm)
3823 { 3823 {
3824 UUID agentID; 3824 UUID agentID;
3825 3825
3826 if (!UUID.TryParse(agent, out agentID)) 3826 if (!UUID.TryParse(agent, out agentID))
3827 return; 3827 return;
3828 3828
3829 if (agentID == UUID.Zero || perm == 0) // Releasing permissions 3829 if (agentID == UUID.Zero || perm == 0) // Releasing permissions
3830 { 3830 {
3831 llReleaseControls(); 3831 llReleaseControls();
3832 3832
3833 m_item.PermsGranter = UUID.Zero; 3833 m_item.PermsGranter = UUID.Zero;
3834 m_item.PermsMask = 0; 3834 m_item.PermsMask = 0;
3835 3835
3836 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3836 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3837 "run_time_permissions", new Object[] { 3837 "run_time_permissions", new Object[] {
3838 new LSL_Integer(0) }, 3838 new LSL_Integer(0) },
3839 new DetectParams[0])); 3839 new DetectParams[0]));
3840 3840
3841 return; 3841 return;
3842 } 3842 }
3843 3843
3844 if (m_item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3844 if (m_item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3845 llReleaseControls(); 3845 llReleaseControls();
3846 3846
3847 m_host.AddScriptLPS(1); 3847 m_host.AddScriptLPS(1);
3848 3848
3849 int implicitPerms = 0; 3849 int implicitPerms = 0;
3850 3850
3851 if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar) 3851 if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar)
3852 { 3852 {
3853 // When attached, certain permissions are implicit if requested from owner 3853 // When attached, certain permissions are implicit if requested from owner
3854 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | 3854 implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS |
3855 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3855 ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3856 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3856 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3857 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3857 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3858 ScriptBaseClass.PERMISSION_ATTACH; 3858 ScriptBaseClass.PERMISSION_ATTACH;
3859 } 3859 }
3860 else 3860 else
3861 { 3861 {
3862 if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null) 3862 if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null)
3863 { 3863 {
3864 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3864 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3865 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3865 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
3866 ScriptBaseClass.PERMISSION_CONTROL_CAMERA | 3866 ScriptBaseClass.PERMISSION_CONTROL_CAMERA |
3867 ScriptBaseClass.PERMISSION_TRACK_CAMERA | 3867 ScriptBaseClass.PERMISSION_TRACK_CAMERA |
3868 ScriptBaseClass.PERMISSION_TAKE_CONTROLS; 3868 ScriptBaseClass.PERMISSION_TAKE_CONTROLS;
3869 } 3869 }
3870 else 3870 else
3871 { 3871 {
3872 if (World.GetExtraSetting("auto_grant_attach_perms") == "true") 3872 if (World.GetExtraSetting("auto_grant_attach_perms") == "true")
3873 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; 3873 implicitPerms = ScriptBaseClass.PERMISSION_ATTACH;
3874 } 3874 }
3875 } 3875 }
3876 3876
3877 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms 3877 if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms
3878 { 3878 {
3879 lock (m_host.TaskInventory) 3879 lock (m_host.TaskInventory)
3880 { 3880 {
3881 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3881 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3882 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3882 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3883 } 3883 }
3884 3884
3885 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 3885 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
3886 "run_time_permissions", new Object[] { 3886 "run_time_permissions", new Object[] {
3887 new LSL_Integer(perm) }, 3887 new LSL_Integer(perm) },
3888 new DetectParams[0])); 3888 new DetectParams[0]));
3889 3889
3890 return; 3890 return;
3891 } 3891 }
3892 3892
3893 ScenePresence presence = World.GetScenePresence(agentID); 3893 ScenePresence presence = World.GetScenePresence(agentID);
3894 3894
3895 if (presence != null) 3895 if (presence != null)
3896 { 3896 {
3897 // If permissions are being requested from an NPC and were not implicitly granted above then 3897 // If permissions are being requested from an NPC and were not implicitly granted above then
3898 // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner 3898 // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner
3899 INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); 3899 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
3900 if (npcModule != null && npcModule.IsNPC(agentID, World)) 3900 if (npcModule != null && npcModule.IsNPC(agentID, World))
3901 { 3901 {
3902 if (npcModule.CheckPermissions(agentID, m_host.OwnerID)) 3902 if (npcModule.CheckPermissions(agentID, m_host.OwnerID))
3903 { 3903 {
3904 lock (m_host.TaskInventory) 3904 lock (m_host.TaskInventory)
3905 { 3905 {
3906 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3906 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3907 m_host.TaskInventory[m_item.ItemID].PermsMask = perm; 3907 m_host.TaskInventory[m_item.ItemID].PermsMask = perm;
3908 } 3908 }
3909 3909
3910 m_ScriptEngine.PostScriptEvent( 3910 m_ScriptEngine.PostScriptEvent(
3911 m_item.ItemID, 3911 m_item.ItemID,
3912 new EventParams( 3912 new EventParams(
3913 "run_time_permissions", new Object[] { new LSL_Integer(perm) }, new DetectParams[0])); 3913 "run_time_permissions", new Object[] { new LSL_Integer(perm) }, new DetectParams[0]));
3914 } 3914 }
3915 3915
3916 // it is an NPC, exit even if the permissions werent granted above, they are not going to answer 3916 // it is an NPC, exit even if the permissions werent granted above, they are not going to answer
3917 // the question! 3917 // the question!
3918 return; 3918 return;
3919 } 3919 }
3920 3920
3921 string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID); 3921 string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID);
3922 if (ownerName == String.Empty) 3922 if (ownerName == String.Empty)
3923 ownerName = "(hippos)"; 3923 ownerName = "(hippos)";
3924 3924
3925 if (!m_waitingForScriptAnswer) 3925 if (!m_waitingForScriptAnswer)
3926 { 3926 {
3927 lock (m_host.TaskInventory) 3927 lock (m_host.TaskInventory)
3928 { 3928 {
3929 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; 3929 m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID;
3930 m_host.TaskInventory[m_item.ItemID].PermsMask = 0; 3930 m_host.TaskInventory[m_item.ItemID].PermsMask = 0;
3931 } 3931 }
3932 3932
3933 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; 3933 presence.ControllingClient.OnScriptAnswer += handleScriptAnswer;
3934 m_waitingForScriptAnswer=true; 3934 m_waitingForScriptAnswer=true;
3935 } 3935 }
3936 3936
3937 presence.ControllingClient.SendScriptQuestion( 3937 presence.ControllingClient.SendScriptQuestion(
3938 m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, m_item.ItemID, perm); 3938 m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, m_item.ItemID, perm);
3939 3939
3940 return; 3940 return;
3941 } 3941 }
3942 3942
3943 // Requested agent is not in range, refuse perms 3943 // Requested agent is not in range, refuse perms
3944 m_ScriptEngine.PostScriptEvent( 3944 m_ScriptEngine.PostScriptEvent(
3945 m_item.ItemID, 3945 m_item.ItemID,
3946 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(0) }, new DetectParams[0])); 3946 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(0) }, new DetectParams[0]));
3947 } 3947 }
3948 3948
3949 void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer) 3949 void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer)
3950 { 3950 {
3951 if (taskID != m_host.UUID) 3951 if (taskID != m_host.UUID)
3952 return; 3952 return;
3953 3953
3954 client.OnScriptAnswer -= handleScriptAnswer; 3954 client.OnScriptAnswer -= handleScriptAnswer;
3955 m_waitingForScriptAnswer = false; 3955 m_waitingForScriptAnswer = false;
3956 3956
3957 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) 3957 if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0)
3958 llReleaseControls(); 3958 llReleaseControls();
3959 3959
3960 lock (m_host.TaskInventory) 3960 lock (m_host.TaskInventory)
3961 { 3961 {
3962 m_host.TaskInventory[m_item.ItemID].PermsMask = answer; 3962 m_host.TaskInventory[m_item.ItemID].PermsMask = answer;
3963 } 3963 }
3964 3964
3965 m_ScriptEngine.PostScriptEvent( 3965 m_ScriptEngine.PostScriptEvent(
3966 m_item.ItemID, 3966 m_item.ItemID,
3967 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); 3967 new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0]));
3968 } 3968 }
3969 3969
3970 public LSL_String llGetPermissionsKey() 3970 public LSL_String llGetPermissionsKey()
3971 { 3971 {
3972 m_host.AddScriptLPS(1); 3972 m_host.AddScriptLPS(1);
3973 3973
3974 return m_item.PermsGranter.ToString(); 3974 return m_item.PermsGranter.ToString();
3975 } 3975 }
3976 3976
3977 public LSL_Integer llGetPermissions() 3977 public LSL_Integer llGetPermissions()
3978 { 3978 {
3979 m_host.AddScriptLPS(1); 3979 m_host.AddScriptLPS(1);
3980 3980
3981 int perms = m_item.PermsMask; 3981 int perms = m_item.PermsMask;
3982 3982
3983 if (m_automaticLinkPermission) 3983 if (m_automaticLinkPermission)
3984 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; 3984 perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS;
3985 3985
3986 return perms; 3986 return perms;
3987 } 3987 }
3988 3988
3989 public LSL_Integer llGetLinkNumber() 3989 public LSL_Integer llGetLinkNumber()
3990 { 3990 {
3991 m_host.AddScriptLPS(1); 3991 m_host.AddScriptLPS(1);
3992 3992
3993 if (m_host.ParentGroup.PrimCount > 1) 3993 if (m_host.ParentGroup.PrimCount > 1)
3994 { 3994 {
3995 return m_host.LinkNum; 3995 return m_host.LinkNum;
3996 } 3996 }
3997 else 3997 else
3998 { 3998 {
3999 return 0; 3999 return 0;
4000 } 4000 }
4001 } 4001 }
4002 4002
4003 public void llSetLinkColor(int linknumber, LSL_Vector color, int face) 4003 public void llSetLinkColor(int linknumber, LSL_Vector color, int face)
4004 { 4004 {
4005 List<SceneObjectPart> parts = GetLinkParts(linknumber); 4005 List<SceneObjectPart> parts = GetLinkParts(linknumber);
4006 4006
4007 foreach (SceneObjectPart part in parts) 4007 foreach (SceneObjectPart part in parts)
4008 part.SetFaceColorAlpha(face, color, null); 4008 part.SetFaceColorAlpha(face, color, null);
4009 } 4009 }
4010 4010
4011 public void llCreateLink(string target, int parent) 4011 public void llCreateLink(string target, int parent)
4012 { 4012 {
4013 m_host.AddScriptLPS(1); 4013 m_host.AddScriptLPS(1);
4014 4014
4015 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4015 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4016 && !m_automaticLinkPermission) 4016 && !m_automaticLinkPermission)
4017 { 4017 {
4018 Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set"); 4018 Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set");
4019 return; 4019 return;
4020 } 4020 }
4021 4021
4022 CreateLink(target, parent); 4022 CreateLink(target, parent);
4023 } 4023 }
4024 4024
4025 public void CreateLink(string target, int parent) 4025 public void CreateLink(string target, int parent)
4026 { 4026 {
4027 UUID targetID; 4027 UUID targetID;
4028 4028
4029 if (!UUID.TryParse(target, out targetID)) 4029 if (!UUID.TryParse(target, out targetID))
4030 return; 4030 return;
4031 4031
4032 SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); 4032 SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID);
4033 4033
4034 if (targetPart.ParentGroup.AttachmentPoint != 0) 4034 if (targetPart.ParentGroup.AttachmentPoint != 0)
4035 return; // Fail silently if attached 4035 return; // Fail silently if attached
4036 4036
4037 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID) 4037 if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID)
4038 return; 4038 return;
4039 4039
4040 SceneObjectGroup parentPrim = null, childPrim = null; 4040 SceneObjectGroup parentPrim = null, childPrim = null;
4041 4041
4042 if (targetPart != null) 4042 if (targetPart != null)
4043 { 4043 {
4044 if (parent != 0) 4044 if (parent != 0)
4045 { 4045 {
4046 parentPrim = m_host.ParentGroup; 4046 parentPrim = m_host.ParentGroup;
4047 childPrim = targetPart.ParentGroup; 4047 childPrim = targetPart.ParentGroup;
4048 } 4048 }
4049 else 4049 else
4050 { 4050 {
4051 parentPrim = targetPart.ParentGroup; 4051 parentPrim = targetPart.ParentGroup;
4052 childPrim = m_host.ParentGroup; 4052 childPrim = m_host.ParentGroup;
4053 } 4053 }
4054 4054
4055 // Required for linking 4055 // Required for linking
4056 childPrim.RootPart.ClearUpdateSchedule(); 4056 childPrim.RootPart.ClearUpdateSchedule();
4057 parentPrim.LinkToGroup(childPrim, true); 4057 parentPrim.LinkToGroup(childPrim, true);
4058 } 4058 }
4059 4059
4060 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4060 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4061 parentPrim.RootPart.CreateSelected = true; 4061 parentPrim.RootPart.CreateSelected = true;
4062 parentPrim.HasGroupChanged = true; 4062 parentPrim.HasGroupChanged = true;
4063 parentPrim.ScheduleGroupForFullUpdate(); 4063 parentPrim.ScheduleGroupForFullUpdate();
4064 4064
4065 IClientAPI client = null; 4065 IClientAPI client = null;
4066 ScenePresence sp = World.GetScenePresence(m_host.OwnerID); 4066 ScenePresence sp = World.GetScenePresence(m_host.OwnerID);
4067 if (sp != null) 4067 if (sp != null)
4068 client = sp.ControllingClient; 4068 client = sp.ControllingClient;
4069 4069
4070 if (client != null) 4070 if (client != null)
4071 parentPrim.SendPropertiesToClient(client); 4071 parentPrim.SendPropertiesToClient(client);
4072 4072
4073 ScriptSleep(m_sleepMsOnCreateLink); 4073 ScriptSleep(m_sleepMsOnCreateLink);
4074 } 4074 }
4075 4075
4076 public void llBreakLink(int linknum) 4076 public void llBreakLink(int linknum)
4077 { 4077 {
4078 m_host.AddScriptLPS(1); 4078 m_host.AddScriptLPS(1);
4079 4079
4080 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4080 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4081 && !m_automaticLinkPermission) 4081 && !m_automaticLinkPermission)
4082 { 4082 {
4083 Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set"); 4083 Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set");
4084 return; 4084 return;
4085 } 4085 }
4086 4086
4087 BreakLink(linknum); 4087 BreakLink(linknum);
4088 } 4088 }
4089 4089
4090 public void BreakLink(int linknum) 4090 public void BreakLink(int linknum)
4091 { 4091 {
4092 if (linknum < ScriptBaseClass.LINK_THIS) 4092 if (linknum < ScriptBaseClass.LINK_THIS)
4093 return; 4093 return;
4094 4094
4095 SceneObjectGroup parentPrim = m_host.ParentGroup; 4095 SceneObjectGroup parentPrim = m_host.ParentGroup;
4096 4096
4097 if (parentPrim.AttachmentPoint != 0) 4097 if (parentPrim.AttachmentPoint != 0)
4098 return; // Fail silently if attached 4098 return; // Fail silently if attached
4099 SceneObjectPart childPrim = null; 4099 SceneObjectPart childPrim = null;
4100 4100
4101 switch (linknum) 4101 switch (linknum)
4102 { 4102 {
4103 case ScriptBaseClass.LINK_ROOT: 4103 case ScriptBaseClass.LINK_ROOT:
4104 break; 4104 break;
4105 case ScriptBaseClass.LINK_SET: 4105 case ScriptBaseClass.LINK_SET:
4106 case ScriptBaseClass.LINK_ALL_OTHERS: 4106 case ScriptBaseClass.LINK_ALL_OTHERS:
4107 case ScriptBaseClass.LINK_ALL_CHILDREN: 4107 case ScriptBaseClass.LINK_ALL_CHILDREN:
4108 case ScriptBaseClass.LINK_THIS: 4108 case ScriptBaseClass.LINK_THIS:
4109 foreach (SceneObjectPart part in parentPrim.Parts) 4109 foreach (SceneObjectPart part in parentPrim.Parts)
4110 { 4110 {
4111 if (part.UUID != m_host.UUID) 4111 if (part.UUID != m_host.UUID)
4112 { 4112 {
4113 childPrim = part; 4113 childPrim = part;
4114 break; 4114 break;
4115 } 4115 }
4116 } 4116 }
4117 break; 4117 break;
4118 default: 4118 default:
4119 childPrim = parentPrim.GetLinkNumPart(linknum); 4119 childPrim = parentPrim.GetLinkNumPart(linknum);
4120 if (childPrim.UUID == m_host.UUID) 4120 if (childPrim.UUID == m_host.UUID)
4121 childPrim = null; 4121 childPrim = null;
4122 break; 4122 break;
4123 } 4123 }
4124 4124
4125 if (linknum == ScriptBaseClass.LINK_ROOT) 4125 if (linknum == ScriptBaseClass.LINK_ROOT)
4126 { 4126 {
4127 // Restructuring Multiple Prims. 4127 // Restructuring Multiple Prims.
4128 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4128 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
4129 parts.Remove(parentPrim.RootPart); 4129 parts.Remove(parentPrim.RootPart);
4130 foreach (SceneObjectPart part in parts) 4130 foreach (SceneObjectPart part in parts)
4131 { 4131 {
4132 parentPrim.DelinkFromGroup(part.LocalId, true); 4132 parentPrim.DelinkFromGroup(part.LocalId, true);
4133 } 4133 }
4134 parentPrim.HasGroupChanged = true; 4134 parentPrim.HasGroupChanged = true;
4135 parentPrim.ScheduleGroupForFullUpdate(); 4135 parentPrim.ScheduleGroupForFullUpdate();
4136 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4136 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4137 4137
4138 if (parts.Count > 0) 4138 if (parts.Count > 0)
4139 { 4139 {
4140 SceneObjectPart newRoot = parts[0]; 4140 SceneObjectPart newRoot = parts[0];
4141 parts.Remove(newRoot); 4141 parts.Remove(newRoot);
4142 foreach (SceneObjectPart part in parts) 4142 foreach (SceneObjectPart part in parts)
4143 { 4143 {
4144 // Required for linking 4144 // Required for linking
4145 part.ClearUpdateSchedule(); 4145 part.ClearUpdateSchedule();
4146 newRoot.ParentGroup.LinkToGroup(part.ParentGroup); 4146 newRoot.ParentGroup.LinkToGroup(part.ParentGroup);
4147 } 4147 }
4148 newRoot.ParentGroup.HasGroupChanged = true; 4148 newRoot.ParentGroup.HasGroupChanged = true;
4149 newRoot.ParentGroup.ScheduleGroupForFullUpdate(); 4149 newRoot.ParentGroup.ScheduleGroupForFullUpdate();
4150 } 4150 }
4151 } 4151 }
4152 else 4152 else
4153 { 4153 {
4154 if (childPrim == null) 4154 if (childPrim == null)
4155 return; 4155 return;
4156 4156
4157 parentPrim.DelinkFromGroup(childPrim.LocalId, true); 4157 parentPrim.DelinkFromGroup(childPrim.LocalId, true);
4158 parentPrim.HasGroupChanged = true; 4158 parentPrim.HasGroupChanged = true;
4159 parentPrim.ScheduleGroupForFullUpdate(); 4159 parentPrim.ScheduleGroupForFullUpdate();
4160 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4160 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4161 } 4161 }
4162 } 4162 }
4163 4163
4164 public void llBreakAllLinks() 4164 public void llBreakAllLinks()
4165 { 4165 {
4166 m_host.AddScriptLPS(1); 4166 m_host.AddScriptLPS(1);
4167 4167
4168 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 4168 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0
4169 && !m_automaticLinkPermission) 4169 && !m_automaticLinkPermission)
4170 { 4170 {
4171 Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set"); 4171 Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set");
4172 return; 4172 return;
4173 } 4173 }
4174 4174
4175 BreakAllLinks(); 4175 BreakAllLinks();
4176 } 4176 }
4177 4177
4178 public void BreakAllLinks() 4178 public void BreakAllLinks()
4179 { 4179 {
4180 SceneObjectGroup parentPrim = m_host.ParentGroup; 4180 SceneObjectGroup parentPrim = m_host.ParentGroup;
4181 if (parentPrim.AttachmentPoint != 0) 4181 if (parentPrim.AttachmentPoint != 0)
4182 return; // Fail silently if attached 4182 return; // Fail silently if attached
4183 4183
4184 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); 4184 List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts);
4185 parts.Remove(parentPrim.RootPart); 4185 parts.Remove(parentPrim.RootPart);
4186 4186
4187 foreach (SceneObjectPart part in parts) 4187 foreach (SceneObjectPart part in parts)
4188 { 4188 {
4189 parentPrim.DelinkFromGroup(part.LocalId, true); 4189 parentPrim.DelinkFromGroup(part.LocalId, true);
4190 parentPrim.TriggerScriptChangedEvent(Changed.LINK); 4190 parentPrim.TriggerScriptChangedEvent(Changed.LINK);
4191 } 4191 }
4192 parentPrim.HasGroupChanged = true; 4192 parentPrim.HasGroupChanged = true;
4193 parentPrim.ScheduleGroupForFullUpdate(); 4193 parentPrim.ScheduleGroupForFullUpdate();
4194 } 4194 }
4195 4195
4196 public LSL_String llGetLinkKey(int linknum) 4196 public LSL_String llGetLinkKey(int linknum)
4197 { 4197 {
4198 m_host.AddScriptLPS(1); 4198 m_host.AddScriptLPS(1);
4199 4199
4200 ISceneEntity entity = GetLinkEntity(m_host, linknum); 4200 ISceneEntity entity = GetLinkEntity(m_host, linknum);
4201 4201
4202 if (entity != null) 4202 if (entity != null)
4203 return entity.UUID.ToString(); 4203 return entity.UUID.ToString();
4204 else 4204 else
4205 return ScriptBaseClass.NULL_KEY; 4205 return ScriptBaseClass.NULL_KEY;
4206 } 4206 }
4207 4207
4208 /// <summary> 4208 /// <summary>
4209 /// Returns the name of the child prim or seated avatar matching the 4209 /// Returns the name of the child prim or seated avatar matching the
4210 /// specified link number. 4210 /// specified link number.
4211 /// </summary> 4211 /// </summary>
4212 /// <param name="linknum"> 4212 /// <param name="linknum">
4213 /// The number of a link in the linkset or a link-related constant. 4213 /// The number of a link in the linkset or a link-related constant.
4214 /// </param> 4214 /// </param>
4215 /// <returns> 4215 /// <returns>
4216 /// The name determined to match the specified link number. 4216 /// The name determined to match the specified link number.
4217 /// </returns> 4217 /// </returns>
4218 /// <remarks> 4218 /// <remarks>
4219 /// The rules governing the returned name are not simple. The only 4219 /// The rules governing the returned name are not simple. The only
4220 /// time a blank name is returned is if the target prim has a blank 4220 /// time a blank name is returned is if the target prim has a blank
4221 /// name. If no prim with the given link number can be found then 4221 /// name. If no prim with the given link number can be found then
4222 /// usually NULL_KEY is returned but there are exceptions. 4222 /// usually NULL_KEY is returned but there are exceptions.
4223 /// 4223 ///
4224 /// In a single unlinked prim, A call with 0 returns the name, all 4224 /// In a single unlinked prim, A call with 0 returns the name, all
4225 /// other values for link number return NULL_KEY 4225 /// other values for link number return NULL_KEY
4226 /// 4226 ///
4227 /// In link sets it is more complicated. 4227 /// In link sets it is more complicated.
4228 /// 4228 ///
4229 /// If the script is in the root prim:- 4229 /// If the script is in the root prim:-
4230 /// A zero link number returns NULL_KEY. 4230 /// A zero link number returns NULL_KEY.
4231 /// Positive link numbers return the name of the prim, or NULL_KEY 4231 /// Positive link numbers return the name of the prim, or NULL_KEY
4232 /// if a prim does not exist at that position. 4232 /// if a prim does not exist at that position.
4233 /// Negative link numbers return the name of the first child prim. 4233 /// Negative link numbers return the name of the first child prim.
4234 /// 4234 ///
4235 /// If the script is in a child prim:- 4235 /// If the script is in a child prim:-
4236 /// Link numbers 0 or 1 return the name of the root prim. 4236 /// Link numbers 0 or 1 return the name of the root prim.
4237 /// Positive link numbers return the name of the prim or NULL_KEY 4237 /// Positive link numbers return the name of the prim or NULL_KEY
4238 /// if a prim does not exist at that position. 4238 /// if a prim does not exist at that position.
4239 /// Negative numbers return the name of the root prim. 4239 /// Negative numbers return the name of the root prim.
4240 /// 4240 ///
4241 /// References 4241 /// References
4242 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName 4242 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName
4243 /// Mentions NULL_KEY being returned 4243 /// Mentions NULL_KEY being returned
4244 /// http://wiki.secondlife.com/wiki/LlGetLinkName 4244 /// http://wiki.secondlife.com/wiki/LlGetLinkName
4245 /// Mentions using the LINK_* constants, some of which are negative 4245 /// Mentions using the LINK_* constants, some of which are negative
4246 /// </remarks> 4246 /// </remarks>
4247 public LSL_String llGetLinkName(int linknum) 4247 public LSL_String llGetLinkName(int linknum)
4248 { 4248 {
4249 m_host.AddScriptLPS(1); 4249 m_host.AddScriptLPS(1);
4250 4250
4251 ISceneEntity entity = GetLinkEntity(m_host, linknum); 4251 ISceneEntity entity = GetLinkEntity(m_host, linknum);
4252 4252
4253 if (entity != null) 4253 if (entity != null)
4254 return entity.Name; 4254 return entity.Name;
4255 else 4255 else
4256 return ScriptBaseClass.NULL_KEY; 4256 return ScriptBaseClass.NULL_KEY;
4257 } 4257 }
4258 4258
4259 public LSL_Integer llGetInventoryNumber(int type) 4259 public LSL_Integer llGetInventoryNumber(int type)
4260 { 4260 {
4261 m_host.AddScriptLPS(1); 4261 m_host.AddScriptLPS(1);
4262 int count = 0; 4262 int count = 0;
4263 4263
4264 lock (m_host.TaskInventory) 4264 lock (m_host.TaskInventory)
4265 { 4265 {
4266 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4266 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4267 { 4267 {
4268 if (inv.Value.Type == type || type == -1) 4268 if (inv.Value.Type == type || type == -1)
4269 { 4269 {
4270 count = count + 1; 4270 count = count + 1;
4271 } 4271 }
4272 } 4272 }
4273 } 4273 }
4274 4274
4275 return count; 4275 return count;
4276 } 4276 }
4277 4277
4278 public LSL_String llGetInventoryName(int type, int number) 4278 public LSL_String llGetInventoryName(int type, int number)
4279 { 4279 {
4280 m_host.AddScriptLPS(1); 4280 m_host.AddScriptLPS(1);
4281 ArrayList keys = new ArrayList(); 4281 ArrayList keys = new ArrayList();
4282 4282
4283 lock (m_host.TaskInventory) 4283 lock (m_host.TaskInventory)
4284 { 4284 {
4285 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) 4285 foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory)
4286 { 4286 {
4287 if (inv.Value.Type == type || type == -1) 4287 if (inv.Value.Type == type || type == -1)
4288 { 4288 {
4289 keys.Add(inv.Value.Name); 4289 keys.Add(inv.Value.Name);
4290 } 4290 }
4291 } 4291 }
4292 } 4292 }
4293 4293
4294 if (keys.Count == 0) 4294 if (keys.Count == 0)
4295 { 4295 {
4296 return String.Empty; 4296 return String.Empty;
4297 } 4297 }
4298 keys.Sort(); 4298 keys.Sort();
4299 if (keys.Count > number) 4299 if (keys.Count > number)
4300 { 4300 {
4301 return (string)keys[number]; 4301 return (string)keys[number];
4302 } 4302 }
4303 return String.Empty; 4303 return String.Empty;
4304 } 4304 }
4305 4305
4306 public LSL_Float llGetEnergy() 4306 public LSL_Float llGetEnergy()
4307 { 4307 {
4308 m_host.AddScriptLPS(1); 4308 m_host.AddScriptLPS(1);
4309 // TODO: figure out real energy value 4309 // TODO: figure out real energy value
4310 return 1.0f; 4310 return 1.0f;
4311 } 4311 }
4312 4312
4313 public void llGiveInventory(string destination, string inventory) 4313 public void llGiveInventory(string destination, string inventory)
4314 { 4314 {
4315 m_host.AddScriptLPS(1); 4315 m_host.AddScriptLPS(1);
4316 4316
4317 UUID destId = UUID.Zero; 4317 UUID destId = UUID.Zero;
4318 4318
4319 if (!UUID.TryParse(destination, out destId)) 4319 if (!UUID.TryParse(destination, out destId))
4320 { 4320 {
4321 Error("llGiveInventory", "Can't parse destination key '" + destination + "'"); 4321 Error("llGiveInventory", "Can't parse destination key '" + destination + "'");
4322 return; 4322 return;
4323 } 4323 }
4324 4324
4325 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); 4325 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory);
4326 4326
4327 if (item == null) 4327 if (item == null)
4328 { 4328 {
4329 Error("llGiveInventory", "Can't find inventory object '" + inventory + "'"); 4329 Error("llGiveInventory", "Can't find inventory object '" + inventory + "'");
4330 return; 4330 return;
4331 } 4331 }
4332 4332
4333 UUID objId = item.ItemID; 4333 UUID objId = item.ItemID;
4334 4334
4335 // check if destination is an object 4335 // check if destination is an object
4336 if (World.GetSceneObjectPart(destId) != null) 4336 if (World.GetSceneObjectPart(destId) != null)
4337 { 4337 {
4338 // destination is an object 4338 // destination is an object
4339 World.MoveTaskInventoryItem(destId, m_host, objId); 4339 World.MoveTaskInventoryItem(destId, m_host, objId);
4340 } 4340 }
4341 else 4341 else
4342 { 4342 {
4343 ScenePresence presence = World.GetScenePresence(destId); 4343 ScenePresence presence = World.GetScenePresence(destId);
4344 4344
4345 if (presence == null) 4345 if (presence == null)
4346 { 4346 {
4347 UserAccount account = 4347 UserAccount account =
4348 World.UserAccountService.GetUserAccount( 4348 World.UserAccountService.GetUserAccount(
4349 World.RegionInfo.ScopeID, 4349 World.RegionInfo.ScopeID,
4350 destId); 4350 destId);
4351 4351
4352 if (account == null) 4352 if (account == null)
4353 { 4353 {
4354 GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString()); 4354 GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString());
4355 if(info == null || info.Online == false) 4355 if(info == null || info.Online == false)
4356 { 4356 {
4357 Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'"); 4357 Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'");
4358 return; 4358 return;
4359 } 4359 }
4360 } 4360 }
4361 } 4361 }
4362 // destination is an avatar 4362 // destination is an avatar
4363 string message; 4363 string message;
4364 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message); 4364 InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message);
4365 4365
4366 if (agentItem == null) 4366 if (agentItem == null)
4367 { 4367 {
4368 llSay(0, message); 4368 llSay(0, message);
4369 return; 4369 return;
4370 } 4370 }
4371 4371
4372 if (m_TransferModule != null) 4372 if (m_TransferModule != null)
4373 { 4373 {
4374 byte[] bucket = new byte[1]; 4374 byte[] bucket = new byte[1];
4375 bucket[0] = (byte)item.Type; 4375 bucket[0] = (byte)item.Type;
4376 4376
4377 GridInstantMessage msg = new GridInstantMessage(World, 4377 GridInstantMessage msg = new GridInstantMessage(World,
4378 m_host.OwnerID, m_host.Name, destId, 4378 m_host.OwnerID, m_host.Name, destId,
4379 (byte)InstantMessageDialog.TaskInventoryOffered, 4379 (byte)InstantMessageDialog.TaskInventoryOffered,
4380 false, item.Name+". "+m_host.Name+" is located at "+ 4380 false, item.Name+". "+m_host.Name+" is located at "+
4381 World.RegionInfo.RegionName+" "+ 4381 World.RegionInfo.RegionName+" "+
4382 m_host.AbsolutePosition.ToString(), 4382 m_host.AbsolutePosition.ToString(),
4383 agentItem.ID, true, m_host.AbsolutePosition, 4383 agentItem.ID, true, m_host.AbsolutePosition,
4384 bucket, true); 4384 bucket, true);
4385 4385
4386 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 4386 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
4387 } 4387 }
4388 4388
4389 ScriptSleep(m_sleepMsOnGiveInventory); 4389 ScriptSleep(m_sleepMsOnGiveInventory);
4390 } 4390 }
4391 } 4391 }
4392 4392
4393 public void llRemoveInventory(string name) 4393 public void llRemoveInventory(string name)
4394 { 4394 {
4395 m_host.AddScriptLPS(1); 4395 m_host.AddScriptLPS(1);
4396 4396
4397 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 4397 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
4398 4398
4399 if (item == null) 4399 if (item == null)
4400 return; 4400 return;
4401 4401
4402 if (item.ItemID == m_item.ItemID) 4402 if (item.ItemID == m_item.ItemID)
4403 throw new ScriptDeleteException(); 4403 throw new ScriptDeleteException();
4404 else 4404 else
4405 m_host.Inventory.RemoveInventoryItem(item.ItemID); 4405 m_host.Inventory.RemoveInventoryItem(item.ItemID);
4406 } 4406 }
4407 4407
4408 public void llSetText(string text, LSL_Vector color, double alpha) 4408 public void llSetText(string text, LSL_Vector color, double alpha)
4409 { 4409 {
4410 m_host.AddScriptLPS(1); 4410 m_host.AddScriptLPS(1);
4411 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); 4411 Vector3 av3 = Util.Clip(color, 0.0f, 1.0f);
4412 if (text.Length > 254) 4412 if (text.Length > 254)
4413 text = text.Remove(254); 4413 text = text.Remove(254);
4414 4414
4415 byte[] data; 4415 byte[] data;
4416 do 4416 do
4417 { 4417 {
4418 data = Util.UTF8.GetBytes(text); 4418 data = Util.UTF8.GetBytes(text);
4419 if (data.Length > 254) 4419 if (data.Length > 254)
4420 text = text.Substring(0, text.Length - 1); 4420 text = text.Substring(0, text.Length - 1);
4421 } while (data.Length > 254); 4421 } while (data.Length > 254);
4422 4422
4423 m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); 4423 m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f));
4424 //m_host.ParentGroup.HasGroupChanged = true; 4424 //m_host.ParentGroup.HasGroupChanged = true;
4425 //m_host.ParentGroup.ScheduleGroupForFullUpdate(); 4425 //m_host.ParentGroup.ScheduleGroupForFullUpdate();
4426 } 4426 }
4427 4427
4428 public LSL_Float llWater(LSL_Vector offset) 4428 public LSL_Float llWater(LSL_Vector offset)
4429 { 4429 {
4430 m_host.AddScriptLPS(1); 4430 m_host.AddScriptLPS(1);
4431 return World.RegionInfo.RegionSettings.WaterHeight; 4431 return World.RegionInfo.RegionSettings.WaterHeight;
4432 } 4432 }
4433 4433
4434 public void llPassTouches(int pass) 4434 public void llPassTouches(int pass)
4435 { 4435 {
4436 m_host.AddScriptLPS(1); 4436 m_host.AddScriptLPS(1);
4437 if (pass != 0) 4437 if (pass != 0)
4438 m_host.PassTouches = true; 4438 m_host.PassTouches = true;
4439 else 4439 else
4440 m_host.PassTouches = false; 4440 m_host.PassTouches = false;
4441 } 4441 }
4442 4442
4443 public LSL_String llRequestAgentData(string id, int data) 4443 public LSL_String llRequestAgentData(string id, int data)
4444 { 4444 {
4445 m_host.AddScriptLPS(1); 4445 m_host.AddScriptLPS(1);
4446 4446
4447 UUID uuid = (UUID)id; 4447 UUID uuid = (UUID)id;
4448 PresenceInfo pinfo = null; 4448 PresenceInfo pinfo = null;
4449 UserAccount account; 4449 UserAccount account;
4450 4450
4451 UserInfoCacheEntry ce; 4451 UserInfoCacheEntry ce;
4452 4452
4453 lock (m_userInfoCache) 4453 lock (m_userInfoCache)
4454 { 4454 {
4455 if (!m_userInfoCache.TryGetValue(uuid, out ce)) 4455 if (!m_userInfoCache.TryGetValue(uuid, out ce))
4456 { 4456 {
4457 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); 4457 account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid);
4458 if (account == null) 4458 if (account == null)
4459 { 4459 {
4460 m_userInfoCache[uuid] = null; // Cache negative 4460 m_userInfoCache[uuid] = null; // Cache negative
4461 return UUID.Zero.ToString(); 4461 return UUID.Zero.ToString();
4462 } 4462 }
4463 4463
4464 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4464 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4465 if (pinfos != null && pinfos.Length > 0) 4465 if (pinfos != null && pinfos.Length > 0)
4466 { 4466 {
4467 foreach (PresenceInfo p in pinfos) 4467 foreach (PresenceInfo p in pinfos)
4468 { 4468 {
4469 if (p.RegionID != UUID.Zero) 4469 if (p.RegionID != UUID.Zero)
4470 { 4470 {
4471 pinfo = p; 4471 pinfo = p;
4472 } 4472 }
4473 } 4473 }
4474 } 4474 }
4475 4475
4476 ce = new UserInfoCacheEntry(); 4476 ce = new UserInfoCacheEntry();
4477 ce.time = Util.EnvironmentTickCount(); 4477 ce.time = Util.EnvironmentTickCount();
4478 ce.account = account; 4478 ce.account = account;
4479 ce.pinfo = pinfo; 4479 ce.pinfo = pinfo;
4480 4480
4481 m_userInfoCache[uuid] = ce; 4481 m_userInfoCache[uuid] = ce;
4482 } 4482 }
4483 else 4483 else
4484 { 4484 {
4485 if (ce == null) 4485 if (ce == null)
4486 return UUID.Zero.ToString(); 4486 return UUID.Zero.ToString();
4487 4487
4488 account = ce.account; 4488 account = ce.account;
4489 4489
4490 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) 4490 if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time)
4491 >= LlRequestAgentDataCacheTimeoutMs) 4491 >= LlRequestAgentDataCacheTimeoutMs)
4492 { 4492 {
4493 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); 4493 PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() });
4494 if (pinfos != null && pinfos.Length > 0) 4494 if (pinfos != null && pinfos.Length > 0)
4495 { 4495 {
4496 foreach (PresenceInfo p in pinfos) 4496 foreach (PresenceInfo p in pinfos)
4497 { 4497 {
4498 if (p.RegionID != UUID.Zero) 4498 if (p.RegionID != UUID.Zero)
4499 { 4499 {
4500 pinfo = p; 4500 pinfo = p;
4501 } 4501 }
4502 } 4502 }
4503 } 4503 }
4504 else 4504 else
4505 { 4505 {
4506 pinfo = null; 4506 pinfo = null;
4507 } 4507 }
4508 4508
4509 ce.time = Util.EnvironmentTickCount(); 4509 ce.time = Util.EnvironmentTickCount();
4510 ce.pinfo = pinfo; 4510 ce.pinfo = pinfo;
4511 } 4511 }
4512 else 4512 else
4513 { 4513 {
4514 pinfo = ce.pinfo; 4514 pinfo = ce.pinfo;
4515 } 4515 }
4516 } 4516 }
4517 } 4517 }
4518 4518
4519 string reply = String.Empty; 4519 string reply = String.Empty;
4520 4520
4521 switch (data) 4521 switch (data)
4522 { 4522 {
4523 case ScriptBaseClass.DATA_ONLINE: 4523 case ScriptBaseClass.DATA_ONLINE:
4524 if (pinfo != null && pinfo.RegionID != UUID.Zero) 4524 if (pinfo != null && pinfo.RegionID != UUID.Zero)
4525 reply = "1"; 4525 reply = "1";
4526 else 4526 else
4527 reply = "0"; 4527 reply = "0";
4528 break; 4528 break;
4529 case ScriptBaseClass.DATA_NAME: // (First Last) 4529 case ScriptBaseClass.DATA_NAME: // (First Last)
4530 reply = account.FirstName + " " + account.LastName; 4530 reply = account.FirstName + " " + account.LastName;
4531 break; 4531 break;
4532 case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD) 4532 case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD)
4533 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); 4533 DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0);
4534 born = born.AddSeconds(account.Created); 4534 born = born.AddSeconds(account.Created);
4535 reply = born.ToString("yyyy-MM-dd"); 4535 reply = born.ToString("yyyy-MM-dd");
4536 break; 4536 break;
4537 case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0) 4537 case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0)
4538 reply = "0,0,0,0,0,0"; 4538 reply = "0,0,0,0,0,0";
4539 break; 4539 break;
4540 case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant. 4540 case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant.
4541 reply = account.UserLevel.ToString(); 4541 reply = account.UserLevel.ToString();
4542 break; 4542 break;
4543 case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3) 4543 case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3)
4544 reply = "0"; 4544 reply = "0";
4545 break; 4545 break;
4546 default: 4546 default:
4547 return UUID.Zero.ToString(); // Raise no event 4547 return UUID.Zero.ToString(); // Raise no event
4548 } 4548 }
4549 4549
4550 UUID rq = UUID.Random(); 4550 UUID rq = UUID.Random();
4551 4551
4552 UUID tid = AsyncCommands. 4552 UUID tid = AsyncCommands.
4553 DataserverPlugin.RegisterRequest(m_host.LocalId, 4553 DataserverPlugin.RegisterRequest(m_host.LocalId,
4554 m_item.ItemID, rq.ToString()); 4554 m_item.ItemID, rq.ToString());
4555 4555
4556 AsyncCommands. 4556 AsyncCommands.
4557 DataserverPlugin.DataserverReply(rq.ToString(), reply); 4557 DataserverPlugin.DataserverReply(rq.ToString(), reply);
4558 4558
4559 ScriptSleep(m_sleepMsOnRequestAgentData); 4559 ScriptSleep(m_sleepMsOnRequestAgentData);
4560 return tid.ToString(); 4560 return tid.ToString();
4561 } 4561 }
4562 4562
4563 public LSL_String llRequestInventoryData(string name) 4563 public LSL_String llRequestInventoryData(string name)
4564 { 4564 {
4565 m_host.AddScriptLPS(1); 4565 m_host.AddScriptLPS(1);
4566 4566
4567 foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems()) 4567 foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems())
4568 { 4568 {
4569 if (item.Type == 3 && item.Name == name) 4569 if (item.Type == 3 && item.Name == name)
4570 { 4570 {
4571 UUID tid = AsyncCommands. 4571 UUID tid = AsyncCommands.
4572 DataserverPlugin.RegisterRequest(m_host.LocalId, 4572 DataserverPlugin.RegisterRequest(m_host.LocalId,
4573 m_item.ItemID, item.AssetID.ToString()); 4573 m_item.ItemID, item.AssetID.ToString());
4574 4574
4575 Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); 4575 Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
4576 4576
4577 World.AssetService.Get(item.AssetID.ToString(), this, 4577 World.AssetService.Get(item.AssetID.ToString(), this,
4578 delegate(string i, object sender, AssetBase a) 4578 delegate(string i, object sender, AssetBase a)
4579 { 4579 {
4580 AssetLandmark lm = new AssetLandmark(a); 4580 AssetLandmark lm = new AssetLandmark(a);
4581 4581
4582 float rx = (uint)(lm.RegionHandle >> 32); 4582 float rx = (uint)(lm.RegionHandle >> 32);
4583 float ry = (uint)lm.RegionHandle; 4583 float ry = (uint)lm.RegionHandle;
4584 region = lm.Position + new Vector3(rx, ry, 0) - region; 4584 region = lm.Position + new Vector3(rx, ry, 0) - region;
4585 4585
4586 string reply = region.ToString(); 4586 string reply = region.ToString();
4587 AsyncCommands. 4587 AsyncCommands.
4588 DataserverPlugin.DataserverReply(i.ToString(), 4588 DataserverPlugin.DataserverReply(i.ToString(),
4589 reply); 4589 reply);
4590 }); 4590 });
4591 4591
4592 ScriptSleep(m_sleepMsOnRequestInventoryData); 4592 ScriptSleep(m_sleepMsOnRequestInventoryData);
4593 return tid.ToString(); 4593 return tid.ToString();
4594 } 4594 }
4595 } 4595 }
4596 4596
4597 ScriptSleep(m_sleepMsOnRequestInventoryData); 4597 ScriptSleep(m_sleepMsOnRequestInventoryData);
4598 return String.Empty; 4598 return String.Empty;
4599 } 4599 }
4600 4600
4601 public void llSetDamage(double damage) 4601 public void llSetDamage(double damage)
4602 { 4602 {
4603 m_host.AddScriptLPS(1); 4603 m_host.AddScriptLPS(1);
4604 m_host.ParentGroup.Damage = (float)damage; 4604 m_host.ParentGroup.Damage = (float)damage;
4605 } 4605 }
4606 4606
4607 public void llTeleportAgentHome(string agent) 4607 public void llTeleportAgentHome(string agent)
4608 { 4608 {
4609 m_host.AddScriptLPS(1); 4609 m_host.AddScriptLPS(1);
4610 UUID agentId = new UUID(); 4610 UUID agentId = new UUID();
4611 if (UUID.TryParse(agent, out agentId)) 4611 if (UUID.TryParse(agent, out agentId))
4612 { 4612 {
4613 ScenePresence presence = World.GetScenePresence(agentId); 4613 ScenePresence presence = World.GetScenePresence(agentId);
4614 if (presence != null) 4614 if (presence != null)
4615 { 4615 {
4616 // agent must be over the owners land 4616 // agent must be over the owners land
4617 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 4617 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4618 { 4618 {
4619 World.TeleportClientHome(agentId, presence.ControllingClient); 4619 World.TeleportClientHome(agentId, presence.ControllingClient);
4620 } 4620 }
4621 } 4621 }
4622 } 4622 }
4623 4623
4624 ScriptSleep(m_sleepMsOnSetDamage); 4624 ScriptSleep(m_sleepMsOnSetDamage);
4625 } 4625 }
4626 4626
4627 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) 4627 public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt)
4628 { 4628 {
4629 m_host.AddScriptLPS(1); 4629 m_host.AddScriptLPS(1);
4630 UUID agentId = new UUID(); 4630 UUID agentId = new UUID();
4631 4631
4632 if (UUID.TryParse(agent, out agentId)) 4632 if (UUID.TryParse(agent, out agentId))
4633 { 4633 {
4634 ScenePresence presence = World.GetScenePresence(agentId); 4634 ScenePresence presence = World.GetScenePresence(agentId);
4635 if (presence != null && presence.PresenceType != PresenceType.Npc) 4635 if (presence != null && presence.PresenceType != PresenceType.Npc)
4636 { 4636 {
4637 // agent must not be a god 4637 // agent must not be a god
4638 if (presence.GodLevel >= 200) return; 4638 if (presence.GodLevel >= 200) return;
4639 4639
4640 if (destination == String.Empty) 4640 if (destination == String.Empty)
4641 destination = World.RegionInfo.RegionName; 4641 destination = World.RegionInfo.RegionName;
4642 4642
4643 // agent must be over the owners land 4643 // agent must be over the owners land
4644 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 4644 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4645 { 4645 {
4646 DoLLTeleport(presence, destination, targetPos, targetLookAt); 4646 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4647 } 4647 }
4648 else // or must be wearing the prim 4648 else // or must be wearing the prim
4649 { 4649 {
4650 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) 4650 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4651 { 4651 {
4652 DoLLTeleport(presence, destination, targetPos, targetLookAt); 4652 DoLLTeleport(presence, destination, targetPos, targetLookAt);
4653 } 4653 }
4654 } 4654 }
4655 } 4655 }
4656 } 4656 }
4657 } 4657 }
4658 4658
4659 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) 4659 public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt)
4660 { 4660 {
4661 m_host.AddScriptLPS(1); 4661 m_host.AddScriptLPS(1);
4662 UUID agentId = new UUID(); 4662 UUID agentId = new UUID();
4663 4663
4664 ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y); 4664 ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y);
4665 4665
4666 if (UUID.TryParse(agent, out agentId)) 4666 if (UUID.TryParse(agent, out agentId))
4667 { 4667 {
4668 ScenePresence presence = World.GetScenePresence(agentId); 4668 ScenePresence presence = World.GetScenePresence(agentId);
4669 if (presence != null && presence.PresenceType != PresenceType.Npc) 4669 if (presence != null && presence.PresenceType != PresenceType.Npc)
4670 { 4670 {
4671 // agent must not be a god 4671 // agent must not be a god
4672 if (presence.GodLevel >= 200) return; 4672 if (presence.GodLevel >= 200) return;
4673 4673
4674 // agent must be over the owners land 4674 // agent must be over the owners land
4675 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 4675 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
4676 { 4676 {
4677 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); 4677 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4678 } 4678 }
4679 else // or must be wearing the prim 4679 else // or must be wearing the prim
4680 { 4680 {
4681 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) 4681 if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID)
4682 { 4682 {
4683 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); 4683 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4684 } 4684 }
4685 } 4685 }
4686 } 4686 }
4687 } 4687 }
4688 } 4688 }
4689 4689
4690 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) 4690 private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt)
4691 { 4691 {
4692 UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination); 4692 UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination);
4693 4693
4694 // The destinaion is not an asset ID and also doesn't name a landmark. 4694 // The destinaion is not an asset ID and also doesn't name a landmark.
4695 // Use it as a sim name 4695 // Use it as a sim name
4696 if (assetID == UUID.Zero) 4696 if (assetID == UUID.Zero)
4697 { 4697 {
4698 World.RequestTeleportLocation(sp.ControllingClient, destination, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); 4698 World.RequestTeleportLocation(sp.ControllingClient, destination, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4699 return; 4699 return;
4700 } 4700 }
4701 4701
4702 AssetBase lma = World.AssetService.Get(assetID.ToString()); 4702 AssetBase lma = World.AssetService.Get(assetID.ToString());
4703 if (lma == null) 4703 if (lma == null)
4704 return; 4704 return;
4705 4705
4706 if (lma.Type != (sbyte)AssetType.Landmark) 4706 if (lma.Type != (sbyte)AssetType.Landmark)
4707 return; 4707 return;
4708 4708
4709 AssetLandmark lm = new AssetLandmark(lma); 4709 AssetLandmark lm = new AssetLandmark(lma);
4710 4710
4711 World.RequestTeleportLocation(sp.ControllingClient, lm.RegionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); 4711 World.RequestTeleportLocation(sp.ControllingClient, lm.RegionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation);
4712 } 4712 }
4713 4713
4714 public void llTextBox(string agent, string message, int chatChannel) 4714 public void llTextBox(string agent, string message, int chatChannel)
4715 { 4715 {
4716 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 4716 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
4717 4717
4718 if (dm == null) 4718 if (dm == null)
4719 return; 4719 return;
4720 4720
4721 m_host.AddScriptLPS(1); 4721 m_host.AddScriptLPS(1);
4722 UUID av = new UUID(); 4722 UUID av = new UUID();
4723 if (!UUID.TryParse(agent,out av)) 4723 if (!UUID.TryParse(agent,out av))
4724 { 4724 {
4725 Error("llTextBox", "First parameter must be a key"); 4725 Error("llTextBox", "First parameter must be a key");
4726 return; 4726 return;
4727 } 4727 }
4728 4728
4729 if (message == string.Empty) 4729 if (message == string.Empty)
4730 { 4730 {
4731 Error("llTextBox", "Empty message"); 4731 Error("llTextBox", "Empty message");
4732 } 4732 }
4733 else if (message.Length > 512) 4733 else if (message.Length > 512)
4734 { 4734 {
4735 Error("llTextBox", "Message more than 512 characters"); 4735 Error("llTextBox", "Message more than 512 characters");
4736 } 4736 }
4737 else 4737 else
4738 { 4738 {
4739 dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID); 4739 dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID);
4740 ScriptSleep(m_sleepMsOnTextBox); 4740 ScriptSleep(m_sleepMsOnTextBox);
4741 } 4741 }
4742 } 4742 }
4743 4743
4744 public void llModifyLand(int action, int brush) 4744 public void llModifyLand(int action, int brush)
4745 { 4745 {
4746 m_host.AddScriptLPS(1); 4746 m_host.AddScriptLPS(1);
4747 ITerrainModule tm = m_ScriptEngine.World.RequestModuleInterface<ITerrainModule>(); 4747 ITerrainModule tm = m_ScriptEngine.World.RequestModuleInterface<ITerrainModule>();
4748 if (tm != null) 4748 if (tm != null)
4749 { 4749 {
4750 tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID); 4750 tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID);
4751 } 4751 }
4752 } 4752 }
4753 4753
4754 public void llCollisionSound(string impact_sound, double impact_volume) 4754 public void llCollisionSound(string impact_sound, double impact_volume)
4755 { 4755 {
4756 m_host.AddScriptLPS(1); 4756 m_host.AddScriptLPS(1);
4757 4757
4758 // TODO: Parameter check logic required. 4758 // TODO: Parameter check logic required.
4759 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); 4759 m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound);
4760 m_host.CollisionSoundVolume = (float)impact_volume; 4760 m_host.CollisionSoundVolume = (float)impact_volume;
4761 } 4761 }
4762 4762
4763 public LSL_String llGetAnimation(string id) 4763 public LSL_String llGetAnimation(string id)
4764 { 4764 {
4765 // This should only return a value if the avatar is in the same region 4765 // This should only return a value if the avatar is in the same region
4766 m_host.AddScriptLPS(1); 4766 m_host.AddScriptLPS(1);
4767 UUID avatar = (UUID)id; 4767 UUID avatar = (UUID)id;
4768 ScenePresence presence = World.GetScenePresence(avatar); 4768 ScenePresence presence = World.GetScenePresence(avatar);
4769 if (presence == null) 4769 if (presence == null)
4770 return ""; 4770 return "";
4771 4771
4772 if (m_host.RegionHandle == presence.RegionHandle) 4772 if (m_host.RegionHandle == presence.RegionHandle)
4773 { 4773 {
4774 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames; 4774 Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames;
4775 4775
4776 if (presence != null) 4776 if (presence != null)
4777 { 4777 {
4778 AnimationSet currentAnims = presence.Animator.Animations; 4778 AnimationSet currentAnims = presence.Animator.Animations;
4779 string currentAnimationState = String.Empty; 4779 string currentAnimationState = String.Empty;
4780 if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) 4780 if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState))
4781 return currentAnimationState; 4781 return currentAnimationState;
4782 } 4782 }
4783 } 4783 }
4784 4784
4785 return String.Empty; 4785 return String.Empty;
4786 } 4786 }
4787 4787
4788 public void llMessageLinked(int linknumber, int num, string msg, string id) 4788 public void llMessageLinked(int linknumber, int num, string msg, string id)
4789 { 4789 {
4790 m_host.AddScriptLPS(1); 4790 m_host.AddScriptLPS(1);
4791 4791
4792 List<SceneObjectPart> parts = GetLinkParts(linknumber); 4792 List<SceneObjectPart> parts = GetLinkParts(linknumber);
4793 4793
4794 UUID partItemID; 4794 UUID partItemID;
4795 foreach (SceneObjectPart part in parts) 4795 foreach (SceneObjectPart part in parts)
4796 { 4796 {
4797 foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems()) 4797 foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems())
4798 { 4798 {
4799 if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT) 4799 if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT)
4800 { 4800 {
4801 partItemID = item.ItemID; 4801 partItemID = item.ItemID;
4802 int linkNumber = m_host.LinkNum; 4802 int linkNumber = m_host.LinkNum;
4803 if (m_host.ParentGroup.PrimCount == 1) 4803 if (m_host.ParentGroup.PrimCount == 1)
4804 linkNumber = 0; 4804 linkNumber = 0;
4805 4805
4806 object[] resobj = new object[] 4806 object[] resobj = new object[]
4807 { 4807 {
4808 new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) 4808 new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id)
4809 }; 4809 };
4810 4810
4811 m_ScriptEngine.PostScriptEvent(partItemID, 4811 m_ScriptEngine.PostScriptEvent(partItemID,
4812 new EventParams("link_message", 4812 new EventParams("link_message",
4813 resobj, new DetectParams[0])); 4813 resobj, new DetectParams[0]));
4814 } 4814 }
4815 } 4815 }
4816 } 4816 }
4817 } 4817 }
4818 4818
4819 public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local) 4819 public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local)
4820 { 4820 {
4821 m_host.AddScriptLPS(1); 4821 m_host.AddScriptLPS(1);
4822 bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing; 4822 bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing;
4823 bool pushAllowed = false; 4823 bool pushAllowed = false;
4824 4824
4825 bool pusheeIsAvatar = false; 4825 bool pusheeIsAvatar = false;
4826 UUID targetID = UUID.Zero; 4826 UUID targetID = UUID.Zero;
4827 4827
4828 if (!UUID.TryParse(target,out targetID)) 4828 if (!UUID.TryParse(target,out targetID))
4829 return; 4829 return;
4830 4830
4831 ScenePresence pusheeav = null; 4831 ScenePresence pusheeav = null;
4832 Vector3 PusheePos = Vector3.Zero; 4832 Vector3 PusheePos = Vector3.Zero;
4833 SceneObjectPart pusheeob = null; 4833 SceneObjectPart pusheeob = null;
4834 4834
4835 ScenePresence avatar = World.GetScenePresence(targetID); 4835 ScenePresence avatar = World.GetScenePresence(targetID);
4836 if (avatar != null) 4836 if (avatar != null)
4837 { 4837 {
4838 pusheeIsAvatar = true; 4838 pusheeIsAvatar = true;
4839 4839
4840 // Pushee doesn't have a physics actor 4840 // Pushee doesn't have a physics actor
4841 if (avatar.PhysicsActor == null) 4841 if (avatar.PhysicsActor == null)
4842 return; 4842 return;
4843 4843
4844 // Pushee is in GodMode this pushing object isn't owned by them 4844 // Pushee is in GodMode this pushing object isn't owned by them
4845 if (avatar.GodLevel > 0 && m_host.OwnerID != targetID) 4845 if (avatar.GodLevel > 0 && m_host.OwnerID != targetID)
4846 return; 4846 return;
4847 4847
4848 pusheeav = avatar; 4848 pusheeav = avatar;
4849 4849
4850 // Find pushee position 4850 // Find pushee position
4851 // Pushee Linked? 4851 // Pushee Linked?
4852 SceneObjectPart sitPart = pusheeav.ParentPart; 4852 SceneObjectPart sitPart = pusheeav.ParentPart;
4853 if (sitPart != null) 4853 if (sitPart != null)
4854 PusheePos = sitPart.AbsolutePosition; 4854 PusheePos = sitPart.AbsolutePosition;
4855 else 4855 else
4856 PusheePos = pusheeav.AbsolutePosition; 4856 PusheePos = pusheeav.AbsolutePosition;
4857 } 4857 }
4858 4858
4859 if (!pusheeIsAvatar) 4859 if (!pusheeIsAvatar)
4860 { 4860 {
4861 // not an avatar so push is not affected by parcel flags 4861 // not an avatar so push is not affected by parcel flags
4862 pusheeob = World.GetSceneObjectPart((UUID)target); 4862 pusheeob = World.GetSceneObjectPart((UUID)target);
4863 4863
4864 // We can't find object 4864 // We can't find object
4865 if (pusheeob == null) 4865 if (pusheeob == null)
4866 return; 4866 return;
4867 4867
4868 // Object not pushable. Not an attachment and has no physics component 4868 // Object not pushable. Not an attachment and has no physics component
4869 if (!pusheeob.ParentGroup.IsAttachment && pusheeob.PhysActor == null) 4869 if (!pusheeob.ParentGroup.IsAttachment && pusheeob.PhysActor == null)
4870 return; 4870 return;
4871 4871
4872 PusheePos = pusheeob.AbsolutePosition; 4872 PusheePos = pusheeob.AbsolutePosition;
4873 pushAllowed = true; 4873 pushAllowed = true;
4874 } 4874 }
4875 else 4875 else
4876 { 4876 {
4877 if (pushrestricted) 4877 if (pushrestricted)
4878 { 4878 {
4879 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); 4879 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
4880 4880
4881 // We didn't find the parcel but region is push restricted so assume it is NOT ok 4881 // We didn't find the parcel but region is push restricted so assume it is NOT ok
4882 if (targetlandObj == null) 4882 if (targetlandObj == null)
4883 return; 4883 return;
4884 4884
4885 // Need provisions for Group Owned here 4885 // Need provisions for Group Owned here
4886 if (m_host.OwnerID == targetlandObj.LandData.OwnerID || 4886 if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
4887 targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID) 4887 targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID)
4888 { 4888 {
4889 pushAllowed = true; 4889 pushAllowed = true;
4890 } 4890 }
4891 } 4891 }
4892 else 4892 else
4893 { 4893 {
4894 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); 4894 ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos);
4895 if (targetlandObj == null) 4895 if (targetlandObj == null)
4896 { 4896 {
4897 // We didn't find the parcel but region isn't push restricted so assume it's ok 4897 // We didn't find the parcel but region isn't push restricted so assume it's ok
4898 pushAllowed = true; 4898 pushAllowed = true;
4899 } 4899 }
4900 else 4900 else
4901 { 4901 {
4902 // Parcel push restriction 4902 // Parcel push restriction
4903 if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject) 4903 if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject)
4904 { 4904 {
4905 // Need provisions for Group Owned here 4905 // Need provisions for Group Owned here
4906 if (m_host.OwnerID == targetlandObj.LandData.OwnerID || 4906 if (m_host.OwnerID == targetlandObj.LandData.OwnerID ||
4907 targetlandObj.LandData.IsGroupOwned || 4907 targetlandObj.LandData.IsGroupOwned ||
4908 m_host.OwnerID == targetID) 4908 m_host.OwnerID == targetID)
4909 { 4909 {
4910 pushAllowed = true; 4910 pushAllowed = true;
4911 } 4911 }
4912 4912
4913 //ParcelFlags.RestrictPushObject 4913 //ParcelFlags.RestrictPushObject
4914 //pushAllowed = true; 4914 //pushAllowed = true;
4915 } 4915 }
4916 else 4916 else
4917 { 4917 {
4918 // Parcel isn't push restricted 4918 // Parcel isn't push restricted
4919 pushAllowed = true; 4919 pushAllowed = true;
4920 } 4920 }
4921 } 4921 }
4922 } 4922 }
4923 } 4923 }
4924 4924
4925 if (pushAllowed) 4925 if (pushAllowed)
4926 { 4926 {
4927 float distance = (PusheePos - m_host.AbsolutePosition).Length(); 4927 float distance = (PusheePos - m_host.AbsolutePosition).Length();
4928 float distance_term = distance * distance * distance; // Script Energy 4928 float distance_term = distance * distance * distance; // Script Energy
4929 float pusher_mass = m_host.GetMass(); 4929 float pusher_mass = m_host.GetMass();
4930 4930
4931 float PUSH_ATTENUATION_DISTANCE = 17f; 4931 float PUSH_ATTENUATION_DISTANCE = 17f;
4932 float PUSH_ATTENUATION_SCALE = 5f; 4932 float PUSH_ATTENUATION_SCALE = 5f;
4933 float distance_attenuation = 1f; 4933 float distance_attenuation = 1f;
4934 if (distance > PUSH_ATTENUATION_DISTANCE) 4934 if (distance > PUSH_ATTENUATION_DISTANCE)
4935 { 4935 {
4936 float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE; 4936 float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE;
4937 distance_attenuation = 1f / normalized_units; 4937 distance_attenuation = 1f / normalized_units;
4938 } 4938 }
4939 4939
4940 Vector3 applied_linear_impulse = impulse; 4940 Vector3 applied_linear_impulse = impulse;
4941 { 4941 {
4942 float impulse_length = applied_linear_impulse.Length(); 4942 float impulse_length = applied_linear_impulse.Length();
4943 4943
4944 float desired_energy = impulse_length * pusher_mass; 4944 float desired_energy = impulse_length * pusher_mass;
4945 if (desired_energy > 0f) 4945 if (desired_energy > 0f)
4946 desired_energy += distance_term; 4946 desired_energy += distance_term;
4947 4947
4948 float scaling_factor = 1f; 4948 float scaling_factor = 1f;
4949 scaling_factor *= distance_attenuation; 4949 scaling_factor *= distance_attenuation;
4950 applied_linear_impulse *= scaling_factor; 4950 applied_linear_impulse *= scaling_factor;
4951 4951
4952 } 4952 }
4953 4953
4954 if (pusheeIsAvatar) 4954 if (pusheeIsAvatar)
4955 { 4955 {
4956 if (pusheeav != null) 4956 if (pusheeav != null)
4957 { 4957 {
4958 PhysicsActor pa = pusheeav.PhysicsActor; 4958 PhysicsActor pa = pusheeav.PhysicsActor;
4959 4959
4960 if (pa != null) 4960 if (pa != null)
4961 { 4961 {
4962 if (local != 0) 4962 if (local != 0)
4963 { 4963 {
4964 applied_linear_impulse *= m_host.GetWorldRotation(); 4964 applied_linear_impulse *= m_host.GetWorldRotation();
4965 } 4965 }
4966 4966
4967 pa.AddForce(applied_linear_impulse, true); 4967 pa.AddForce(applied_linear_impulse, true);
4968 } 4968 }
4969 } 4969 }
4970 } 4970 }
4971 else 4971 else
4972 { 4972 {
4973 if (pusheeob != null) 4973 if (pusheeob != null)
4974 { 4974 {
4975 if (pusheeob.PhysActor != null) 4975 if (pusheeob.PhysActor != null)
4976 { 4976 {
4977 pusheeob.ApplyImpulse(applied_linear_impulse, local != 0); 4977 pusheeob.ApplyImpulse(applied_linear_impulse, local != 0);
4978 } 4978 }
4979 } 4979 }
4980 } 4980 }
4981 } 4981 }
4982 } 4982 }
4983 4983
4984 public void llPassCollisions(int pass) 4984 public void llPassCollisions(int pass)
4985 { 4985 {
4986 m_host.AddScriptLPS(1); 4986 m_host.AddScriptLPS(1);
4987 if (pass == 0) 4987 if (pass == 0)
4988 { 4988 {
4989 m_host.PassCollisions = false; 4989 m_host.PassCollisions = false;
4990 } 4990 }
4991 else 4991 else
4992 { 4992 {
4993 m_host.PassCollisions = true; 4993 m_host.PassCollisions = true;
4994 } 4994 }
4995 } 4995 }
4996 4996
4997 public LSL_String llGetScriptName() 4997 public LSL_String llGetScriptName()
4998 { 4998 {
4999 m_host.AddScriptLPS(1); 4999 m_host.AddScriptLPS(1);
5000 5000
5001 return m_item.Name != null ? m_item.Name : String.Empty; 5001 return m_item.Name != null ? m_item.Name : String.Empty;
5002 } 5002 }
5003 5003
5004 public LSL_Integer llGetLinkNumberOfSides(int link) 5004 public LSL_Integer llGetLinkNumberOfSides(int link)
5005 { 5005 {
5006 m_host.AddScriptLPS(1); 5006 m_host.AddScriptLPS(1);
5007 5007
5008 SceneObjectPart linkedPart; 5008 SceneObjectPart linkedPart;
5009 5009
5010 if (link == ScriptBaseClass.LINK_ROOT) 5010 if (link == ScriptBaseClass.LINK_ROOT)
5011 linkedPart = m_host.ParentGroup.RootPart; 5011 linkedPart = m_host.ParentGroup.RootPart;
5012 else if (link == ScriptBaseClass.LINK_THIS) 5012 else if (link == ScriptBaseClass.LINK_THIS)
5013 linkedPart = m_host; 5013 linkedPart = m_host;
5014 else 5014 else
5015 linkedPart = m_host.ParentGroup.GetLinkNumPart(link); 5015 linkedPart = m_host.ParentGroup.GetLinkNumPart(link);
5016 5016
5017 return GetNumberOfSides(linkedPart); 5017 return GetNumberOfSides(linkedPart);
5018 } 5018 }
5019 5019
5020 public LSL_Integer llGetNumberOfSides() 5020 public LSL_Integer llGetNumberOfSides()
5021 { 5021 {
5022 m_host.AddScriptLPS(1); 5022 m_host.AddScriptLPS(1);
5023 5023
5024 return GetNumberOfSides(m_host); 5024 return GetNumberOfSides(m_host);
5025 } 5025 }
5026 5026
5027 protected int GetNumberOfSides(SceneObjectPart part) 5027 protected int GetNumberOfSides(SceneObjectPart part)
5028 { 5028 {
5029 int sides = part.GetNumberOfSides(); 5029 int sides = part.GetNumberOfSides();
5030 5030
5031 if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0) 5031 if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0)
5032 { 5032 {
5033 // Make up for a bug where LSL shows 4 sides rather than 2 5033 // Make up for a bug where LSL shows 4 sides rather than 2
5034 sides += 2; 5034 sides += 2;
5035 } 5035 }
5036 5036
5037 return sides; 5037 return sides;
5038 } 5038 }
5039 5039
5040 5040
5041 /* The new / changed functions were tested with the following LSL script: 5041 /* The new / changed functions were tested with the following LSL script:
5042 5042
5043 default 5043 default
5044 { 5044 {
5045 state_entry() 5045 state_entry()
5046 { 5046 {
5047 rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD); 5047 rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD);
5048 5048
5049 llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot)); 5049 llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot));
5050 llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG)); 5050 llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG));
5051 5051
5052 // convert back and forth between quaternion <-> vector and angle 5052 // convert back and forth between quaternion <-> vector and angle
5053 5053
5054 rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot)); 5054 rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot));
5055 5055
5056 llOwnerSay("Old rotation was: "+(string) rot); 5056 llOwnerSay("Old rotation was: "+(string) rot);
5057 llOwnerSay("re-converted rotation is: "+(string) newrot); 5057 llOwnerSay("re-converted rotation is: "+(string) newrot);
5058 5058
5059 llSetRot(rot); // to check the parameters in the prim 5059 llSetRot(rot); // to check the parameters in the prim
5060 } 5060 }
5061 } 5061 }
5062 */ 5062 */
5063 5063
5064 // Xantor 29/apr/2008 5064 // Xantor 29/apr/2008
5065 // Returns rotation described by rotating angle radians about axis. 5065 // Returns rotation described by rotating angle radians about axis.
5066 // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2)) 5066 // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2))
5067 public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle) 5067 public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle)
5068 { 5068 {
5069 m_host.AddScriptLPS(1); 5069 m_host.AddScriptLPS(1);
5070 5070
5071 double x, y, z, s, t; 5071 double x, y, z, s, t;
5072 5072
5073 s = Math.Cos(angle * 0.5); 5073 s = Math.Cos(angle * 0.5);
5074 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs 5074 t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs
5075 axis = LSL_Vector.Norm(axis); 5075 axis = LSL_Vector.Norm(axis);
5076 x = axis.x * t; 5076 x = axis.x * t;
5077 y = axis.y * t; 5077 y = axis.y * t;
5078 z = axis.z * t; 5078 z = axis.z * t;
5079 5079
5080 return new LSL_Rotation(x,y,z,s); 5080 return new LSL_Rotation(x,y,z,s);
5081 } 5081 }
5082 5082
5083 /// <summary> 5083 /// <summary>
5084 /// Returns the axis of rotation for a quaternion 5084 /// Returns the axis of rotation for a quaternion
5085 /// </summary> 5085 /// </summary>
5086 /// <returns></returns> 5086 /// <returns></returns>
5087 /// <param name='rot'></param> 5087 /// <param name='rot'></param>
5088 public LSL_Vector llRot2Axis(LSL_Rotation rot) 5088 public LSL_Vector llRot2Axis(LSL_Rotation rot)
5089 { 5089 {
5090 m_host.AddScriptLPS(1); 5090 m_host.AddScriptLPS(1);
5091 5091
5092 if (Math.Abs(rot.s) > 1) // normalization needed 5092 if (Math.Abs(rot.s) > 1) // normalization needed
5093 rot.Normalize(); 5093 rot.Normalize();
5094 5094
5095 double s = Math.Sqrt(1 - rot.s * rot.s); 5095 double s = Math.Sqrt(1 - rot.s * rot.s);
5096 if (s < 0.001) 5096 if (s < 0.001)
5097 { 5097 {
5098 return new LSL_Vector(1, 0, 0); 5098 return new LSL_Vector(1, 0, 0);
5099 } 5099 }
5100 else 5100 else
5101 { 5101 {
5102 double invS = 1.0 / s; 5102 double invS = 1.0 / s;
5103 if (rot.s < 0) invS = -invS; 5103 if (rot.s < 0) invS = -invS;
5104 return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS); 5104 return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS);
5105 } 5105 }
5106 } 5106 }
5107 5107
5108 5108
5109 // Returns the angle of a quaternion (see llRot2Axis for the axis) 5109 // Returns the angle of a quaternion (see llRot2Axis for the axis)
5110 public LSL_Float llRot2Angle(LSL_Rotation rot) 5110 public LSL_Float llRot2Angle(LSL_Rotation rot)
5111 { 5111 {
5112 m_host.AddScriptLPS(1); 5112 m_host.AddScriptLPS(1);
5113 5113
5114 if (Math.Abs(rot.s) > 1) // normalization needed 5114 if (Math.Abs(rot.s) > 1) // normalization needed
5115 rot.Normalize(); 5115 rot.Normalize();
5116 5116
5117 double angle = 2 * Math.Acos(rot.s); 5117 double angle = 2 * Math.Acos(rot.s);
5118 if (angle > Math.PI) 5118 if (angle > Math.PI)
5119 angle = 2 * Math.PI - angle; 5119 angle = 2 * Math.PI - angle;
5120 5120
5121 return angle; 5121 return angle;
5122 } 5122 }
5123 5123
5124 public LSL_Float llAcos(double val) 5124 public LSL_Float llAcos(double val)
5125 { 5125 {
5126 m_host.AddScriptLPS(1); 5126 m_host.AddScriptLPS(1);
5127 return (double)Math.Acos(val); 5127 return (double)Math.Acos(val);
5128 } 5128 }
5129 5129
5130 public LSL_Float llAsin(double val) 5130 public LSL_Float llAsin(double val)
5131 { 5131 {
5132 m_host.AddScriptLPS(1); 5132 m_host.AddScriptLPS(1);
5133 return (double)Math.Asin(val); 5133 return (double)Math.Asin(val);
5134 } 5134 }
5135 5135
5136 // jcochran 5/jan/2012 5136 // jcochran 5/jan/2012
5137 public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) 5137 public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b)
5138 { 5138 {
5139 m_host.AddScriptLPS(1); 5139 m_host.AddScriptLPS(1);
5140 5140
5141 double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s); 5141 double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s);
5142 double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s); 5142 double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s);
5143 double aa_bb = aa * bb; 5143 double aa_bb = aa * bb;
5144 if (aa_bb == 0) return 0.0; 5144 if (aa_bb == 0) return 0.0;
5145 double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s); 5145 double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s);
5146 double quotient = (ab * ab) / aa_bb; 5146 double quotient = (ab * ab) / aa_bb;
5147 if (quotient >= 1.0) return 0.0; 5147 if (quotient >= 1.0) return 0.0;
5148 return Math.Acos(2 * quotient - 1); 5148 return Math.Acos(2 * quotient - 1);
5149 } 5149 }
5150 5150
5151 public LSL_String llGetInventoryKey(string name) 5151 public LSL_String llGetInventoryKey(string name)
5152 { 5152 {
5153 m_host.AddScriptLPS(1); 5153 m_host.AddScriptLPS(1);
5154 5154
5155 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 5155 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
5156 5156
5157 if (item == null) 5157 if (item == null)
5158 return UUID.Zero.ToString(); 5158 return UUID.Zero.ToString();
5159 5159
5160 if ((item.CurrentPermissions 5160 if ((item.CurrentPermissions
5161 & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5161 & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
5162 == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) 5162 == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify))
5163 { 5163 {
5164 return item.AssetID.ToString(); 5164 return item.AssetID.ToString();
5165 } 5165 }
5166 5166
5167 return UUID.Zero.ToString(); 5167 return UUID.Zero.ToString();
5168 } 5168 }
5169 5169
5170 public void llAllowInventoryDrop(int add) 5170 public void llAllowInventoryDrop(int add)
5171 { 5171 {
5172 m_host.AddScriptLPS(1); 5172 m_host.AddScriptLPS(1);
5173 5173
5174 if (add != 0) 5174 if (add != 0)
5175 m_host.ParentGroup.RootPart.AllowedDrop = true; 5175 m_host.ParentGroup.RootPart.AllowedDrop = true;
5176 else 5176 else
5177 m_host.ParentGroup.RootPart.AllowedDrop = false; 5177 m_host.ParentGroup.RootPart.AllowedDrop = false;
5178 5178
5179 // Update the object flags 5179 // Update the object flags
5180 m_host.ParentGroup.RootPart.aggregateScriptEvents(); 5180 m_host.ParentGroup.RootPart.aggregateScriptEvents();
5181 } 5181 }
5182 5182
5183 public LSL_Vector llGetSunDirection() 5183 public LSL_Vector llGetSunDirection()
5184 { 5184 {
5185 m_host.AddScriptLPS(1); 5185 m_host.AddScriptLPS(1);
5186 5186
5187 LSL_Vector SunDoubleVector3; 5187 LSL_Vector SunDoubleVector3;
5188 Vector3 SunFloatVector3; 5188 Vector3 SunFloatVector3;
5189 5189
5190 // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule 5190 // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule
5191 // have to convert from Vector3 (float) to LSL_Vector (double) 5191 // have to convert from Vector3 (float) to LSL_Vector (double)
5192 SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector; 5192 SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector;
5193 SunDoubleVector3.x = (double)SunFloatVector3.X; 5193 SunDoubleVector3.x = (double)SunFloatVector3.X;
5194 SunDoubleVector3.y = (double)SunFloatVector3.Y; 5194 SunDoubleVector3.y = (double)SunFloatVector3.Y;
5195 SunDoubleVector3.z = (double)SunFloatVector3.Z; 5195 SunDoubleVector3.z = (double)SunFloatVector3.Z;
5196 5196
5197 return SunDoubleVector3; 5197 return SunDoubleVector3;
5198 } 5198 }
5199 5199
5200 public LSL_Vector llGetTextureOffset(int face) 5200 public LSL_Vector llGetTextureOffset(int face)
5201 { 5201 {
5202 m_host.AddScriptLPS(1); 5202 m_host.AddScriptLPS(1);
5203 return GetTextureOffset(m_host, face); 5203 return GetTextureOffset(m_host, face);
5204 } 5204 }
5205 5205
5206 protected LSL_Vector GetTextureOffset(SceneObjectPart part, int face) 5206 protected LSL_Vector GetTextureOffset(SceneObjectPart part, int face)
5207 { 5207 {
5208 Primitive.TextureEntry tex = part.Shape.Textures; 5208 Primitive.TextureEntry tex = part.Shape.Textures;
5209 LSL_Vector offset = new LSL_Vector(); 5209 LSL_Vector offset = new LSL_Vector();
5210 if (face == ScriptBaseClass.ALL_SIDES) 5210 if (face == ScriptBaseClass.ALL_SIDES)
5211 { 5211 {
5212 face = 0; 5212 face = 0;
5213 } 5213 }
5214 if (face >= 0 && face < GetNumberOfSides(part)) 5214 if (face >= 0 && face < GetNumberOfSides(part))
5215 { 5215 {
5216 offset.x = tex.GetFace((uint)face).OffsetU; 5216 offset.x = tex.GetFace((uint)face).OffsetU;
5217 offset.y = tex.GetFace((uint)face).OffsetV; 5217 offset.y = tex.GetFace((uint)face).OffsetV;
5218 offset.z = 0.0; 5218 offset.z = 0.0;
5219 return offset; 5219 return offset;
5220 } 5220 }
5221 else 5221 else
5222 { 5222 {
5223 return offset; 5223 return offset;
5224 } 5224 }
5225 } 5225 }
5226 5226
5227 public LSL_Vector llGetTextureScale(int side) 5227 public LSL_Vector llGetTextureScale(int side)
5228 { 5228 {
5229 m_host.AddScriptLPS(1); 5229 m_host.AddScriptLPS(1);
5230 Primitive.TextureEntry tex = m_host.Shape.Textures; 5230 Primitive.TextureEntry tex = m_host.Shape.Textures;
5231 LSL_Vector scale; 5231 LSL_Vector scale;
5232 if (side == -1) 5232 if (side == -1)
5233 { 5233 {
5234 side = 0; 5234 side = 0;
5235 } 5235 }
5236 scale.x = tex.GetFace((uint)side).RepeatU; 5236 scale.x = tex.GetFace((uint)side).RepeatU;
5237 scale.y = tex.GetFace((uint)side).RepeatV; 5237 scale.y = tex.GetFace((uint)side).RepeatV;
5238 scale.z = 0.0; 5238 scale.z = 0.0;
5239 return scale; 5239 return scale;
5240 } 5240 }
5241 5241
5242 public LSL_Float llGetTextureRot(int face) 5242 public LSL_Float llGetTextureRot(int face)
5243 { 5243 {
5244 m_host.AddScriptLPS(1); 5244 m_host.AddScriptLPS(1);
5245 return GetTextureRot(m_host, face); 5245 return GetTextureRot(m_host, face);
5246 } 5246 }
5247 5247
5248 protected LSL_Float GetTextureRot(SceneObjectPart part, int face) 5248 protected LSL_Float GetTextureRot(SceneObjectPart part, int face)
5249 { 5249 {
5250 Primitive.TextureEntry tex = part.Shape.Textures; 5250 Primitive.TextureEntry tex = part.Shape.Textures;
5251 if (face == -1) 5251 if (face == -1)
5252 { 5252 {
5253 face = 0; 5253 face = 0;
5254 } 5254 }
5255 if (face >= 0 && face < GetNumberOfSides(part)) 5255 if (face >= 0 && face < GetNumberOfSides(part))
5256 { 5256 {
5257 return tex.GetFace((uint)face).Rotation; 5257 return tex.GetFace((uint)face).Rotation;
5258 } 5258 }
5259 else 5259 else
5260 { 5260 {
5261 return 0.0; 5261 return 0.0;
5262 } 5262 }
5263 } 5263 }
5264 5264
5265 public LSL_Integer llSubStringIndex(string source, string pattern) 5265 public LSL_Integer llSubStringIndex(string source, string pattern)
5266 { 5266 {
5267 m_host.AddScriptLPS(1); 5267 m_host.AddScriptLPS(1);
5268 return source.IndexOf(pattern); 5268 return source.IndexOf(pattern);
5269 } 5269 }
5270 5270
5271 public LSL_String llGetOwnerKey(string id) 5271 public LSL_String llGetOwnerKey(string id)
5272 { 5272 {
5273 m_host.AddScriptLPS(1); 5273 m_host.AddScriptLPS(1);
5274 UUID key = new UUID(); 5274 UUID key = new UUID();
5275 if (UUID.TryParse(id, out key)) 5275 if (UUID.TryParse(id, out key))
5276 { 5276 {
5277 try 5277 try
5278 { 5278 {
5279 SceneObjectPart obj = World.GetSceneObjectPart(key); 5279 SceneObjectPart obj = World.GetSceneObjectPart(key);
5280 if (obj == null) 5280 if (obj == null)
5281 return id; // the key is for an agent so just return the key 5281 return id; // the key is for an agent so just return the key
5282 else 5282 else
5283 return obj.OwnerID.ToString(); 5283 return obj.OwnerID.ToString();
5284 } 5284 }
5285 catch (KeyNotFoundException) 5285 catch (KeyNotFoundException)
5286 { 5286 {
5287 return id; // The Object/Agent not in the region so just return the key 5287 return id; // The Object/Agent not in the region so just return the key
5288 } 5288 }
5289 } 5289 }
5290 else 5290 else
5291 { 5291 {
5292 return UUID.Zero.ToString(); 5292 return UUID.Zero.ToString();
5293 } 5293 }
5294 } 5294 }
5295 5295
5296 public LSL_Vector llGetCenterOfMass() 5296 public LSL_Vector llGetCenterOfMass()
5297 { 5297 {
5298 m_host.AddScriptLPS(1); 5298 m_host.AddScriptLPS(1);
5299 5299
5300 return new LSL_Vector(m_host.GetCenterOfMass()); 5300 return new LSL_Vector(m_host.GetCenterOfMass());
5301 } 5301 }
5302 5302
5303 public LSL_List llListSort(LSL_List src, int stride, int ascending) 5303 public LSL_List llListSort(LSL_List src, int stride, int ascending)
5304 { 5304 {
5305 m_host.AddScriptLPS(1); 5305 m_host.AddScriptLPS(1);
5306 5306
5307 if (stride <= 0) 5307 if (stride <= 0)
5308 { 5308 {
5309 stride = 1; 5309 stride = 1;
5310 } 5310 }
5311 return src.Sort(stride, ascending); 5311 return src.Sort(stride, ascending);
5312 } 5312 }
5313 5313
5314 public LSL_Integer llGetListLength(LSL_List src) 5314 public LSL_Integer llGetListLength(LSL_List src)
5315 { 5315 {
5316 m_host.AddScriptLPS(1); 5316 m_host.AddScriptLPS(1);
5317 5317
5318 if (src == null) 5318 if (src == null)
5319 { 5319 {
5320 return 0; 5320 return 0;
5321 } 5321 }
5322 else 5322 else
5323 { 5323 {
5324 return src.Length; 5324 return src.Length;
5325 } 5325 }
5326 } 5326 }
5327 5327
5328 public LSL_Integer llList2Integer(LSL_List src, int index) 5328 public LSL_Integer llList2Integer(LSL_List src, int index)
5329 { 5329 {
5330 m_host.AddScriptLPS(1); 5330 m_host.AddScriptLPS(1);
5331 if (index < 0) 5331 if (index < 0)
5332 { 5332 {
5333 index = src.Length + index; 5333 index = src.Length + index;
5334 } 5334 }
5335 if (index >= src.Length || index < 0) 5335 if (index >= src.Length || index < 0)
5336 { 5336 {
5337 return 0; 5337 return 0;
5338 } 5338 }
5339 5339
5340 // Vectors & Rotations always return zero in SL, but 5340 // Vectors & Rotations always return zero in SL, but
5341 // keys don't always return zero, it seems to be a bit complex. 5341 // keys don't always return zero, it seems to be a bit complex.
5342 else if (src.Data[index] is LSL_Vector || 5342 else if (src.Data[index] is LSL_Vector ||
5343 src.Data[index] is LSL_Rotation) 5343 src.Data[index] is LSL_Rotation)
5344 { 5344 {
5345 return 0; 5345 return 0;
5346 } 5346 }
5347 try 5347 try
5348 { 5348 {
5349 5349
5350 if (src.Data[index] is LSL_Integer) 5350 if (src.Data[index] is LSL_Integer)
5351 return (LSL_Integer)src.Data[index]; 5351 return (LSL_Integer)src.Data[index];
5352 else if (src.Data[index] is LSL_Float) 5352 else if (src.Data[index] is LSL_Float)
5353 return Convert.ToInt32(((LSL_Float)src.Data[index]).value); 5353 return Convert.ToInt32(((LSL_Float)src.Data[index]).value);
5354 return new LSL_Integer(src.Data[index].ToString()); 5354 return new LSL_Integer(src.Data[index].ToString());
5355 } 5355 }
5356 catch (FormatException) 5356 catch (FormatException)
5357 { 5357 {
5358 return 0; 5358 return 0;
5359 } 5359 }
5360 } 5360 }
5361 5361
5362 public LSL_Float llList2Float(LSL_List src, int index) 5362 public LSL_Float llList2Float(LSL_List src, int index)
5363 { 5363 {
5364 m_host.AddScriptLPS(1); 5364 m_host.AddScriptLPS(1);
5365 if (index < 0) 5365 if (index < 0)
5366 { 5366 {
5367 index = src.Length + index; 5367 index = src.Length + index;
5368 } 5368 }
5369 if (index >= src.Length || index < 0) 5369 if (index >= src.Length || index < 0)
5370 { 5370 {
5371 return 0.0; 5371 return 0.0;
5372 } 5372 }
5373 5373
5374 // Vectors & Rotations always return zero in SL 5374 // Vectors & Rotations always return zero in SL
5375 else if (src.Data[index] is LSL_Vector || 5375 else if (src.Data[index] is LSL_Vector ||
5376 src.Data[index] is LSL_Rotation) 5376 src.Data[index] is LSL_Rotation)
5377 { 5377 {
5378 return 0; 5378 return 0;
5379 } 5379 }
5380 // valid keys seem to get parsed as integers then converted to floats 5380 // valid keys seem to get parsed as integers then converted to floats
5381 else 5381 else
5382 { 5382 {
5383 UUID uuidt; 5383 UUID uuidt;
5384 if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt)) 5384 if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt))
5385 { 5385 {
5386 return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value); 5386 return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value);
5387 } 5387 }
5388 } 5388 }
5389 try 5389 try
5390 { 5390 {
5391 if (src.Data[index] is LSL_Integer) 5391 if (src.Data[index] is LSL_Integer)
5392 return Convert.ToDouble(((LSL_Integer)src.Data[index]).value); 5392 return Convert.ToDouble(((LSL_Integer)src.Data[index]).value);
5393 else if (src.Data[index] is LSL_Float) 5393 else if (src.Data[index] is LSL_Float)
5394 return Convert.ToDouble(((LSL_Float)src.Data[index]).value); 5394 return Convert.ToDouble(((LSL_Float)src.Data[index]).value);
5395 else if (src.Data[index] is LSL_String) 5395 else if (src.Data[index] is LSL_String)
5396 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); 5396 return Convert.ToDouble(((LSL_String)src.Data[index]).m_string);
5397 return Convert.ToDouble(src.Data[index]); 5397 return Convert.ToDouble(src.Data[index]);
5398 } 5398 }
5399 catch (FormatException) 5399 catch (FormatException)
5400 { 5400 {
5401 return 0.0; 5401 return 0.0;
5402 } 5402 }
5403 } 5403 }
5404 5404
5405 public LSL_String llList2String(LSL_List src, int index) 5405 public LSL_String llList2String(LSL_List src, int index)
5406 { 5406 {
5407 m_host.AddScriptLPS(1); 5407 m_host.AddScriptLPS(1);
5408 if (index < 0) 5408 if (index < 0)
5409 { 5409 {
5410 index = src.Length + index; 5410 index = src.Length + index;
5411 } 5411 }
5412 if (index >= src.Length || index < 0) 5412 if (index >= src.Length || index < 0)
5413 { 5413 {
5414 return String.Empty; 5414 return String.Empty;
5415 } 5415 }
5416 return src.Data[index].ToString(); 5416 return src.Data[index].ToString();
5417 } 5417 }
5418 5418
5419 public LSL_Key llList2Key(LSL_List src, int index) 5419 public LSL_Key llList2Key(LSL_List src, int index)
5420 { 5420 {
5421 m_host.AddScriptLPS(1); 5421 m_host.AddScriptLPS(1);
5422 if (index < 0) 5422 if (index < 0)
5423 { 5423 {
5424 index = src.Length + index; 5424 index = src.Length + index;
5425 } 5425 }
5426 5426
5427 if (index >= src.Length || index < 0) 5427 if (index >= src.Length || index < 0)
5428 { 5428 {
5429 return ""; 5429 return "";
5430 } 5430 }
5431 5431
5432 // SL spits out an empty string for types other than key & string 5432 // SL spits out an empty string for types other than key & string
5433 // At the time of patching, LSL_Key is currently LSL_String, 5433 // At the time of patching, LSL_Key is currently LSL_String,
5434 // so the OR check may be a little redundant, but it's being done 5434 // so the OR check may be a little redundant, but it's being done
5435 // for completion and should LSL_Key ever be implemented 5435 // for completion and should LSL_Key ever be implemented
5436 // as it's own struct 5436 // as it's own struct
5437 // NOTE: 3rd case is needed because a NULL_KEY comes through as 5437 // NOTE: 3rd case is needed because a NULL_KEY comes through as
5438 // type 'obj' and wrongly returns "" 5438 // type 'obj' and wrongly returns ""
5439 else if (!(src.Data[index] is LSL_String || 5439 else if (!(src.Data[index] is LSL_String ||
5440 src.Data[index] is LSL_Key || 5440 src.Data[index] is LSL_Key ||
5441 src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000")) 5441 src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000"))
5442 { 5442 {
5443 return ""; 5443 return "";
5444 } 5444 }
5445 5445
5446 return src.Data[index].ToString(); 5446 return src.Data[index].ToString();
5447 } 5447 }
5448 5448
5449 public LSL_Vector llList2Vector(LSL_List src, int index) 5449 public LSL_Vector llList2Vector(LSL_List src, int index)
5450 { 5450 {
5451 m_host.AddScriptLPS(1); 5451 m_host.AddScriptLPS(1);
5452 if (index < 0) 5452 if (index < 0)
5453 { 5453 {
5454 index = src.Length + index; 5454 index = src.Length + index;
5455 } 5455 }
5456 if (index >= src.Length || index < 0) 5456 if (index >= src.Length || index < 0)
5457 { 5457 {
5458 return new LSL_Vector(0, 0, 0); 5458 return new LSL_Vector(0, 0, 0);
5459 } 5459 }
5460 if (src.Data[index].GetType() == typeof(LSL_Vector)) 5460 if (src.Data[index].GetType() == typeof(LSL_Vector))
5461 { 5461 {
5462 return (LSL_Vector)src.Data[index]; 5462 return (LSL_Vector)src.Data[index];
5463 } 5463 }
5464 5464
5465 // SL spits always out ZERO_VECTOR for anything other than 5465 // SL spits always out ZERO_VECTOR for anything other than
5466 // strings or vectors. Although keys always return ZERO_VECTOR, 5466 // strings or vectors. Although keys always return ZERO_VECTOR,
5467 // it is currently difficult to make the distinction between 5467 // it is currently difficult to make the distinction between
5468 // a string, a key as string and a string that by coincidence 5468 // a string, a key as string and a string that by coincidence
5469 // is a string, so we're going to leave that up to the 5469 // is a string, so we're going to leave that up to the
5470 // LSL_Vector constructor. 5470 // LSL_Vector constructor.
5471 else if (!(src.Data[index] is LSL_String || 5471 else if (!(src.Data[index] is LSL_String ||
5472 src.Data[index] is LSL_Vector)) 5472 src.Data[index] is LSL_Vector))
5473 { 5473 {
5474 return new LSL_Vector(0, 0, 0); 5474 return new LSL_Vector(0, 0, 0);
5475 } 5475 }
5476 else 5476 else
5477 { 5477 {
5478 return new LSL_Vector(src.Data[index].ToString()); 5478 return new LSL_Vector(src.Data[index].ToString());
5479 } 5479 }
5480 } 5480 }
5481 5481
5482 public LSL_Rotation llList2Rot(LSL_List src, int index) 5482 public LSL_Rotation llList2Rot(LSL_List src, int index)
5483 { 5483 {
5484 m_host.AddScriptLPS(1); 5484 m_host.AddScriptLPS(1);
5485 if (index < 0) 5485 if (index < 0)
5486 { 5486 {
5487 index = src.Length + index; 5487 index = src.Length + index;
5488 } 5488 }
5489 if (index >= src.Length || index < 0) 5489 if (index >= src.Length || index < 0)
5490 { 5490 {
5491 return new LSL_Rotation(0, 0, 0, 1); 5491 return new LSL_Rotation(0, 0, 0, 1);
5492 } 5492 }
5493 5493
5494 // SL spits always out ZERO_ROTATION for anything other than 5494 // SL spits always out ZERO_ROTATION for anything other than
5495 // strings or vectors. Although keys always return ZERO_ROTATION, 5495 // strings or vectors. Although keys always return ZERO_ROTATION,
5496 // it is currently difficult to make the distinction between 5496 // it is currently difficult to make the distinction between
5497 // a string, a key as string and a string that by coincidence 5497 // a string, a key as string and a string that by coincidence
5498 // is a string, so we're going to leave that up to the 5498 // is a string, so we're going to leave that up to the
5499 // LSL_Rotation constructor. 5499 // LSL_Rotation constructor.
5500 else if (!(src.Data[index] is LSL_String || 5500 else if (!(src.Data[index] is LSL_String ||
5501 src.Data[index] is LSL_Rotation)) 5501 src.Data[index] is LSL_Rotation))
5502 { 5502 {
5503 return new LSL_Rotation(0, 0, 0, 1); 5503 return new LSL_Rotation(0, 0, 0, 1);
5504 } 5504 }
5505 else if (src.Data[index].GetType() == typeof(LSL_Rotation)) 5505 else if (src.Data[index].GetType() == typeof(LSL_Rotation))
5506 { 5506 {
5507 return (LSL_Rotation)src.Data[index]; 5507 return (LSL_Rotation)src.Data[index];
5508 } 5508 }
5509 else 5509 else
5510 { 5510 {
5511 return new LSL_Rotation(src.Data[index].ToString()); 5511 return new LSL_Rotation(src.Data[index].ToString());
5512 } 5512 }
5513 } 5513 }
5514 5514
5515 public LSL_List llList2List(LSL_List src, int start, int end) 5515 public LSL_List llList2List(LSL_List src, int start, int end)
5516 { 5516 {
5517 m_host.AddScriptLPS(1); 5517 m_host.AddScriptLPS(1);
5518 return src.GetSublist(start, end); 5518 return src.GetSublist(start, end);
5519 } 5519 }
5520 5520
5521 public LSL_List llDeleteSubList(LSL_List src, int start, int end) 5521 public LSL_List llDeleteSubList(LSL_List src, int start, int end)
5522 { 5522 {
5523 return src.DeleteSublist(start, end); 5523 return src.DeleteSublist(start, end);
5524 } 5524 }
5525 5525
5526 public LSL_Integer llGetListEntryType(LSL_List src, int index) 5526 public LSL_Integer llGetListEntryType(LSL_List src, int index)
5527 { 5527 {
5528 m_host.AddScriptLPS(1); 5528 m_host.AddScriptLPS(1);
5529 if (index < 0) 5529 if (index < 0)
5530 { 5530 {
5531 index = src.Length + index; 5531 index = src.Length + index;
5532 } 5532 }
5533 if (index >= src.Length) 5533 if (index >= src.Length)
5534 { 5534 {
5535 return 0; 5535 return 0;
5536 } 5536 }
5537 5537
5538 if (src.Data[index] is LSL_Integer || src.Data[index] is Int32) 5538 if (src.Data[index] is LSL_Integer || src.Data[index] is Int32)
5539 return 1; 5539 return 1;
5540 if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double) 5540 if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double)
5541 return 2; 5541 return 2;
5542 if (src.Data[index] is LSL_String || src.Data[index] is String) 5542 if (src.Data[index] is LSL_String || src.Data[index] is String)
5543 { 5543 {
5544 UUID tuuid; 5544 UUID tuuid;
5545 if (UUID.TryParse(src.Data[index].ToString(), out tuuid)) 5545 if (UUID.TryParse(src.Data[index].ToString(), out tuuid))
5546 { 5546 {
5547 return 4; 5547 return 4;
5548 } 5548 }
5549 else 5549 else
5550 { 5550 {
5551 return 3; 5551 return 3;
5552 } 5552 }
5553 } 5553 }
5554 if (src.Data[index] is LSL_Vector) 5554 if (src.Data[index] is LSL_Vector)
5555 return 5; 5555 return 5;
5556 if (src.Data[index] is LSL_Rotation) 5556 if (src.Data[index] is LSL_Rotation)
5557 return 6; 5557 return 6;
5558 if (src.Data[index] is LSL_List) 5558 if (src.Data[index] is LSL_List)
5559 return 7; 5559 return 7;
5560 return 0; 5560 return 0;
5561 5561
5562 } 5562 }
5563 5563
5564 /// <summary> 5564 /// <summary>
5565 /// Process the supplied list and return the 5565 /// Process the supplied list and return the
5566 /// content of the list formatted as a comma 5566 /// content of the list formatted as a comma
5567 /// separated list. There is a space after 5567 /// separated list. There is a space after
5568 /// each comma. 5568 /// each comma.
5569 /// </summary> 5569 /// </summary>
5570 public LSL_String llList2CSV(LSL_List src) 5570 public LSL_String llList2CSV(LSL_List src)
5571 { 5571 {
5572 m_host.AddScriptLPS(1); 5572 m_host.AddScriptLPS(1);
5573 5573
5574 return string.Join(", ", 5574 return string.Join(", ",
5575 (new List<object>(src.Data)).ConvertAll<string>(o => 5575 (new List<object>(src.Data)).ConvertAll<string>(o =>
5576 { 5576 {
5577 return o.ToString(); 5577 return o.ToString();
5578 }).ToArray()); 5578 }).ToArray());
5579 } 5579 }
5580 5580
5581 /// <summary> 5581 /// <summary>
5582 /// The supplied string is scanned for commas 5582 /// The supplied string is scanned for commas
5583 /// and converted into a list. Commas are only 5583 /// and converted into a list. Commas are only
5584 /// effective if they are encountered outside 5584 /// effective if they are encountered outside
5585 /// of '<' '>' delimiters. Any whitespace 5585 /// of '<' '>' delimiters. Any whitespace
5586 /// before or after an element is trimmed. 5586 /// before or after an element is trimmed.
5587 /// </summary> 5587 /// </summary>
5588 5588
5589 public LSL_List llCSV2List(string src) 5589 public LSL_List llCSV2List(string src)
5590 { 5590 {
5591 5591
5592 LSL_List result = new LSL_List(); 5592 LSL_List result = new LSL_List();
5593 int parens = 0; 5593 int parens = 0;
5594 int start = 0; 5594 int start = 0;
5595 int length = 0; 5595 int length = 0;
5596 5596
5597 m_host.AddScriptLPS(1); 5597 m_host.AddScriptLPS(1);
5598 5598
5599 for (int i = 0; i < src.Length; i++) 5599 for (int i = 0; i < src.Length; i++)
5600 { 5600 {
5601 switch (src[i]) 5601 switch (src[i])
5602 { 5602 {
5603 case '<': 5603 case '<':
5604 parens++; 5604 parens++;
5605 length++; 5605 length++;
5606 break; 5606 break;
5607 case '>': 5607 case '>':
5608 if (parens > 0) 5608 if (parens > 0)
5609 parens--; 5609 parens--;
5610 length++; 5610 length++;
5611 break; 5611 break;
5612 case ',': 5612 case ',':
5613 if (parens == 0) 5613 if (parens == 0)
5614 { 5614 {
5615 result.Add(new LSL_String(src.Substring(start,length).Trim())); 5615 result.Add(new LSL_String(src.Substring(start,length).Trim()));
5616 start += length+1; 5616 start += length+1;
5617 length = 0; 5617 length = 0;
5618 } 5618 }
5619 else 5619 else
5620 { 5620 {
5621 length++; 5621 length++;
5622 } 5622 }
5623 break; 5623 break;
5624 default: 5624 default:
5625 length++; 5625 length++;
5626 break; 5626 break;
5627 } 5627 }
5628 } 5628 }
5629 5629
5630 result.Add(new LSL_String(src.Substring(start,length).Trim())); 5630 result.Add(new LSL_String(src.Substring(start,length).Trim()));
5631 5631
5632 return result; 5632 return result;
5633 } 5633 }
5634 5634
5635 /// <summary> 5635 /// <summary>
5636 /// Randomizes the list, be arbitrarily reordering 5636 /// Randomizes the list, be arbitrarily reordering
5637 /// sublists of stride elements. As the stride approaches 5637 /// sublists of stride elements. As the stride approaches
5638 /// the size of the list, the options become very 5638 /// the size of the list, the options become very
5639 /// limited. 5639 /// limited.
5640 /// </summary> 5640 /// </summary>
5641 /// <remarks> 5641 /// <remarks>
5642 /// This could take a while for very large list 5642 /// This could take a while for very large list
5643 /// sizes. 5643 /// sizes.
5644 /// </remarks> 5644 /// </remarks>
5645 5645
5646 public LSL_List llListRandomize(LSL_List src, int stride) 5646 public LSL_List llListRandomize(LSL_List src, int stride)
5647 { 5647 {
5648 LSL_List result; 5648 LSL_List result;
5649 BetterRandom rand = new BetterRandom(); 5649 BetterRandom rand = new BetterRandom();
5650 5650
5651 int chunkk; 5651 int chunkk;
5652 int[] chunks; 5652 int[] chunks;
5653 5653
5654 m_host.AddScriptLPS(1); 5654 m_host.AddScriptLPS(1);
5655 5655
5656 if (stride <= 0) 5656 if (stride <= 0)
5657 { 5657 {
5658 stride = 1; 5658 stride = 1;
5659 } 5659 }
5660 5660
5661 // Stride MUST be a factor of the list length 5661 // Stride MUST be a factor of the list length
5662 // If not, then return the src list. This also 5662 // If not, then return the src list. This also
5663 // traps those cases where stride > length. 5663 // traps those cases where stride > length.
5664 5664
5665 if (src.Length != stride && src.Length % stride == 0) 5665 if (src.Length != stride && src.Length % stride == 0)
5666 { 5666 {
5667 chunkk = src.Length/stride; 5667 chunkk = src.Length/stride;
5668 5668
5669 chunks = new int[chunkk]; 5669 chunks = new int[chunkk];
5670 5670
5671 for (int i = 0; i < chunkk; i++) 5671 for (int i = 0; i < chunkk; i++)
5672 { 5672 {
5673 chunks[i] = i; 5673 chunks[i] = i;
5674 } 5674 }
5675 5675
5676 // Knuth shuffle the chunkk index 5676 // Knuth shuffle the chunkk index
5677 for (int i = chunkk - 1; i > 0; i--) 5677 for (int i = chunkk - 1; i > 0; i--)
5678 { 5678 {
5679 // Elect an unrandomized chunk to swap 5679 // Elect an unrandomized chunk to swap
5680 int index = rand.Next(i + 1); 5680 int index = rand.Next(i + 1);
5681 5681
5682 // and swap position with first unrandomized chunk 5682 // and swap position with first unrandomized chunk
5683 int tmp = chunks[i]; 5683 int tmp = chunks[i];
5684 chunks[i] = chunks[index]; 5684 chunks[i] = chunks[index];
5685 chunks[index] = tmp; 5685 chunks[index] = tmp;
5686 } 5686 }
5687 5687
5688 // Construct the randomized list 5688 // Construct the randomized list
5689 5689
5690 result = new LSL_List(); 5690 result = new LSL_List();
5691 5691
5692 for (int i = 0; i < chunkk; i++) 5692 for (int i = 0; i < chunkk; i++)
5693 { 5693 {
5694 for (int j = 0; j < stride; j++) 5694 for (int j = 0; j < stride; j++)
5695 { 5695 {
5696 result.Add(src.Data[chunks[i] * stride + j]); 5696 result.Add(src.Data[chunks[i] * stride + j]);
5697 } 5697 }
5698 } 5698 }
5699 } 5699 }
5700 else { 5700 else {
5701 object[] array = new object[src.Length]; 5701 object[] array = new object[src.Length];
5702 Array.Copy(src.Data, 0, array, 0, src.Length); 5702 Array.Copy(src.Data, 0, array, 0, src.Length);
5703 result = new LSL_List(array); 5703 result = new LSL_List(array);
5704 } 5704 }
5705 5705
5706 return result; 5706 return result;
5707 } 5707 }
5708 5708
5709 /// <summary> 5709 /// <summary>
5710 /// Elements in the source list starting with 0 and then 5710 /// Elements in the source list starting with 0 and then
5711 /// every i+stride. If the stride is negative then the scan 5711 /// every i+stride. If the stride is negative then the scan
5712 /// is backwards producing an inverted result. 5712 /// is backwards producing an inverted result.
5713 /// Only those elements that are also in the specified 5713 /// Only those elements that are also in the specified
5714 /// range are included in the result. 5714 /// range are included in the result.
5715 /// </summary> 5715 /// </summary>
5716 5716
5717 public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride) 5717 public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride)
5718 { 5718 {
5719 5719
5720 LSL_List result = new LSL_List(); 5720 LSL_List result = new LSL_List();
5721 int[] si = new int[2]; 5721 int[] si = new int[2];
5722 int[] ei = new int[2]; 5722 int[] ei = new int[2];
5723 bool twopass = false; 5723 bool twopass = false;
5724 5724
5725 m_host.AddScriptLPS(1); 5725 m_host.AddScriptLPS(1);
5726 5726
5727 // First step is always to deal with negative indices 5727 // First step is always to deal with negative indices
5728 5728
5729 if (start < 0) 5729 if (start < 0)
5730 start = src.Length+start; 5730 start = src.Length+start;
5731 if (end < 0) 5731 if (end < 0)
5732 end = src.Length+end; 5732 end = src.Length+end;
5733 5733
5734 // Out of bounds indices are OK, just trim them 5734 // Out of bounds indices are OK, just trim them
5735 // accordingly 5735 // accordingly
5736 5736
5737 if (start > src.Length) 5737 if (start > src.Length)
5738 start = src.Length; 5738 start = src.Length;
5739 5739
5740 if (end > src.Length) 5740 if (end > src.Length)
5741 end = src.Length; 5741 end = src.Length;
5742 5742
5743 if (stride == 0) 5743 if (stride == 0)
5744 stride = 1; 5744 stride = 1;
5745 5745
5746 // There may be one or two ranges to be considered 5746 // There may be one or two ranges to be considered
5747 5747
5748 if (start != end) 5748 if (start != end)
5749 { 5749 {
5750 5750
5751 if (start <= end) 5751 if (start <= end)
5752 { 5752 {
5753 si[0] = start; 5753 si[0] = start;
5754 ei[0] = end; 5754 ei[0] = end;
5755 } 5755 }
5756 else 5756 else
5757 { 5757 {
5758 si[1] = start; 5758 si[1] = start;
5759 ei[1] = src.Length; 5759 ei[1] = src.Length;
5760 si[0] = 0; 5760 si[0] = 0;
5761 ei[0] = end; 5761 ei[0] = end;
5762 twopass = true; 5762 twopass = true;
5763 } 5763 }
5764 5764
5765 // The scan always starts from the beginning of the 5765 // The scan always starts from the beginning of the
5766 // source list, but members are only selected if they 5766 // source list, but members are only selected if they
5767 // fall within the specified sub-range. The specified 5767 // fall within the specified sub-range. The specified
5768 // range values are inclusive. 5768 // range values are inclusive.
5769 // A negative stride reverses the direction of the 5769 // A negative stride reverses the direction of the
5770 // scan producing an inverted list as a result. 5770 // scan producing an inverted list as a result.
5771 5771
5772 if (stride > 0) 5772 if (stride > 0)
5773 { 5773 {
5774 for (int i = 0; i < src.Length; i += stride) 5774 for (int i = 0; i < src.Length; i += stride)
5775 { 5775 {
5776 if (i<=ei[0] && i>=si[0]) 5776 if (i<=ei[0] && i>=si[0])
5777 result.Add(src.Data[i]); 5777 result.Add(src.Data[i]);
5778 if (twopass && i>=si[1] && i<=ei[1]) 5778 if (twopass && i>=si[1] && i<=ei[1])
5779 result.Add(src.Data[i]); 5779 result.Add(src.Data[i]);
5780 } 5780 }
5781 } 5781 }
5782 else if (stride < 0) 5782 else if (stride < 0)
5783 { 5783 {
5784 for (int i = src.Length - 1; i >= 0; i += stride) 5784 for (int i = src.Length - 1; i >= 0; i += stride)
5785 { 5785 {
5786 if (i <= ei[0] && i >= si[0]) 5786 if (i <= ei[0] && i >= si[0])
5787 result.Add(src.Data[i]); 5787 result.Add(src.Data[i]);
5788 if (twopass && i >= si[1] && i <= ei[1]) 5788 if (twopass && i >= si[1] && i <= ei[1])
5789 result.Add(src.Data[i]); 5789 result.Add(src.Data[i]);
5790 } 5790 }
5791 } 5791 }
5792 } 5792 }
5793 else 5793 else
5794 { 5794 {
5795 if (start%stride == 0) 5795 if (start%stride == 0)
5796 { 5796 {
5797 result.Add(src.Data[start]); 5797 result.Add(src.Data[start]);
5798 } 5798 }
5799 } 5799 }
5800 5800
5801 return result; 5801 return result;
5802 } 5802 }
5803 5803
5804 public LSL_Integer llGetRegionAgentCount() 5804 public LSL_Integer llGetRegionAgentCount()
5805 { 5805 {
5806 m_host.AddScriptLPS(1); 5806 m_host.AddScriptLPS(1);
5807 return new LSL_Integer(World.GetRootAgentCount()); 5807 return new LSL_Integer(World.GetRootAgentCount());
5808 } 5808 }
5809 5809
5810 public LSL_Vector llGetRegionCorner() 5810 public LSL_Vector llGetRegionCorner()
5811 { 5811 {
5812 m_host.AddScriptLPS(1); 5812 m_host.AddScriptLPS(1);
5813 return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); 5813 return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0);
5814 } 5814 }
5815 5815
5816 public LSL_String llGetEnv(LSL_String name) 5816 public LSL_String llGetEnv(LSL_String name)
5817 { 5817 {
5818 m_host.AddScriptLPS(1); 5818 m_host.AddScriptLPS(1);
5819 if (name == "agent_limit") 5819 if (name == "agent_limit")
5820 { 5820 {
5821 return World.RegionInfo.RegionSettings.AgentLimit.ToString(); 5821 return World.RegionInfo.RegionSettings.AgentLimit.ToString();
5822 } 5822 }
5823 else if (name == "dynamic_pathfinding") 5823 else if (name == "dynamic_pathfinding")
5824 { 5824 {
5825 return "0"; 5825 return "0";
5826 } 5826 }
5827 else if (name == "estate_id") 5827 else if (name == "estate_id")
5828 { 5828 {
5829 return World.RegionInfo.EstateSettings.EstateID.ToString(); 5829 return World.RegionInfo.EstateSettings.EstateID.ToString();
5830 } 5830 }
5831 else if (name == "estate_name") 5831 else if (name == "estate_name")
5832 { 5832 {
5833 return World.RegionInfo.EstateSettings.EstateName; 5833 return World.RegionInfo.EstateSettings.EstateName;
5834 } 5834 }
5835 else if (name == "frame_number") 5835 else if (name == "frame_number")
5836 { 5836 {
5837 return World.Frame.ToString(); 5837 return World.Frame.ToString();
5838 } 5838 }
5839 else if (name == "region_cpu_ratio") 5839 else if (name == "region_cpu_ratio")
5840 { 5840 {
5841 return "1"; 5841 return "1";
5842 } 5842 }
5843 else if (name == "region_idle") 5843 else if (name == "region_idle")
5844 { 5844 {
5845 return "0"; 5845 return "0";
5846 } 5846 }
5847 else if (name == "region_product_name") 5847 else if (name == "region_product_name")
5848 { 5848 {
5849 if (World.RegionInfo.RegionType != String.Empty) 5849 if (World.RegionInfo.RegionType != String.Empty)
5850 return World.RegionInfo.RegionType; 5850 return World.RegionInfo.RegionType;
5851 else 5851 else
5852 return ""; 5852 return "";
5853 } 5853 }
5854 else if (name == "region_product_sku") 5854 else if (name == "region_product_sku")
5855 { 5855 {
5856 return "OpenSim"; 5856 return "OpenSim";
5857 } 5857 }
5858 else if (name == "region_start_time") 5858 else if (name == "region_start_time")
5859 { 5859 {
5860 return World.UnixStartTime.ToString(); 5860 return World.UnixStartTime.ToString();
5861 } 5861 }
5862 else if (name == "sim_channel") 5862 else if (name == "sim_channel")
5863 { 5863 {
5864 return "OpenSim"; 5864 return "OpenSim";
5865 } 5865 }
5866 else if (name == "sim_version") 5866 else if (name == "sim_version")
5867 { 5867 {
5868 return World.GetSimulatorVersion(); 5868 return World.GetSimulatorVersion();
5869 } 5869 }
5870 else if (name == "simulator_hostname") 5870 else if (name == "simulator_hostname")
5871 { 5871 {
5872 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); 5872 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
5873 return UrlModule.ExternalHostNameForLSL; 5873 return UrlModule.ExternalHostNameForLSL;
5874 } 5874 }
5875 else 5875 else
5876 { 5876 {
5877 return ""; 5877 return "";
5878 } 5878 }
5879 } 5879 }
5880 5880
5881 /// <summary> 5881 /// <summary>
5882 /// Insert the list identified by <paramref name="src"/> into the 5882 /// Insert the list identified by <paramref name="src"/> into the
5883 /// list designated by <paramref name="dest"/> such that the first 5883 /// list designated by <paramref name="dest"/> such that the first
5884 /// new element has the index specified by <paramref name="index"/> 5884 /// new element has the index specified by <paramref name="index"/>
5885 /// </summary> 5885 /// </summary>
5886 5886
5887 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) 5887 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
5888 { 5888 {
5889 5889
5890 LSL_List pref = null; 5890 LSL_List pref = null;
5891 LSL_List suff = null; 5891 LSL_List suff = null;
5892 5892
5893 m_host.AddScriptLPS(1); 5893 m_host.AddScriptLPS(1);
5894 5894
5895 if (index < 0) 5895 if (index < 0)
5896 { 5896 {
5897 index = index+dest.Length; 5897 index = index+dest.Length;
5898 if (index < 0) 5898 if (index < 0)
5899 { 5899 {
5900 index = 0; 5900 index = 0;
5901 } 5901 }
5902 } 5902 }
5903 5903
5904 if (index != 0) 5904 if (index != 0)
5905 { 5905 {
5906 pref = dest.GetSublist(0,index-1); 5906 pref = dest.GetSublist(0,index-1);
5907 if (index < dest.Length) 5907 if (index < dest.Length)
5908 { 5908 {
5909 suff = dest.GetSublist(index,-1); 5909 suff = dest.GetSublist(index,-1);
5910 return pref + src + suff; 5910 return pref + src + suff;
5911 } 5911 }
5912 else 5912 else
5913 { 5913 {
5914 return pref + src; 5914 return pref + src;
5915 } 5915 }
5916 } 5916 }
5917 else 5917 else
5918 { 5918 {
5919 if (index < dest.Length) 5919 if (index < dest.Length)
5920 { 5920 {
5921 suff = dest.GetSublist(index,-1); 5921 suff = dest.GetSublist(index,-1);
5922 return src + suff; 5922 return src + suff;
5923 } 5923 }
5924 else 5924 else
5925 { 5925 {
5926 return src; 5926 return src;
5927 } 5927 }
5928 } 5928 }
5929 5929
5930 } 5930 }
5931 5931
5932 /// <summary> 5932 /// <summary>
5933 /// Returns the index of the first occurrence of test 5933 /// Returns the index of the first occurrence of test
5934 /// in src. 5934 /// in src.
5935 /// </summary> 5935 /// </summary>
5936 /// <param name="src">Source list</param> 5936 /// <param name="src">Source list</param>
5937 /// <param name="test">List to search for</param> 5937 /// <param name="test">List to search for</param>
5938 /// <returns> 5938 /// <returns>
5939 /// The index number of the point in src where test was found if it was found. 5939 /// The index number of the point in src where test was found if it was found.
5940 /// Otherwise returns -1 5940 /// Otherwise returns -1
5941 /// </returns> 5941 /// </returns>
5942 public LSL_Integer llListFindList(LSL_List src, LSL_List test) 5942 public LSL_Integer llListFindList(LSL_List src, LSL_List test)
5943 { 5943 {
5944 int index = -1; 5944 int index = -1;
5945 int length = src.Length - test.Length + 1; 5945 int length = src.Length - test.Length + 1;
5946 5946
5947 m_host.AddScriptLPS(1); 5947 m_host.AddScriptLPS(1);
5948 5948
5949 // If either list is empty, do not match 5949 // If either list is empty, do not match
5950 if (src.Length != 0 && test.Length != 0) 5950 if (src.Length != 0 && test.Length != 0)
5951 { 5951 {
5952 for (int i = 0; i < length; i++) 5952 for (int i = 0; i < length; i++)
5953 { 5953 {
5954 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) 5954 // Why this piece of insanity? This is because most script constants are C# value types (e.g. int)
5955 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code 5955 // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code
5956 // and so the comparison fails even if the LSL_Integer conceptually has the same value. 5956 // and so the comparison fails even if the LSL_Integer conceptually has the same value.
5957 // Therefore, here we test Equals on both the source and destination objects. 5957 // Therefore, here we test Equals on both the source and destination objects.
5958 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). 5958 // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)).
5959 if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) 5959 if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i]))
5960 { 5960 {
5961 int j; 5961 int j;
5962 for (j = 1; j < test.Length; j++) 5962 for (j = 1; j < test.Length; j++)
5963 if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) 5963 if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j])))
5964 break; 5964 break;
5965 5965
5966 if (j == test.Length) 5966 if (j == test.Length)
5967 { 5967 {
5968 index = i; 5968 index = i;
5969 break; 5969 break;
5970 } 5970 }
5971 } 5971 }
5972 } 5972 }
5973 } 5973 }
5974 5974
5975 return index; 5975 return index;
5976 } 5976 }
5977 5977
5978 public LSL_String llGetObjectName() 5978 public LSL_String llGetObjectName()
5979 { 5979 {
5980 m_host.AddScriptLPS(1); 5980 m_host.AddScriptLPS(1);
5981 return m_host.Name !=null ? m_host.Name : String.Empty; 5981 return m_host.Name !=null ? m_host.Name : String.Empty;
5982 } 5982 }
5983 5983
5984 public void llSetObjectName(string name) 5984 public void llSetObjectName(string name)
5985 { 5985 {
5986 m_host.AddScriptLPS(1); 5986 m_host.AddScriptLPS(1);
5987 m_host.Name = name != null ? name : String.Empty; 5987 m_host.Name = name != null ? name : String.Empty;
5988 } 5988 }
5989 5989
5990 public LSL_String llGetDate() 5990 public LSL_String llGetDate()
5991 { 5991 {
5992 m_host.AddScriptLPS(1); 5992 m_host.AddScriptLPS(1);
5993 DateTime date = DateTime.Now.ToUniversalTime(); 5993 DateTime date = DateTime.Now.ToUniversalTime();
5994 string result = date.ToString("yyyy-MM-dd"); 5994 string result = date.ToString("yyyy-MM-dd");
5995 return result; 5995 return result;
5996 } 5996 }
5997 5997
5998 public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir) 5998 public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir)
5999 { 5999 {
6000 m_host.AddScriptLPS(1); 6000 m_host.AddScriptLPS(1);
6001 6001
6002 // edge will be used to pass the Region Coordinates offset 6002 // edge will be used to pass the Region Coordinates offset
6003 // we want to check for a neighboring sim 6003 // we want to check for a neighboring sim
6004 LSL_Vector edge = new LSL_Vector(0, 0, 0); 6004 LSL_Vector edge = new LSL_Vector(0, 0, 0);
6005 6005
6006 if (dir.x == 0) 6006 if (dir.x == 0)
6007 { 6007 {
6008 if (dir.y == 0) 6008 if (dir.y == 0)
6009 { 6009 {
6010 // Direction vector is 0,0 so return 6010 // Direction vector is 0,0 so return
6011 // false since we're staying in the sim 6011 // false since we're staying in the sim
6012 return 0; 6012 return 0;
6013 } 6013 }
6014 else 6014 else
6015 { 6015 {
6016 // Y is the only valid direction 6016 // Y is the only valid direction
6017 edge.y = dir.y / Math.Abs(dir.y); 6017 edge.y = dir.y / Math.Abs(dir.y);
6018 } 6018 }
6019 } 6019 }
6020 else 6020 else
6021 { 6021 {
6022 LSL_Float mag; 6022 LSL_Float mag;
6023 if (dir.x > 0) 6023 if (dir.x > 0)
6024 { 6024 {
6025 mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x; 6025 mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x;
6026 } 6026 }
6027 else 6027 else
6028 { 6028 {
6029 mag = (pos.x/dir.x); 6029 mag = (pos.x/dir.x);
6030 } 6030 }
6031 6031
6032 mag = Math.Abs(mag); 6032 mag = Math.Abs(mag);
6033 6033
6034 edge.y = pos.y + (dir.y * mag); 6034 edge.y = pos.y + (dir.y * mag);
6035 6035
6036 if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0) 6036 if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0)
6037 { 6037 {
6038 // Y goes out of bounds first 6038 // Y goes out of bounds first
6039 edge.y = dir.y / Math.Abs(dir.y); 6039 edge.y = dir.y / Math.Abs(dir.y);
6040 } 6040 }
6041 else 6041 else
6042 { 6042 {
6043 // X goes out of bounds first or its a corner exit 6043 // X goes out of bounds first or its a corner exit
6044 edge.y = 0; 6044 edge.y = 0;
6045 edge.x = dir.x / Math.Abs(dir.x); 6045 edge.x = dir.x / Math.Abs(dir.x);
6046 } 6046 }
6047 } 6047 }
6048 6048
6049 List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID); 6049 List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID);
6050 6050
6051 uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x; 6051 uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x;
6052 uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y; 6052 uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y;
6053 6053
6054 foreach (GridRegion sri in neighbors) 6054 foreach (GridRegion sri in neighbors)
6055 { 6055 {
6056 if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY) 6056 if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY)
6057 return 0; 6057 return 0;
6058 } 6058 }
6059 6059
6060 return 1; 6060 return 1;
6061 } 6061 }
6062 6062
6063 /// <summary> 6063 /// <summary>
6064 /// Not fully implemented yet. Still to do:- 6064 /// Not fully implemented yet. Still to do:-
6065 /// AGENT_BUSY 6065 /// AGENT_BUSY
6066 /// Remove as they are done 6066 /// Remove as they are done
6067 /// </summary> 6067 /// </summary>
6068 public LSL_Integer llGetAgentInfo(string id) 6068 public LSL_Integer llGetAgentInfo(string id)
6069 { 6069 {
6070 m_host.AddScriptLPS(1); 6070 m_host.AddScriptLPS(1);
6071 6071
6072 UUID key = new UUID(); 6072 UUID key = new UUID();
6073 if (!UUID.TryParse(id, out key)) 6073 if (!UUID.TryParse(id, out key))
6074 { 6074 {
6075 return 0; 6075 return 0;
6076 } 6076 }
6077 6077
6078 int flags = 0; 6078 int flags = 0;
6079 6079
6080 ScenePresence agent = World.GetScenePresence(key); 6080 ScenePresence agent = World.GetScenePresence(key);
6081 if (agent == null) 6081 if (agent == null)
6082 { 6082 {
6083 return 0; 6083 return 0;
6084 } 6084 }
6085 6085
6086 if (agent.IsChildAgent) 6086 if (agent.IsChildAgent)
6087 return 0; // Fail if they are not in the same region 6087 return 0; // Fail if they are not in the same region
6088 6088
6089 // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL 6089 // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL
6090 if (agent.SetAlwaysRun) 6090 if (agent.SetAlwaysRun)
6091 { 6091 {
6092 flags |= ScriptBaseClass.AGENT_ALWAYS_RUN; 6092 flags |= ScriptBaseClass.AGENT_ALWAYS_RUN;
6093 } 6093 }
6094 6094
6095 if (agent.HasAttachments()) 6095 if (agent.HasAttachments())
6096 { 6096 {
6097 flags |= ScriptBaseClass.AGENT_ATTACHMENTS; 6097 flags |= ScriptBaseClass.AGENT_ATTACHMENTS;
6098 if (agent.HasScriptedAttachments()) 6098 if (agent.HasScriptedAttachments())
6099 flags |= ScriptBaseClass.AGENT_SCRIPTED; 6099 flags |= ScriptBaseClass.AGENT_SCRIPTED;
6100 } 6100 }
6101 6101
6102 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) 6102 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
6103 { 6103 {
6104 flags |= ScriptBaseClass.AGENT_FLYING; 6104 flags |= ScriptBaseClass.AGENT_FLYING;
6105 flags |= ScriptBaseClass.AGENT_IN_AIR; // flying always implies in-air, even if colliding with e.g. a wall 6105 flags |= ScriptBaseClass.AGENT_IN_AIR; // flying always implies in-air, even if colliding with e.g. a wall
6106 } 6106 }
6107 6107
6108 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0) 6108 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0)
6109 { 6109 {
6110 flags |= ScriptBaseClass.AGENT_AWAY; 6110 flags |= ScriptBaseClass.AGENT_AWAY;
6111 } 6111 }
6112 6112
6113 // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? 6113 // seems to get unset, even if in mouselook, when avatar is sitting on a prim???
6114 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 6114 if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
6115 { 6115 {
6116 flags |= ScriptBaseClass.AGENT_MOUSELOOK; 6116 flags |= ScriptBaseClass.AGENT_MOUSELOOK;
6117 } 6117 }
6118 6118
6119 if ((agent.State & (byte)AgentState.Typing) != (byte)0) 6119 if ((agent.State & (byte)AgentState.Typing) != (byte)0)
6120 { 6120 {
6121 flags |= ScriptBaseClass.AGENT_TYPING; 6121 flags |= ScriptBaseClass.AGENT_TYPING;
6122 } 6122 }
6123 6123
6124 string agentMovementAnimation = agent.Animator.CurrentMovementAnimation; 6124 string agentMovementAnimation = agent.Animator.CurrentMovementAnimation;
6125 6125
6126 if (agentMovementAnimation == "CROUCH") 6126 if (agentMovementAnimation == "CROUCH")
6127 { 6127 {
6128 flags |= ScriptBaseClass.AGENT_CROUCHING; 6128 flags |= ScriptBaseClass.AGENT_CROUCHING;
6129 } 6129 }
6130 6130
6131 if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK") 6131 if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK")
6132 { 6132 {
6133 flags |= ScriptBaseClass.AGENT_WALKING; 6133 flags |= ScriptBaseClass.AGENT_WALKING;
6134 } 6134 }
6135 6135
6136 // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above) 6136 // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above)
6137 6137
6138 // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL. 6138 // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL.
6139 6139
6140 // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant 6140 // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant
6141 // and don't collide when walking downhill, which instantly registers as in-air, briefly. should 6141 // and don't collide when walking downhill, which instantly registers as in-air, briefly. should
6142 // there be some minimum non-collision threshold time before claiming the avatar is in-air? 6142 // there be some minimum non-collision threshold time before claiming the avatar is in-air?
6143 if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 && !agent.IsColliding ) 6143 if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 && !agent.IsColliding )
6144 { 6144 {
6145 flags |= ScriptBaseClass.AGENT_IN_AIR; 6145 flags |= ScriptBaseClass.AGENT_IN_AIR;
6146 } 6146 }
6147 6147
6148 if (agent.ParentPart != null) 6148 if (agent.ParentPart != null)
6149 { 6149 {
6150 flags |= ScriptBaseClass.AGENT_ON_OBJECT; 6150 flags |= ScriptBaseClass.AGENT_ON_OBJECT;
6151 flags |= ScriptBaseClass.AGENT_SITTING; 6151 flags |= ScriptBaseClass.AGENT_SITTING;
6152 } 6152 }
6153 6153
6154 if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID 6154 if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID
6155 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 6155 == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
6156 { 6156 {
6157 flags |= ScriptBaseClass.AGENT_SITTING; 6157 flags |= ScriptBaseClass.AGENT_SITTING;
6158 } 6158 }
6159 6159
6160 return flags; 6160 return flags;
6161 } 6161 }
6162 6162
6163 public LSL_String llGetAgentLanguage(string id) 6163 public LSL_String llGetAgentLanguage(string id)
6164 { 6164 {
6165 // This should only return a value if the avatar is in the same region, but eh. idc. 6165 // This should only return a value if the avatar is in the same region, but eh. idc.
6166 m_host.AddScriptLPS(1); 6166 m_host.AddScriptLPS(1);
6167 if (World.AgentPreferencesService == null) 6167 if (World.AgentPreferencesService == null)
6168 { 6168 {
6169 Error("llGetAgentLanguage", "No AgentPreferencesService present"); 6169 Error("llGetAgentLanguage", "No AgentPreferencesService present");
6170 } 6170 }
6171 else 6171 else
6172 { 6172 {
6173 UUID key = new UUID(); 6173 UUID key = new UUID();
6174 if (UUID.TryParse(id, out key)) 6174 if (UUID.TryParse(id, out key))
6175 { 6175 {
6176 return new LSL_String(World.AgentPreferencesService.GetLang(key)); 6176 return new LSL_String(World.AgentPreferencesService.GetLang(key));
6177 } 6177 }
6178 } 6178 }
6179 return new LSL_String("en-us"); 6179 return new LSL_String("en-us");
6180 } 6180 }
6181 /// <summary> 6181 /// <summary>
6182 /// http://wiki.secondlife.com/wiki/LlGetAgentList 6182 /// http://wiki.secondlife.com/wiki/LlGetAgentList
6183 /// The list of options is currently not used in SL 6183 /// The list of options is currently not used in SL
6184 /// scope is one of:- 6184 /// scope is one of:-
6185 /// AGENT_LIST_REGION - all in the region 6185 /// AGENT_LIST_REGION - all in the region
6186 /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object 6186 /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object
6187 /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the 6187 /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the
6188 /// current parcel. 6188 /// current parcel.
6189 /// </summary> 6189 /// </summary>
6190 public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options) 6190 public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options)
6191 { 6191 {
6192 m_host.AddScriptLPS(1); 6192 m_host.AddScriptLPS(1);
6193 6193
6194 // the constants are 1, 2 and 4 so bits are being set, but you 6194 // the constants are 1, 2 and 4 so bits are being set, but you
6195 // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4 6195 // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4
6196 bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION; 6196 bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION;
6197 bool parcelOwned = scope == ScriptBaseClass.AGENT_LIST_PARCEL_OWNER; 6197 bool parcelOwned = scope == ScriptBaseClass.AGENT_LIST_PARCEL_OWNER;
6198 bool parcel = scope == ScriptBaseClass.AGENT_LIST_PARCEL; 6198 bool parcel = scope == ScriptBaseClass.AGENT_LIST_PARCEL;
6199 6199
6200 LSL_List result = new LSL_List(); 6200 LSL_List result = new LSL_List();
6201 6201
6202 if (!regionWide && !parcelOwned && !parcel) 6202 if (!regionWide && !parcelOwned && !parcel)
6203 { 6203 {
6204 result.Add("INVALID_SCOPE"); 6204 result.Add("INVALID_SCOPE");
6205 return result; 6205 return result;
6206 } 6206 }
6207 6207
6208 ILandObject land; 6208 ILandObject land;
6209 UUID id = UUID.Zero; 6209 UUID id = UUID.Zero;
6210 6210
6211 if (parcel || parcelOwned) 6211 if (parcel || parcelOwned)
6212 { 6212 {
6213 land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition()); 6213 land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition());
6214 if (land == null) 6214 if (land == null)
6215 { 6215 {
6216 id = UUID.Zero; 6216 id = UUID.Zero;
6217 } 6217 }
6218 else 6218 else
6219 { 6219 {
6220 if (parcelOwned) 6220 if (parcelOwned)
6221 { 6221 {
6222 id = land.LandData.OwnerID; 6222 id = land.LandData.OwnerID;
6223 } 6223 }
6224 else 6224 else
6225 { 6225 {
6226 id = land.LandData.GlobalID; 6226 id = land.LandData.GlobalID;
6227 } 6227 }
6228 } 6228 }
6229 } 6229 }
6230 6230
6231 World.ForEachRootScenePresence( 6231 World.ForEachRootScenePresence(
6232 delegate (ScenePresence ssp) 6232 delegate (ScenePresence ssp)
6233 { 6233 {
6234 // Gods are not listed in SL 6234 // Gods are not listed in SL
6235 if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent) 6235 if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent)
6236 { 6236 {
6237 if (!regionWide) 6237 if (!regionWide)
6238 { 6238 {
6239 land = World.LandChannel.GetLandObject(ssp.AbsolutePosition); 6239 land = World.LandChannel.GetLandObject(ssp.AbsolutePosition);
6240 if (land != null) 6240 if (land != null)
6241 { 6241 {
6242 if (parcelOwned && land.LandData.OwnerID == id || 6242 if (parcelOwned && land.LandData.OwnerID == id ||
6243 parcel && land.LandData.GlobalID == id) 6243 parcel && land.LandData.GlobalID == id)
6244 { 6244 {
6245 result.Add(new LSL_Key(ssp.UUID.ToString())); 6245 result.Add(new LSL_Key(ssp.UUID.ToString()));
6246 } 6246 }
6247 } 6247 }
6248 } 6248 }
6249 else 6249 else
6250 { 6250 {
6251 result.Add(new LSL_Key(ssp.UUID.ToString())); 6251 result.Add(new LSL_Key(ssp.UUID.ToString()));
6252 } 6252 }
6253 } 6253 }
6254 // Maximum of 100 results 6254 // Maximum of 100 results
6255 if (result.Length > 99) 6255 if (result.Length > 99)
6256 { 6256 {
6257 return; 6257 return;
6258 } 6258 }
6259 } 6259 }
6260 ); 6260 );
6261 return result; 6261 return result;
6262 } 6262 }
6263 6263
6264 public void llAdjustSoundVolume(double volume) 6264 public void llAdjustSoundVolume(double volume)
6265 { 6265 {
6266 m_host.AddScriptLPS(1); 6266 m_host.AddScriptLPS(1);
6267 m_host.AdjustSoundGain(volume); 6267 m_host.AdjustSoundGain(volume);
6268 ScriptSleep(m_sleepMsOnAdjustSoundVolume); 6268 ScriptSleep(m_sleepMsOnAdjustSoundVolume);
6269 } 6269 }
6270 6270
6271 public void llSetSoundRadius(double radius) 6271 public void llSetSoundRadius(double radius)
6272 { 6272 {
6273 m_host.AddScriptLPS(1); 6273 m_host.AddScriptLPS(1);
6274 m_host.SoundRadius = radius; 6274 m_host.SoundRadius = radius;
6275 } 6275 }
6276 6276
6277 public LSL_String llKey2Name(string id) 6277 public LSL_String llKey2Name(string id)
6278 { 6278 {
6279 m_host.AddScriptLPS(1); 6279 m_host.AddScriptLPS(1);
6280 UUID key = new UUID(); 6280 UUID key = new UUID();
6281 if (UUID.TryParse(id,out key)) 6281 if (UUID.TryParse(id,out key))
6282 { 6282 {
6283 ScenePresence presence = World.GetScenePresence(key); 6283 ScenePresence presence = World.GetScenePresence(key);
6284 6284
6285 if (presence != null) 6285 if (presence != null)
6286 { 6286 {
6287 return presence.ControllingClient.Name; 6287 return presence.ControllingClient.Name;
6288 //return presence.Name; 6288 //return presence.Name;
6289 } 6289 }
6290 6290
6291 if (World.GetSceneObjectPart(key) != null) 6291 if (World.GetSceneObjectPart(key) != null)
6292 { 6292 {
6293 return World.GetSceneObjectPart(key).Name; 6293 return World.GetSceneObjectPart(key).Name;
6294 } 6294 }
6295 } 6295 }
6296 return String.Empty; 6296 return String.Empty;
6297 } 6297 }
6298 6298
6299 6299
6300 6300
6301 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) 6301 public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate)
6302 { 6302 {
6303 m_host.AddScriptLPS(1); 6303 m_host.AddScriptLPS(1);
6304 6304
6305 SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate); 6305 SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate);
6306 } 6306 }
6307 6307
6308 public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate) 6308 public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate)
6309 { 6309 {
6310 m_host.AddScriptLPS(1); 6310 m_host.AddScriptLPS(1);
6311 6311
6312 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6312 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6313 6313
6314 foreach (SceneObjectPart part in parts) 6314 foreach (SceneObjectPart part in parts)
6315 { 6315 {
6316 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); 6316 SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate);
6317 } 6317 }
6318 } 6318 }
6319 6319
6320 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) 6320 private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate)
6321 { 6321 {
6322 6322
6323 Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); 6323 Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation();
6324 pTexAnim.Flags = (Primitive.TextureAnimMode)mode; 6324 pTexAnim.Flags = (Primitive.TextureAnimMode)mode;
6325 6325
6326 //ALL_SIDES 6326 //ALL_SIDES
6327 if (face == ScriptBaseClass.ALL_SIDES) 6327 if (face == ScriptBaseClass.ALL_SIDES)
6328 face = 255; 6328 face = 255;
6329 6329
6330 pTexAnim.Face = (uint)face; 6330 pTexAnim.Face = (uint)face;
6331 pTexAnim.Length = (float)length; 6331 pTexAnim.Length = (float)length;
6332 pTexAnim.Rate = (float)rate; 6332 pTexAnim.Rate = (float)rate;
6333 pTexAnim.SizeX = (uint)sizex; 6333 pTexAnim.SizeX = (uint)sizex;
6334 pTexAnim.SizeY = (uint)sizey; 6334 pTexAnim.SizeY = (uint)sizey;
6335 pTexAnim.Start = (float)start; 6335 pTexAnim.Start = (float)start;
6336 6336
6337 part.AddTextureAnimation(pTexAnim); 6337 part.AddTextureAnimation(pTexAnim);
6338 part.SendFullUpdateToAllClients(); 6338 part.SendFullUpdateToAllClients();
6339 part.ParentGroup.HasGroupChanged = true; 6339 part.ParentGroup.HasGroupChanged = true;
6340 } 6340 }
6341 6341
6342 public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, 6342 public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east,
6343 LSL_Vector bottom_south_west) 6343 LSL_Vector bottom_south_west)
6344 { 6344 {
6345 m_host.AddScriptLPS(1); 6345 m_host.AddScriptLPS(1);
6346 if (m_SoundModule != null) 6346 if (m_SoundModule != null)
6347 { 6347 {
6348 m_SoundModule.TriggerSoundLimited(m_host.UUID, 6348 m_SoundModule.TriggerSoundLimited(m_host.UUID,
6349 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, 6349 ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume,
6350 bottom_south_west, top_north_east); 6350 bottom_south_west, top_north_east);
6351 } 6351 }
6352 } 6352 }
6353 6353
6354 public void llEjectFromLand(string pest) 6354 public void llEjectFromLand(string pest)
6355 { 6355 {
6356 m_host.AddScriptLPS(1); 6356 m_host.AddScriptLPS(1);
6357 UUID agentID = new UUID(); 6357 UUID agentID = new UUID();
6358 if (UUID.TryParse(pest, out agentID)) 6358 if (UUID.TryParse(pest, out agentID))
6359 { 6359 {
6360 ScenePresence presence = World.GetScenePresence(agentID); 6360 ScenePresence presence = World.GetScenePresence(agentID);
6361 if (presence != null) 6361 if (presence != null)
6362 { 6362 {
6363 // agent must be over the owners land 6363 // agent must be over the owners land
6364 ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition); 6364 ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition);
6365 if (land == null) 6365 if (land == null)
6366 return; 6366 return;
6367 6367
6368 if (m_host.OwnerID == land.LandData.OwnerID) 6368 if (m_host.OwnerID == land.LandData.OwnerID)
6369 { 6369 {
6370 World.TeleportClientHome(agentID, presence.ControllingClient); 6370 World.TeleportClientHome(agentID, presence.ControllingClient);
6371 } 6371 }
6372 } 6372 }
6373 } 6373 }
6374 ScriptSleep(m_sleepMsOnEjectFromLand); 6374 ScriptSleep(m_sleepMsOnEjectFromLand);
6375 } 6375 }
6376 6376
6377 public LSL_Integer llOverMyLand(string id) 6377 public LSL_Integer llOverMyLand(string id)
6378 { 6378 {
6379 m_host.AddScriptLPS(1); 6379 m_host.AddScriptLPS(1);
6380 UUID key = new UUID(); 6380 UUID key = new UUID();
6381 if (UUID.TryParse(id, out key)) 6381 if (UUID.TryParse(id, out key))
6382 { 6382 {
6383 ScenePresence presence = World.GetScenePresence(key); 6383 ScenePresence presence = World.GetScenePresence(key);
6384 if (presence != null) // object is an avatar 6384 if (presence != null) // object is an avatar
6385 { 6385 {
6386 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) 6386 if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID)
6387 return 1; 6387 return 1;
6388 } 6388 }
6389 else // object is not an avatar 6389 else // object is not an avatar
6390 { 6390 {
6391 SceneObjectPart obj = World.GetSceneObjectPart(key); 6391 SceneObjectPart obj = World.GetSceneObjectPart(key);
6392 6392
6393 if (obj != null) 6393 if (obj != null)
6394 { 6394 {
6395 if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID) 6395 if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID)
6396 return 1; 6396 return 1;
6397 } 6397 }
6398 } 6398 }
6399 } 6399 }
6400 6400
6401 return 0; 6401 return 0;
6402 } 6402 }
6403 6403
6404 public LSL_String llGetLandOwnerAt(LSL_Vector pos) 6404 public LSL_String llGetLandOwnerAt(LSL_Vector pos)
6405 { 6405 {
6406 m_host.AddScriptLPS(1); 6406 m_host.AddScriptLPS(1);
6407 ILandObject land = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); 6407 ILandObject land = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
6408 if (land == null) 6408 if (land == null)
6409 return UUID.Zero.ToString(); 6409 return UUID.Zero.ToString();
6410 return land.LandData.OwnerID.ToString(); 6410 return land.LandData.OwnerID.ToString();
6411 } 6411 }
6412 6412
6413 /// <summary> 6413 /// <summary>
6414 /// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize 6414 /// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize
6415 /// only the height of avatars vary and that says: 6415 /// only the height of avatars vary and that says:
6416 /// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively). 6416 /// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively).
6417 /// </summary> 6417 /// </summary>
6418 public LSL_Vector llGetAgentSize(string id) 6418 public LSL_Vector llGetAgentSize(string id)
6419 { 6419 {
6420 m_host.AddScriptLPS(1); 6420 m_host.AddScriptLPS(1);
6421 ScenePresence avatar = World.GetScenePresence((UUID)id); 6421 ScenePresence avatar = World.GetScenePresence((UUID)id);
6422 LSL_Vector agentSize; 6422 LSL_Vector agentSize;
6423 if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region 6423 if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region
6424 { 6424 {
6425 agentSize = ScriptBaseClass.ZERO_VECTOR; 6425 agentSize = ScriptBaseClass.ZERO_VECTOR;
6426 } 6426 }
6427 else 6427 else
6428 { 6428 {
6429 agentSize = GetAgentSize(avatar); 6429 agentSize = GetAgentSize(avatar);
6430 } 6430 }
6431 6431
6432 return agentSize; 6432 return agentSize;
6433 } 6433 }
6434 6434
6435 public LSL_Integer llSameGroup(string agent) 6435 public LSL_Integer llSameGroup(string agent)
6436 { 6436 {
6437 m_host.AddScriptLPS(1); 6437 m_host.AddScriptLPS(1);
6438 UUID agentId = new UUID(); 6438 UUID agentId = new UUID();
6439 if (!UUID.TryParse(agent, out agentId)) 6439 if (!UUID.TryParse(agent, out agentId))
6440 return new LSL_Integer(0); 6440 return new LSL_Integer(0);
6441 ScenePresence presence = World.GetScenePresence(agentId); 6441 ScenePresence presence = World.GetScenePresence(agentId);
6442 if (presence == null || presence.IsChildAgent) // Return flase for child agents 6442 if (presence == null || presence.IsChildAgent) // Return flase for child agents
6443 return new LSL_Integer(0); 6443 return new LSL_Integer(0);
6444 IClientAPI client = presence.ControllingClient; 6444 IClientAPI client = presence.ControllingClient;
6445 if (m_host.GroupID == client.ActiveGroupId) 6445 if (m_host.GroupID == client.ActiveGroupId)
6446 return new LSL_Integer(1); 6446 return new LSL_Integer(1);
6447 else 6447 else
6448 return new LSL_Integer(0); 6448 return new LSL_Integer(0);
6449 } 6449 }
6450 6450
6451 public void llUnSit(string id) 6451 public void llUnSit(string id)
6452 { 6452 {
6453 m_host.AddScriptLPS(1); 6453 m_host.AddScriptLPS(1);
6454 6454
6455 UUID key = new UUID(); 6455 UUID key = new UUID();
6456 if (UUID.TryParse(id, out key)) 6456 if (UUID.TryParse(id, out key))
6457 { 6457 {
6458 ScenePresence av = World.GetScenePresence(key); 6458 ScenePresence av = World.GetScenePresence(key);
6459 List<ScenePresence> sittingAvatars = m_host.ParentGroup.GetSittingAvatars(); 6459 List<ScenePresence> sittingAvatars = m_host.ParentGroup.GetSittingAvatars();
6460 6460
6461 if (av != null) 6461 if (av != null)
6462 { 6462 {
6463 if (sittingAvatars.Contains(av)) 6463 if (sittingAvatars.Contains(av))
6464 { 6464 {
6465 // if the avatar is sitting on this object, then 6465 // if the avatar is sitting on this object, then
6466 // we can unsit them. We don't want random scripts unsitting random people 6466 // we can unsit them. We don't want random scripts unsitting random people
6467 // Lets avoid the popcorn avatar scenario. 6467 // Lets avoid the popcorn avatar scenario.
6468 av.StandUp(); 6468 av.StandUp();
6469 } 6469 }
6470 else 6470 else
6471 { 6471 {
6472 // If the object owner also owns the parcel 6472 // If the object owner also owns the parcel
6473 // or 6473 // or
6474 // if the land is group owned and the object is group owned by the same group 6474 // if the land is group owned and the object is group owned by the same group
6475 // or 6475 // or
6476 // if the object is owned by a person with estate access. 6476 // if the object is owned by a person with estate access.
6477 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition); 6477 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition);
6478 if (parcel != null) 6478 if (parcel != null)
6479 { 6479 {
6480 if (m_host.OwnerID == parcel.LandData.OwnerID || 6480 if (m_host.OwnerID == parcel.LandData.OwnerID ||
6481 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID 6481 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID
6482 && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID)) 6482 && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID))
6483 { 6483 {
6484 av.StandUp(); 6484 av.StandUp();
6485 } 6485 }
6486 } 6486 }
6487 } 6487 }
6488 } 6488 }
6489 } 6489 }
6490 } 6490 }
6491 6491
6492 public LSL_Vector llGroundSlope(LSL_Vector offset) 6492 public LSL_Vector llGroundSlope(LSL_Vector offset)
6493 { 6493 {
6494 m_host.AddScriptLPS(1); 6494 m_host.AddScriptLPS(1);
6495 6495
6496 //Get the slope normal. This gives us the equation of the plane tangent to the slope. 6496 //Get the slope normal. This gives us the equation of the plane tangent to the slope.
6497 LSL_Vector vsn = llGroundNormal(offset); 6497 LSL_Vector vsn = llGroundNormal(offset);
6498 6498
6499 //Plug the x,y coordinates of the slope normal into the equation of the plane to get 6499 //Plug the x,y coordinates of the slope normal into the equation of the plane to get
6500 //the height of that point on the plane. The resulting vector gives the slope. 6500 //the height of that point on the plane. The resulting vector gives the slope.
6501 Vector3 vsl = vsn; 6501 Vector3 vsl = vsn;
6502 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); 6502 vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z));
6503 vsl.Normalize(); 6503 vsl.Normalize();
6504 //Normalization might be overkill here 6504 //Normalization might be overkill here
6505 6505
6506 vsn.x = vsl.X; 6506 vsn.x = vsl.X;
6507 vsn.y = vsl.Y; 6507 vsn.y = vsl.Y;
6508 vsn.z = vsl.Z; 6508 vsn.z = vsl.Z;
6509 6509
6510 return vsn; 6510 return vsn;
6511 } 6511 }
6512 6512
6513 public LSL_Vector llGroundNormal(LSL_Vector offset) 6513 public LSL_Vector llGroundNormal(LSL_Vector offset)
6514 { 6514 {
6515 m_host.AddScriptLPS(1); 6515 m_host.AddScriptLPS(1);
6516 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; 6516 Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset;
6517 // Clamp to valid position 6517 // Clamp to valid position
6518 if (pos.X < 0) 6518 if (pos.X < 0)
6519 pos.X = 0; 6519 pos.X = 0;
6520 else if (pos.X >= World.Heightmap.Width) 6520 else if (pos.X >= World.Heightmap.Width)
6521 pos.X = World.Heightmap.Width - 1; 6521 pos.X = World.Heightmap.Width - 1;
6522 if (pos.Y < 0) 6522 if (pos.Y < 0)
6523 pos.Y = 0; 6523 pos.Y = 0;
6524 else if (pos.Y >= World.Heightmap.Height) 6524 else if (pos.Y >= World.Heightmap.Height)
6525 pos.Y = World.Heightmap.Height - 1; 6525 pos.Y = World.Heightmap.Height - 1;
6526 6526
6527 //Find two points in addition to the position to define a plane 6527 //Find two points in addition to the position to define a plane
6528 Vector3 p0 = new Vector3(pos.X, pos.Y, 6528 Vector3 p0 = new Vector3(pos.X, pos.Y,
6529 (float)World.Heightmap[(int)pos.X, (int)pos.Y]); 6529 (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
6530 Vector3 p1 = new Vector3(); 6530 Vector3 p1 = new Vector3();
6531 Vector3 p2 = new Vector3(); 6531 Vector3 p2 = new Vector3();
6532 if ((pos.X + 1.0f) >= World.Heightmap.Width) 6532 if ((pos.X + 1.0f) >= World.Heightmap.Width)
6533 p1 = new Vector3(pos.X + 1.0f, pos.Y, 6533 p1 = new Vector3(pos.X + 1.0f, pos.Y,
6534 (float)World.Heightmap[(int)pos.X, (int)pos.Y]); 6534 (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
6535 else 6535 else
6536 p1 = new Vector3(pos.X + 1.0f, pos.Y, 6536 p1 = new Vector3(pos.X + 1.0f, pos.Y,
6537 (float)World.Heightmap[(int)(pos.X + 1.0f), (int)pos.Y]); 6537 (float)World.Heightmap[(int)(pos.X + 1.0f), (int)pos.Y]);
6538 if ((pos.Y + 1.0f) >= World.Heightmap.Height) 6538 if ((pos.Y + 1.0f) >= World.Heightmap.Height)
6539 p2 = new Vector3(pos.X, pos.Y + 1.0f, 6539 p2 = new Vector3(pos.X, pos.Y + 1.0f,
6540 (float)World.Heightmap[(int)pos.X, (int)pos.Y]); 6540 (float)World.Heightmap[(int)pos.X, (int)pos.Y]);
6541 else 6541 else
6542 p2 = new Vector3(pos.X, pos.Y + 1.0f, 6542 p2 = new Vector3(pos.X, pos.Y + 1.0f,
6543 (float)World.Heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]); 6543 (float)World.Heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]);
6544 6544
6545 //Find normalized vectors from p0 to p1 and p0 to p2 6545 //Find normalized vectors from p0 to p1 and p0 to p2
6546 Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); 6546 Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z);
6547 Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); 6547 Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z);
6548 v0.Normalize(); 6548 v0.Normalize();
6549 v1.Normalize(); 6549 v1.Normalize();
6550 6550
6551 //Find the cross product of the vectors (the slope normal). 6551 //Find the cross product of the vectors (the slope normal).
6552 Vector3 vsn = new Vector3(); 6552 Vector3 vsn = new Vector3();
6553 vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); 6553 vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y);
6554 vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z); 6554 vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z);
6555 vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X); 6555 vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X);
6556 vsn.Normalize(); 6556 vsn.Normalize();
6557 //I believe the crossproduct of two normalized vectors is a normalized vector so 6557 //I believe the crossproduct of two normalized vectors is a normalized vector so
6558 //this normalization may be overkill 6558 //this normalization may be overkill
6559 6559
6560 return new LSL_Vector(vsn); 6560 return new LSL_Vector(vsn);
6561 } 6561 }
6562 6562
6563 public LSL_Vector llGroundContour(LSL_Vector offset) 6563 public LSL_Vector llGroundContour(LSL_Vector offset)
6564 { 6564 {
6565 m_host.AddScriptLPS(1); 6565 m_host.AddScriptLPS(1);
6566 LSL_Vector x = llGroundSlope(offset); 6566 LSL_Vector x = llGroundSlope(offset);
6567 return new LSL_Vector(-x.y, x.x, 0.0); 6567 return new LSL_Vector(-x.y, x.x, 0.0);
6568 } 6568 }
6569 6569
6570 public LSL_Integer llGetAttached() 6570 public LSL_Integer llGetAttached()
6571 { 6571 {
6572 m_host.AddScriptLPS(1); 6572 m_host.AddScriptLPS(1);
6573 return m_host.ParentGroup.AttachmentPoint; 6573 return m_host.ParentGroup.AttachmentPoint;
6574 } 6574 }
6575 6575
6576 public virtual LSL_Integer llGetFreeMemory() 6576 public virtual LSL_Integer llGetFreeMemory()
6577 { 6577 {
6578 m_host.AddScriptLPS(1); 6578 m_host.AddScriptLPS(1);
6579 // Make scripts designed for Mono happy 6579 // Make scripts designed for Mono happy
6580 return 65536; 6580 return 65536;
6581 } 6581 }
6582 6582
6583 public LSL_Integer llGetFreeURLs() 6583 public LSL_Integer llGetFreeURLs()
6584 { 6584 {
6585 m_host.AddScriptLPS(1); 6585 m_host.AddScriptLPS(1);
6586 if (m_UrlModule != null) 6586 if (m_UrlModule != null)
6587 return new LSL_Integer(m_UrlModule.GetFreeUrls()); 6587 return new LSL_Integer(m_UrlModule.GetFreeUrls());
6588 return new LSL_Integer(0); 6588 return new LSL_Integer(0);
6589 } 6589 }
6590 6590
6591 6591
6592 public LSL_String llGetRegionName() 6592 public LSL_String llGetRegionName()
6593 { 6593 {
6594 m_host.AddScriptLPS(1); 6594 m_host.AddScriptLPS(1);
6595 return World.RegionInfo.RegionName; 6595 return World.RegionInfo.RegionName;
6596 } 6596 }
6597 6597
6598 public LSL_Float llGetRegionTimeDilation() 6598 public LSL_Float llGetRegionTimeDilation()
6599 { 6599 {
6600 m_host.AddScriptLPS(1); 6600 m_host.AddScriptLPS(1);
6601 return (double)World.TimeDilation; 6601 return (double)World.TimeDilation;
6602 } 6602 }
6603 6603
6604 /// <summary> 6604 /// <summary>
6605 /// Returns the value reported in the client Statistics window 6605 /// Returns the value reported in the client Statistics window
6606 /// </summary> 6606 /// </summary>
6607 public LSL_Float llGetRegionFPS() 6607 public LSL_Float llGetRegionFPS()
6608 { 6608 {
6609 m_host.AddScriptLPS(1); 6609 m_host.AddScriptLPS(1);
6610 return World.StatsReporter.LastReportedSimFPS; 6610 return World.StatsReporter.LastReportedSimFPS;
6611 } 6611 }
6612 6612
6613 6613
6614 /* particle system rules should be coming into this routine as doubles, that is 6614 /* particle system rules should be coming into this routine as doubles, that is
6615 rule[0] should be an integer from this list and rule[1] should be the arg 6615 rule[0] should be an integer from this list and rule[1] should be the arg
6616 for the same integer. wiki.secondlife.com has most of this mapping, but some 6616 for the same integer. wiki.secondlife.com has most of this mapping, but some
6617 came from http://www.caligari-designs.com/p4u2 6617 came from http://www.caligari-designs.com/p4u2
6618 6618
6619 We iterate through the list for 'Count' elements, incrementing by two for each 6619 We iterate through the list for 'Count' elements, incrementing by two for each
6620 iteration and set the members of Primitive.ParticleSystem, one at a time. 6620 iteration and set the members of Primitive.ParticleSystem, one at a time.
6621 */ 6621 */
6622 6622
6623 public enum PrimitiveRule : int 6623 public enum PrimitiveRule : int
6624 { 6624 {
6625 PSYS_PART_FLAGS = 0, 6625 PSYS_PART_FLAGS = 0,
6626 PSYS_PART_START_COLOR = 1, 6626 PSYS_PART_START_COLOR = 1,
6627 PSYS_PART_START_ALPHA = 2, 6627 PSYS_PART_START_ALPHA = 2,
6628 PSYS_PART_END_COLOR = 3, 6628 PSYS_PART_END_COLOR = 3,
6629 PSYS_PART_END_ALPHA = 4, 6629 PSYS_PART_END_ALPHA = 4,
6630 PSYS_PART_START_SCALE = 5, 6630 PSYS_PART_START_SCALE = 5,
6631 PSYS_PART_END_SCALE = 6, 6631 PSYS_PART_END_SCALE = 6,
6632 PSYS_PART_MAX_AGE = 7, 6632 PSYS_PART_MAX_AGE = 7,
6633 PSYS_SRC_ACCEL = 8, 6633 PSYS_SRC_ACCEL = 8,
6634 PSYS_SRC_PATTERN = 9, 6634 PSYS_SRC_PATTERN = 9,
6635 PSYS_SRC_INNERANGLE = 10, 6635 PSYS_SRC_INNERANGLE = 10,
6636 PSYS_SRC_OUTERANGLE = 11, 6636 PSYS_SRC_OUTERANGLE = 11,
6637 PSYS_SRC_TEXTURE = 12, 6637 PSYS_SRC_TEXTURE = 12,
6638 PSYS_SRC_BURST_RATE = 13, 6638 PSYS_SRC_BURST_RATE = 13,
6639 PSYS_SRC_BURST_PART_COUNT = 15, 6639 PSYS_SRC_BURST_PART_COUNT = 15,
6640 PSYS_SRC_BURST_RADIUS = 16, 6640 PSYS_SRC_BURST_RADIUS = 16,
6641 PSYS_SRC_BURST_SPEED_MIN = 17, 6641 PSYS_SRC_BURST_SPEED_MIN = 17,
6642 PSYS_SRC_BURST_SPEED_MAX = 18, 6642 PSYS_SRC_BURST_SPEED_MAX = 18,
6643 PSYS_SRC_MAX_AGE = 19, 6643 PSYS_SRC_MAX_AGE = 19,
6644 PSYS_SRC_TARGET_KEY = 20, 6644 PSYS_SRC_TARGET_KEY = 20,
6645 PSYS_SRC_OMEGA = 21, 6645 PSYS_SRC_OMEGA = 21,
6646 PSYS_SRC_ANGLE_BEGIN = 22, 6646 PSYS_SRC_ANGLE_BEGIN = 22,
6647 PSYS_SRC_ANGLE_END = 23, 6647 PSYS_SRC_ANGLE_END = 23,
6648 PSYS_PART_BLEND_FUNC_SOURCE = 24, 6648 PSYS_PART_BLEND_FUNC_SOURCE = 24,
6649 PSYS_PART_BLEND_FUNC_DEST = 25, 6649 PSYS_PART_BLEND_FUNC_DEST = 25,
6650 PSYS_PART_START_GLOW = 26, 6650 PSYS_PART_START_GLOW = 26,
6651 PSYS_PART_END_GLOW = 27 6651 PSYS_PART_END_GLOW = 27
6652 } 6652 }
6653 6653
6654 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) 6654 internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags)
6655 { 6655 {
6656 Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None; 6656 Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None;
6657 6657
6658 return returnval; 6658 return returnval;
6659 } 6659 }
6660 6660
6661 protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues() 6661 protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues()
6662 { 6662 {
6663 Primitive.ParticleSystem ps = new Primitive.ParticleSystem(); 6663 Primitive.ParticleSystem ps = new Primitive.ParticleSystem();
6664 6664
6665 // TODO find out about the other defaults and add them here 6665 // TODO find out about the other defaults and add them here
6666 ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); 6666 ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
6667 ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); 6667 ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
6668 ps.PartStartScaleX = 1.0f; 6668 ps.PartStartScaleX = 1.0f;
6669 ps.PartStartScaleY = 1.0f; 6669 ps.PartStartScaleY = 1.0f;
6670 ps.PartEndScaleX = 1.0f; 6670 ps.PartEndScaleX = 1.0f;
6671 ps.PartEndScaleY = 1.0f; 6671 ps.PartEndScaleY = 1.0f;
6672 ps.BurstSpeedMin = 1.0f; 6672 ps.BurstSpeedMin = 1.0f;
6673 ps.BurstSpeedMax = 1.0f; 6673 ps.BurstSpeedMax = 1.0f;
6674 ps.BurstRate = 0.1f; 6674 ps.BurstRate = 0.1f;
6675 ps.PartMaxAge = 10.0f; 6675 ps.PartMaxAge = 10.0f;
6676 ps.BurstPartCount = 1; 6676 ps.BurstPartCount = 1;
6677 ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA; 6677 ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA;
6678 ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA; 6678 ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA;
6679 ps.PartStartGlow = 0.0f; 6679 ps.PartStartGlow = 0.0f;
6680 ps.PartEndGlow = 0.0f; 6680 ps.PartEndGlow = 0.0f;
6681 6681
6682 return ps; 6682 return ps;
6683 } 6683 }
6684 6684
6685 public void llLinkParticleSystem(int linknumber, LSL_List rules) 6685 public void llLinkParticleSystem(int linknumber, LSL_List rules)
6686 { 6686 {
6687 m_host.AddScriptLPS(1); 6687 m_host.AddScriptLPS(1);
6688 6688
6689 List<SceneObjectPart> parts = GetLinkParts(linknumber); 6689 List<SceneObjectPart> parts = GetLinkParts(linknumber);
6690 6690
6691 foreach (SceneObjectPart part in parts) 6691 foreach (SceneObjectPart part in parts)
6692 { 6692 {
6693 SetParticleSystem(part, rules, "llLinkParticleSystem"); 6693 SetParticleSystem(part, rules, "llLinkParticleSystem");
6694 } 6694 }
6695 } 6695 }
6696 6696
6697 public void llParticleSystem(LSL_List rules) 6697 public void llParticleSystem(LSL_List rules)
6698 { 6698 {
6699 m_host.AddScriptLPS(1); 6699 m_host.AddScriptLPS(1);
6700 SetParticleSystem(m_host, rules, "llParticleSystem"); 6700 SetParticleSystem(m_host, rules, "llParticleSystem");
6701 } 6701 }
6702 6702
6703 private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc) 6703 private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc)
6704 { 6704 {
6705 if (rules.Length == 0) 6705 if (rules.Length == 0)
6706 { 6706 {
6707 part.RemoveParticleSystem(); 6707 part.RemoveParticleSystem();
6708 part.ParentGroup.HasGroupChanged = true; 6708 part.ParentGroup.HasGroupChanged = true;
6709 } 6709 }
6710 else 6710 else
6711 { 6711 {
6712 Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues(); 6712 Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues();
6713 LSL_Vector tempv = new LSL_Vector(); 6713 LSL_Vector tempv = new LSL_Vector();
6714 6714
6715 float tempf = 0; 6715 float tempf = 0;
6716 int tmpi = 0; 6716 int tmpi = 0;
6717 6717
6718 for (int i = 0; i < rules.Length; i += 2) 6718 for (int i = 0; i < rules.Length; i += 2)
6719 { 6719 {
6720 int psystype; 6720 int psystype;
6721 try 6721 try
6722 { 6722 {
6723 psystype = rules.GetLSLIntegerItem(i); 6723 psystype = rules.GetLSLIntegerItem(i);
6724 } 6724 }
6725 catch (InvalidCastException) 6725 catch (InvalidCastException)
6726 { 6726 {
6727 Error(originFunc, string.Format("Error running particle system params index #{0}: particle system parameter type must be integer", i)); 6727 Error(originFunc, string.Format("Error running particle system params index #{0}: particle system parameter type must be integer", i));
6728 return; 6728 return;
6729 } 6729 }
6730 switch (psystype) 6730 switch (psystype)
6731 { 6731 {
6732 case (int)ScriptBaseClass.PSYS_PART_FLAGS: 6732 case (int)ScriptBaseClass.PSYS_PART_FLAGS:
6733 try 6733 try
6734 { 6734 {
6735 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); 6735 prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1);
6736 } 6736 }
6737 catch(InvalidCastException) 6737 catch(InvalidCastException)
6738 { 6738 {
6739 Error(originFunc, string.Format("Error running rule PSYS_PART_FLAGS: arg #{0} - parameter 1 must be integer", i + 1)); 6739 Error(originFunc, string.Format("Error running rule PSYS_PART_FLAGS: arg #{0} - parameter 1 must be integer", i + 1));
6740 return; 6740 return;
6741 } 6741 }
6742 break; 6742 break;
6743 6743
6744 case (int)ScriptBaseClass.PSYS_PART_START_COLOR: 6744 case (int)ScriptBaseClass.PSYS_PART_START_COLOR:
6745 try 6745 try
6746 { 6746 {
6747 tempv = rules.GetVector3Item(i + 1); 6747 tempv = rules.GetVector3Item(i + 1);
6748 } 6748 }
6749 catch(InvalidCastException) 6749 catch(InvalidCastException)
6750 { 6750 {
6751 Error(originFunc, string.Format("Error running rule PSYS_PART_START_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); 6751 Error(originFunc, string.Format("Error running rule PSYS_PART_START_COLOR: arg #{0} - parameter 1 must be vector", i + 1));
6752 return; 6752 return;
6753 } 6753 }
6754 prules.PartStartColor.R = (float)tempv.x; 6754 prules.PartStartColor.R = (float)tempv.x;
6755 prules.PartStartColor.G = (float)tempv.y; 6755 prules.PartStartColor.G = (float)tempv.y;
6756 prules.PartStartColor.B = (float)tempv.z; 6756 prules.PartStartColor.B = (float)tempv.z;
6757 break; 6757 break;
6758 6758
6759 case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: 6759 case (int)ScriptBaseClass.PSYS_PART_START_ALPHA:
6760 try 6760 try
6761 { 6761 {
6762 tempf = (float)rules.GetLSLFloatItem(i + 1); 6762 tempf = (float)rules.GetLSLFloatItem(i + 1);
6763 } 6763 }
6764 catch(InvalidCastException) 6764 catch(InvalidCastException)
6765 { 6765 {
6766 Error(originFunc, string.Format("Error running rule PSYS_PART_START_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); 6766 Error(originFunc, string.Format("Error running rule PSYS_PART_START_ALPHA: arg #{0} - parameter 1 must be float", i + 1));
6767 return; 6767 return;
6768 } 6768 }
6769 prules.PartStartColor.A = tempf; 6769 prules.PartStartColor.A = tempf;
6770 break; 6770 break;
6771 6771
6772 case (int)ScriptBaseClass.PSYS_PART_END_COLOR: 6772 case (int)ScriptBaseClass.PSYS_PART_END_COLOR:
6773 try 6773 try
6774 { 6774 {
6775 tempv = rules.GetVector3Item(i + 1); 6775 tempv = rules.GetVector3Item(i + 1);
6776 } 6776 }
6777 catch(InvalidCastException) 6777 catch(InvalidCastException)
6778 { 6778 {
6779 Error(originFunc, string.Format("Error running rule PSYS_PART_END_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); 6779 Error(originFunc, string.Format("Error running rule PSYS_PART_END_COLOR: arg #{0} - parameter 1 must be vector", i + 1));
6780 return; 6780 return;
6781 } 6781 }
6782 prules.PartEndColor.R = (float)tempv.x; 6782 prules.PartEndColor.R = (float)tempv.x;
6783 prules.PartEndColor.G = (float)tempv.y; 6783 prules.PartEndColor.G = (float)tempv.y;
6784 prules.PartEndColor.B = (float)tempv.z; 6784 prules.PartEndColor.B = (float)tempv.z;
6785 break; 6785 break;
6786 6786
6787 case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: 6787 case (int)ScriptBaseClass.PSYS_PART_END_ALPHA:
6788 try 6788 try
6789 { 6789 {
6790 tempf = (float)rules.GetLSLFloatItem(i + 1); 6790 tempf = (float)rules.GetLSLFloatItem(i + 1);
6791 } 6791 }
6792 catch(InvalidCastException) 6792 catch(InvalidCastException)
6793 { 6793 {
6794 Error(originFunc, string.Format("Error running rule PSYS_PART_END_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); 6794 Error(originFunc, string.Format("Error running rule PSYS_PART_END_ALPHA: arg #{0} - parameter 1 must be float", i + 1));
6795 return; 6795 return;
6796 } 6796 }
6797 prules.PartEndColor.A = tempf; 6797 prules.PartEndColor.A = tempf;
6798 break; 6798 break;
6799 6799
6800 case (int)ScriptBaseClass.PSYS_PART_START_SCALE: 6800 case (int)ScriptBaseClass.PSYS_PART_START_SCALE:
6801 try 6801 try
6802 { 6802 {
6803 tempv = rules.GetVector3Item(i + 1); 6803 tempv = rules.GetVector3Item(i + 1);
6804 } 6804 }
6805 catch(InvalidCastException) 6805 catch(InvalidCastException)
6806 { 6806 {
6807 Error(originFunc, string.Format("Error running rule PSYS_PART_START_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); 6807 Error(originFunc, string.Format("Error running rule PSYS_PART_START_SCALE: arg #{0} - parameter 1 must be vector", i + 1));
6808 return; 6808 return;
6809 } 6809 }
6810 prules.PartStartScaleX = validParticleScale((float)tempv.x); 6810 prules.PartStartScaleX = validParticleScale((float)tempv.x);
6811 prules.PartStartScaleY = validParticleScale((float)tempv.y); 6811 prules.PartStartScaleY = validParticleScale((float)tempv.y);
6812 break; 6812 break;
6813 6813
6814 case (int)ScriptBaseClass.PSYS_PART_END_SCALE: 6814 case (int)ScriptBaseClass.PSYS_PART_END_SCALE:
6815 try 6815 try
6816 { 6816 {
6817 tempv = rules.GetVector3Item(i + 1); 6817 tempv = rules.GetVector3Item(i + 1);
6818 } 6818 }
6819 catch(InvalidCastException) 6819 catch(InvalidCastException)
6820 { 6820 {
6821 Error(originFunc, string.Format("Error running rule PSYS_PART_END_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); 6821 Error(originFunc, string.Format("Error running rule PSYS_PART_END_SCALE: arg #{0} - parameter 1 must be vector", i + 1));
6822 return; 6822 return;
6823 } 6823 }
6824 prules.PartEndScaleX = validParticleScale((float)tempv.x); 6824 prules.PartEndScaleX = validParticleScale((float)tempv.x);
6825 prules.PartEndScaleY = validParticleScale((float)tempv.y); 6825 prules.PartEndScaleY = validParticleScale((float)tempv.y);
6826 break; 6826 break;
6827 6827
6828 case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: 6828 case (int)ScriptBaseClass.PSYS_PART_MAX_AGE:
6829 try 6829 try
6830 { 6830 {
6831 tempf = (float)rules.GetLSLFloatItem(i + 1); 6831 tempf = (float)rules.GetLSLFloatItem(i + 1);
6832 } 6832 }
6833 catch(InvalidCastException) 6833 catch(InvalidCastException)
6834 { 6834 {
6835 Error(originFunc, string.Format("Error running rule PSYS_PART_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); 6835 Error(originFunc, string.Format("Error running rule PSYS_PART_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1));
6836 return; 6836 return;
6837 } 6837 }
6838 prules.PartMaxAge = tempf; 6838 prules.PartMaxAge = tempf;
6839 break; 6839 break;
6840 6840
6841 case (int)ScriptBaseClass.PSYS_SRC_ACCEL: 6841 case (int)ScriptBaseClass.PSYS_SRC_ACCEL:
6842 try 6842 try
6843 { 6843 {
6844 tempv = rules.GetVector3Item(i + 1); 6844 tempv = rules.GetVector3Item(i + 1);
6845 } 6845 }
6846 catch(InvalidCastException) 6846 catch(InvalidCastException)
6847 { 6847 {
6848 Error(originFunc, string.Format("Error running rule PSYS_SRC_ACCEL: arg #{0} - parameter 1 must be vector", i + 1)); 6848 Error(originFunc, string.Format("Error running rule PSYS_SRC_ACCEL: arg #{0} - parameter 1 must be vector", i + 1));
6849 return; 6849 return;
6850 } 6850 }
6851 prules.PartAcceleration.X = (float)tempv.x; 6851 prules.PartAcceleration.X = (float)tempv.x;
6852 prules.PartAcceleration.Y = (float)tempv.y; 6852 prules.PartAcceleration.Y = (float)tempv.y;
6853 prules.PartAcceleration.Z = (float)tempv.z; 6853 prules.PartAcceleration.Z = (float)tempv.z;
6854 break; 6854 break;
6855 6855
6856 case (int)ScriptBaseClass.PSYS_SRC_PATTERN: 6856 case (int)ScriptBaseClass.PSYS_SRC_PATTERN:
6857 try 6857 try
6858 { 6858 {
6859 tmpi = (int)rules.GetLSLIntegerItem(i + 1); 6859 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6860 } 6860 }
6861 catch(InvalidCastException) 6861 catch(InvalidCastException)
6862 { 6862 {
6863 Error(originFunc, string.Format("Error running rule PSYS_SRC_PATTERN: arg #{0} - parameter 1 must be integer", i + 1)); 6863 Error(originFunc, string.Format("Error running rule PSYS_SRC_PATTERN: arg #{0} - parameter 1 must be integer", i + 1));
6864 return; 6864 return;
6865 } 6865 }
6866 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; 6866 prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi;
6867 break; 6867 break;
6868 6868
6869 // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The 6869 // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The
6870 // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The 6870 // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The
6871 // client tells the difference between the two by looking at the 0x02 bit in 6871 // client tells the difference between the two by looking at the 0x02 bit in
6872 // the PartFlags variable. 6872 // the PartFlags variable.
6873 case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: 6873 case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE:
6874 try 6874 try
6875 { 6875 {
6876 tempf = (float)rules.GetLSLFloatItem(i + 1); 6876 tempf = (float)rules.GetLSLFloatItem(i + 1);
6877 } 6877 }
6878 catch(InvalidCastException) 6878 catch(InvalidCastException)
6879 { 6879 {
6880 Error(originFunc, string.Format("Error running rule PSYS_SRC_INNERANGLE: arg #{0} - parameter 1 must be float", i + 1)); 6880 Error(originFunc, string.Format("Error running rule PSYS_SRC_INNERANGLE: arg #{0} - parameter 1 must be float", i + 1));
6881 return; 6881 return;
6882 } 6882 }
6883 prules.InnerAngle = (float)tempf; 6883 prules.InnerAngle = (float)tempf;
6884 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. 6884 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
6885 break; 6885 break;
6886 6886
6887 case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: 6887 case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE:
6888 try 6888 try
6889 { 6889 {
6890 tempf = (float)rules.GetLSLFloatItem(i + 1); 6890 tempf = (float)rules.GetLSLFloatItem(i + 1);
6891 } 6891 }
6892 catch(InvalidCastException) 6892 catch(InvalidCastException)
6893 { 6893 {
6894 Error(originFunc, string.Format("Error running rule PSYS_SRC_OUTERANGLE: arg #{0} - parameter 1 must be float", i + 1)); 6894 Error(originFunc, string.Format("Error running rule PSYS_SRC_OUTERANGLE: arg #{0} - parameter 1 must be float", i + 1));
6895 return; 6895 return;
6896 } 6896 }
6897 prules.OuterAngle = (float)tempf; 6897 prules.OuterAngle = (float)tempf;
6898 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. 6898 prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off.
6899 break; 6899 break;
6900 6900
6901 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE: 6901 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE:
6902 try 6902 try
6903 { 6903 {
6904 tmpi = (int)rules.GetLSLIntegerItem(i + 1); 6904 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6905 } 6905 }
6906 catch(InvalidCastException) 6906 catch(InvalidCastException)
6907 { 6907 {
6908 Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_SOURCE: arg #{0} - parameter 1 must be integer", i + 1)); 6908 Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_SOURCE: arg #{0} - parameter 1 must be integer", i + 1));
6909 return; 6909 return;
6910 } 6910 }
6911 prules.BlendFuncSource = (byte)tmpi; 6911 prules.BlendFuncSource = (byte)tmpi;
6912 break; 6912 break;
6913 6913
6914 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST: 6914 case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST:
6915 try 6915 try
6916 { 6916 {
6917 tmpi = (int)rules.GetLSLIntegerItem(i + 1); 6917 tmpi = (int)rules.GetLSLIntegerItem(i + 1);
6918 } 6918 }
6919 catch(InvalidCastException) 6919 catch(InvalidCastException)
6920 { 6920 {
6921 Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_DEST: arg #{0} - parameter 1 must be integer", i + 1)); 6921 Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_DEST: arg #{0} - parameter 1 must be integer", i + 1));
6922 return; 6922 return;
6923 } 6923 }
6924 prules.BlendFuncDest = (byte)tmpi; 6924 prules.BlendFuncDest = (byte)tmpi;
6925 break; 6925 break;
6926 6926
6927 case (int)ScriptBaseClass.PSYS_PART_START_GLOW: 6927 case (int)ScriptBaseClass.PSYS_PART_START_GLOW:
6928 try 6928 try
6929 { 6929 {
6930 tempf = (float)rules.GetLSLFloatItem(i + 1); 6930 tempf = (float)rules.GetLSLFloatItem(i + 1);
6931 } 6931 }
6932 catch(InvalidCastException) 6932 catch(InvalidCastException)
6933 { 6933 {
6934 Error(originFunc, string.Format("Error running rule PSYS_PART_START_GLOW: arg #{0} - parameter 1 must be float", i + 1)); 6934 Error(originFunc, string.Format("Error running rule PSYS_PART_START_GLOW: arg #{0} - parameter 1 must be float", i + 1));
6935 return; 6935 return;
6936 } 6936 }
6937 prules.PartStartGlow = (float)tempf; 6937 prules.PartStartGlow = (float)tempf;
6938 break; 6938 break;
6939 6939
6940 case (int)ScriptBaseClass.PSYS_PART_END_GLOW: 6940 case (int)ScriptBaseClass.PSYS_PART_END_GLOW:
6941 try 6941 try
6942 { 6942 {
6943 tempf = (float)rules.GetLSLFloatItem(i + 1); 6943 tempf = (float)rules.GetLSLFloatItem(i + 1);
6944 } 6944 }
6945 catch(InvalidCastException) 6945 catch(InvalidCastException)
6946 { 6946 {
6947 Error(originFunc, string.Format("Error running rule PSYS_PART_END_GLOW: arg #{0} - parameter 1 must be float", i + 1)); 6947 Error(originFunc, string.Format("Error running rule PSYS_PART_END_GLOW: arg #{0} - parameter 1 must be float", i + 1));
6948 return; 6948 return;
6949 } 6949 }
6950 prules.PartEndGlow = (float)tempf; 6950 prules.PartEndGlow = (float)tempf;
6951 break; 6951 break;
6952 6952
6953 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: 6953 case (int)ScriptBaseClass.PSYS_SRC_TEXTURE:
6954 try 6954 try
6955 { 6955 {
6956 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1)); 6956 prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1));
6957 } 6957 }
6958 catch(InvalidCastException) 6958 catch(InvalidCastException)
6959 { 6959 {
6960 Error(originFunc, string.Format("Error running rule PSYS_SRC_TEXTURE: arg #{0} - parameter 1 must be string or key", i + 1)); 6960 Error(originFunc, string.Format("Error running rule PSYS_SRC_TEXTURE: arg #{0} - parameter 1 must be string or key", i + 1));
6961 return; 6961 return;
6962 } 6962 }
6963 break; 6963 break;
6964 6964
6965 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: 6965 case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE:
6966 try 6966 try
6967 { 6967 {
6968 tempf = (float)rules.GetLSLFloatItem(i + 1); 6968 tempf = (float)rules.GetLSLFloatItem(i + 1);
6969 } 6969 }
6970 catch(InvalidCastException) 6970 catch(InvalidCastException)
6971 { 6971 {
6972 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RATE: arg #{0} - parameter 1 must be float", i + 1)); 6972 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RATE: arg #{0} - parameter 1 must be float", i + 1));
6973 return; 6973 return;
6974 } 6974 }
6975 prules.BurstRate = (float)tempf; 6975 prules.BurstRate = (float)tempf;
6976 break; 6976 break;
6977 6977
6978 case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: 6978 case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT:
6979 try 6979 try
6980 { 6980 {
6981 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); 6981 prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1);
6982 } 6982 }
6983 catch(InvalidCastException) 6983 catch(InvalidCastException)
6984 { 6984 {
6985 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_PART_COUNT: arg #{0} - parameter 1 must be integer", i + 1)); 6985 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_PART_COUNT: arg #{0} - parameter 1 must be integer", i + 1));
6986 return; 6986 return;
6987 } 6987 }
6988 break; 6988 break;
6989 6989
6990 case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: 6990 case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS:
6991 try 6991 try
6992 { 6992 {
6993 tempf = (float)rules.GetLSLFloatItem(i + 1); 6993 tempf = (float)rules.GetLSLFloatItem(i + 1);
6994 } 6994 }
6995 catch(InvalidCastException) 6995 catch(InvalidCastException)
6996 { 6996 {
6997 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RADIUS: arg #{0} - parameter 1 must be float", i + 1)); 6997 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RADIUS: arg #{0} - parameter 1 must be float", i + 1));
6998 return; 6998 return;
6999 } 6999 }
7000 prules.BurstRadius = (float)tempf; 7000 prules.BurstRadius = (float)tempf;
7001 break; 7001 break;
7002 7002
7003 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: 7003 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN:
7004 try 7004 try
7005 { 7005 {
7006 tempf = (float)rules.GetLSLFloatItem(i + 1); 7006 tempf = (float)rules.GetLSLFloatItem(i + 1);
7007 } 7007 }
7008 catch(InvalidCastException) 7008 catch(InvalidCastException)
7009 { 7009 {
7010 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MIN: arg #{0} - parameter 1 must be float", i + 1)); 7010 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MIN: arg #{0} - parameter 1 must be float", i + 1));
7011 return; 7011 return;
7012 } 7012 }
7013 prules.BurstSpeedMin = (float)tempf; 7013 prules.BurstSpeedMin = (float)tempf;
7014 break; 7014 break;
7015 7015
7016 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: 7016 case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX:
7017 try 7017 try
7018 { 7018 {
7019 tempf = (float)rules.GetLSLFloatItem(i + 1); 7019 tempf = (float)rules.GetLSLFloatItem(i + 1);
7020 } 7020 }
7021 catch(InvalidCastException) 7021 catch(InvalidCastException)
7022 { 7022 {
7023 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MAX: arg #{0} - parameter 1 must be float", i + 1)); 7023 Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MAX: arg #{0} - parameter 1 must be float", i + 1));
7024 return; 7024 return;
7025 } 7025 }
7026 prules.BurstSpeedMax = (float)tempf; 7026 prules.BurstSpeedMax = (float)tempf;
7027 break; 7027 break;
7028 7028
7029 case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: 7029 case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE:
7030 try 7030 try
7031 { 7031 {
7032 tempf = (float)rules.GetLSLFloatItem(i + 1); 7032 tempf = (float)rules.GetLSLFloatItem(i + 1);
7033 } 7033 }
7034 catch(InvalidCastException) 7034 catch(InvalidCastException)
7035 { 7035 {
7036 Error(originFunc, string.Format("Error running rule PSYS_SRC_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); 7036 Error(originFunc, string.Format("Error running rule PSYS_SRC_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1));
7037 return; 7037 return;
7038 } 7038 }
7039 prules.MaxAge = (float)tempf; 7039 prules.MaxAge = (float)tempf;
7040 break; 7040 break;
7041 7041
7042 case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY: 7042 case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY:
7043 UUID key = UUID.Zero; 7043 UUID key = UUID.Zero;
7044 if (UUID.TryParse(rules.Data[i + 1].ToString(), out key)) 7044 if (UUID.TryParse(rules.Data[i + 1].ToString(), out key))
7045 { 7045 {
7046 prules.Target = key; 7046 prules.Target = key;
7047 } 7047 }
7048 else 7048 else
7049 { 7049 {
7050 prules.Target = part.UUID; 7050 prules.Target = part.UUID;
7051 } 7051 }
7052 break; 7052 break;
7053 7053
7054 case (int)ScriptBaseClass.PSYS_SRC_OMEGA: 7054 case (int)ScriptBaseClass.PSYS_SRC_OMEGA:
7055 // AL: This is an assumption, since it is the only thing that would match. 7055 // AL: This is an assumption, since it is the only thing that would match.
7056 try 7056 try
7057 { 7057 {
7058 tempv = rules.GetVector3Item(i + 1); 7058 tempv = rules.GetVector3Item(i + 1);
7059 } 7059 }
7060 catch(InvalidCastException) 7060 catch(InvalidCastException)
7061 { 7061 {
7062 Error(originFunc, string.Format("Error running rule PSYS_SRC_OMEGA: arg #{0} - parameter 1 must be vector", i + 1)); 7062 Error(originFunc, string.Format("Error running rule PSYS_SRC_OMEGA: arg #{0} - parameter 1 must be vector", i + 1));
7063 return; 7063 return;
7064 } 7064 }
7065 prules.AngularVelocity.X = (float)tempv.x; 7065 prules.AngularVelocity.X = (float)tempv.x;
7066 prules.AngularVelocity.Y = (float)tempv.y; 7066 prules.AngularVelocity.Y = (float)tempv.y;
7067 prules.AngularVelocity.Z = (float)tempv.z; 7067 prules.AngularVelocity.Z = (float)tempv.z;
7068 break; 7068 break;
7069 7069
7070 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: 7070 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN:
7071 try 7071 try
7072 { 7072 {
7073 tempf = (float)rules.GetLSLFloatItem(i + 1); 7073 tempf = (float)rules.GetLSLFloatItem(i + 1);
7074 } 7074 }
7075 catch(InvalidCastException) 7075 catch(InvalidCastException)
7076 { 7076 {
7077 Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_BEGIN: arg #{0} - parameter 1 must be float", i + 1)); 7077 Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_BEGIN: arg #{0} - parameter 1 must be float", i + 1));
7078 return; 7078 return;
7079 } 7079 }
7080 prules.InnerAngle = (float)tempf; 7080 prules.InnerAngle = (float)tempf;
7081 prules.PartFlags |= 0x02; // Set new angle format. 7081 prules.PartFlags |= 0x02; // Set new angle format.
7082 break; 7082 break;
7083 7083
7084 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: 7084 case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END:
7085 try 7085 try
7086 { 7086 {
7087 tempf = (float)rules.GetLSLFloatItem(i + 1); 7087 tempf = (float)rules.GetLSLFloatItem(i + 1);
7088 } 7088 }
7089 catch (InvalidCastException) 7089 catch (InvalidCastException)
7090 { 7090 {
7091 Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_END: arg #{0} - parameter 1 must be float", i + 1)); 7091 Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_END: arg #{0} - parameter 1 must be float", i + 1));
7092 return; 7092 return;
7093 } 7093 }
7094 prules.OuterAngle = (float)tempf; 7094 prules.OuterAngle = (float)tempf;
7095 prules.PartFlags |= 0x02; // Set new angle format. 7095 prules.PartFlags |= 0x02; // Set new angle format.
7096 break; 7096 break;
7097 } 7097 }
7098 7098
7099 } 7099 }
7100 prules.CRC = 1; 7100 prules.CRC = 1;
7101 7101
7102 part.AddNewParticleSystem(prules); 7102 part.AddNewParticleSystem(prules);
7103 part.ParentGroup.HasGroupChanged = true; 7103 part.ParentGroup.HasGroupChanged = true;
7104 } 7104 }
7105 part.SendFullUpdateToAllClients(); 7105 part.SendFullUpdateToAllClients();
7106 } 7106 }
7107 7107
7108 private float validParticleScale(float value) 7108 private float validParticleScale(float value)
7109 { 7109 {
7110 if (value > 4.0f) return 4.0f; 7110 if (value > 4.0f) return 4.0f;
7111 return value; 7111 return value;
7112 } 7112 }
7113 7113
7114 public void llGroundRepel(double height, int water, double tau) 7114 public void llGroundRepel(double height, int water, double tau)
7115 { 7115 {
7116 m_host.AddScriptLPS(1); 7116 m_host.AddScriptLPS(1);
7117 if (m_host.PhysActor != null) 7117 if (m_host.PhysActor != null)
7118 { 7118 {
7119 float ground = (float)llGround(new LSL_Types.Vector3(0, 0, 0)); 7119 float ground = (float)llGround(new LSL_Types.Vector3(0, 0, 0));
7120 float waterLevel = (float)llWater(new LSL_Types.Vector3(0, 0, 0)); 7120 float waterLevel = (float)llWater(new LSL_Types.Vector3(0, 0, 0));
7121 PIDHoverType hoverType = PIDHoverType.Ground; 7121 PIDHoverType hoverType = PIDHoverType.Ground;
7122 if (water != 0) 7122 if (water != 0)
7123 { 7123 {
7124 hoverType = PIDHoverType.GroundAndWater; 7124 hoverType = PIDHoverType.GroundAndWater;
7125 if (ground < waterLevel) 7125 if (ground < waterLevel)
7126 height += waterLevel; 7126 height += waterLevel;
7127 else 7127 else
7128 height += ground; 7128 height += ground;
7129 } 7129 }
7130 else 7130 else
7131 { 7131 {
7132 height += ground; 7132 height += ground;
7133 } 7133 }
7134 7134
7135 m_host.SetHoverHeight((float)height, hoverType, (float)tau); 7135 m_host.SetHoverHeight((float)height, hoverType, (float)tau);
7136 } 7136 }
7137 } 7137 }
7138 7138
7139 public void llGiveInventoryList(string destination, string category, LSL_List inventory) 7139 public void llGiveInventoryList(string destination, string category, LSL_List inventory)
7140 { 7140 {
7141 m_host.AddScriptLPS(1); 7141 m_host.AddScriptLPS(1);
7142 7142
7143 UUID destID; 7143 UUID destID;
7144 if (!UUID.TryParse(destination, out destID)) 7144 if (!UUID.TryParse(destination, out destID))
7145 return; 7145 return;
7146 7146
7147 List<UUID> itemList = new List<UUID>(); 7147 List<UUID> itemList = new List<UUID>();
7148 7148
7149 foreach (Object item in inventory.Data) 7149 foreach (Object item in inventory.Data)
7150 { 7150 {
7151 string rawItemString = item.ToString(); 7151 string rawItemString = item.ToString();
7152 7152
7153 UUID itemID; 7153 UUID itemID;
7154 if (UUID.TryParse(rawItemString, out itemID)) 7154 if (UUID.TryParse(rawItemString, out itemID))
7155 { 7155 {
7156 itemList.Add(itemID); 7156 itemList.Add(itemID);
7157 } 7157 }
7158 else 7158 else
7159 { 7159 {
7160 TaskInventoryItem taskItem = m_host.Inventory.GetInventoryItem(rawItemString); 7160 TaskInventoryItem taskItem = m_host.Inventory.GetInventoryItem(rawItemString);
7161 7161
7162 if (taskItem != null) 7162 if (taskItem != null)
7163 itemList.Add(taskItem.ItemID); 7163 itemList.Add(taskItem.ItemID);
7164 } 7164 }
7165 } 7165 }
7166 7166
7167 if (itemList.Count == 0) 7167 if (itemList.Count == 0)
7168 return; 7168 return;
7169 7169
7170 UUID folderID = m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList); 7170 UUID folderID = m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList);
7171 7171
7172 if (folderID == UUID.Zero) 7172 if (folderID == UUID.Zero)
7173 return; 7173 return;
7174 7174
7175 if (m_TransferModule != null) 7175 if (m_TransferModule != null)
7176 { 7176 {
7177 byte[] bucket = new byte[] { (byte)AssetType.Folder }; 7177 byte[] bucket = new byte[] { (byte)AssetType.Folder };
7178 7178
7179 Vector3 pos = m_host.AbsolutePosition; 7179 Vector3 pos = m_host.AbsolutePosition;
7180 7180
7181 GridInstantMessage msg = new GridInstantMessage(World, 7181 GridInstantMessage msg = new GridInstantMessage(World,
7182 m_host.OwnerID, m_host.Name, destID, 7182 m_host.OwnerID, m_host.Name, destID,
7183 (byte)InstantMessageDialog.TaskInventoryOffered, 7183 (byte)InstantMessageDialog.TaskInventoryOffered,
7184 false, string.Format("'{0}'", category), 7184 false, string.Format("'{0}'", category),
7185// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 7185// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06
7186// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), 7186// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z),
7187 folderID, false, pos, 7187 folderID, false, pos,
7188 bucket, false); 7188 bucket, false);
7189 7189
7190 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); 7190 m_TransferModule.SendInstantMessage(msg, delegate(bool success) {});
7191 } 7191 }
7192 } 7192 }
7193 7193
7194 public void llSetVehicleType(int type) 7194 public void llSetVehicleType(int type)
7195 { 7195 {
7196 m_host.AddScriptLPS(1); 7196 m_host.AddScriptLPS(1);
7197 7197
7198 if (!m_host.ParentGroup.IsDeleted) 7198 if (!m_host.ParentGroup.IsDeleted)
7199 { 7199 {
7200 m_host.ParentGroup.RootPart.SetVehicleType(type); 7200 m_host.ParentGroup.RootPart.SetVehicleType(type);
7201 } 7201 }
7202 } 7202 }
7203 7203
7204 //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in 7204 //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
7205 //CFK 9/28: so these are not complete yet. 7205 //CFK 9/28: so these are not complete yet.
7206 public void llSetVehicleFloatParam(int param, LSL_Float value) 7206 public void llSetVehicleFloatParam(int param, LSL_Float value)
7207 { 7207 {
7208 m_host.AddScriptLPS(1); 7208 m_host.AddScriptLPS(1);
7209 7209
7210 if (!m_host.ParentGroup.IsDeleted) 7210 if (!m_host.ParentGroup.IsDeleted)
7211 { 7211 {
7212 m_host.ParentGroup.RootPart.SetVehicleFloatParam(param, (float)value); 7212 m_host.ParentGroup.RootPart.SetVehicleFloatParam(param, (float)value);
7213 } 7213 }
7214 } 7214 }
7215 7215
7216 //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in 7216 //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
7217 //CFK 9/28: so these are not complete yet. 7217 //CFK 9/28: so these are not complete yet.
7218 public void llSetVehicleVectorParam(int param, LSL_Vector vec) 7218 public void llSetVehicleVectorParam(int param, LSL_Vector vec)
7219 { 7219 {
7220 m_host.AddScriptLPS(1); 7220 m_host.AddScriptLPS(1);
7221 7221
7222 if (!m_host.ParentGroup.IsDeleted) 7222 if (!m_host.ParentGroup.IsDeleted)
7223 { 7223 {
7224 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); 7224 m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec);
7225 } 7225 }
7226 } 7226 }
7227 7227
7228 //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in 7228 //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in
7229 //CFK 9/28: so these are not complete yet. 7229 //CFK 9/28: so these are not complete yet.
7230 public void llSetVehicleRotationParam(int param, LSL_Rotation rot) 7230 public void llSetVehicleRotationParam(int param, LSL_Rotation rot)
7231 { 7231 {
7232 m_host.AddScriptLPS(1); 7232 m_host.AddScriptLPS(1);
7233 7233
7234 if (!m_host.ParentGroup.IsDeleted) 7234 if (!m_host.ParentGroup.IsDeleted)
7235 { 7235 {
7236 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); 7236 m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot);
7237 } 7237 }
7238 } 7238 }
7239 7239
7240 public void llSetVehicleFlags(int flags) 7240 public void llSetVehicleFlags(int flags)
7241 { 7241 {
7242 m_host.AddScriptLPS(1); 7242 m_host.AddScriptLPS(1);
7243 7243
7244 if (!m_host.ParentGroup.IsDeleted) 7244 if (!m_host.ParentGroup.IsDeleted)
7245 { 7245 {
7246 m_host.ParentGroup.RootPart.SetVehicleFlags(flags, false); 7246 m_host.ParentGroup.RootPart.SetVehicleFlags(flags, false);
7247 } 7247 }
7248 } 7248 }
7249 7249
7250 public void llRemoveVehicleFlags(int flags) 7250 public void llRemoveVehicleFlags(int flags)
7251 { 7251 {
7252 m_host.AddScriptLPS(1); 7252 m_host.AddScriptLPS(1);
7253 7253
7254 if (!m_host.ParentGroup.IsDeleted) 7254 if (!m_host.ParentGroup.IsDeleted)
7255 { 7255 {
7256 m_host.ParentGroup.RootPart.SetVehicleFlags(flags, true); 7256 m_host.ParentGroup.RootPart.SetVehicleFlags(flags, true);
7257 } 7257 }
7258 } 7258 }
7259 7259
7260 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) 7260 protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot)
7261 { 7261 {
7262 part.SitTargetPosition = offset; 7262 part.SitTargetPosition = offset;
7263 part.SitTargetOrientation = rot; 7263 part.SitTargetOrientation = rot;
7264 part.ParentGroup.HasGroupChanged = true; 7264 part.ParentGroup.HasGroupChanged = true;
7265 } 7265 }
7266 7266
7267 public void llSitTarget(LSL_Vector offset, LSL_Rotation rot) 7267 public void llSitTarget(LSL_Vector offset, LSL_Rotation rot)
7268 { 7268 {
7269 m_host.AddScriptLPS(1); 7269 m_host.AddScriptLPS(1);
7270 SitTarget(m_host, offset, rot); 7270 SitTarget(m_host, offset, rot);
7271 } 7271 }
7272 7272
7273 public void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot) 7273 public void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot)
7274 { 7274 {
7275 m_host.AddScriptLPS(1); 7275 m_host.AddScriptLPS(1);
7276 if (link == ScriptBaseClass.LINK_ROOT) 7276 if (link == ScriptBaseClass.LINK_ROOT)
7277 SitTarget(m_host.ParentGroup.RootPart, offset, rot); 7277 SitTarget(m_host.ParentGroup.RootPart, offset, rot);
7278 else if (link == ScriptBaseClass.LINK_THIS) 7278 else if (link == ScriptBaseClass.LINK_THIS)
7279 SitTarget(m_host, offset, rot); 7279 SitTarget(m_host, offset, rot);
7280 else 7280 else
7281 { 7281 {
7282 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); 7282 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
7283 if (null != part) 7283 if (null != part)
7284 { 7284 {
7285 SitTarget(part, offset, rot); 7285 SitTarget(part, offset, rot);
7286 } 7286 }
7287 } 7287 }
7288 } 7288 }
7289 7289
7290 public LSL_String llAvatarOnSitTarget() 7290 public LSL_String llAvatarOnSitTarget()
7291 { 7291 {
7292 m_host.AddScriptLPS(1); 7292 m_host.AddScriptLPS(1);
7293 return m_host.SitTargetAvatar.ToString(); 7293 return m_host.SitTargetAvatar.ToString();
7294 } 7294 }
7295 7295
7296 // http://wiki.secondlife.com/wiki/LlAvatarOnLinkSitTarget 7296 // http://wiki.secondlife.com/wiki/LlAvatarOnLinkSitTarget
7297 public LSL_String llAvatarOnLinkSitTarget(int linknum) 7297 public LSL_String llAvatarOnLinkSitTarget(int linknum)
7298 { 7298 {
7299 m_host.AddScriptLPS(1); 7299 m_host.AddScriptLPS(1);
7300 if(linknum == ScriptBaseClass.LINK_SET || 7300 if(linknum == ScriptBaseClass.LINK_SET ||
7301 linknum == ScriptBaseClass.LINK_ALL_CHILDREN || 7301 linknum == ScriptBaseClass.LINK_ALL_CHILDREN ||
7302 linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); 7302 linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString();
7303 7303
7304 List<SceneObjectPart> parts = GetLinkParts(linknum); 7304 List<SceneObjectPart> parts = GetLinkParts(linknum);
7305 if (parts.Count == 0) return UUID.Zero.ToString(); 7305 if (parts.Count == 0) return UUID.Zero.ToString();
7306 return parts[0].SitTargetAvatar.ToString(); 7306 return parts[0].SitTargetAvatar.ToString();
7307 } 7307 }
7308 7308
7309 7309
7310 public void llAddToLandPassList(string avatar, double hours) 7310 public void llAddToLandPassList(string avatar, double hours)
7311 { 7311 {
7312 m_host.AddScriptLPS(1); 7312 m_host.AddScriptLPS(1);
7313 UUID key; 7313 UUID key;
7314 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 7314 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
7315 7315
7316 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 7316 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
7317 { 7317 {
7318 int expires = 0; 7318 int expires = 0;
7319 if (hours != 0) 7319 if (hours != 0)
7320 expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours); 7320 expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours);
7321 7321
7322 if (UUID.TryParse(avatar, out key)) 7322 if (UUID.TryParse(avatar, out key))
7323 { 7323 {
7324 int idx = land.LandData.ParcelAccessList.FindIndex( 7324 int idx = land.LandData.ParcelAccessList.FindIndex(
7325 delegate(LandAccessEntry e) 7325 delegate(LandAccessEntry e)
7326 { 7326 {
7327 if (e.AgentID == key && e.Flags == AccessList.Access) 7327 if (e.AgentID == key && e.Flags == AccessList.Access)
7328 return true; 7328 return true;
7329 return false; 7329 return false;
7330 }); 7330 });
7331 7331
7332 if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires))) 7332 if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires)))
7333 return; 7333 return;
7334 7334
7335 if (idx != -1) 7335 if (idx != -1)
7336 land.LandData.ParcelAccessList.RemoveAt(idx); 7336 land.LandData.ParcelAccessList.RemoveAt(idx);
7337 7337
7338 LandAccessEntry entry = new LandAccessEntry(); 7338 LandAccessEntry entry = new LandAccessEntry();
7339 7339
7340 entry.AgentID = key; 7340 entry.AgentID = key;
7341 entry.Flags = AccessList.Access; 7341 entry.Flags = AccessList.Access;
7342 entry.Expires = expires; 7342 entry.Expires = expires;
7343 7343
7344 land.LandData.ParcelAccessList.Add(entry); 7344 land.LandData.ParcelAccessList.Add(entry);
7345 7345
7346 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 7346 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
7347 } 7347 }
7348 } 7348 }
7349 ScriptSleep(m_sleepMsOnAddToLandPassList); 7349 ScriptSleep(m_sleepMsOnAddToLandPassList);
7350 } 7350 }
7351 7351
7352 public void llSetTouchText(string text) 7352 public void llSetTouchText(string text)
7353 { 7353 {
7354 m_host.AddScriptLPS(1); 7354 m_host.AddScriptLPS(1);
7355 m_host.TouchName = text; 7355 m_host.TouchName = text;
7356 } 7356 }
7357 7357
7358 public void llSetSitText(string text) 7358 public void llSetSitText(string text)
7359 { 7359 {
7360 m_host.AddScriptLPS(1); 7360 m_host.AddScriptLPS(1);
7361 m_host.SitName = text; 7361 m_host.SitName = text;
7362 } 7362 }
7363 7363
7364 public void llSetCameraEyeOffset(LSL_Vector offset) 7364 public void llSetCameraEyeOffset(LSL_Vector offset)
7365 { 7365 {
7366 m_host.AddScriptLPS(1); 7366 m_host.AddScriptLPS(1);
7367 m_host.SetCameraEyeOffset(offset); 7367 m_host.SetCameraEyeOffset(offset);
7368 7368
7369 if (m_host.ParentGroup.RootPart.GetCameraEyeOffset() == Vector3.Zero) 7369 if (m_host.ParentGroup.RootPart.GetCameraEyeOffset() == Vector3.Zero)
7370 m_host.ParentGroup.RootPart.SetCameraEyeOffset(offset); 7370 m_host.ParentGroup.RootPart.SetCameraEyeOffset(offset);
7371 } 7371 }
7372 7372
7373 public void llSetCameraAtOffset(LSL_Vector offset) 7373 public void llSetCameraAtOffset(LSL_Vector offset)
7374 { 7374 {
7375 m_host.AddScriptLPS(1); 7375 m_host.AddScriptLPS(1);
7376 m_host.SetCameraAtOffset(offset); 7376 m_host.SetCameraAtOffset(offset);
7377 7377
7378 if (m_host.ParentGroup.RootPart.GetCameraAtOffset() == Vector3.Zero) 7378 if (m_host.ParentGroup.RootPart.GetCameraAtOffset() == Vector3.Zero)
7379 m_host.ParentGroup.RootPart.SetCameraAtOffset(offset); 7379 m_host.ParentGroup.RootPart.SetCameraAtOffset(offset);
7380 } 7380 }
7381 7381
7382 public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at) 7382 public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at)
7383 { 7383 {
7384 m_host.AddScriptLPS(1); 7384 m_host.AddScriptLPS(1);
7385 7385
7386 if (link == ScriptBaseClass.LINK_SET || 7386 if (link == ScriptBaseClass.LINK_SET ||
7387 link == ScriptBaseClass.LINK_ALL_CHILDREN || 7387 link == ScriptBaseClass.LINK_ALL_CHILDREN ||
7388 link == ScriptBaseClass.LINK_ALL_OTHERS) return; 7388 link == ScriptBaseClass.LINK_ALL_OTHERS) return;
7389 7389
7390 SceneObjectPart part = null; 7390 SceneObjectPart part = null;
7391 7391
7392 switch (link) 7392 switch (link)
7393 { 7393 {
7394 case ScriptBaseClass.LINK_ROOT: 7394 case ScriptBaseClass.LINK_ROOT:
7395 part = m_host.ParentGroup.RootPart; 7395 part = m_host.ParentGroup.RootPart;
7396 break; 7396 break;
7397 case ScriptBaseClass.LINK_THIS: 7397 case ScriptBaseClass.LINK_THIS:
7398 part = m_host; 7398 part = m_host;
7399 break; 7399 break;
7400 default: 7400 default:
7401 part = m_host.ParentGroup.GetLinkNumPart(link); 7401 part = m_host.ParentGroup.GetLinkNumPart(link);
7402 break; 7402 break;
7403 } 7403 }
7404 7404
7405 if (null != part) 7405 if (null != part)
7406 { 7406 {
7407 part.SetCameraEyeOffset(eye); 7407 part.SetCameraEyeOffset(eye);
7408 part.SetCameraAtOffset(at); 7408 part.SetCameraAtOffset(at);
7409 } 7409 }
7410 } 7410 }
7411 7411
7412 public LSL_String llDumpList2String(LSL_List src, string seperator) 7412 public LSL_String llDumpList2String(LSL_List src, string seperator)
7413 { 7413 {
7414 m_host.AddScriptLPS(1); 7414 m_host.AddScriptLPS(1);
7415 if (src.Length == 0) 7415 if (src.Length == 0)
7416 { 7416 {
7417 return String.Empty; 7417 return String.Empty;
7418 } 7418 }
7419 string ret = String.Empty; 7419 string ret = String.Empty;
7420 foreach (object o in src.Data) 7420 foreach (object o in src.Data)
7421 { 7421 {
7422 ret = ret + o.ToString() + seperator; 7422 ret = ret + o.ToString() + seperator;
7423 } 7423 }
7424 ret = ret.Substring(0, ret.Length - seperator.Length); 7424 ret = ret.Substring(0, ret.Length - seperator.Length);
7425 return ret; 7425 return ret;
7426 } 7426 }
7427 7427
7428 public LSL_Integer llScriptDanger(LSL_Vector pos) 7428 public LSL_Integer llScriptDanger(LSL_Vector pos)
7429 { 7429 {
7430 m_host.AddScriptLPS(1); 7430 m_host.AddScriptLPS(1);
7431 bool result = World.ScriptDanger(m_host.LocalId, pos); 7431 bool result = World.ScriptDanger(m_host.LocalId, pos);
7432 if (result) 7432 if (result)
7433 { 7433 {
7434 return 1; 7434 return 1;
7435 } 7435 }
7436 else 7436 else
7437 { 7437 {
7438 return 0; 7438 return 0;
7439 } 7439 }
7440 7440
7441 } 7441 }
7442 7442
7443 public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel) 7443 public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel)
7444 { 7444 {
7445 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 7445 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
7446 7446
7447 if (dm == null) 7447 if (dm == null)
7448 return; 7448 return;
7449 7449
7450 m_host.AddScriptLPS(1); 7450 m_host.AddScriptLPS(1);
7451 UUID av = new UUID(); 7451 UUID av = new UUID();
7452 if (!UUID.TryParse(avatar,out av)) 7452 if (!UUID.TryParse(avatar,out av))
7453 { 7453 {
7454 Error("llDialog", "First parameter must be a key"); 7454 Error("llDialog", "First parameter must be a key");
7455 return; 7455 return;
7456 } 7456 }
7457 if (buttons.Length < 1) 7457 if (buttons.Length < 1)
7458 { 7458 {
7459 Error("llDialog", "At least 1 button must be shown"); 7459 Error("llDialog", "At least 1 button must be shown");
7460 return; 7460 return;
7461 } 7461 }
7462 if (buttons.Length > 12) 7462 if (buttons.Length > 12)
7463 { 7463 {
7464 Error("llDialog", "No more than 12 buttons can be shown"); 7464 Error("llDialog", "No more than 12 buttons can be shown");
7465 return; 7465 return;
7466 } 7466 }
7467 string[] buts = new string[buttons.Length]; 7467 string[] buts = new string[buttons.Length];
7468 for (int i = 0; i < buttons.Length; i++) 7468 for (int i = 0; i < buttons.Length; i++)
7469 { 7469 {
7470 if (buttons.Data[i].ToString() == String.Empty) 7470 if (buttons.Data[i].ToString() == String.Empty)
7471 { 7471 {
7472 Error("llDialog", "Button label cannot be blank"); 7472 Error("llDialog", "Button label cannot be blank");
7473 return; 7473 return;
7474 } 7474 }
7475 if (buttons.Data[i].ToString().Length > 24) 7475 if (buttons.Data[i].ToString().Length > 24)
7476 { 7476 {
7477 Error("llDialog", "Button label cannot be longer than 24 characters"); 7477 Error("llDialog", "Button label cannot be longer than 24 characters");
7478 return; 7478 return;
7479 } 7479 }
7480 buts[i] = buttons.Data[i].ToString(); 7480 buts[i] = buttons.Data[i].ToString();
7481 } 7481 }
7482 7482
7483 dm.SendDialogToUser( 7483 dm.SendDialogToUser(
7484 av, m_host.Name, m_host.UUID, m_host.OwnerID, 7484 av, m_host.Name, m_host.UUID, m_host.OwnerID,
7485 message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); 7485 message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts);
7486 7486
7487 ScriptSleep(m_sleepMsOnDialog); 7487 ScriptSleep(m_sleepMsOnDialog);
7488 } 7488 }
7489 7489
7490 public void llVolumeDetect(int detect) 7490 public void llVolumeDetect(int detect)
7491 { 7491 {
7492 m_host.AddScriptLPS(1); 7492 m_host.AddScriptLPS(1);
7493 7493
7494 if (!m_host.ParentGroup.IsDeleted) 7494 if (!m_host.ParentGroup.IsDeleted)
7495 m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0); 7495 m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0);
7496 } 7496 }
7497 7497
7498 public void llRemoteLoadScript(string target, string name, int running, int start_param) 7498 public void llRemoteLoadScript(string target, string name, int running, int start_param)
7499 { 7499 {
7500 m_host.AddScriptLPS(1); 7500 m_host.AddScriptLPS(1);
7501 Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead"); 7501 Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead");
7502 ScriptSleep(m_sleepMsOnRemoteLoadScript); 7502 ScriptSleep(m_sleepMsOnRemoteLoadScript);
7503 } 7503 }
7504 7504
7505 public void llSetRemoteScriptAccessPin(int pin) 7505 public void llSetRemoteScriptAccessPin(int pin)
7506 { 7506 {
7507 m_host.AddScriptLPS(1); 7507 m_host.AddScriptLPS(1);
7508 m_host.ScriptAccessPin = pin; 7508 m_host.ScriptAccessPin = pin;
7509 } 7509 }
7510 7510
7511 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) 7511 public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param)
7512 { 7512 {
7513 m_host.AddScriptLPS(1); 7513 m_host.AddScriptLPS(1);
7514 7514
7515 UUID destId = UUID.Zero; 7515 UUID destId = UUID.Zero;
7516 7516
7517 if (!UUID.TryParse(target, out destId)) 7517 if (!UUID.TryParse(target, out destId))
7518 { 7518 {
7519 Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'"); 7519 Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'");
7520 return; 7520 return;
7521 } 7521 }
7522 7522
7523 // target must be a different prim than the one containing the script 7523 // target must be a different prim than the one containing the script
7524 if (m_host.UUID == destId) 7524 if (m_host.UUID == destId)
7525 { 7525 {
7526 return; 7526 return;
7527 } 7527 }
7528 7528
7529 // copy the first script found with this inventory name 7529 // copy the first script found with this inventory name
7530 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 7530 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
7531 7531
7532 // make sure the object is a script 7532 // make sure the object is a script
7533 if (item == null || item.Type != 10) 7533 if (item == null || item.Type != 10)
7534 { 7534 {
7535 Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'"); 7535 Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'");
7536 return; 7536 return;
7537 } 7537 }
7538 7538
7539 // the rest of the permission checks are done in RezScript, so check the pin there as well 7539 // the rest of the permission checks are done in RezScript, so check the pin there as well
7540 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); 7540 World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param);
7541 7541
7542 // this will cause the delay even if the script pin or permissions were wrong - seems ok 7542 // this will cause the delay even if the script pin or permissions were wrong - seems ok
7543 ScriptSleep(m_sleepMsOnRemoteLoadScriptPin); 7543 ScriptSleep(m_sleepMsOnRemoteLoadScriptPin);
7544 } 7544 }
7545 7545
7546 public void llOpenRemoteDataChannel() 7546 public void llOpenRemoteDataChannel()
7547 { 7547 {
7548 m_host.AddScriptLPS(1); 7548 m_host.AddScriptLPS(1);
7549 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7549 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7550 if (xmlrpcMod != null && xmlrpcMod.IsEnabled()) 7550 if (xmlrpcMod != null && xmlrpcMod.IsEnabled())
7551 { 7551 {
7552 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); 7552 UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero);
7553 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); 7553 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
7554 if (xmlRpcRouter != null) 7554 if (xmlRpcRouter != null)
7555 { 7555 {
7556 string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName; 7556 string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName;
7557 7557
7558 xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID, 7558 xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID,
7559 m_item.ItemID, String.Format("http://{0}:{1}/", ExternalHostName, 7559 m_item.ItemID, String.Format("http://{0}:{1}/", ExternalHostName,
7560 xmlrpcMod.Port.ToString())); 7560 xmlrpcMod.Port.ToString()));
7561 } 7561 }
7562 object[] resobj = new object[] 7562 object[] resobj = new object[]
7563 { 7563 {
7564 new LSL_Integer(1), 7564 new LSL_Integer(1),
7565 new LSL_String(channelID.ToString()), 7565 new LSL_String(channelID.ToString()),
7566 new LSL_String(UUID.Zero.ToString()), 7566 new LSL_String(UUID.Zero.ToString()),
7567 new LSL_String(String.Empty), 7567 new LSL_String(String.Empty),
7568 new LSL_Integer(0), 7568 new LSL_Integer(0),
7569 new LSL_String(String.Empty) 7569 new LSL_String(String.Empty)
7570 }; 7570 };
7571 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj, 7571 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj,
7572 new DetectParams[0])); 7572 new DetectParams[0]));
7573 } 7573 }
7574 ScriptSleep(m_sleepMsOnOpenRemoteDataChannel); 7574 ScriptSleep(m_sleepMsOnOpenRemoteDataChannel);
7575 } 7575 }
7576 7576
7577 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) 7577 public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata)
7578 { 7578 {
7579 m_host.AddScriptLPS(1); 7579 m_host.AddScriptLPS(1);
7580 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7580 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7581 ScriptSleep(m_sleepMsOnSendRemoteData); 7581 ScriptSleep(m_sleepMsOnSendRemoteData);
7582 if (xmlrpcMod == null) 7582 if (xmlrpcMod == null)
7583 return ""; 7583 return "";
7584 return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); 7584 return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString();
7585 } 7585 }
7586 7586
7587 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) 7587 public void llRemoteDataReply(string channel, string message_id, string sdata, int idata)
7588 { 7588 {
7589 m_host.AddScriptLPS(1); 7589 m_host.AddScriptLPS(1);
7590 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7590 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7591 if (xmlrpcMod != null) 7591 if (xmlrpcMod != null)
7592 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); 7592 xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata);
7593 ScriptSleep(m_sleepMsOnRemoteDataReply); 7593 ScriptSleep(m_sleepMsOnRemoteDataReply);
7594 } 7594 }
7595 7595
7596 public void llCloseRemoteDataChannel(string channel) 7596 public void llCloseRemoteDataChannel(string channel)
7597 { 7597 {
7598 m_host.AddScriptLPS(1); 7598 m_host.AddScriptLPS(1);
7599 7599
7600 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); 7600 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
7601 if (xmlRpcRouter != null) 7601 if (xmlRpcRouter != null)
7602 { 7602 {
7603 xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID); 7603 xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID);
7604 } 7604 }
7605 7605
7606 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7606 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7607 if (xmlrpcMod != null) 7607 if (xmlrpcMod != null)
7608 xmlrpcMod.CloseXMLRPCChannel((UUID)channel); 7608 xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
7609 ScriptSleep(m_sleepMsOnCloseRemoteDataChannel); 7609 ScriptSleep(m_sleepMsOnCloseRemoteDataChannel);
7610 } 7610 }
7611 7611
7612 public LSL_String llMD5String(string src, int nonce) 7612 public LSL_String llMD5String(string src, int nonce)
7613 { 7613 {
7614 m_host.AddScriptLPS(1); 7614 m_host.AddScriptLPS(1);
7615 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); 7615 return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString()));
7616 } 7616 }
7617 7617
7618 public LSL_String llSHA1String(string src) 7618 public LSL_String llSHA1String(string src)
7619 { 7619 {
7620 m_host.AddScriptLPS(1); 7620 m_host.AddScriptLPS(1);
7621 return Util.SHA1Hash(src).ToLower(); 7621 return Util.SHA1Hash(src).ToLower();
7622 } 7622 }
7623 7623
7624 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7624 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
7625 { 7625 {
7626 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7626 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7627 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7627 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7628 7628
7629 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && 7629 if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT &&
7630 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && 7630 holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE &&
7631 holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE && 7631 holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE &&
7632 holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE) 7632 holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE)
7633 { 7633 {
7634 holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT; 7634 holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT;
7635 } 7635 }
7636 shapeBlock.PathCurve = pathcurve; 7636 shapeBlock.PathCurve = pathcurve;
7637 shapeBlock.ProfileCurve = (byte)holeshape; // Set the hole shape. 7637 shapeBlock.ProfileCurve = (byte)holeshape; // Set the hole shape.
7638 shapeBlock.ProfileCurve += profileshape; // Add in the profile shape. 7638 shapeBlock.ProfileCurve += profileshape; // Add in the profile shape.
7639 if (cut.x < 0f) 7639 if (cut.x < 0f)
7640 { 7640 {
7641 cut.x = 0f; 7641 cut.x = 0f;
7642 } 7642 }
7643 if (cut.x > 1f) 7643 if (cut.x > 1f)
7644 { 7644 {
7645 cut.x = 1f; 7645 cut.x = 1f;
7646 } 7646 }
7647 if (cut.y < 0f) 7647 if (cut.y < 0f)
7648 { 7648 {
7649 cut.y = 0f; 7649 cut.y = 0f;
7650 } 7650 }
7651 if (cut.y > 1f) 7651 if (cut.y > 1f)
7652 { 7652 {
7653 cut.y = 1f; 7653 cut.y = 1f;
7654 } 7654 }
7655 if (cut.y - cut.x < 0.02f) 7655 if (cut.y - cut.x < 0.02f)
7656 { 7656 {
7657 cut.x = cut.y - 0.02f; 7657 cut.x = cut.y - 0.02f;
7658 if (cut.x < 0.0f) 7658 if (cut.x < 0.0f)
7659 { 7659 {
7660 cut.x = 0.0f; 7660 cut.x = 0.0f;
7661 cut.y = 0.02f; 7661 cut.y = 0.02f;
7662 } 7662 }
7663 } 7663 }
7664 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); 7664 shapeBlock.ProfileBegin = (ushort)(50000 * cut.x);
7665 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y)); 7665 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y));
7666 if (hollow < 0f) 7666 if (hollow < 0f)
7667 { 7667 {
7668 hollow = 0f; 7668 hollow = 0f;
7669 } 7669 }
7670 // If the prim is a Cylinder, Prism, Sphere, Torus or Ring (or not a 7670 // If the prim is a Cylinder, Prism, Sphere, Torus or Ring (or not a
7671 // Box or Tube) and the hole shape is a square, hollow is limited to 7671 // Box or Tube) and the hole shape is a square, hollow is limited to
7672 // a max of 70%. The viewer performs its own check on this value but 7672 // a max of 70%. The viewer performs its own check on this value but
7673 // we need to do it here also so llGetPrimitiveParams can have access 7673 // we need to do it here also so llGetPrimitiveParams can have access
7674 // to the correct value. 7674 // to the correct value.
7675 if (profileshape != (byte)ProfileCurve.Square && 7675 if (profileshape != (byte)ProfileCurve.Square &&
7676 holeshape == (int)ScriptBaseClass.PRIM_HOLE_SQUARE) 7676 holeshape == (int)ScriptBaseClass.PRIM_HOLE_SQUARE)
7677 { 7677 {
7678 if (hollow > 0.70f) 7678 if (hollow > 0.70f)
7679 { 7679 {
7680 hollow = 0.70f; 7680 hollow = 0.70f;
7681 } 7681 }
7682 } 7682 }
7683 // Otherwise, hollow is limited to 99%. 7683 // Otherwise, hollow is limited to 99%.
7684 else 7684 else
7685 { 7685 {
7686 if (hollow > 0.99f) 7686 if (hollow > 0.99f)
7687 { 7687 {
7688 hollow = 0.99f; 7688 hollow = 0.99f;
7689 } 7689 }
7690 } 7690 }
7691 shapeBlock.ProfileHollow = (ushort)(50000 * hollow); 7691 shapeBlock.ProfileHollow = (ushort)(50000 * hollow);
7692 if (twist.x < -1.0f) 7692 if (twist.x < -1.0f)
7693 { 7693 {
7694 twist.x = -1.0f; 7694 twist.x = -1.0f;
7695 } 7695 }
7696 if (twist.x > 1.0f) 7696 if (twist.x > 1.0f)
7697 { 7697 {
7698 twist.x = 1.0f; 7698 twist.x = 1.0f;
7699 } 7699 }
7700 if (twist.y < -1.0f) 7700 if (twist.y < -1.0f)
7701 { 7701 {
7702 twist.y = -1.0f; 7702 twist.y = -1.0f;
7703 } 7703 }
7704 if (twist.y > 1.0f) 7704 if (twist.y > 1.0f)
7705 { 7705 {
7706 twist.y = 1.0f; 7706 twist.y = 1.0f;
7707 } 7707 }
7708 // A fairly large precision error occurs for some calculations, 7708 // A fairly large precision error occurs for some calculations,
7709 // if a float or double is directly cast to a byte or sbyte 7709 // if a float or double is directly cast to a byte or sbyte
7710 // variable, in both .Net and Mono. In .Net, coding 7710 // variable, in both .Net and Mono. In .Net, coding
7711 // "(sbyte)(float)(some expression)" corrects the precision 7711 // "(sbyte)(float)(some expression)" corrects the precision
7712 // errors. But this does not work for Mono. This longer coding 7712 // errors. But this does not work for Mono. This longer coding
7713 // form of creating a tempoary float variable from the 7713 // form of creating a tempoary float variable from the
7714 // expression first, then casting that variable to a byte or 7714 // expression first, then casting that variable to a byte or
7715 // sbyte, works for both .Net and Mono. These types of 7715 // sbyte, works for both .Net and Mono. These types of
7716 // assignments occur in SetPrimtiveBlockShapeParams and 7716 // assignments occur in SetPrimtiveBlockShapeParams and
7717 // SetPrimitiveShapeParams in support of llSetPrimitiveParams. 7717 // SetPrimitiveShapeParams in support of llSetPrimitiveParams.
7718 tempFloat = (float)(100.0d * twist.x); 7718 tempFloat = (float)(100.0d * twist.x);
7719 shapeBlock.PathTwistBegin = (sbyte)tempFloat; 7719 shapeBlock.PathTwistBegin = (sbyte)tempFloat;
7720 tempFloat = (float)(100.0d * twist.y); 7720 tempFloat = (float)(100.0d * twist.y);
7721 shapeBlock.PathTwist = (sbyte)tempFloat; 7721 shapeBlock.PathTwist = (sbyte)tempFloat;
7722 7722
7723 shapeBlock.ObjectLocalID = part.LocalId; 7723 shapeBlock.ObjectLocalID = part.LocalId;
7724 7724
7725 part.Shape.SculptEntry = false; 7725 part.Shape.SculptEntry = false;
7726 return shapeBlock; 7726 return shapeBlock;
7727 } 7727 }
7728 7728
7729 // Prim type box, cylinder and prism. 7729 // Prim type box, cylinder and prism.
7730 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) 7730 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve)
7731 { 7731 {
7732 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7732 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7733 ObjectShapePacket.ObjectDataBlock shapeBlock; 7733 ObjectShapePacket.ObjectDataBlock shapeBlock;
7734 7734
7735 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7735 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
7736 7736
7737 if (taper_b.x < 0f) 7737 if (taper_b.x < 0f)
7738 { 7738 {
7739 taper_b.x = 0f; 7739 taper_b.x = 0f;
7740 } 7740 }
7741 if (taper_b.x > 2f) 7741 if (taper_b.x > 2f)
7742 { 7742 {
7743 taper_b.x = 2f; 7743 taper_b.x = 2f;
7744 } 7744 }
7745 if (taper_b.y < 0f) 7745 if (taper_b.y < 0f)
7746 { 7746 {
7747 taper_b.y = 0f; 7747 taper_b.y = 0f;
7748 } 7748 }
7749 if (taper_b.y > 2f) 7749 if (taper_b.y > 2f)
7750 { 7750 {
7751 taper_b.y = 2f; 7751 taper_b.y = 2f;
7752 } 7752 }
7753 tempFloat = (float)(100.0d * (2.0d - taper_b.x)); 7753 tempFloat = (float)(100.0d * (2.0d - taper_b.x));
7754 shapeBlock.PathScaleX = (byte)tempFloat; 7754 shapeBlock.PathScaleX = (byte)tempFloat;
7755 tempFloat = (float)(100.0d * (2.0d - taper_b.y)); 7755 tempFloat = (float)(100.0d * (2.0d - taper_b.y));
7756 shapeBlock.PathScaleY = (byte)tempFloat; 7756 shapeBlock.PathScaleY = (byte)tempFloat;
7757 if (topshear.x < -0.5f) 7757 if (topshear.x < -0.5f)
7758 { 7758 {
7759 topshear.x = -0.5f; 7759 topshear.x = -0.5f;
7760 } 7760 }
7761 if (topshear.x > 0.5f) 7761 if (topshear.x > 0.5f)
7762 { 7762 {
7763 topshear.x = 0.5f; 7763 topshear.x = 0.5f;
7764 } 7764 }
7765 if (topshear.y < -0.5f) 7765 if (topshear.y < -0.5f)
7766 { 7766 {
7767 topshear.y = -0.5f; 7767 topshear.y = -0.5f;
7768 } 7768 }
7769 if (topshear.y > 0.5f) 7769 if (topshear.y > 0.5f)
7770 { 7770 {
7771 topshear.y = 0.5f; 7771 topshear.y = 0.5f;
7772 } 7772 }
7773 tempFloat = (float)(100.0d * topshear.x); 7773 tempFloat = (float)(100.0d * topshear.x);
7774 shapeBlock.PathShearX = (byte)tempFloat; 7774 shapeBlock.PathShearX = (byte)tempFloat;
7775 tempFloat = (float)(100.0d * topshear.y); 7775 tempFloat = (float)(100.0d * topshear.y);
7776 shapeBlock.PathShearY = (byte)tempFloat; 7776 shapeBlock.PathShearY = (byte)tempFloat;
7777 7777
7778 part.Shape.SculptEntry = false; 7778 part.Shape.SculptEntry = false;
7779 part.UpdateShape(shapeBlock); 7779 part.UpdateShape(shapeBlock);
7780 } 7780 }
7781 7781
7782 // Prim type sphere. 7782 // Prim type sphere.
7783 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) 7783 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve)
7784 { 7784 {
7785 ObjectShapePacket.ObjectDataBlock shapeBlock; 7785 ObjectShapePacket.ObjectDataBlock shapeBlock;
7786 7786
7787 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7787 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
7788 7788
7789 // profile/path swapped for a sphere 7789 // profile/path swapped for a sphere
7790 shapeBlock.PathBegin = shapeBlock.ProfileBegin; 7790 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
7791 shapeBlock.PathEnd = shapeBlock.ProfileEnd; 7791 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
7792 7792
7793 shapeBlock.PathScaleX = 100; 7793 shapeBlock.PathScaleX = 100;
7794 shapeBlock.PathScaleY = 100; 7794 shapeBlock.PathScaleY = 100;
7795 7795
7796 if (dimple.x < 0f) 7796 if (dimple.x < 0f)
7797 { 7797 {
7798 dimple.x = 0f; 7798 dimple.x = 0f;
7799 } 7799 }
7800 if (dimple.x > 1f) 7800 if (dimple.x > 1f)
7801 { 7801 {
7802 dimple.x = 1f; 7802 dimple.x = 1f;
7803 } 7803 }
7804 if (dimple.y < 0f) 7804 if (dimple.y < 0f)
7805 { 7805 {
7806 dimple.y = 0f; 7806 dimple.y = 0f;
7807 } 7807 }
7808 if (dimple.y > 1f) 7808 if (dimple.y > 1f)
7809 { 7809 {
7810 dimple.y = 1f; 7810 dimple.y = 1f;
7811 } 7811 }
7812 if (dimple.y - dimple.x < 0.02f) 7812 if (dimple.y - dimple.x < 0.02f)
7813 { 7813 {
7814 dimple.x = dimple.y - 0.02f; 7814 dimple.x = dimple.y - 0.02f;
7815 if (dimple.x < 0.0f) 7815 if (dimple.x < 0.0f)
7816 { 7816 {
7817 dimple.x = 0.0f; 7817 dimple.x = 0.0f;
7818 dimple.y = 0.02f; 7818 dimple.y = 0.02f;
7819 } 7819 }
7820 } 7820 }
7821 shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); 7821 shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x);
7822 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); 7822 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y));
7823 7823
7824 part.Shape.SculptEntry = false; 7824 part.Shape.SculptEntry = false;
7825 part.UpdateShape(shapeBlock); 7825 part.UpdateShape(shapeBlock);
7826 } 7826 }
7827 7827
7828 // Prim type torus, tube and ring. 7828 // Prim type torus, tube and ring.
7829 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) 7829 protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve)
7830 { 7830 {
7831 float tempFloat; // Use in float expressions below to avoid byte cast precision issues. 7831 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7832 ObjectShapePacket.ObjectDataBlock shapeBlock; 7832 ObjectShapePacket.ObjectDataBlock shapeBlock;
7833 7833
7834 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7834 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
7835 7835
7836 // profile/path swapped for a torrus, tube, ring 7836 // profile/path swapped for a torrus, tube, ring
7837 shapeBlock.PathBegin = shapeBlock.ProfileBegin; 7837 shapeBlock.PathBegin = shapeBlock.ProfileBegin;
7838 shapeBlock.PathEnd = shapeBlock.ProfileEnd; 7838 shapeBlock.PathEnd = shapeBlock.ProfileEnd;
7839 7839
7840 if (holesize.x < 0.01f) 7840 if (holesize.x < 0.01f)
7841 { 7841 {
7842 holesize.x = 0.01f; 7842 holesize.x = 0.01f;
7843 } 7843 }
7844 if (holesize.x > 1f) 7844 if (holesize.x > 1f)
7845 { 7845 {
7846 holesize.x = 1f; 7846 holesize.x = 1f;
7847 } 7847 }
7848 if (holesize.y < 0.01f) 7848 if (holesize.y < 0.01f)
7849 { 7849 {
7850 holesize.y = 0.01f; 7850 holesize.y = 0.01f;
7851 } 7851 }
7852 if (holesize.y > 0.5f) 7852 if (holesize.y > 0.5f)
7853 { 7853 {
7854 holesize.y = 0.5f; 7854 holesize.y = 0.5f;
7855 } 7855 }
7856 tempFloat = (float)(100.0d * (2.0d - holesize.x)); 7856 tempFloat = (float)(100.0d * (2.0d - holesize.x));
7857 shapeBlock.PathScaleX = (byte)tempFloat; 7857 shapeBlock.PathScaleX = (byte)tempFloat;
7858 tempFloat = (float)(100.0d * (2.0d - holesize.y)); 7858 tempFloat = (float)(100.0d * (2.0d - holesize.y));
7859 shapeBlock.PathScaleY = (byte)tempFloat; 7859 shapeBlock.PathScaleY = (byte)tempFloat;
7860 if (topshear.x < -0.5f) 7860 if (topshear.x < -0.5f)
7861 { 7861 {
7862 topshear.x = -0.5f; 7862 topshear.x = -0.5f;
7863 } 7863 }
7864 if (topshear.x > 0.5f) 7864 if (topshear.x > 0.5f)
7865 { 7865 {
7866 topshear.x = 0.5f; 7866 topshear.x = 0.5f;
7867 } 7867 }
7868 if (topshear.y < -0.5f) 7868 if (topshear.y < -0.5f)
7869 { 7869 {
7870 topshear.y = -0.5f; 7870 topshear.y = -0.5f;
7871 } 7871 }
7872 if (topshear.y > 0.5f) 7872 if (topshear.y > 0.5f)
7873 { 7873 {
7874 topshear.y = 0.5f; 7874 topshear.y = 0.5f;
7875 } 7875 }
7876 tempFloat = (float)(100.0d * topshear.x); 7876 tempFloat = (float)(100.0d * topshear.x);
7877 shapeBlock.PathShearX = (byte)tempFloat; 7877 shapeBlock.PathShearX = (byte)tempFloat;
7878 tempFloat = (float)(100.0d * topshear.y); 7878 tempFloat = (float)(100.0d * topshear.y);
7879 shapeBlock.PathShearY = (byte)tempFloat; 7879 shapeBlock.PathShearY = (byte)tempFloat;
7880 if (profilecut.x < 0f) 7880 if (profilecut.x < 0f)
7881 { 7881 {
7882 profilecut.x = 0f; 7882 profilecut.x = 0f;
7883 } 7883 }
7884 if (profilecut.x > 1f) 7884 if (profilecut.x > 1f)
7885 { 7885 {
7886 profilecut.x = 1f; 7886 profilecut.x = 1f;
7887 } 7887 }
7888 if (profilecut.y < 0f) 7888 if (profilecut.y < 0f)
7889 { 7889 {
7890 profilecut.y = 0f; 7890 profilecut.y = 0f;
7891 } 7891 }
7892 if (profilecut.y > 1f) 7892 if (profilecut.y > 1f)
7893 { 7893 {
7894 profilecut.y = 1f; 7894 profilecut.y = 1f;
7895 } 7895 }
7896 if (profilecut.y - profilecut.x < 0.02f) 7896 if (profilecut.y - profilecut.x < 0.02f)
7897 { 7897 {
7898 profilecut.x = profilecut.y - 0.02f; 7898 profilecut.x = profilecut.y - 0.02f;
7899 if (profilecut.x < 0.0f) 7899 if (profilecut.x < 0.0f)
7900 { 7900 {
7901 profilecut.x = 0.0f; 7901 profilecut.x = 0.0f;
7902 profilecut.y = 0.02f; 7902 profilecut.y = 0.02f;
7903 } 7903 }
7904 } 7904 }
7905 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); 7905 shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x);
7906 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y)); 7906 shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y));
7907 if (taper_a.x < -1f) 7907 if (taper_a.x < -1f)
7908 { 7908 {
7909 taper_a.x = -1f; 7909 taper_a.x = -1f;
7910 } 7910 }
7911 if (taper_a.x > 1f) 7911 if (taper_a.x > 1f)
7912 { 7912 {
7913 taper_a.x = 1f; 7913 taper_a.x = 1f;
7914 } 7914 }
7915 if (taper_a.y < -1f) 7915 if (taper_a.y < -1f)
7916 { 7916 {
7917 taper_a.y = -1f; 7917 taper_a.y = -1f;
7918 } 7918 }
7919 if (taper_a.y > 1f) 7919 if (taper_a.y > 1f)
7920 { 7920 {
7921 taper_a.y = 1f; 7921 taper_a.y = 1f;
7922 } 7922 }
7923 tempFloat = (float)(100.0d * taper_a.x); 7923 tempFloat = (float)(100.0d * taper_a.x);
7924 shapeBlock.PathTaperX = (sbyte)tempFloat; 7924 shapeBlock.PathTaperX = (sbyte)tempFloat;
7925 tempFloat = (float)(100.0d * taper_a.y); 7925 tempFloat = (float)(100.0d * taper_a.y);
7926 shapeBlock.PathTaperY = (sbyte)tempFloat; 7926 shapeBlock.PathTaperY = (sbyte)tempFloat;
7927 if (revolutions < 1f) 7927 if (revolutions < 1f)
7928 { 7928 {
7929 revolutions = 1f; 7929 revolutions = 1f;
7930 } 7930 }
7931 if (revolutions > 4f) 7931 if (revolutions > 4f)
7932 { 7932 {
7933 revolutions = 4f; 7933 revolutions = 4f;
7934 } 7934 }
7935 tempFloat = 66.66667f * (revolutions - 1.0f); 7935 tempFloat = 66.66667f * (revolutions - 1.0f);
7936 shapeBlock.PathRevolutions = (byte)tempFloat; 7936 shapeBlock.PathRevolutions = (byte)tempFloat;
7937 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 7937 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
7938 if (radiusoffset < 0f) 7938 if (radiusoffset < 0f)
7939 { 7939 {
7940 radiusoffset = 0f; 7940 radiusoffset = 0f;
7941 } 7941 }
7942 if (radiusoffset > 1f) 7942 if (radiusoffset > 1f)
7943 { 7943 {
7944 radiusoffset = 1f; 7944 radiusoffset = 1f;
7945 } 7945 }
7946 tempFloat = 100.0f * radiusoffset; 7946 tempFloat = 100.0f * radiusoffset;
7947 shapeBlock.PathRadiusOffset = (sbyte)tempFloat; 7947 shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
7948 if (skew < -0.95f) 7948 if (skew < -0.95f)
7949 { 7949 {
7950 skew = -0.95f; 7950 skew = -0.95f;
7951 } 7951 }
7952 if (skew > 0.95f) 7952 if (skew > 0.95f)
7953 { 7953 {
7954 skew = 0.95f; 7954 skew = 0.95f;
7955 } 7955 }
7956 tempFloat = 100.0f * skew; 7956 tempFloat = 100.0f * skew;
7957 shapeBlock.PathSkew = (sbyte)tempFloat; 7957 shapeBlock.PathSkew = (sbyte)tempFloat;
7958 7958
7959 part.Shape.SculptEntry = false; 7959 part.Shape.SculptEntry = false;
7960 part.UpdateShape(shapeBlock); 7960 part.UpdateShape(shapeBlock);
7961 } 7961 }
7962 7962
7963 // Prim type sculpt. 7963 // Prim type sculpt.
7964 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) 7964 protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve)
7965 { 7965 {
7966 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7966 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7967 UUID sculptId; 7967 UUID sculptId;
7968 7968
7969 if (!UUID.TryParse(map, out sculptId)) 7969 if (!UUID.TryParse(map, out sculptId))
7970 sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture); 7970 sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture);
7971 7971
7972 if (sculptId == UUID.Zero) 7972 if (sculptId == UUID.Zero)
7973 return; 7973 return;
7974 7974
7975 shapeBlock.PathCurve = pathcurve; 7975 shapeBlock.PathCurve = pathcurve;
7976 shapeBlock.ObjectLocalID = part.LocalId; 7976 shapeBlock.ObjectLocalID = part.LocalId;
7977 shapeBlock.PathScaleX = 100; 7977 shapeBlock.PathScaleX = 100;
7978 shapeBlock.PathScaleY = 150; 7978 shapeBlock.PathScaleY = 150;
7979 7979
7980 int flag = type & (ScriptBaseClass.PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass.PRIM_SCULPT_FLAG_MIRROR); 7980 int flag = type & (ScriptBaseClass.PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass.PRIM_SCULPT_FLAG_MIRROR);
7981 7981
7982 if (type != (ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER | flag) && 7982 if (type != (ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER | flag) &&
7983 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE | flag) && 7983 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE | flag) &&
7984 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE | flag) && 7984 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE | flag) &&
7985 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) 7985 type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag))
7986 { 7986 {
7987 // default 7987 // default
7988 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; 7988 type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE;
7989 } 7989 }
7990 7990
7991 part.Shape.SetSculptProperties((byte)type, sculptId); 7991 part.Shape.SetSculptProperties((byte)type, sculptId);
7992 part.Shape.SculptEntry = true; 7992 part.Shape.SculptEntry = true;
7993 part.UpdateShape(shapeBlock); 7993 part.UpdateShape(shapeBlock);
7994 } 7994 }
7995 7995
7996 public void llSetPrimitiveParams(LSL_List rules) 7996 public void llSetPrimitiveParams(LSL_List rules)
7997 { 7997 {
7998 m_host.AddScriptLPS(1); 7998 m_host.AddScriptLPS(1);
7999 7999
8000 SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); 8000 SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams");
8001 8001
8002 ScriptSleep(m_sleepMsOnSetPrimitiveParams); 8002 ScriptSleep(m_sleepMsOnSetPrimitiveParams);
8003 } 8003 }
8004 8004
8005 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) 8005 public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules)
8006 { 8006 {
8007 m_host.AddScriptLPS(1); 8007 m_host.AddScriptLPS(1);
8008 8008
8009 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); 8009 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams");
8010 8010
8011 ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams); 8011 ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams);
8012 } 8012 }
8013 8013
8014 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) 8014 public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules)
8015 { 8015 {
8016 m_host.AddScriptLPS(1); 8016 m_host.AddScriptLPS(1);
8017 8017
8018 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); 8018 SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast");
8019 } 8019 }
8020 8020
8021 protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc) 8021 protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc)
8022 { 8022 {
8023 SetEntityParams(GetLinkEntities(linknumber), rules, originFunc); 8023 SetEntityParams(GetLinkEntities(linknumber), rules, originFunc);
8024 } 8024 }
8025 8025
8026 protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc) 8026 protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc)
8027 { 8027 {
8028 LSL_List remaining = null; 8028 LSL_List remaining = null;
8029 uint rulesParsed = 0; 8029 uint rulesParsed = 0;
8030 8030
8031 foreach (ISceneEntity entity in entities) 8031 foreach (ISceneEntity entity in entities)
8032 { 8032 {
8033 if (entity is SceneObjectPart) 8033 if (entity is SceneObjectPart)
8034 remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); 8034 remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed);
8035 else 8035 else
8036 remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); 8036 remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed);
8037 } 8037 }
8038 8038
8039 while (remaining != null && remaining.Length > 2) 8039 while (remaining != null && remaining.Length > 2)
8040 { 8040 {
8041 int linknumber; 8041 int linknumber;
8042 try 8042 try
8043 { 8043 {
8044 linknumber = remaining.GetLSLIntegerItem(0); 8044 linknumber = remaining.GetLSLIntegerItem(0);
8045 } 8045 }
8046 catch(InvalidCastException) 8046 catch(InvalidCastException)
8047 { 8047 {
8048 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_LINK_TARGET: parameter 2 must be integer", rulesParsed)); 8048 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_LINK_TARGET: parameter 2 must be integer", rulesParsed));
8049 return; 8049 return;
8050 } 8050 }
8051 8051
8052 rules = remaining.GetSublist(1, -1); 8052 rules = remaining.GetSublist(1, -1);
8053 entities = GetLinkEntities(linknumber); 8053 entities = GetLinkEntities(linknumber);
8054 8054
8055 foreach (ISceneEntity entity in entities) 8055 foreach (ISceneEntity entity in entities)
8056 { 8056 {
8057 if (entity is SceneObjectPart) 8057 if (entity is SceneObjectPart)
8058 remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); 8058 remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed);
8059 else 8059 else
8060 remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); 8060 remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed);
8061 } 8061 }
8062 } 8062 }
8063 } 8063 }
8064 8064
8065 public void llSetKeyframedMotion(LSL_List frames, LSL_List options) 8065 public void llSetKeyframedMotion(LSL_List frames, LSL_List options)
8066 { 8066 {
8067 SceneObjectGroup group = m_host.ParentGroup; 8067 SceneObjectGroup group = m_host.ParentGroup;
8068 8068
8069 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical) 8069 if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical)
8070 return; 8070 return;
8071 if (group.IsAttachment) 8071 if (group.IsAttachment)
8072 return; 8072 return;
8073 8073
8074 if (frames.Data.Length > 0) // We are getting a new motion 8074 if (frames.Data.Length > 0) // We are getting a new motion
8075 { 8075 {
8076 if (group.RootPart.KeyframeMotion != null) 8076 if (group.RootPart.KeyframeMotion != null)
8077 group.RootPart.KeyframeMotion.Delete(); 8077 group.RootPart.KeyframeMotion.Delete();
8078 group.RootPart.KeyframeMotion = null; 8078 group.RootPart.KeyframeMotion = null;
8079 8079
8080 int idx = 0; 8080 int idx = 0;
8081 8081
8082 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward; 8082 KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward;
8083 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation; 8083 KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation;
8084 8084
8085 while (idx < options.Data.Length) 8085 while (idx < options.Data.Length)
8086 { 8086 {
8087 int option = (int)options.GetLSLIntegerItem(idx++); 8087 int option = (int)options.GetLSLIntegerItem(idx++);
8088 int remain = options.Data.Length - idx; 8088 int remain = options.Data.Length - idx;
8089 8089
8090 switch (option) 8090 switch (option)
8091 { 8091 {
8092 case ScriptBaseClass.KFM_MODE: 8092 case ScriptBaseClass.KFM_MODE:
8093 if (remain < 1) 8093 if (remain < 1)
8094 break; 8094 break;
8095 int modeval = (int)options.GetLSLIntegerItem(idx++); 8095 int modeval = (int)options.GetLSLIntegerItem(idx++);
8096 switch(modeval) 8096 switch(modeval)
8097 { 8097 {
8098 case ScriptBaseClass.KFM_FORWARD: 8098 case ScriptBaseClass.KFM_FORWARD:
8099 mode = KeyframeMotion.PlayMode.Forward; 8099 mode = KeyframeMotion.PlayMode.Forward;
8100 break; 8100 break;
8101 case ScriptBaseClass.KFM_REVERSE: 8101 case ScriptBaseClass.KFM_REVERSE:
8102 mode = KeyframeMotion.PlayMode.Reverse; 8102 mode = KeyframeMotion.PlayMode.Reverse;
8103 break; 8103 break;
8104 case ScriptBaseClass.KFM_LOOP: 8104 case ScriptBaseClass.KFM_LOOP:
8105 mode = KeyframeMotion.PlayMode.Loop; 8105 mode = KeyframeMotion.PlayMode.Loop;
8106 break; 8106 break;
8107 case ScriptBaseClass.KFM_PING_PONG: 8107 case ScriptBaseClass.KFM_PING_PONG:
8108 mode = KeyframeMotion.PlayMode.PingPong; 8108 mode = KeyframeMotion.PlayMode.PingPong;
8109 break; 8109 break;
8110 } 8110 }
8111 break; 8111 break;
8112 case ScriptBaseClass.KFM_DATA: 8112 case ScriptBaseClass.KFM_DATA:
8113 if (remain < 1) 8113 if (remain < 1)
8114 break; 8114 break;
8115 int dataval = (int)options.GetLSLIntegerItem(idx++); 8115 int dataval = (int)options.GetLSLIntegerItem(idx++);
8116 data = (KeyframeMotion.DataFormat)dataval; 8116 data = (KeyframeMotion.DataFormat)dataval;
8117 break; 8117 break;
8118 } 8118 }
8119 } 8119 }
8120 8120
8121 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data); 8121 group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data);
8122 8122
8123 idx = 0; 8123 idx = 0;
8124 8124
8125 int elemLength = 2; 8125 int elemLength = 2;
8126 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation)) 8126 if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation))
8127 elemLength = 3; 8127 elemLength = 3;
8128 8128
8129 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>(); 8129 List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>();
8130 while (idx < frames.Data.Length) 8130 while (idx < frames.Data.Length)
8131 { 8131 {
8132 int remain = frames.Data.Length - idx; 8132 int remain = frames.Data.Length - idx;
8133 8133
8134 if (remain < elemLength) 8134 if (remain < elemLength)
8135 break; 8135 break;
8136 8136
8137 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe(); 8137 KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe();
8138 frame.Position = null; 8138 frame.Position = null;
8139 frame.Rotation = null; 8139 frame.Rotation = null;
8140 8140
8141 if ((data & KeyframeMotion.DataFormat.Translation) != 0) 8141 if ((data & KeyframeMotion.DataFormat.Translation) != 0)
8142 { 8142 {
8143 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++); 8143 LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++);
8144 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z); 8144 frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z);
8145 } 8145 }
8146 if ((data & KeyframeMotion.DataFormat.Rotation) != 0) 8146 if ((data & KeyframeMotion.DataFormat.Rotation) != 0)
8147 { 8147 {
8148 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++); 8148 LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++);
8149 Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s); 8149 Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s);
8150 q.Normalize(); 8150 q.Normalize();
8151 frame.Rotation = q; 8151 frame.Rotation = q;
8152 } 8152 }
8153 8153
8154 float tempf = (float)frames.GetLSLFloatItem(idx++); 8154 float tempf = (float)frames.GetLSLFloatItem(idx++);
8155 frame.TimeMS = (int)(tempf * 1000.0f); 8155 frame.TimeMS = (int)(tempf * 1000.0f);
8156 8156
8157 keyframes.Add(frame); 8157 keyframes.Add(frame);
8158 } 8158 }
8159 8159
8160 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray()); 8160 group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray());
8161 group.RootPart.KeyframeMotion.Start(); 8161 group.RootPart.KeyframeMotion.Start();
8162 } 8162 }
8163 else 8163 else
8164 { 8164 {
8165 if (group.RootPart.KeyframeMotion == null) 8165 if (group.RootPart.KeyframeMotion == null)
8166 return; 8166 return;
8167 8167
8168 if (options.Data.Length == 0) 8168 if (options.Data.Length == 0)
8169 { 8169 {
8170 group.RootPart.KeyframeMotion.Stop(); 8170 group.RootPart.KeyframeMotion.Stop();
8171 return; 8171 return;
8172 } 8172 }
8173 8173
8174 int idx = 0; 8174 int idx = 0;
8175 8175
8176 while (idx < options.Data.Length) 8176 while (idx < options.Data.Length)
8177 { 8177 {
8178 int option = (int)options.GetLSLIntegerItem(idx++); 8178 int option = (int)options.GetLSLIntegerItem(idx++);
8179 8179
8180 switch (option) 8180 switch (option)
8181 { 8181 {
8182 case ScriptBaseClass.KFM_COMMAND: 8182 case ScriptBaseClass.KFM_COMMAND:
8183 int cmd = (int)options.GetLSLIntegerItem(idx++); 8183 int cmd = (int)options.GetLSLIntegerItem(idx++);
8184 switch (cmd) 8184 switch (cmd)
8185 { 8185 {
8186 case ScriptBaseClass.KFM_CMD_PLAY: 8186 case ScriptBaseClass.KFM_CMD_PLAY:
8187 group.RootPart.KeyframeMotion.Start(); 8187 group.RootPart.KeyframeMotion.Start();
8188 break; 8188 break;
8189 case ScriptBaseClass.KFM_CMD_STOP: 8189 case ScriptBaseClass.KFM_CMD_STOP:
8190 group.RootPart.KeyframeMotion.Stop(); 8190 group.RootPart.KeyframeMotion.Stop();
8191 break; 8191 break;
8192 case ScriptBaseClass.KFM_CMD_PAUSE: 8192 case ScriptBaseClass.KFM_CMD_PAUSE:
8193 group.RootPart.KeyframeMotion.Pause(); 8193 group.RootPart.KeyframeMotion.Pause();
8194 break; 8194 break;
8195 } 8195 }
8196 break; 8196 break;
8197 } 8197 }
8198 } 8198 }
8199 } 8199 }
8200 } 8200 }
8201 8201
8202 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) 8202 protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed)
8203 { 8203 {
8204 int idx = 0; 8204 int idx = 0;
8205 int idxStart = 0; 8205 int idxStart = 0;
8206 8206
8207 bool positionChanged = false; 8207 bool positionChanged = false;
8208 LSL_Vector currentPosition = GetPartLocalPos(part); 8208 LSL_Vector currentPosition = GetPartLocalPos(part);
8209 8209
8210 try 8210 try
8211 { 8211 {
8212 while (idx < rules.Length) 8212 while (idx < rules.Length)
8213 { 8213 {
8214 ++rulesParsed; 8214 ++rulesParsed;
8215 int code = rules.GetLSLIntegerItem(idx++); 8215 int code = rules.GetLSLIntegerItem(idx++);
8216 8216
8217 int remain = rules.Length - idx; 8217 int remain = rules.Length - idx;
8218 idxStart = idx; 8218 idxStart = idx;
8219 8219
8220 int face; 8220 int face;
8221 LSL_Vector v; 8221 LSL_Vector v;
8222 8222
8223 switch (code) 8223 switch (code)
8224 { 8224 {
8225 case ScriptBaseClass.PRIM_POSITION: 8225 case ScriptBaseClass.PRIM_POSITION:
8226 case ScriptBaseClass.PRIM_POS_LOCAL: 8226 case ScriptBaseClass.PRIM_POS_LOCAL:
8227 if (remain < 1) 8227 if (remain < 1)
8228 return null; 8228 return null;
8229 8229
8230 try 8230 try
8231 { 8231 {
8232 v = rules.GetVector3Item(idx++); 8232 v = rules.GetVector3Item(idx++);
8233 } 8233 }
8234 catch(InvalidCastException) 8234 catch(InvalidCastException)
8235 { 8235 {
8236 if(code == ScriptBaseClass.PRIM_POSITION) 8236 if(code == ScriptBaseClass.PRIM_POSITION)
8237 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); 8237 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8238 else 8238 else
8239 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); 8239 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1));
8240 return null; 8240 return null;
8241 } 8241 }
8242 positionChanged = true; 8242 positionChanged = true;
8243 currentPosition = GetSetPosTarget(part, v, currentPosition); 8243 currentPosition = GetSetPosTarget(part, v, currentPosition);
8244 8244
8245 break; 8245 break;
8246 case ScriptBaseClass.PRIM_SIZE: 8246 case ScriptBaseClass.PRIM_SIZE:
8247 if (remain < 1) 8247 if (remain < 1)
8248 return null; 8248 return null;
8249 8249
8250 v=rules.GetVector3Item(idx++); 8250 v=rules.GetVector3Item(idx++);
8251 SetScale(part, v); 8251 SetScale(part, v);
8252 8252
8253 break; 8253 break;
8254 case ScriptBaseClass.PRIM_ROTATION: 8254 case ScriptBaseClass.PRIM_ROTATION:
8255 if (remain < 1) 8255 if (remain < 1)
8256 return null; 8256 return null;
8257 LSL_Rotation q; 8257 LSL_Rotation q;
8258 try 8258 try
8259 { 8259 {
8260 q = rules.GetQuaternionItem(idx++); 8260 q = rules.GetQuaternionItem(idx++);
8261 } 8261 }
8262 catch(InvalidCastException) 8262 catch(InvalidCastException)
8263 { 8263 {
8264 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 1 must be rotation", rulesParsed, idx - idxStart - 1)); 8264 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 1 must be rotation", rulesParsed, idx - idxStart - 1));
8265 return null; 8265 return null;
8266 } 8266 }
8267 // try to let this work as in SL... 8267 // try to let this work as in SL...
8268 if (part.ParentID == 0) 8268 if (part.ParentID == 0)
8269 { 8269 {
8270 // special case: If we are root, rotate complete SOG to new rotation 8270 // special case: If we are root, rotate complete SOG to new rotation
8271 SetRot(part, q); 8271 SetRot(part, q);
8272 } 8272 }
8273 else 8273 else
8274 { 8274 {
8275 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. 8275 // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask.
8276 SceneObjectPart rootPart = part.ParentGroup.RootPart; 8276 SceneObjectPart rootPart = part.ParentGroup.RootPart;
8277 SetRot(part, rootPart.RotationOffset * (Quaternion)q); 8277 SetRot(part, rootPart.RotationOffset * (Quaternion)q);
8278 } 8278 }
8279 8279
8280 break; 8280 break;
8281 8281
8282 case ScriptBaseClass.PRIM_TYPE: 8282 case ScriptBaseClass.PRIM_TYPE:
8283 if (remain < 3) 8283 if (remain < 3)
8284 return null; 8284 return null;
8285 8285
8286 try 8286 try
8287 { 8287 {
8288 code = (int)rules.GetLSLIntegerItem(idx++); 8288 code = (int)rules.GetLSLIntegerItem(idx++);
8289 } 8289 }
8290 catch(InvalidCastException) 8290 catch(InvalidCastException)
8291 { 8291 {
8292 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1)); 8292 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1));
8293 return null; 8293 return null;
8294 } 8294 }
8295 8295
8296 remain = rules.Length - idx; 8296 remain = rules.Length - idx;
8297 float hollow; 8297 float hollow;
8298 LSL_Vector twist; 8298 LSL_Vector twist;
8299 LSL_Vector taper_b; 8299 LSL_Vector taper_b;
8300 LSL_Vector topshear; 8300 LSL_Vector topshear;
8301 float revolutions; 8301 float revolutions;
8302 float radiusoffset; 8302 float radiusoffset;
8303 float skew; 8303 float skew;
8304 LSL_Vector holesize; 8304 LSL_Vector holesize;
8305 LSL_Vector profilecut; 8305 LSL_Vector profilecut;
8306 8306
8307 switch (code) 8307 switch (code)
8308 { 8308 {
8309 case ScriptBaseClass.PRIM_TYPE_BOX: 8309 case ScriptBaseClass.PRIM_TYPE_BOX:
8310 if (remain < 6) 8310 if (remain < 6)
8311 return null; 8311 return null;
8312 8312
8313 try 8313 try
8314 { 8314 {
8315 face = (int)rules.GetLSLIntegerItem(idx++); 8315 face = (int)rules.GetLSLIntegerItem(idx++);
8316 } 8316 }
8317 catch(InvalidCastException) 8317 catch(InvalidCastException)
8318 { 8318 {
8319 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 8319 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
8320 return null; 8320 return null;
8321 } 8321 }
8322 try 8322 try
8323 { 8323 {
8324 v = rules.GetVector3Item(idx++); // cut 8324 v = rules.GetVector3Item(idx++); // cut
8325 } 8325 }
8326 catch(InvalidCastException) 8326 catch(InvalidCastException)
8327 { 8327 {
8328 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); 8328 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
8329 return null; 8329 return null;
8330 } 8330 }
8331 try 8331 try
8332 { 8332 {
8333 hollow = (float)rules.GetLSLFloatItem(idx++); 8333 hollow = (float)rules.GetLSLFloatItem(idx++);
8334 } 8334 }
8335 catch(InvalidCastException) 8335 catch(InvalidCastException)
8336 { 8336 {
8337 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); 8337 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
8338 return null; 8338 return null;
8339 } 8339 }
8340 try 8340 try
8341 { 8341 {
8342 twist = rules.GetVector3Item(idx++); 8342 twist = rules.GetVector3Item(idx++);
8343 } 8343 }
8344 catch(InvalidCastException) 8344 catch(InvalidCastException)
8345 { 8345 {
8346 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 5 must be vector", rulesParsed, idx - idxStart - 1)); 8346 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 5 must be vector", rulesParsed, idx - idxStart - 1));
8347 return null; 8347 return null;
8348 } 8348 }
8349 try 8349 try
8350 { 8350 {
8351 taper_b = rules.GetVector3Item(idx++); 8351 taper_b = rules.GetVector3Item(idx++);
8352 } 8352 }
8353 catch(InvalidCastException) 8353 catch(InvalidCastException)
8354 { 8354 {
8355 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); 8355 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8356 return null; 8356 return null;
8357 } 8357 }
8358 try 8358 try
8359 { 8359 {
8360 topshear = rules.GetVector3Item(idx++); 8360 topshear = rules.GetVector3Item(idx++);
8361 } 8361 }
8362 catch(InvalidCastException) 8362 catch(InvalidCastException)
8363 { 8363 {
8364 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); 8364 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8365 return null; 8365 return null;
8366 } 8366 }
8367 8367
8368 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 8368 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
8369 (byte)ProfileShape.Square, (byte)Extrusion.Straight); 8369 (byte)ProfileShape.Square, (byte)Extrusion.Straight);
8370 break; 8370 break;
8371 8371
8372 case ScriptBaseClass.PRIM_TYPE_CYLINDER: 8372 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
8373 if (remain < 6) 8373 if (remain < 6)
8374 return null; 8374 return null;
8375 8375
8376 try 8376 try
8377 { 8377 {
8378 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8378 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8379 } 8379 }
8380 catch(InvalidCastException) 8380 catch(InvalidCastException)
8381 { 8381 {
8382 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 8382 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8383 return null; 8383 return null;
8384 } 8384 }
8385 try 8385 try
8386 { 8386 {
8387 v = rules.GetVector3Item(idx++); // cut 8387 v = rules.GetVector3Item(idx++); // cut
8388 } 8388 }
8389 catch(InvalidCastException) 8389 catch(InvalidCastException)
8390 { 8390 {
8391 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); 8391 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8392 return null; 8392 return null;
8393 } 8393 }
8394 try 8394 try
8395 { 8395 {
8396 hollow = (float)rules.GetLSLFloatItem(idx++); 8396 hollow = (float)rules.GetLSLFloatItem(idx++);
8397 } 8397 }
8398 catch(InvalidCastException) 8398 catch(InvalidCastException)
8399 { 8399 {
8400 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 8400 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8401 return null; 8401 return null;
8402 } 8402 }
8403 try 8403 try
8404 { 8404 {
8405 twist = rules.GetVector3Item(idx++); 8405 twist = rules.GetVector3Item(idx++);
8406 } 8406 }
8407 catch(InvalidCastException) 8407 catch(InvalidCastException)
8408 { 8408 {
8409 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); 8409 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8410 return null; 8410 return null;
8411 } 8411 }
8412 try 8412 try
8413 { 8413 {
8414 taper_b = rules.GetVector3Item(idx++); 8414 taper_b = rules.GetVector3Item(idx++);
8415 } 8415 }
8416 catch(InvalidCastException) 8416 catch(InvalidCastException)
8417 { 8417 {
8418 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); 8418 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8419 return null; 8419 return null;
8420 } 8420 }
8421 try 8421 try
8422 { 8422 {
8423 topshear = rules.GetVector3Item(idx++); 8423 topshear = rules.GetVector3Item(idx++);
8424 } 8424 }
8425 catch(InvalidCastException) 8425 catch(InvalidCastException)
8426 { 8426 {
8427 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); 8427 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8428 return null; 8428 return null;
8429 } 8429 }
8430 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 8430 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
8431 (byte)ProfileShape.Circle, (byte)Extrusion.Straight); 8431 (byte)ProfileShape.Circle, (byte)Extrusion.Straight);
8432 break; 8432 break;
8433 8433
8434 case ScriptBaseClass.PRIM_TYPE_PRISM: 8434 case ScriptBaseClass.PRIM_TYPE_PRISM:
8435 if (remain < 6) 8435 if (remain < 6)
8436 return null; 8436 return null;
8437 8437
8438 try 8438 try
8439 { 8439 {
8440 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8440 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8441 } 8441 }
8442 catch(InvalidCastException) 8442 catch(InvalidCastException)
8443 { 8443 {
8444 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 8444 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8445 return null; 8445 return null;
8446 } 8446 }
8447 try 8447 try
8448 { 8448 {
8449 v = rules.GetVector3Item(idx++); //cut 8449 v = rules.GetVector3Item(idx++); //cut
8450 } 8450 }
8451 catch(InvalidCastException) 8451 catch(InvalidCastException)
8452 { 8452 {
8453 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); 8453 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8454 return null; 8454 return null;
8455 } 8455 }
8456 try 8456 try
8457 { 8457 {
8458 hollow = (float)rules.GetLSLFloatItem(idx++); 8458 hollow = (float)rules.GetLSLFloatItem(idx++);
8459 } 8459 }
8460 catch(InvalidCastException) 8460 catch(InvalidCastException)
8461 { 8461 {
8462 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 8462 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8463 return null; 8463 return null;
8464 } 8464 }
8465 try 8465 try
8466 { 8466 {
8467 twist = rules.GetVector3Item(idx++); 8467 twist = rules.GetVector3Item(idx++);
8468 } 8468 }
8469 catch(InvalidCastException) 8469 catch(InvalidCastException)
8470 { 8470 {
8471 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); 8471 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8472 return null; 8472 return null;
8473 } 8473 }
8474 try 8474 try
8475 { 8475 {
8476 taper_b = rules.GetVector3Item(idx++); 8476 taper_b = rules.GetVector3Item(idx++);
8477 } 8477 }
8478 catch(InvalidCastException) 8478 catch(InvalidCastException)
8479 { 8479 {
8480 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); 8480 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8481 return null; 8481 return null;
8482 } 8482 }
8483 try 8483 try
8484 { 8484 {
8485 topshear = rules.GetVector3Item(idx++); 8485 topshear = rules.GetVector3Item(idx++);
8486 } 8486 }
8487 catch(InvalidCastException) 8487 catch(InvalidCastException)
8488 { 8488 {
8489 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); 8489 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8490 return null; 8490 return null;
8491 } 8491 }
8492 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 8492 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear,
8493 (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight); 8493 (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight);
8494 break; 8494 break;
8495 8495
8496 case ScriptBaseClass.PRIM_TYPE_SPHERE: 8496 case ScriptBaseClass.PRIM_TYPE_SPHERE:
8497 if (remain < 5) 8497 if (remain < 5)
8498 return null; 8498 return null;
8499 8499
8500 try 8500 try
8501 { 8501 {
8502 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8502 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8503 } 8503 }
8504 catch(InvalidCastException) 8504 catch(InvalidCastException)
8505 { 8505 {
8506 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 8506 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8507 return null; 8507 return null;
8508 } 8508 }
8509 try 8509 try
8510 { 8510 {
8511 v = rules.GetVector3Item(idx++); // cut 8511 v = rules.GetVector3Item(idx++); // cut
8512 } 8512 }
8513 catch(InvalidCastException) 8513 catch(InvalidCastException)
8514 { 8514 {
8515 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); 8515 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8516 return null; 8516 return null;
8517 } 8517 }
8518 try 8518 try
8519 { 8519 {
8520 hollow = (float)rules.GetLSLFloatItem(idx++); 8520 hollow = (float)rules.GetLSLFloatItem(idx++);
8521 } 8521 }
8522 catch(InvalidCastException) 8522 catch(InvalidCastException)
8523 { 8523 {
8524 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 8524 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8525 return null; 8525 return null;
8526 } 8526 }
8527 try 8527 try
8528 { 8528 {
8529 twist = rules.GetVector3Item(idx++); 8529 twist = rules.GetVector3Item(idx++);
8530 } 8530 }
8531 catch(InvalidCastException) 8531 catch(InvalidCastException)
8532 { 8532 {
8533 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); 8533 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8534 return null; 8534 return null;
8535 } 8535 }
8536 try 8536 try
8537 { 8537 {
8538 taper_b = rules.GetVector3Item(idx++); // dimple 8538 taper_b = rules.GetVector3Item(idx++); // dimple
8539 } 8539 }
8540 catch(InvalidCastException) 8540 catch(InvalidCastException)
8541 { 8541 {
8542 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); 8542 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8543 return null; 8543 return null;
8544 } 8544 }
8545 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 8545 SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b,
8546 (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1); 8546 (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1);
8547 break; 8547 break;
8548 8548
8549 case ScriptBaseClass.PRIM_TYPE_TORUS: 8549 case ScriptBaseClass.PRIM_TYPE_TORUS:
8550 if (remain < 11) 8550 if (remain < 11)
8551 return null; 8551 return null;
8552 8552
8553 try 8553 try
8554 { 8554 {
8555 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8555 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8556 } 8556 }
8557 catch(InvalidCastException) 8557 catch(InvalidCastException)
8558 { 8558 {
8559 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 8559 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8560 return null; 8560 return null;
8561 } 8561 }
8562 try 8562 try
8563 { 8563 {
8564 v = rules.GetVector3Item(idx++); //cut 8564 v = rules.GetVector3Item(idx++); //cut
8565 } 8565 }
8566 catch(InvalidCastException) 8566 catch(InvalidCastException)
8567 { 8567 {
8568 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); 8568 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8569 return null; 8569 return null;
8570 } 8570 }
8571 try 8571 try
8572 { 8572 {
8573 hollow = (float)rules.GetLSLFloatItem(idx++); 8573 hollow = (float)rules.GetLSLFloatItem(idx++);
8574 } 8574 }
8575 catch(InvalidCastException) 8575 catch(InvalidCastException)
8576 { 8576 {
8577 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 8577 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8578 return null; 8578 return null;
8579 } 8579 }
8580 try 8580 try
8581 { 8581 {
8582 twist = rules.GetVector3Item(idx++); 8582 twist = rules.GetVector3Item(idx++);
8583 } 8583 }
8584 catch(InvalidCastException) 8584 catch(InvalidCastException)
8585 { 8585 {
8586 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); 8586 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8587 return null; 8587 return null;
8588 } 8588 }
8589 try 8589 try
8590 { 8590 {
8591 holesize = rules.GetVector3Item(idx++); 8591 holesize = rules.GetVector3Item(idx++);
8592 } 8592 }
8593 catch(InvalidCastException) 8593 catch(InvalidCastException)
8594 { 8594 {
8595 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); 8595 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8596 return null; 8596 return null;
8597 } 8597 }
8598 try 8598 try
8599 { 8599 {
8600 topshear = rules.GetVector3Item(idx++); 8600 topshear = rules.GetVector3Item(idx++);
8601 } 8601 }
8602 catch(InvalidCastException) 8602 catch(InvalidCastException)
8603 { 8603 {
8604 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); 8604 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8605 return null; 8605 return null;
8606 } 8606 }
8607 try 8607 try
8608 { 8608 {
8609 profilecut = rules.GetVector3Item(idx++); 8609 profilecut = rules.GetVector3Item(idx++);
8610 } 8610 }
8611 catch(InvalidCastException) 8611 catch(InvalidCastException)
8612 { 8612 {
8613 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); 8613 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
8614 return null; 8614 return null;
8615 } 8615 }
8616 try 8616 try
8617 { 8617 {
8618 taper_b = rules.GetVector3Item(idx++); // taper_a 8618 taper_b = rules.GetVector3Item(idx++); // taper_a
8619 } 8619 }
8620 catch(InvalidCastException) 8620 catch(InvalidCastException)
8621 { 8621 {
8622 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); 8622 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
8623 return null; 8623 return null;
8624 } 8624 }
8625 try 8625 try
8626 { 8626 {
8627 revolutions = (float)rules.GetLSLFloatItem(idx++); 8627 revolutions = (float)rules.GetLSLFloatItem(idx++);
8628 } 8628 }
8629 catch(InvalidCastException) 8629 catch(InvalidCastException)
8630 { 8630 {
8631 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); 8631 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
8632 return null; 8632 return null;
8633 } 8633 }
8634 try 8634 try
8635 { 8635 {
8636 radiusoffset = (float)rules.GetLSLFloatItem(idx++); 8636 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
8637 } 8637 }
8638 catch(InvalidCastException) 8638 catch(InvalidCastException)
8639 { 8639 {
8640 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); 8640 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
8641 return null; 8641 return null;
8642 } 8642 }
8643 try 8643 try
8644 { 8644 {
8645 skew = (float)rules.GetLSLFloatItem(idx++); 8645 skew = (float)rules.GetLSLFloatItem(idx++);
8646 } 8646 }
8647 catch(InvalidCastException) 8647 catch(InvalidCastException)
8648 { 8648 {
8649 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 13 must be vector", rulesParsed, idx - idxStart - 1)); 8649 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 13 must be vector", rulesParsed, idx - idxStart - 1));
8650 return null; 8650 return null;
8651 } 8651 }
8652 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, 8652 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
8653 revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1); 8653 revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1);
8654 break; 8654 break;
8655 8655
8656 case ScriptBaseClass.PRIM_TYPE_TUBE: 8656 case ScriptBaseClass.PRIM_TYPE_TUBE:
8657 if (remain < 11) 8657 if (remain < 11)
8658 return null; 8658 return null;
8659 8659
8660 try 8660 try
8661 { 8661 {
8662 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8662 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8663 } 8663 }
8664 catch(InvalidCastException) 8664 catch(InvalidCastException)
8665 { 8665 {
8666 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 8666 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8667 return null; 8667 return null;
8668 } 8668 }
8669 try 8669 try
8670 { 8670 {
8671 v = rules.GetVector3Item(idx++); //cut 8671 v = rules.GetVector3Item(idx++); //cut
8672 } 8672 }
8673 catch(InvalidCastException) 8673 catch(InvalidCastException)
8674 { 8674 {
8675 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); 8675 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8676 return null; 8676 return null;
8677 } 8677 }
8678 try 8678 try
8679 { 8679 {
8680 hollow = (float)rules.GetLSLFloatItem(idx++); 8680 hollow = (float)rules.GetLSLFloatItem(idx++);
8681 } 8681 }
8682 catch(InvalidCastException) 8682 catch(InvalidCastException)
8683 { 8683 {
8684 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 8684 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8685 return null; 8685 return null;
8686 } 8686 }
8687 try 8687 try
8688 { 8688 {
8689 twist = rules.GetVector3Item(idx++); 8689 twist = rules.GetVector3Item(idx++);
8690 } 8690 }
8691 catch(InvalidCastException) 8691 catch(InvalidCastException)
8692 { 8692 {
8693 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); 8693 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8694 return null; 8694 return null;
8695 } 8695 }
8696 try 8696 try
8697 { 8697 {
8698 holesize = rules.GetVector3Item(idx++); 8698 holesize = rules.GetVector3Item(idx++);
8699 } 8699 }
8700 catch(InvalidCastException) 8700 catch(InvalidCastException)
8701 { 8701 {
8702 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); 8702 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8703 return null; 8703 return null;
8704 } 8704 }
8705 try 8705 try
8706 { 8706 {
8707 topshear = rules.GetVector3Item(idx++); 8707 topshear = rules.GetVector3Item(idx++);
8708 } 8708 }
8709 catch(InvalidCastException) 8709 catch(InvalidCastException)
8710 { 8710 {
8711 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); 8711 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8712 return null; 8712 return null;
8713 } 8713 }
8714 try 8714 try
8715 { 8715 {
8716 profilecut = rules.GetVector3Item(idx++); 8716 profilecut = rules.GetVector3Item(idx++);
8717 } 8717 }
8718 catch(InvalidCastException) 8718 catch(InvalidCastException)
8719 { 8719 {
8720 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); 8720 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
8721 return null; 8721 return null;
8722 } 8722 }
8723 try 8723 try
8724 { 8724 {
8725 taper_b = rules.GetVector3Item(idx++); // taper_a 8725 taper_b = rules.GetVector3Item(idx++); // taper_a
8726 } 8726 }
8727 catch(InvalidCastException) 8727 catch(InvalidCastException)
8728 { 8728 {
8729 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); 8729 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
8730 return null; 8730 return null;
8731 } 8731 }
8732 try 8732 try
8733 { 8733 {
8734 revolutions = (float)rules.GetLSLFloatItem(idx++); 8734 revolutions = (float)rules.GetLSLFloatItem(idx++);
8735 } 8735 }
8736 catch(InvalidCastException) 8736 catch(InvalidCastException)
8737 { 8737 {
8738 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); 8738 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
8739 return null; 8739 return null;
8740 } 8740 }
8741 try 8741 try
8742 { 8742 {
8743 radiusoffset = (float)rules.GetLSLFloatItem(idx++); 8743 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
8744 } 8744 }
8745 catch(InvalidCastException) 8745 catch(InvalidCastException)
8746 { 8746 {
8747 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); 8747 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
8748 return null; 8748 return null;
8749 } 8749 }
8750 try 8750 try
8751 { 8751 {
8752 skew = (float)rules.GetLSLFloatItem(idx++); 8752 skew = (float)rules.GetLSLFloatItem(idx++);
8753 } 8753 }
8754 catch(InvalidCastException) 8754 catch(InvalidCastException)
8755 { 8755 {
8756 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); 8756 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1));
8757 return null; 8757 return null;
8758 } 8758 }
8759 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, 8759 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
8760 revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1); 8760 revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1);
8761 break; 8761 break;
8762 8762
8763 case ScriptBaseClass.PRIM_TYPE_RING: 8763 case ScriptBaseClass.PRIM_TYPE_RING:
8764 if (remain < 11) 8764 if (remain < 11)
8765 return null; 8765 return null;
8766 8766
8767 try 8767 try
8768 { 8768 {
8769 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape 8769 face = (int)rules.GetLSLIntegerItem(idx++); // holeshape
8770 } 8770 }
8771 catch(InvalidCastException) 8771 catch(InvalidCastException)
8772 { 8772 {
8773 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 8773 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
8774 return null; 8774 return null;
8775 } 8775 }
8776 try 8776 try
8777 { 8777 {
8778 v = rules.GetVector3Item(idx++); //cut 8778 v = rules.GetVector3Item(idx++); //cut
8779 } 8779 }
8780 catch(InvalidCastException) 8780 catch(InvalidCastException)
8781 { 8781 {
8782 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); 8782 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8783 return null; 8783 return null;
8784 } 8784 }
8785 try 8785 try
8786 { 8786 {
8787 hollow = (float)rules.GetLSLFloatItem(idx++); 8787 hollow = (float)rules.GetLSLFloatItem(idx++);
8788 } 8788 }
8789 catch(InvalidCastException) 8789 catch(InvalidCastException)
8790 { 8790 {
8791 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 8791 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8792 return null; 8792 return null;
8793 } 8793 }
8794 try 8794 try
8795 { 8795 {
8796 twist = rules.GetVector3Item(idx++); 8796 twist = rules.GetVector3Item(idx++);
8797 } 8797 }
8798 catch(InvalidCastException) 8798 catch(InvalidCastException)
8799 { 8799 {
8800 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); 8800 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1));
8801 return null; 8801 return null;
8802 } 8802 }
8803 try 8803 try
8804 { 8804 {
8805 holesize = rules.GetVector3Item(idx++); 8805 holesize = rules.GetVector3Item(idx++);
8806 } 8806 }
8807 catch(InvalidCastException) 8807 catch(InvalidCastException)
8808 { 8808 {
8809 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); 8809 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1));
8810 return null; 8810 return null;
8811 } 8811 }
8812 try 8812 try
8813 { 8813 {
8814 topshear = rules.GetVector3Item(idx++); 8814 topshear = rules.GetVector3Item(idx++);
8815 } 8815 }
8816 catch(InvalidCastException) 8816 catch(InvalidCastException)
8817 { 8817 {
8818 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); 8818 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
8819 return null; 8819 return null;
8820 } 8820 }
8821 try 8821 try
8822 { 8822 {
8823 profilecut = rules.GetVector3Item(idx++); 8823 profilecut = rules.GetVector3Item(idx++);
8824 } 8824 }
8825 catch(InvalidCastException) 8825 catch(InvalidCastException)
8826 { 8826 {
8827 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); 8827 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1));
8828 return null; 8828 return null;
8829 } 8829 }
8830 try 8830 try
8831 { 8831 {
8832 taper_b = rules.GetVector3Item(idx++); // taper_a 8832 taper_b = rules.GetVector3Item(idx++); // taper_a
8833 } 8833 }
8834 catch(InvalidCastException) 8834 catch(InvalidCastException)
8835 { 8835 {
8836 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); 8836 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1));
8837 return null; 8837 return null;
8838 } 8838 }
8839 try 8839 try
8840 { 8840 {
8841 revolutions = (float)rules.GetLSLFloatItem(idx++); 8841 revolutions = (float)rules.GetLSLFloatItem(idx++);
8842 } 8842 }
8843 catch(InvalidCastException) 8843 catch(InvalidCastException)
8844 { 8844 {
8845 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); 8845 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1));
8846 return null; 8846 return null;
8847 } 8847 }
8848 try 8848 try
8849 { 8849 {
8850 radiusoffset = (float)rules.GetLSLFloatItem(idx++); 8850 radiusoffset = (float)rules.GetLSLFloatItem(idx++);
8851 } 8851 }
8852 catch(InvalidCastException) 8852 catch(InvalidCastException)
8853 { 8853 {
8854 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); 8854 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1));
8855 return null; 8855 return null;
8856 } 8856 }
8857 try 8857 try
8858 { 8858 {
8859 skew = (float)rules.GetLSLFloatItem(idx++); 8859 skew = (float)rules.GetLSLFloatItem(idx++);
8860 } 8860 }
8861 catch(InvalidCastException) 8861 catch(InvalidCastException)
8862 { 8862 {
8863 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); 8863 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1));
8864 return null; 8864 return null;
8865 } 8865 }
8866 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, 8866 SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b,
8867 revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1); 8867 revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1);
8868 break; 8868 break;
8869 8869
8870 case ScriptBaseClass.PRIM_TYPE_SCULPT: 8870 case ScriptBaseClass.PRIM_TYPE_SCULPT:
8871 if (remain < 2) 8871 if (remain < 2)
8872 return null; 8872 return null;
8873 8873
8874 string map = rules.Data[idx++].ToString(); 8874 string map = rules.Data[idx++].ToString();
8875 try 8875 try
8876 { 8876 {
8877 face = (int)rules.GetLSLIntegerItem(idx++); // type 8877 face = (int)rules.GetLSLIntegerItem(idx++); // type
8878 } 8878 }
8879 catch(InvalidCastException) 8879 catch(InvalidCastException)
8880 { 8880 {
8881 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SCULPT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); 8881 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SCULPT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
8882 return null; 8882 return null;
8883 } 8883 }
8884 SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1); 8884 SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1);
8885 break; 8885 break;
8886 } 8886 }
8887 8887
8888 break; 8888 break;
8889 8889
8890 case ScriptBaseClass.PRIM_TEXTURE: 8890 case ScriptBaseClass.PRIM_TEXTURE:
8891 if (remain < 5) 8891 if (remain < 5)
8892 return null; 8892 return null;
8893 8893
8894 face=(int)rules.GetLSLIntegerItem(idx++); 8894 face=(int)rules.GetLSLIntegerItem(idx++);
8895 string tex; 8895 string tex;
8896 LSL_Vector repeats; 8896 LSL_Vector repeats;
8897 LSL_Vector offsets; 8897 LSL_Vector offsets;
8898 double rotation; 8898 double rotation;
8899 8899
8900 tex = rules.Data[idx++].ToString(); 8900 tex = rules.Data[idx++].ToString();
8901 try 8901 try
8902 { 8902 {
8903 repeats = rules.GetVector3Item(idx++); 8903 repeats = rules.GetVector3Item(idx++);
8904 } 8904 }
8905 catch(InvalidCastException) 8905 catch(InvalidCastException)
8906 { 8906 {
8907 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); 8907 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
8908 return null; 8908 return null;
8909 } 8909 }
8910 try 8910 try
8911 { 8911 {
8912 offsets = rules.GetVector3Item(idx++); 8912 offsets = rules.GetVector3Item(idx++);
8913 } 8913 }
8914 catch(InvalidCastException) 8914 catch(InvalidCastException)
8915 { 8915 {
8916 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); 8916 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1));
8917 return null; 8917 return null;
8918 } 8918 }
8919 try 8919 try
8920 { 8920 {
8921 rotation = (double)rules.GetLSLFloatItem(idx++); 8921 rotation = (double)rules.GetLSLFloatItem(idx++);
8922 } 8922 }
8923 catch(InvalidCastException) 8923 catch(InvalidCastException)
8924 { 8924 {
8925 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 8925 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
8926 return null; 8926 return null;
8927 } 8927 }
8928 8928
8929 SetTexture(part, tex, face); 8929 SetTexture(part, tex, face);
8930 ScaleTexture(part, repeats.x, repeats.y, face); 8930 ScaleTexture(part, repeats.x, repeats.y, face);
8931 OffsetTexture(part, offsets.x, offsets.y, face); 8931 OffsetTexture(part, offsets.x, offsets.y, face);
8932 RotateTexture(part, rotation, face); 8932 RotateTexture(part, rotation, face);
8933 8933
8934 break; 8934 break;
8935 8935
8936 case ScriptBaseClass.PRIM_COLOR: 8936 case ScriptBaseClass.PRIM_COLOR:
8937 if (remain < 3) 8937 if (remain < 3)
8938 return null; 8938 return null;
8939 8939
8940 LSL_Vector color; 8940 LSL_Vector color;
8941 double alpha; 8941 double alpha;
8942 8942
8943 try 8943 try
8944 { 8944 {
8945 face = (int)rules.GetLSLIntegerItem(idx++); 8945 face = (int)rules.GetLSLIntegerItem(idx++);
8946 } 8946 }
8947 catch(InvalidCastException) 8947 catch(InvalidCastException)
8948 { 8948 {
8949 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 8949 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
8950 return null; 8950 return null;
8951 } 8951 }
8952 try 8952 try
8953 { 8953 {
8954 color = rules.GetVector3Item(idx++); 8954 color = rules.GetVector3Item(idx++);
8955 } 8955 }
8956 catch(InvalidCastException) 8956 catch(InvalidCastException)
8957 { 8957 {
8958 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); 8958 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
8959 return null; 8959 return null;
8960 } 8960 }
8961 try 8961 try
8962 { 8962 {
8963 alpha = (double)rules.GetLSLFloatItem(idx++); 8963 alpha = (double)rules.GetLSLFloatItem(idx++);
8964 } 8964 }
8965 catch(InvalidCastException) 8965 catch(InvalidCastException)
8966 { 8966 {
8967 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); 8967 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
8968 return null; 8968 return null;
8969 } 8969 }
8970 8970
8971 part.SetFaceColorAlpha(face, color, alpha); 8971 part.SetFaceColorAlpha(face, color, alpha);
8972 8972
8973 break; 8973 break;
8974 8974
8975 case ScriptBaseClass.PRIM_FLEXIBLE: 8975 case ScriptBaseClass.PRIM_FLEXIBLE:
8976 if (remain < 7) 8976 if (remain < 7)
8977 return null; 8977 return null;
8978 bool flexi; 8978 bool flexi;
8979 int softness; 8979 int softness;
8980 float gravity; 8980 float gravity;
8981 float friction; 8981 float friction;
8982 float wind; 8982 float wind;
8983 float tension; 8983 float tension;
8984 LSL_Vector force; 8984 LSL_Vector force;
8985 8985
8986 try 8986 try
8987 { 8987 {
8988 flexi = rules.GetLSLIntegerItem(idx++); 8988 flexi = rules.GetLSLIntegerItem(idx++);
8989 } 8989 }
8990 catch(InvalidCastException) 8990 catch(InvalidCastException)
8991 { 8991 {
8992 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 8992 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
8993 return null; 8993 return null;
8994 } 8994 }
8995 try 8995 try
8996 { 8996 {
8997 softness = rules.GetLSLIntegerItem(idx++); 8997 softness = rules.GetLSLIntegerItem(idx++);
8998 } 8998 }
8999 catch(InvalidCastException) 8999 catch(InvalidCastException)
9000 { 9000 {
9001 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 9001 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9002 return null; 9002 return null;
9003 } 9003 }
9004 try 9004 try
9005 { 9005 {
9006 gravity = (float)rules.GetLSLFloatItem(idx++); 9006 gravity = (float)rules.GetLSLFloatItem(idx++);
9007 } 9007 }
9008 catch(InvalidCastException) 9008 catch(InvalidCastException)
9009 { 9009 {
9010 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); 9010 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9011 return null; 9011 return null;
9012 } 9012 }
9013 try 9013 try
9014 { 9014 {
9015 friction = (float)rules.GetLSLFloatItem(idx++); 9015 friction = (float)rules.GetLSLFloatItem(idx++);
9016 } 9016 }
9017 catch(InvalidCastException) 9017 catch(InvalidCastException)
9018 { 9018 {
9019 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 9019 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9020 return null; 9020 return null;
9021 } 9021 }
9022 try 9022 try
9023 { 9023 {
9024 wind = (float)rules.GetLSLFloatItem(idx++); 9024 wind = (float)rules.GetLSLFloatItem(idx++);
9025 } 9025 }
9026 catch(InvalidCastException) 9026 catch(InvalidCastException)
9027 { 9027 {
9028 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); 9028 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1));
9029 return null; 9029 return null;
9030 } 9030 }
9031 try 9031 try
9032 { 9032 {
9033 tension = (float)rules.GetLSLFloatItem(idx++); 9033 tension = (float)rules.GetLSLFloatItem(idx++);
9034 } 9034 }
9035 catch(InvalidCastException) 9035 catch(InvalidCastException)
9036 { 9036 {
9037 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 7 must be float", rulesParsed, idx - idxStart - 1)); 9037 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 7 must be float", rulesParsed, idx - idxStart - 1));
9038 return null; 9038 return null;
9039 } 9039 }
9040 try 9040 try
9041 { 9041 {
9042 force = rules.GetVector3Item(idx++); 9042 force = rules.GetVector3Item(idx++);
9043 } 9043 }
9044 catch(InvalidCastException) 9044 catch(InvalidCastException)
9045 { 9045 {
9046 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); 9046 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1));
9047 return null; 9047 return null;
9048 } 9048 }
9049 9049
9050 SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); 9050 SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force);
9051 9051
9052 break; 9052 break;
9053 9053
9054 case ScriptBaseClass.PRIM_POINT_LIGHT: 9054 case ScriptBaseClass.PRIM_POINT_LIGHT:
9055 if (remain < 5) 9055 if (remain < 5)
9056 return null; 9056 return null;
9057 bool light; 9057 bool light;
9058 LSL_Vector lightcolor; 9058 LSL_Vector lightcolor;
9059 float intensity; 9059 float intensity;
9060 float radius; 9060 float radius;
9061 float falloff; 9061 float falloff;
9062 9062
9063 try 9063 try
9064 { 9064 {
9065 light = rules.GetLSLIntegerItem(idx++); 9065 light = rules.GetLSLIntegerItem(idx++);
9066 } 9066 }
9067 catch(InvalidCastException) 9067 catch(InvalidCastException)
9068 { 9068 {
9069 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 9069 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9070 return null; 9070 return null;
9071 } 9071 }
9072 try 9072 try
9073 { 9073 {
9074 lightcolor = rules.GetVector3Item(idx++); 9074 lightcolor = rules.GetVector3Item(idx++);
9075 } 9075 }
9076 catch(InvalidCastException) 9076 catch(InvalidCastException)
9077 { 9077 {
9078 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); 9078 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9079 return null; 9079 return null;
9080 } 9080 }
9081 try 9081 try
9082 { 9082 {
9083 intensity = (float)rules.GetLSLFloatItem(idx++); 9083 intensity = (float)rules.GetLSLFloatItem(idx++);
9084 } 9084 }
9085 catch(InvalidCastException) 9085 catch(InvalidCastException)
9086 { 9086 {
9087 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); 9087 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9088 return null; 9088 return null;
9089 } 9089 }
9090 try 9090 try
9091 { 9091 {
9092 radius = (float)rules.GetLSLFloatItem(idx++); 9092 radius = (float)rules.GetLSLFloatItem(idx++);
9093 } 9093 }
9094 catch(InvalidCastException) 9094 catch(InvalidCastException)
9095 { 9095 {
9096 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); 9096 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1));
9097 return null; 9097 return null;
9098 } 9098 }
9099 try 9099 try
9100 { 9100 {
9101 falloff = (float)rules.GetLSLFloatItem(idx++); 9101 falloff = (float)rules.GetLSLFloatItem(idx++);
9102 } 9102 }
9103 catch(InvalidCastException) 9103 catch(InvalidCastException)
9104 { 9104 {
9105 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); 9105 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1));
9106 return null; 9106 return null;
9107 } 9107 }
9108 9108
9109 SetPointLight(part, light, lightcolor, intensity, radius, falloff); 9109 SetPointLight(part, light, lightcolor, intensity, radius, falloff);
9110 9110
9111 break; 9111 break;
9112 9112
9113 case ScriptBaseClass.PRIM_GLOW: 9113 case ScriptBaseClass.PRIM_GLOW:
9114 if (remain < 2) 9114 if (remain < 2)
9115 return null; 9115 return null;
9116 9116
9117 float glow; 9117 float glow;
9118 9118
9119 try 9119 try
9120 { 9120 {
9121 face = rules.GetLSLIntegerItem(idx++); 9121 face = rules.GetLSLIntegerItem(idx++);
9122 } 9122 }
9123 catch(InvalidCastException) 9123 catch(InvalidCastException)
9124 { 9124 {
9125 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 9125 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9126 return null; 9126 return null;
9127 } 9127 }
9128 try 9128 try
9129 { 9129 {
9130 glow = (float)rules.GetLSLFloatItem(idx++); 9130 glow = (float)rules.GetLSLFloatItem(idx++);
9131 } 9131 }
9132 catch(InvalidCastException) 9132 catch(InvalidCastException)
9133 { 9133 {
9134 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); 9134 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1));
9135 return null; 9135 return null;
9136 } 9136 }
9137 9137
9138 SetGlow(part, face, glow); 9138 SetGlow(part, face, glow);
9139 9139
9140 break; 9140 break;
9141 9141
9142 case ScriptBaseClass.PRIM_BUMP_SHINY: 9142 case ScriptBaseClass.PRIM_BUMP_SHINY:
9143 if (remain < 3) 9143 if (remain < 3)
9144 return null; 9144 return null;
9145 9145
9146 int shiny; 9146 int shiny;
9147 Bumpiness bump; 9147 Bumpiness bump;
9148 9148
9149 try 9149 try
9150 { 9150 {
9151 face = (int)rules.GetLSLIntegerItem(idx++); 9151 face = (int)rules.GetLSLIntegerItem(idx++);
9152 } 9152 }
9153 catch(InvalidCastException) 9153 catch(InvalidCastException)
9154 { 9154 {
9155 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 9155 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9156 return null; 9156 return null;
9157 } 9157 }
9158 try 9158 try
9159 { 9159 {
9160 shiny = (int)rules.GetLSLIntegerItem(idx++); 9160 shiny = (int)rules.GetLSLIntegerItem(idx++);
9161 } 9161 }
9162 catch(InvalidCastException) 9162 catch(InvalidCastException)
9163 { 9163 {
9164 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 9164 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9165 return null; 9165 return null;
9166 } 9166 }
9167 try 9167 try
9168 { 9168 {
9169 bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); 9169 bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++);
9170 } 9170 }
9171 catch(InvalidCastException) 9171 catch(InvalidCastException)
9172 { 9172 {
9173 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); 9173 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
9174 return null; 9174 return null;
9175 } 9175 }
9176 9176
9177 SetShiny(part, face, shiny, bump); 9177 SetShiny(part, face, shiny, bump);
9178 9178
9179 break; 9179 break;
9180 9180
9181 case ScriptBaseClass.PRIM_FULLBRIGHT: 9181 case ScriptBaseClass.PRIM_FULLBRIGHT:
9182 if (remain < 2) 9182 if (remain < 2)
9183 return null; 9183 return null;
9184 bool st; 9184 bool st;
9185 9185
9186 try 9186 try
9187 { 9187 {
9188 face = rules.GetLSLIntegerItem(idx++); 9188 face = rules.GetLSLIntegerItem(idx++);
9189 } 9189 }
9190 catch(InvalidCastException) 9190 catch(InvalidCastException)
9191 { 9191 {
9192 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 9192 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9193 return null; 9193 return null;
9194 } 9194 }
9195 try 9195 try
9196 { 9196 {
9197 st = rules.GetLSLIntegerItem(idx++); 9197 st = rules.GetLSLIntegerItem(idx++);
9198 } 9198 }
9199 catch(InvalidCastException) 9199 catch(InvalidCastException)
9200 { 9200 {
9201 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); 9201 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1));
9202 return null; 9202 return null;
9203 } 9203 }
9204 SetFullBright(part, face , st); 9204 SetFullBright(part, face , st);
9205 break; 9205 break;
9206 9206
9207 case ScriptBaseClass.PRIM_MATERIAL: 9207 case ScriptBaseClass.PRIM_MATERIAL:
9208 if (remain < 1) 9208 if (remain < 1)
9209 return null; 9209 return null;
9210 int mat; 9210 int mat;
9211 9211
9212 try 9212 try
9213 { 9213 {
9214 mat = rules.GetLSLIntegerItem(idx++); 9214 mat = rules.GetLSLIntegerItem(idx++);
9215 } 9215 }
9216 catch(InvalidCastException) 9216 catch(InvalidCastException)
9217 { 9217 {
9218 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_MATERIAL: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 9218 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_MATERIAL: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9219 return null; 9219 return null;
9220 } 9220 }
9221 if (mat < 0 || mat > 7) 9221 if (mat < 0 || mat > 7)
9222 return null; 9222 return null;
9223 9223
9224 part.Material = Convert.ToByte(mat); 9224 part.Material = Convert.ToByte(mat);
9225 break; 9225 break;
9226 9226
9227 case ScriptBaseClass.PRIM_PHANTOM: 9227 case ScriptBaseClass.PRIM_PHANTOM:
9228 if (remain < 1) 9228 if (remain < 1)
9229 return null; 9229 return null;
9230 9230
9231 string ph = rules.Data[idx++].ToString(); 9231 string ph = rules.Data[idx++].ToString();
9232 part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); 9232 part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1"));
9233 9233
9234 break; 9234 break;
9235 9235
9236 case ScriptBaseClass.PRIM_PHYSICS: 9236 case ScriptBaseClass.PRIM_PHYSICS:
9237 if (remain < 1) 9237 if (remain < 1)
9238 return null; 9238 return null;
9239 string phy = rules.Data[idx++].ToString(); 9239 string phy = rules.Data[idx++].ToString();
9240 part.ScriptSetPhysicsStatus(phy.Equals("1")); 9240 part.ScriptSetPhysicsStatus(phy.Equals("1"));
9241 break; 9241 break;
9242 9242
9243 case ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: 9243 case ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
9244 if (remain < 1) 9244 if (remain < 1)
9245 return null; 9245 return null;
9246 9246
9247 int shape_type; 9247 int shape_type;
9248 9248
9249 try 9249 try
9250 { 9250 {
9251 shape_type = rules.GetLSLIntegerItem(idx++); 9251 shape_type = rules.GetLSLIntegerItem(idx++);
9252 } 9252 }
9253 catch(InvalidCastException) 9253 catch(InvalidCastException)
9254 { 9254 {
9255 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_PHYSICS_SHAPE_TYPE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 9255 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_PHYSICS_SHAPE_TYPE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9256 return null; 9256 return null;
9257 } 9257 }
9258 9258
9259 ExtraPhysicsData physdata = new ExtraPhysicsData(); 9259 ExtraPhysicsData physdata = new ExtraPhysicsData();
9260 physdata.Density = part.Density; 9260 physdata.Density = part.Density;
9261 physdata.Bounce = part.Restitution; 9261 physdata.Bounce = part.Restitution;
9262 physdata.GravitationModifier = part.GravityModifier; 9262 physdata.GravitationModifier = part.GravityModifier;
9263 physdata.PhysShapeType = (PhysShapeType)shape_type; 9263 physdata.PhysShapeType = (PhysShapeType)shape_type;
9264 9264
9265 part.UpdateExtraPhysics(physdata); 9265 part.UpdateExtraPhysics(physdata);
9266 9266
9267 break; 9267 break;
9268 9268
9269 case ScriptBaseClass.PRIM_TEMP_ON_REZ: 9269 case ScriptBaseClass.PRIM_TEMP_ON_REZ:
9270 if (remain < 1) 9270 if (remain < 1)
9271 return null; 9271 return null;
9272 string temp = rules.Data[idx++].ToString(); 9272 string temp = rules.Data[idx++].ToString();
9273 9273
9274 part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); 9274 part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1"));
9275 9275
9276 break; 9276 break;
9277 9277
9278 case ScriptBaseClass.PRIM_TEXGEN: 9278 case ScriptBaseClass.PRIM_TEXGEN:
9279 if (remain < 2) 9279 if (remain < 2)
9280 return null; 9280 return null;
9281 //face,type 9281 //face,type
9282 int style; 9282 int style;
9283 9283
9284 try 9284 try
9285 { 9285 {
9286 face = rules.GetLSLIntegerItem(idx++); 9286 face = rules.GetLSLIntegerItem(idx++);
9287 } 9287 }
9288 catch(InvalidCastException) 9288 catch(InvalidCastException)
9289 { 9289 {
9290 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); 9290 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1));
9291 return null; 9291 return null;
9292 } 9292 }
9293 try 9293 try
9294 { 9294 {
9295 style = rules.GetLSLIntegerItem(idx++); 9295 style = rules.GetLSLIntegerItem(idx++);
9296 } 9296 }
9297 catch(InvalidCastException) 9297 catch(InvalidCastException)
9298 { 9298 {
9299 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); 9299 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1));
9300 return null; 9300 return null;
9301 } 9301 }
9302 SetTexGen(part, face, style); 9302 SetTexGen(part, face, style);
9303 break; 9303 break;
9304 case ScriptBaseClass.PRIM_TEXT: 9304 case ScriptBaseClass.PRIM_TEXT:
9305 if (remain < 3) 9305 if (remain < 3)
9306 return null; 9306 return null;
9307 string primText; 9307 string primText;
9308 LSL_Vector primTextColor; 9308 LSL_Vector primTextColor;
9309 LSL_Float primTextAlpha; 9309 LSL_Float primTextAlpha;
9310 9310
9311 try 9311 try
9312 { 9312 {
9313 primText = rules.GetLSLStringItem(idx++); 9313 primText = rules.GetLSLStringItem(idx++);
9314 } 9314 }
9315 catch(InvalidCastException) 9315 catch(InvalidCastException)
9316 { 9316 {
9317 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); 9317 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9318 return null; 9318 return null;
9319 } 9319 }
9320 try 9320 try
9321 { 9321 {
9322 primTextColor = rules.GetVector3Item(idx++); 9322 primTextColor = rules.GetVector3Item(idx++);
9323 } 9323 }
9324 catch(InvalidCastException) 9324 catch(InvalidCastException)
9325 { 9325 {
9326 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); 9326 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1));
9327 return null; 9327 return null;
9328 } 9328 }
9329 try 9329 try
9330 { 9330 {
9331 primTextAlpha = rules.GetLSLFloatItem(idx++); 9331 primTextAlpha = rules.GetLSLFloatItem(idx++);
9332 } 9332 }
9333 catch(InvalidCastException) 9333 catch(InvalidCastException)
9334 { 9334 {
9335 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); 9335 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9336 return null; 9336 return null;
9337 } 9337 }
9338 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); 9338 Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f);
9339 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); 9339 part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f));
9340 9340
9341 break; 9341 break;
9342 9342
9343 case ScriptBaseClass.PRIM_NAME: 9343 case ScriptBaseClass.PRIM_NAME:
9344 if (remain < 1) 9344 if (remain < 1)
9345 return null; 9345 return null;
9346 try 9346 try
9347 { 9347 {
9348 string primName = rules.GetLSLStringItem(idx++); 9348 string primName = rules.GetLSLStringItem(idx++);
9349 part.Name = primName; 9349 part.Name = primName;
9350 } 9350 }
9351 catch(InvalidCastException) 9351 catch(InvalidCastException)
9352 { 9352 {
9353 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NAME: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); 9353 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NAME: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9354 return null; 9354 return null;
9355 } 9355 }
9356 break; 9356 break;
9357 case ScriptBaseClass.PRIM_DESC: 9357 case ScriptBaseClass.PRIM_DESC:
9358 if (remain < 1) 9358 if (remain < 1)
9359 return null; 9359 return null;
9360 try 9360 try
9361 { 9361 {
9362 string primDesc = rules.GetLSLStringItem(idx++); 9362 string primDesc = rules.GetLSLStringItem(idx++);
9363 part.Description = primDesc; 9363 part.Description = primDesc;
9364 } 9364 }
9365 catch(InvalidCastException) 9365 catch(InvalidCastException)
9366 { 9366 {
9367 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_DESC: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); 9367 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_DESC: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1));
9368 return null; 9368 return null;
9369 } 9369 }
9370 break; 9370 break;
9371 case ScriptBaseClass.PRIM_ROT_LOCAL: 9371 case ScriptBaseClass.PRIM_ROT_LOCAL:
9372 if (remain < 1) 9372 if (remain < 1)
9373 return null; 9373 return null;
9374 LSL_Rotation rot; 9374 LSL_Rotation rot;
9375 try 9375 try
9376 { 9376 {
9377 rot = rules.GetQuaternionItem(idx++); 9377 rot = rules.GetQuaternionItem(idx++);
9378 } 9378 }
9379 catch(InvalidCastException) 9379 catch(InvalidCastException)
9380 { 9380 {
9381 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); 9381 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
9382 return null; 9382 return null;
9383 } 9383 }
9384 SetRot(part, rot); 9384 SetRot(part, rot);
9385 break; 9385 break;
9386 9386
9387 case ScriptBaseClass.PRIM_OMEGA: 9387 case ScriptBaseClass.PRIM_OMEGA:
9388 if (remain < 3) 9388 if (remain < 3)
9389 return null; 9389 return null;
9390 LSL_Vector axis; 9390 LSL_Vector axis;
9391 LSL_Float spinrate; 9391 LSL_Float spinrate;
9392 LSL_Float gain; 9392 LSL_Float gain;
9393 9393
9394 try 9394 try
9395 { 9395 {
9396 axis = rules.GetVector3Item(idx++); 9396 axis = rules.GetVector3Item(idx++);
9397 } 9397 }
9398 catch(InvalidCastException) 9398 catch(InvalidCastException)
9399 { 9399 {
9400 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); 9400 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9401 return null; 9401 return null;
9402 } 9402 }
9403 try 9403 try
9404 { 9404 {
9405 spinrate = rules.GetLSLFloatItem(idx++); 9405 spinrate = rules.GetLSLFloatItem(idx++);
9406 } 9406 }
9407 catch(InvalidCastException) 9407 catch(InvalidCastException)
9408 { 9408 {
9409 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); 9409 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1));
9410 return null; 9410 return null;
9411 } 9411 }
9412 try 9412 try
9413 { 9413 {
9414 gain = rules.GetLSLFloatItem(idx++); 9414 gain = rules.GetLSLFloatItem(idx++);
9415 } 9415 }
9416 catch(InvalidCastException) 9416 catch(InvalidCastException)
9417 { 9417 {
9418 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); 9418 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1));
9419 return null; 9419 return null;
9420 } 9420 }
9421 TargetOmega(part, axis, (double)spinrate, (double)gain); 9421 TargetOmega(part, axis, (double)spinrate, (double)gain);
9422 break; 9422 break;
9423 9423
9424 case ScriptBaseClass.PRIM_SLICE: 9424 case ScriptBaseClass.PRIM_SLICE:
9425 if (remain < 1) 9425 if (remain < 1)
9426 return null; 9426 return null;
9427 LSL_Vector slice; 9427 LSL_Vector slice;
9428 try 9428 try
9429 { 9429 {
9430 slice = rules.GetVector3Item(idx++); 9430 slice = rules.GetVector3Item(idx++);
9431 } 9431 }
9432 catch(InvalidCastException) 9432 catch(InvalidCastException)
9433 { 9433 {
9434 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SLICE: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); 9434 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SLICE: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9435 return null; 9435 return null;
9436 } 9436 }
9437 part.UpdateSlice((float)slice.x, (float)slice.y); 9437 part.UpdateSlice((float)slice.x, (float)slice.y);
9438 break; 9438 break;
9439 9439
9440 case ScriptBaseClass.PRIM_LINK_TARGET: 9440 case ScriptBaseClass.PRIM_LINK_TARGET:
9441 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 9441 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9442 return null; 9442 return null;
9443 9443
9444 return rules.GetSublist(idx, -1); 9444 return rules.GetSublist(idx, -1);
9445 9445
9446 default: 9446 default:
9447 Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - unsupported parameter", rulesParsed, idx - idxStart)); 9447 Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - unsupported parameter", rulesParsed, idx - idxStart));
9448 return null; 9448 return null;
9449 } 9449 }
9450 } 9450 }
9451 } 9451 }
9452 catch (InvalidCastException e) 9452 catch (InvalidCastException e)
9453 { 9453 {
9454 Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); 9454 Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
9455 } 9455 }
9456 finally 9456 finally
9457 { 9457 {
9458 if (positionChanged) 9458 if (positionChanged)
9459 { 9459 {
9460 if (part.ParentGroup.RootPart == part) 9460 if (part.ParentGroup.RootPart == part)
9461 { 9461 {
9462 SceneObjectGroup parent = part.ParentGroup; 9462 SceneObjectGroup parent = part.ParentGroup;
9463 parent.UpdateGroupPosition(currentPosition); 9463 parent.UpdateGroupPosition(currentPosition);
9464 } 9464 }
9465 else 9465 else
9466 { 9466 {
9467 part.OffsetPosition = currentPosition; 9467 part.OffsetPosition = currentPosition;
9468 SceneObjectGroup parent = part.ParentGroup; 9468 SceneObjectGroup parent = part.ParentGroup;
9469 parent.HasGroupChanged = true; 9469 parent.HasGroupChanged = true;
9470 parent.ScheduleGroupForTerseUpdate(); 9470 parent.ScheduleGroupForTerseUpdate();
9471 } 9471 }
9472 } 9472 }
9473 } 9473 }
9474 9474
9475 return null; 9475 return null;
9476 } 9476 }
9477 9477
9478 protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed) 9478 protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed)
9479 { 9479 {
9480 int idx = 0; 9480 int idx = 0;
9481 int idxStart = 0; 9481 int idxStart = 0;
9482 9482
9483 try 9483 try
9484 { 9484 {
9485 while (idx < rules.Length) 9485 while (idx < rules.Length)
9486 { 9486 {
9487 ++rulesParsed; 9487 ++rulesParsed;
9488 int code = rules.GetLSLIntegerItem(idx++); 9488 int code = rules.GetLSLIntegerItem(idx++);
9489 9489
9490 int remain = rules.Length - idx; 9490 int remain = rules.Length - idx;
9491 idxStart = idx; 9491 idxStart = idx;
9492 9492
9493 switch (code) 9493 switch (code)
9494 { 9494 {
9495 case ScriptBaseClass.PRIM_POSITION: 9495 case ScriptBaseClass.PRIM_POSITION:
9496 case ScriptBaseClass.PRIM_POS_LOCAL: 9496 case ScriptBaseClass.PRIM_POS_LOCAL:
9497 if (remain < 1) 9497 if (remain < 1)
9498 return null; 9498 return null;
9499 9499
9500 try 9500 try
9501 { 9501 {
9502 sp.OffsetPosition = rules.GetVector3Item(idx++); 9502 sp.OffsetPosition = rules.GetVector3Item(idx++);
9503 } 9503 }
9504 catch(InvalidCastException) 9504 catch(InvalidCastException)
9505 { 9505 {
9506 if (code == ScriptBaseClass.PRIM_POSITION) 9506 if (code == ScriptBaseClass.PRIM_POSITION)
9507 { 9507 {
9508 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); 9508 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9509 } 9509 }
9510 else 9510 else
9511 { 9511 {
9512 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); 9512 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1));
9513 } 9513 }
9514 return null; 9514 return null;
9515 } 9515 }
9516 break; 9516 break;
9517 9517
9518 case ScriptBaseClass.PRIM_ROTATION: 9518 case ScriptBaseClass.PRIM_ROTATION:
9519 if (remain < 1) 9519 if (remain < 1)
9520 return null; 9520 return null;
9521 9521
9522 Quaternion inRot; 9522 Quaternion inRot;
9523 9523
9524 try 9524 try
9525 { 9525 {
9526 inRot = rules.GetQuaternionItem(idx++); 9526 inRot = rules.GetQuaternionItem(idx++);
9527 } 9527 }
9528 catch(InvalidCastException) 9528 catch(InvalidCastException)
9529 { 9529 {
9530 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); 9530 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
9531 return null; 9531 return null;
9532 } 9532 }
9533 9533
9534 SceneObjectPart parentPart = sp.ParentPart; 9534 SceneObjectPart parentPart = sp.ParentPart;
9535 9535
9536 if (parentPart != null) 9536 if (parentPart != null)
9537 sp.Rotation = m_host.GetWorldRotation() * inRot; 9537 sp.Rotation = m_host.GetWorldRotation() * inRot;
9538 9538
9539 break; 9539 break;
9540 9540
9541 case ScriptBaseClass.PRIM_ROT_LOCAL: 9541 case ScriptBaseClass.PRIM_ROT_LOCAL:
9542 if (remain < 1) 9542 if (remain < 1)
9543 return null; 9543 return null;
9544 9544
9545 try 9545 try
9546 { 9546 {
9547 sp.Rotation = rules.GetQuaternionItem(idx++); 9547 sp.Rotation = rules.GetQuaternionItem(idx++);
9548 } 9548 }
9549 catch(InvalidCastException) 9549 catch(InvalidCastException)
9550 { 9550 {
9551 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); 9551 Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1));
9552 return null; 9552 return null;
9553 } 9553 }
9554 9554
9555 break; 9555 break;
9556 9556
9557 case ScriptBaseClass.PRIM_TYPE: 9557 case ScriptBaseClass.PRIM_TYPE:
9558 Error(originFunc, "PRIM_TYPE disallowed on agent"); 9558 Error(originFunc, "PRIM_TYPE disallowed on agent");
9559 return null; 9559 return null;
9560 9560
9561 case ScriptBaseClass.PRIM_OMEGA: 9561 case ScriptBaseClass.PRIM_OMEGA:
9562 Error(originFunc, "PRIM_OMEGA disallowed on agent"); 9562 Error(originFunc, "PRIM_OMEGA disallowed on agent");
9563 return null; 9563 return null;
9564 9564
9565 case ScriptBaseClass.PRIM_LINK_TARGET: 9565 case ScriptBaseClass.PRIM_LINK_TARGET:
9566 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. 9566 if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless.
9567 return null; 9567 return null;
9568 9568
9569 return rules.GetSublist(idx, -1); 9569 return rules.GetSublist(idx, -1);
9570 9570
9571 default: 9571 default:
9572 Error(originFunc, 9572 Error(originFunc,
9573 string.Format("Error running rule #{0} on agent: arg #{1} - disallowed on agent", rulesParsed, idx - idxStart)); 9573 string.Format("Error running rule #{0} on agent: arg #{1} - disallowed on agent", rulesParsed, idx - idxStart));
9574 return null; 9574 return null;
9575 } 9575 }
9576 } 9576 }
9577 } 9577 }
9578 catch (InvalidCastException e) 9578 catch (InvalidCastException e)
9579 { 9579 {
9580 Error( 9580 Error(
9581 originFunc, 9581 originFunc,
9582 string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); 9582 string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message);
9583 } 9583 }
9584 9584
9585 return null; 9585 return null;
9586 } 9586 }
9587 9587
9588 public LSL_String llStringToBase64(string str) 9588 public LSL_String llStringToBase64(string str)
9589 { 9589 {
9590 m_host.AddScriptLPS(1); 9590 m_host.AddScriptLPS(1);
9591 try 9591 try
9592 { 9592 {
9593 byte[] encData_byte; 9593 byte[] encData_byte;
9594 encData_byte = Util.UTF8.GetBytes(str); 9594 encData_byte = Util.UTF8.GetBytes(str);
9595 string encodedData = Convert.ToBase64String(encData_byte); 9595 string encodedData = Convert.ToBase64String(encData_byte);
9596 return encodedData; 9596 return encodedData;
9597 } 9597 }
9598 catch 9598 catch
9599 { 9599 {
9600 Error("llBase64ToString", "Error encoding string"); 9600 Error("llBase64ToString", "Error encoding string");
9601 return String.Empty; 9601 return String.Empty;
9602 } 9602 }
9603 } 9603 }
9604 9604
9605 public LSL_String llBase64ToString(string str) 9605 public LSL_String llBase64ToString(string str)
9606 { 9606 {
9607 m_host.AddScriptLPS(1); 9607 m_host.AddScriptLPS(1);
9608 try 9608 try
9609 { 9609 {
9610 byte[] b = Convert.FromBase64String(str); 9610 byte[] b = Convert.FromBase64String(str);
9611 return Encoding.UTF8.GetString(b); 9611 return Encoding.UTF8.GetString(b);
9612 } 9612 }
9613 catch 9613 catch
9614 { 9614 {
9615 Error("llBase64ToString", "Error decoding string"); 9615 Error("llBase64ToString", "Error decoding string");
9616 return String.Empty; 9616 return String.Empty;
9617 } 9617 }
9618 } 9618 }
9619 9619
9620 public LSL_String llXorBase64Strings(string str1, string str2) 9620 public LSL_String llXorBase64Strings(string str1, string str2)
9621 { 9621 {
9622 m_host.AddScriptLPS(1); 9622 m_host.AddScriptLPS(1);
9623 Deprecated("llXorBase64Strings", "Use llXorBase64 instead"); 9623 Deprecated("llXorBase64Strings", "Use llXorBase64 instead");
9624 ScriptSleep(m_sleepMsOnXorBase64Strings); 9624 ScriptSleep(m_sleepMsOnXorBase64Strings);
9625 return String.Empty; 9625 return String.Empty;
9626 } 9626 }
9627 9627
9628 public void llRemoteDataSetRegion() 9628 public void llRemoteDataSetRegion()
9629 { 9629 {
9630 m_host.AddScriptLPS(1); 9630 m_host.AddScriptLPS(1);
9631 Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead"); 9631 Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead");
9632 } 9632 }
9633 9633
9634 public LSL_Float llLog10(double val) 9634 public LSL_Float llLog10(double val)
9635 { 9635 {
9636 m_host.AddScriptLPS(1); 9636 m_host.AddScriptLPS(1);
9637 return (double)Math.Log10(val); 9637 return (double)Math.Log10(val);
9638 } 9638 }
9639 9639
9640 public LSL_Float llLog(double val) 9640 public LSL_Float llLog(double val)
9641 { 9641 {
9642 m_host.AddScriptLPS(1); 9642 m_host.AddScriptLPS(1);
9643 return (double)Math.Log(val); 9643 return (double)Math.Log(val);
9644 } 9644 }
9645 9645
9646 public LSL_List llGetAnimationList(string id) 9646 public LSL_List llGetAnimationList(string id)
9647 { 9647 {
9648 m_host.AddScriptLPS(1); 9648 m_host.AddScriptLPS(1);
9649 9649
9650 LSL_List l = new LSL_List(); 9650 LSL_List l = new LSL_List();
9651 ScenePresence av = World.GetScenePresence((UUID)id); 9651 ScenePresence av = World.GetScenePresence((UUID)id);
9652 if (av == null || av.IsChildAgent) // only if in the region 9652 if (av == null || av.IsChildAgent) // only if in the region
9653 return l; 9653 return l;
9654 UUID[] anims; 9654 UUID[] anims;
9655 anims = av.Animator.GetAnimationArray(); 9655 anims = av.Animator.GetAnimationArray();
9656 foreach (UUID foo in anims) 9656 foreach (UUID foo in anims)
9657 l.Add(new LSL_Key(foo.ToString())); 9657 l.Add(new LSL_Key(foo.ToString()));
9658 return l; 9658 return l;
9659 } 9659 }
9660 9660
9661 public void llSetParcelMusicURL(string url) 9661 public void llSetParcelMusicURL(string url)
9662 { 9662 {
9663 m_host.AddScriptLPS(1); 9663 m_host.AddScriptLPS(1);
9664 9664
9665 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 9665 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
9666 9666
9667 if (land.LandData.OwnerID != m_host.OwnerID) 9667 if (land.LandData.OwnerID != m_host.OwnerID)
9668 return; 9668 return;
9669 9669
9670 land.SetMusicUrl(url); 9670 land.SetMusicUrl(url);
9671 9671
9672 ScriptSleep(m_sleepMsOnSetParcelMusicURL); 9672 ScriptSleep(m_sleepMsOnSetParcelMusicURL);
9673 } 9673 }
9674 9674
9675 public LSL_String llGetParcelMusicURL() 9675 public LSL_String llGetParcelMusicURL()
9676 { 9676 {
9677 m_host.AddScriptLPS(1); 9677 m_host.AddScriptLPS(1);
9678 9678
9679 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 9679 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
9680 9680
9681 if (land.LandData.OwnerID != m_host.OwnerID) 9681 if (land.LandData.OwnerID != m_host.OwnerID)
9682 return String.Empty; 9682 return String.Empty;
9683 9683
9684 return land.GetMusicUrl(); 9684 return land.GetMusicUrl();
9685 } 9685 }
9686 9686
9687 public LSL_Vector llGetRootPosition() 9687 public LSL_Vector llGetRootPosition()
9688 { 9688 {
9689 m_host.AddScriptLPS(1); 9689 m_host.AddScriptLPS(1);
9690 9690
9691 return new LSL_Vector(m_host.ParentGroup.AbsolutePosition); 9691 return new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
9692 } 9692 }
9693 9693
9694 /// <summary> 9694 /// <summary>
9695 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot 9695 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot
9696 /// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation 9696 /// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation
9697 /// Also tested in sl in regards to the behaviour in attachments/mouselook 9697 /// Also tested in sl in regards to the behaviour in attachments/mouselook
9698 /// In the root prim:- 9698 /// In the root prim:-
9699 /// Returns the object rotation if not attached 9699 /// Returns the object rotation if not attached
9700 /// Returns the avatars rotation if attached 9700 /// Returns the avatars rotation if attached
9701 /// Returns the camera rotation if attached and the avatar is in mouselook 9701 /// Returns the camera rotation if attached and the avatar is in mouselook
9702 /// </summary> 9702 /// </summary>
9703 public LSL_Rotation llGetRootRotation() 9703 public LSL_Rotation llGetRootRotation()
9704 { 9704 {
9705 m_host.AddScriptLPS(1); 9705 m_host.AddScriptLPS(1);
9706 Quaternion q; 9706 Quaternion q;
9707 if (m_host.ParentGroup.AttachmentPoint != 0) 9707 if (m_host.ParentGroup.AttachmentPoint != 0)
9708 { 9708 {
9709 ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); 9709 ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar);
9710 if (avatar != null) 9710 if (avatar != null)
9711 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) 9711 if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0)
9712 q = avatar.CameraRotation; // Mouselook 9712 q = avatar.CameraRotation; // Mouselook
9713 else 9713 else
9714 q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate 9714 q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate
9715 else 9715 else
9716 q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case 9716 q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case
9717 } 9717 }
9718 else 9718 else
9719 q = m_host.ParentGroup.GroupRotation; // just the group rotation 9719 q = m_host.ParentGroup.GroupRotation; // just the group rotation
9720 9720
9721 return new LSL_Rotation(q); 9721 return new LSL_Rotation(q);
9722 } 9722 }
9723 9723
9724 public LSL_String llGetObjectDesc() 9724 public LSL_String llGetObjectDesc()
9725 { 9725 {
9726 return m_host.Description!=null?m_host.Description:String.Empty; 9726 return m_host.Description!=null?m_host.Description:String.Empty;
9727 } 9727 }
9728 9728
9729 public void llSetObjectDesc(string desc) 9729 public void llSetObjectDesc(string desc)
9730 { 9730 {
9731 m_host.AddScriptLPS(1); 9731 m_host.AddScriptLPS(1);
9732 m_host.Description = desc!=null?desc:String.Empty; 9732 m_host.Description = desc!=null?desc:String.Empty;
9733 } 9733 }
9734 9734
9735 public LSL_String llGetCreator() 9735 public LSL_String llGetCreator()
9736 { 9736 {
9737 m_host.AddScriptLPS(1); 9737 m_host.AddScriptLPS(1);
9738 return m_host.CreatorID.ToString(); 9738 return m_host.CreatorID.ToString();
9739 } 9739 }
9740 9740
9741 public LSL_String llGetTimestamp() 9741 public LSL_String llGetTimestamp()
9742 { 9742 {
9743 m_host.AddScriptLPS(1); 9743 m_host.AddScriptLPS(1);
9744 return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); 9744 return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ");
9745 } 9745 }
9746 9746
9747 public LSL_Integer llGetNumberOfPrims() 9747 public LSL_Integer llGetNumberOfPrims()
9748 { 9748 {
9749 m_host.AddScriptLPS(1); 9749 m_host.AddScriptLPS(1);
9750 9750
9751 return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount(); 9751 return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount();
9752 } 9752 }
9753 9753
9754 /// <summary> 9754 /// <summary>
9755 /// Full implementation of llGetBoundingBox according to SL 2015-04-15. 9755 /// Full implementation of llGetBoundingBox according to SL 2015-04-15.
9756 /// http://wiki.secondlife.com/wiki/LlGetBoundingBox 9756 /// http://wiki.secondlife.com/wiki/LlGetBoundingBox
9757 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox 9757 /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox
9758 /// Returns local bounding box of avatar without attachments 9758 /// Returns local bounding box of avatar without attachments
9759 /// if target is non-seated avatar or prim/mesh in avatar attachment. 9759 /// if target is non-seated avatar or prim/mesh in avatar attachment.
9760 /// Returns local bounding box of object including seated avatars 9760 /// Returns local bounding box of object including seated avatars
9761 /// if target is seated avatar or prim/mesh in object. 9761 /// if target is seated avatar or prim/mesh in object.
9762 /// Uses meshing of prims for high accuracy 9762 /// Uses meshing of prims for high accuracy
9763 /// or less accurate box models for speed. 9763 /// or less accurate box models for speed.
9764 /// </summary> 9764 /// </summary>
9765 public LSL_List llGetBoundingBox(string obj) 9765 public LSL_List llGetBoundingBox(string obj)
9766 { 9766 {
9767 m_host.AddScriptLPS(1); 9767 m_host.AddScriptLPS(1);
9768 9768
9769 // Get target avatar if non-seated avatar or attachment, or prim and object 9769 // Get target avatar if non-seated avatar or attachment, or prim and object
9770 UUID objID = UUID.Zero; 9770 UUID objID = UUID.Zero;
9771 UUID.TryParse(obj, out objID); 9771 UUID.TryParse(obj, out objID);
9772 ScenePresence agent = World.GetScenePresence(objID); 9772 ScenePresence agent = World.GetScenePresence(objID);
9773 if (agent != null) 9773 if (agent != null)
9774 { 9774 {
9775 if (agent.ParentPart != null) 9775 if (agent.ParentPart != null)
9776 { 9776 {
9777 objID = agent.ParentPart.UUID; 9777 objID = agent.ParentPart.UUID;
9778 agent = null; 9778 agent = null;
9779 } 9779 }
9780 } 9780 }
9781 SceneObjectGroup group = null; 9781 SceneObjectGroup group = null;
9782 SceneObjectPart target = World.GetSceneObjectPart(objID); 9782 SceneObjectPart target = World.GetSceneObjectPart(objID);
9783 if (target != null) 9783 if (target != null)
9784 { 9784 {
9785 group = target.ParentGroup; 9785 group = target.ParentGroup;
9786 if (group.IsAttachment) { 9786 if (group.IsAttachment) {
9787 objID = group.AttachedAvatar; 9787 objID = group.AttachedAvatar;
9788 agent = World.GetScenePresence(objID); 9788 agent = World.GetScenePresence(objID);
9789 group = null; 9789 group = null;
9790 target = null; 9790 target = null;
9791 } 9791 }
9792 } 9792 }
9793 9793
9794 // Initialize but break if no target 9794 // Initialize but break if no target
9795 LSL_List result = new LSL_List(); 9795 LSL_List result = new LSL_List();
9796 int groupCount = 0; 9796 int groupCount = 0;
9797 int partCount = 0; 9797 int partCount = 0;
9798 int vertexCount = 0; 9798 int vertexCount = 0;
9799 if (target == null && agent == null) 9799 if (target == null && agent == null)
9800 { 9800 {
9801 result.Add(new LSL_Vector()); 9801 result.Add(new LSL_Vector());
9802 result.Add(new LSL_Vector()); 9802 result.Add(new LSL_Vector());
9803 if (m_addStatsInGetBoundingBox) 9803 if (m_addStatsInGetBoundingBox)
9804 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); 9804 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9805 return result; 9805 return result;
9806 } 9806 }
9807 Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); 9807 Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue);
9808 Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue); 9808 Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue);
9809 9809
9810 // Try to get a mesher 9810 // Try to get a mesher
9811 IRendering primMesher = null; 9811 IRendering primMesher = null;
9812 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 9812 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
9813 if (renderers.Count > 0) 9813 if (renderers.Count > 0)
9814 primMesher = RenderingLoader.LoadRenderer(renderers[0]); 9814 primMesher = RenderingLoader.LoadRenderer(renderers[0]);
9815 9815
9816 // Get bounding box of just avatar, seated or not 9816 // Get bounding box of just avatar, seated or not
9817 if (agent != null) 9817 if (agent != null)
9818 { 9818 {
9819 bool hasParent = false; 9819 bool hasParent = false;
9820 Vector3 lower; 9820 Vector3 lower;
9821 Vector3 upper; 9821 Vector3 upper;
9822 BoundingBoxOfScenePresence(agent, out lower, out upper); 9822 BoundingBoxOfScenePresence(agent, out lower, out upper);
9823 Vector3 offset = Vector3.Zero; 9823 Vector3 offset = Vector3.Zero;
9824 9824
9825 // Since local bounding box unrotated and untilted, keep it simple 9825 // Since local bounding box unrotated and untilted, keep it simple
9826 AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9826 AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9827 partCount++; 9827 partCount++;
9828 groupCount++; 9828 groupCount++;
9829 9829
9830 // Return lower and upper bounding box corners 9830 // Return lower and upper bounding box corners
9831 result.Add(new LSL_Vector(minPosition)); 9831 result.Add(new LSL_Vector(minPosition));
9832 result.Add(new LSL_Vector(maxPosition)); 9832 result.Add(new LSL_Vector(maxPosition));
9833 if (m_addStatsInGetBoundingBox) 9833 if (m_addStatsInGetBoundingBox)
9834 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); 9834 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9835 return result; 9835 return result;
9836 } 9836 }
9837 // Get bounding box of object including seated avatars 9837 // Get bounding box of object including seated avatars
9838 else if (group != null) 9838 else if (group != null)
9839 { 9839 {
9840 // Merge bounding boxes of all parts (prims and mesh) 9840 // Merge bounding boxes of all parts (prims and mesh)
9841 foreach (SceneObjectPart part in group.Parts) 9841 foreach (SceneObjectPart part in group.Parts)
9842 { 9842 {
9843 bool hasParent = (!part.IsRoot); 9843 bool hasParent = (!part.IsRoot);
9844 // When requested or if no mesher, keep it simple 9844 // When requested or if no mesher, keep it simple
9845 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) 9845 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
9846 { 9846 {
9847 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9847 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9848 } 9848 }
9849 // Do the full mounty 9849 // Do the full mounty
9850 else 9850 else
9851 { 9851 {
9852 Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset); 9852 Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset);
9853 byte[] sculptAsset = null; 9853 byte[] sculptAsset = null;
9854 if (omvPrim.Sculpt != null) 9854 if (omvPrim.Sculpt != null)
9855 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); 9855 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
9856 9856
9857 // When part is mesh 9857 // When part is mesh
9858 // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler. 9858 // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler.
9859 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) 9859 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
9860 { 9860 {
9861 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); 9861 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
9862 FacetedMesh mesh = null; 9862 FacetedMesh mesh = null;
9863 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); 9863 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh);
9864 meshAsset = null; 9864 meshAsset = null;
9865 if (mesh != null) 9865 if (mesh != null)
9866 { 9866 {
9867 AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9867 AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9868 mesh = null; 9868 mesh = null;
9869 } 9869 }
9870 } 9870 }
9871 9871
9872 // When part is sculpt 9872 // When part is sculpt
9873 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. 9873 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
9874 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) 9874 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
9875 { 9875 {
9876 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); 9876 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
9877 if (imgDecoder != null) 9877 if (imgDecoder != null)
9878 { 9878 {
9879 Image sculpt = imgDecoder.DecodeToImage(sculptAsset); 9879 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
9880 if (sculpt != null) 9880 if (sculpt != null)
9881 { 9881 {
9882 SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); 9882 SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium);
9883 sculpt.Dispose(); 9883 sculpt.Dispose();
9884 if (mesh != null) 9884 if (mesh != null)
9885 { 9885 {
9886 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9886 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9887 mesh = null; 9887 mesh = null;
9888 } 9888 }
9889 } 9889 }
9890 } 9890 }
9891 } 9891 }
9892 9892
9893 // When part is prim 9893 // When part is prim
9894 else if (omvPrim.Sculpt == null) 9894 else if (omvPrim.Sculpt == null)
9895 { 9895 {
9896 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); 9896 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9897 if (mesh != null) 9897 if (mesh != null)
9898 { 9898 {
9899 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9899 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9900 mesh = null; 9900 mesh = null;
9901 } 9901 }
9902 } 9902 }
9903 9903
9904 // When all else fails, try fallback to simple box 9904 // When all else fails, try fallback to simple box
9905 else 9905 else
9906 { 9906 {
9907 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9907 AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9908 } 9908 }
9909 } 9909 }
9910 partCount++; 9910 partCount++;
9911 } 9911 }
9912 } 9912 }
9913 9913
9914 // Merge bounding boxes of seated avatars 9914 // Merge bounding boxes of seated avatars
9915 foreach (ScenePresence sp in group.GetSittingAvatars()) 9915 foreach (ScenePresence sp in group.GetSittingAvatars())
9916 { 9916 {
9917 Vector3 lower; 9917 Vector3 lower;
9918 Vector3 upper; 9918 Vector3 upper;
9919 BoundingBoxOfScenePresence(sp, out lower, out upper); 9919 BoundingBoxOfScenePresence(sp, out lower, out upper);
9920 Vector3 offset = sp.OffsetPosition; 9920 Vector3 offset = sp.OffsetPosition;
9921 9921
9922 bool hasParent = true; 9922 bool hasParent = true;
9923 // When requested or if no mesher, keep it simple 9923 // When requested or if no mesher, keep it simple
9924 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) 9924 if (m_useSimpleBoxesInGetBoundingBox || primMesher == null)
9925 { 9925 {
9926 AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9926 AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9927 } 9927 }
9928 // Do the full mounty 9928 // Do the full mounty
9929 else 9929 else
9930 { 9930 {
9931 // Prim shapes don't do center offsets, so add it here. 9931 // Prim shapes don't do center offsets, so add it here.
9932 offset = offset + (lower + upper) * 0.5f * sp.Rotation; 9932 offset = offset + (lower + upper) * 0.5f * sp.Rotation;
9933 Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); 9933 Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE);
9934 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); 9934 SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium);
9935 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); 9935 AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount);
9936 mesh = null; 9936 mesh = null;
9937 } 9937 }
9938 partCount++; 9938 partCount++;
9939 } 9939 }
9940 9940
9941 groupCount++; 9941 groupCount++;
9942 9942
9943 // Return lower and upper bounding box corners 9943 // Return lower and upper bounding box corners
9944 result.Add(new LSL_Vector(minPosition)); 9944 result.Add(new LSL_Vector(minPosition));
9945 result.Add(new LSL_Vector(maxPosition)); 9945 result.Add(new LSL_Vector(maxPosition));
9946 if (m_addStatsInGetBoundingBox) 9946 if (m_addStatsInGetBoundingBox)
9947 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); 9947 result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount));
9948 9948
9949 primMesher = null; 9949 primMesher = null;
9950 return result; 9950 return result;
9951 } 9951 }
9952 9952
9953 /// <summary> 9953 /// <summary>
9954 /// Helper to calculate bounding box of an avatar. 9954 /// Helper to calculate bounding box of an avatar.
9955 /// </summary> 9955 /// </summary>
9956 private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) 9956 private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper)
9957 { 9957 {
9958 // Adjust from OS model 9958 // Adjust from OS model
9959 // avatar height = visual height - 0.2, bounding box height = visual height 9959 // avatar height = visual height - 0.2, bounding box height = visual height
9960 // to SL model 9960 // to SL model
9961 // avatar height = visual height, bounding box height = visual height + 0.2 9961 // avatar height = visual height, bounding box height = visual height + 0.2
9962 float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; 9962 float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection;
9963 9963
9964 // According to avatar bounding box in SL 2015-04-18: 9964 // According to avatar bounding box in SL 2015-04-18:
9965 // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> 9965 // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h>
9966 // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> 9966 // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5>
9967 // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> 9967 // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h>
9968 9968
9969 // When avatar is sitting 9969 // When avatar is sitting
9970 if (sp.ParentPart != null) 9970 if (sp.ParentPart != null)
9971 { 9971 {
9972 lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); 9972 lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height);
9973 upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); 9973 upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height);
9974 } 9974 }
9975 // When avatar is groundsitting 9975 // When avatar is groundsitting
9976 else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) 9976 else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"])
9977 { 9977 {
9978 lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); 9978 lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height);
9979 upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); 9979 upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height);
9980 } 9980 }
9981 // When avatar is standing or flying 9981 // When avatar is standing or flying
9982 else 9982 else
9983 { 9983 {
9984 lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); 9984 lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height);
9985 upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); 9985 upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height);
9986 } 9986 }
9987 } 9987 }
9988 9988
9989 /// <summary> 9989 /// <summary>
9990 /// Helper to approximate a part with a simple box. 9990 /// Helper to approximate a part with a simple box.
9991 /// </summary> 9991 /// </summary>
9992 private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) 9992 private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
9993 { 9993 {
9994 // Parse the 8 box corners 9994 // Parse the 8 box corners
9995 for (int i = 0; i < 8; i++) 9995 for (int i = 0; i < 8; i++)
9996 { 9996 {
9997 // Calculate each box corner 9997 // Calculate each box corner
9998 Vector3 position = corner1; 9998 Vector3 position = corner1;
9999 if ((i & 1) != 0) 9999 if ((i & 1) != 0)
10000 position.X = corner2.X; 10000 position.X = corner2.X;
10001 if ((i & 2) != 0) 10001 if ((i & 2) != 0)
10002 position.Y = corner2.Y; 10002 position.Y = corner2.Y;
10003 if ((i & 4) != 0) 10003 if ((i & 4) != 0)
10004 position.Z = corner2.Z; 10004 position.Z = corner2.Z;
10005 // Rotate part unless part is root 10005 // Rotate part unless part is root
10006 if (hasParent) 10006 if (hasParent)
10007 position = position * rotation; 10007 position = position * rotation;
10008 position = position + offset; 10008 position = position + offset;
10009 // Adjust lower and upper bounding box corners if needed 10009 // Adjust lower and upper bounding box corners if needed
10010 lower = Vector3.Min(lower, position); 10010 lower = Vector3.Min(lower, position);
10011 upper = Vector3.Max(upper, position); 10011 upper = Vector3.Max(upper, position);
10012 count++; 10012 count++;
10013 } 10013 }
10014 } 10014 }
10015 10015
10016 /// <summary> 10016 /// <summary>
10017 /// Helper to parse a meshed prim and needed especially 10017 /// Helper to parse a meshed prim and needed especially
10018 /// for accuracy with tortured prims and sculpts. 10018 /// for accuracy with tortured prims and sculpts.
10019 /// </summary> 10019 /// </summary>
10020 private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) 10020 private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
10021 { 10021 {
10022 // Quirk: A meshed box contains 10 instead of the 8 necessary vertices. 10022 // Quirk: A meshed box contains 10 instead of the 8 necessary vertices.
10023 if (mesh != null) 10023 if (mesh != null)
10024 { 10024 {
10025 // Parse each vertex in mesh 10025 // Parse each vertex in mesh
10026 foreach (Vertex vertex in mesh.Vertices) 10026 foreach (Vertex vertex in mesh.Vertices)
10027 { 10027 {
10028 Vector3 position = vertex.Position; 10028 Vector3 position = vertex.Position;
10029 position = position * prim.Scale; 10029 position = position * prim.Scale;
10030 // Rotate part unless part is root 10030 // Rotate part unless part is root
10031 if (hasParent) 10031 if (hasParent)
10032 position = position * prim.Rotation; 10032 position = position * prim.Rotation;
10033 position = position + prim.Position; 10033 position = position + prim.Position;
10034 // Adjust lower and upper bounding box corners if needed 10034 // Adjust lower and upper bounding box corners if needed
10035 lower = Vector3.Min(lower, position); 10035 lower = Vector3.Min(lower, position);
10036 upper = Vector3.Max(upper, position); 10036 upper = Vector3.Max(upper, position);
10037 count++; 10037 count++;
10038 } 10038 }
10039 } 10039 }
10040 } 10040 }
10041 10041
10042 /// <summary> 10042 /// <summary>
10043 /// Helper to parse mesh because no method exists 10043 /// Helper to parse mesh because no method exists
10044 /// to parse mesh assets to SimpleMesh. 10044 /// to parse mesh assets to SimpleMesh.
10045 /// </summary> 10045 /// </summary>
10046 private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) 10046 private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count)
10047 { 10047 {
10048 if (mesh != null) 10048 if (mesh != null)
10049 { 10049 {
10050 // Parse each face in mesh 10050 // Parse each face in mesh
10051 // since vertex array isn't populated. 10051 // since vertex array isn't populated.
10052 // This parses each unique vertex 3-6 times. 10052 // This parses each unique vertex 3-6 times.
10053 foreach (Face face in mesh.Faces) 10053 foreach (Face face in mesh.Faces)
10054 { 10054 {
10055 // Parse each vertex in face 10055 // Parse each vertex in face
10056 foreach (Vertex vertex in face.Vertices) 10056 foreach (Vertex vertex in face.Vertices)
10057 { 10057 {
10058 Vector3 position = vertex.Position; 10058 Vector3 position = vertex.Position;
10059 position = position * prim.Scale; 10059 position = position * prim.Scale;
10060 // Rotate part unless part is root 10060 // Rotate part unless part is root
10061 if (hasParent) 10061 if (hasParent)
10062 position = position * prim.Rotation; 10062 position = position * prim.Rotation;
10063 position = position + prim.Position; 10063 position = position + prim.Position;
10064 // Adjust lower and upper bounding box corners if needed 10064 // Adjust lower and upper bounding box corners if needed
10065 lower = Vector3.Min(lower, position); 10065 lower = Vector3.Min(lower, position);
10066 upper = Vector3.Max(upper, position); 10066 upper = Vector3.Max(upper, position);
10067 count++; 10067 count++;
10068 } 10068 }
10069 } 10069 }
10070 } 10070 }
10071 } 10071 }
10072 10072
10073 /// <summary> 10073 /// <summary>
10074 /// Helper to make up an OpenMetaverse prim 10074 /// Helper to make up an OpenMetaverse prim
10075 /// needed to create mesh from parts. 10075 /// needed to create mesh from parts.
10076 /// </summary> 10076 /// </summary>
10077 private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType) 10077 private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType)
10078 { 10078 {
10079 // Initialize and set common parameters 10079 // Initialize and set common parameters
10080 Primitive prim = new OpenMetaverse.Primitive(); 10080 Primitive prim = new OpenMetaverse.Primitive();
10081 prim.Scale = scale; 10081 prim.Scale = scale;
10082 prim.Position = position; 10082 prim.Position = position;
10083 prim.Rotation = rotation; 10083 prim.Rotation = rotation;
10084 prim.PrimData.PathShearX = 0.0f; 10084 prim.PrimData.PathShearX = 0.0f;
10085 prim.PrimData.PathShearY = 0.0f; 10085 prim.PrimData.PathShearY = 0.0f;
10086 prim.PrimData.PathBegin = 0.0f; 10086 prim.PrimData.PathBegin = 0.0f;
10087 prim.PrimData.PathEnd = 1.0f; 10087 prim.PrimData.PathEnd = 1.0f;
10088 prim.PrimData.PathScaleX = 1.0f; 10088 prim.PrimData.PathScaleX = 1.0f;
10089 prim.PrimData.PathScaleY = 1.0f; 10089 prim.PrimData.PathScaleY = 1.0f;
10090 prim.PrimData.PathTaperX = 0.0f; 10090 prim.PrimData.PathTaperX = 0.0f;
10091 prim.PrimData.PathTaperY = 0.0f; 10091 prim.PrimData.PathTaperY = 0.0f;
10092 prim.PrimData.PathTwistBegin = 0.0f; 10092 prim.PrimData.PathTwistBegin = 0.0f;
10093 prim.PrimData.PathTwist = 0.0f; 10093 prim.PrimData.PathTwist = 0.0f;
10094 prim.PrimData.ProfileBegin = 0.0f; 10094 prim.PrimData.ProfileBegin = 0.0f;
10095 prim.PrimData.ProfileEnd = 1.0f; 10095 prim.PrimData.ProfileEnd = 1.0f;
10096 prim.PrimData.ProfileHollow = 0.0f; 10096 prim.PrimData.ProfileHollow = 0.0f;
10097 prim.PrimData.ProfileCurve = (ProfileCurve)1; 10097 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10098 prim.PrimData.ProfileHole = (HoleType)0; 10098 prim.PrimData.ProfileHole = (HoleType)0;
10099 prim.PrimData.PathCurve = (PathCurve)16; 10099 prim.PrimData.PathCurve = (PathCurve)16;
10100 prim.PrimData.PathRadiusOffset = 0.0f; 10100 prim.PrimData.PathRadiusOffset = 0.0f;
10101 prim.PrimData.PathRevolutions = 1.0f; 10101 prim.PrimData.PathRevolutions = 1.0f;
10102 prim.PrimData.PathSkew = 0.0f; 10102 prim.PrimData.PathSkew = 0.0f;
10103 prim.PrimData.PCode = OpenMetaverse.PCode.Prim; 10103 prim.PrimData.PCode = OpenMetaverse.PCode.Prim;
10104 prim.PrimData.State = (byte)0; 10104 prim.PrimData.State = (byte)0;
10105 10105
10106 // Set type specific parameters 10106 // Set type specific parameters
10107 switch (primType) 10107 switch (primType)
10108 { 10108 {
10109 // Set specific parameters for box 10109 // Set specific parameters for box
10110 case ScriptBaseClass.PRIM_TYPE_BOX: 10110 case ScriptBaseClass.PRIM_TYPE_BOX:
10111 prim.PrimData.PathScaleY = 1.0f; 10111 prim.PrimData.PathScaleY = 1.0f;
10112 prim.PrimData.ProfileCurve = (ProfileCurve)1; 10112 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10113 prim.PrimData.PathCurve = (PathCurve)16; 10113 prim.PrimData.PathCurve = (PathCurve)16;
10114 break; 10114 break;
10115 // Set specific parameters for cylinder 10115 // Set specific parameters for cylinder
10116 case ScriptBaseClass.PRIM_TYPE_CYLINDER: 10116 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
10117 prim.PrimData.PathScaleY = 1.0f; 10117 prim.PrimData.PathScaleY = 1.0f;
10118 prim.PrimData.ProfileCurve = (ProfileCurve)0; 10118 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10119 prim.PrimData.PathCurve = (PathCurve)16; 10119 prim.PrimData.PathCurve = (PathCurve)16;
10120 break; 10120 break;
10121 // Set specific parameters for prism 10121 // Set specific parameters for prism
10122 case ScriptBaseClass.PRIM_TYPE_PRISM: 10122 case ScriptBaseClass.PRIM_TYPE_PRISM:
10123 prim.PrimData.PathScaleY = 1.0f; 10123 prim.PrimData.PathScaleY = 1.0f;
10124 prim.PrimData.ProfileCurve = (ProfileCurve)3; 10124 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10125 prim.PrimData.PathCurve = (PathCurve)16; 10125 prim.PrimData.PathCurve = (PathCurve)16;
10126 break; 10126 break;
10127 // Set specific parameters for sphere 10127 // Set specific parameters for sphere
10128 case ScriptBaseClass.PRIM_TYPE_SPHERE: 10128 case ScriptBaseClass.PRIM_TYPE_SPHERE:
10129 prim.PrimData.PathScaleY = 1.0f; 10129 prim.PrimData.PathScaleY = 1.0f;
10130 prim.PrimData.ProfileCurve = (ProfileCurve)5; 10130 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10131 prim.PrimData.PathCurve = (PathCurve)32; 10131 prim.PrimData.PathCurve = (PathCurve)32;
10132 break; 10132 break;
10133 // Set specific parameters for torus 10133 // Set specific parameters for torus
10134 case ScriptBaseClass.PRIM_TYPE_TORUS: 10134 case ScriptBaseClass.PRIM_TYPE_TORUS:
10135 prim.PrimData.PathScaleY = 0.5f; 10135 prim.PrimData.PathScaleY = 0.5f;
10136 prim.PrimData.ProfileCurve = (ProfileCurve)0; 10136 prim.PrimData.ProfileCurve = (ProfileCurve)0;
10137 prim.PrimData.PathCurve = (PathCurve)32; 10137 prim.PrimData.PathCurve = (PathCurve)32;
10138 break; 10138 break;
10139 // Set specific parameters for tube 10139 // Set specific parameters for tube
10140 case ScriptBaseClass.PRIM_TYPE_TUBE: 10140 case ScriptBaseClass.PRIM_TYPE_TUBE:
10141 prim.PrimData.PathScaleY = 0.5f; 10141 prim.PrimData.PathScaleY = 0.5f;
10142 prim.PrimData.ProfileCurve = (ProfileCurve)1; 10142 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10143 prim.PrimData.PathCurve = (PathCurve)32; 10143 prim.PrimData.PathCurve = (PathCurve)32;
10144 break; 10144 break;
10145 // Set specific parameters for ring 10145 // Set specific parameters for ring
10146 case ScriptBaseClass.PRIM_TYPE_RING: 10146 case ScriptBaseClass.PRIM_TYPE_RING:
10147 prim.PrimData.PathScaleY = 0.5f; 10147 prim.PrimData.PathScaleY = 0.5f;
10148 prim.PrimData.ProfileCurve = (ProfileCurve)3; 10148 prim.PrimData.ProfileCurve = (ProfileCurve)3;
10149 prim.PrimData.PathCurve = (PathCurve)32; 10149 prim.PrimData.PathCurve = (PathCurve)32;
10150 break; 10150 break;
10151 // Set specific parameters for sculpt 10151 // Set specific parameters for sculpt
10152 case ScriptBaseClass.PRIM_TYPE_SCULPT: 10152 case ScriptBaseClass.PRIM_TYPE_SCULPT:
10153 prim.PrimData.PathScaleY = 1.0f; 10153 prim.PrimData.PathScaleY = 1.0f;
10154 prim.PrimData.ProfileCurve = (ProfileCurve)5; 10154 prim.PrimData.ProfileCurve = (ProfileCurve)5;
10155 prim.PrimData.PathCurve = (PathCurve)32; 10155 prim.PrimData.PathCurve = (PathCurve)32;
10156 break; 10156 break;
10157 // Default to specific parameters for box 10157 // Default to specific parameters for box
10158 default: 10158 default:
10159 prim.PrimData.PathScaleY = 1.0f; 10159 prim.PrimData.PathScaleY = 1.0f;
10160 prim.PrimData.ProfileCurve = (ProfileCurve)1; 10160 prim.PrimData.ProfileCurve = (ProfileCurve)1;
10161 prim.PrimData.PathCurve = (PathCurve)16; 10161 prim.PrimData.PathCurve = (PathCurve)16;
10162 break; 10162 break;
10163 } 10163 }
10164 10164
10165 return prim; 10165 return prim;
10166 } 10166 }
10167 10167
10168 /// <summary> 10168 /// <summary>
10169 /// Implementation of llGetGeometricCenter according to SL 2015-04-30. 10169 /// Implementation of llGetGeometricCenter according to SL 2015-04-30.
10170 /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter 10170 /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter
10171 /// Returns the average position offset of all linked parts, 10171 /// Returns the average position offset of all linked parts,
10172 /// including the root prim and seated avatars, 10172 /// including the root prim and seated avatars,
10173 /// relative to the root prim in local coordinates. 10173 /// relative to the root prim in local coordinates.
10174 /// </summary> 10174 /// </summary>
10175 public LSL_Vector llGetGeometricCenter() 10175 public LSL_Vector llGetGeometricCenter()
10176 { 10176 {
10177 // Subtract whatever position the root prim has to make it zero 10177 // Subtract whatever position the root prim has to make it zero
10178 Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f; 10178 Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f;
10179 10179
10180 // Add all prim/part position offsets 10180 // Add all prim/part position offsets
10181 foreach (SceneObjectPart part in m_host.ParentGroup.Parts) 10181 foreach (SceneObjectPart part in m_host.ParentGroup.Parts)
10182 offset = offset + part.OffsetPosition; 10182 offset = offset + part.OffsetPosition;
10183 // Add all avatar/scene presence position offsets 10183 // Add all avatar/scene presence position offsets
10184 foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars()) 10184 foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars())
10185 offset = offset + sp.OffsetPosition; 10185 offset = offset + sp.OffsetPosition;
10186 10186
10187 // Calculate and return the average offset 10187 // Calculate and return the average offset
10188 offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount()); 10188 offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount());
10189 return new LSL_Vector(offset); 10189 return new LSL_Vector(offset);
10190 } 10190 }
10191 10191
10192 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) 10192 public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules)
10193 { 10193 {
10194 LSL_List result = new LSL_List(); 10194 LSL_List result = new LSL_List();
10195 LSL_List remaining = null; 10195 LSL_List remaining = null;
10196 10196
10197 while (true) 10197 while (true)
10198 { 10198 {
10199// m_log.DebugFormat( 10199// m_log.DebugFormat(
10200// "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}", 10200// "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}",
10201// rules.Length, entity != null ? entity.Name : "NULL"); 10201// rules.Length, entity != null ? entity.Name : "NULL");
10202 10202
10203 if (entity == null) 10203 if (entity == null)
10204 return result; 10204 return result;
10205 10205
10206 if (entity is SceneObjectPart) 10206 if (entity is SceneObjectPart)
10207 remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result); 10207 remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result);
10208 else 10208 else
10209 remaining = GetAgentParams((ScenePresence)entity, rules, ref result); 10209 remaining = GetAgentParams((ScenePresence)entity, rules, ref result);
10210 10210
10211 if (remaining == null || remaining.Length < 2) 10211 if (remaining == null || remaining.Length < 2)
10212 return result; 10212 return result;
10213 10213
10214 int linknumber = remaining.GetLSLIntegerItem(0); 10214 int linknumber = remaining.GetLSLIntegerItem(0);
10215 rules = remaining.GetSublist(1, -1); 10215 rules = remaining.GetSublist(1, -1);
10216 entity = GetLinkEntity(m_host, linknumber); 10216 entity = GetLinkEntity(m_host, linknumber);
10217 } 10217 }
10218 } 10218 }
10219 10219
10220 public LSL_List llGetPrimitiveParams(LSL_List rules) 10220 public LSL_List llGetPrimitiveParams(LSL_List rules)
10221 { 10221 {
10222 m_host.AddScriptLPS(1); 10222 m_host.AddScriptLPS(1);
10223 10223
10224 return GetEntityParams(m_host, rules); 10224 return GetEntityParams(m_host, rules);
10225 } 10225 }
10226 10226
10227 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) 10227 public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules)
10228 { 10228 {
10229 m_host.AddScriptLPS(1); 10229 m_host.AddScriptLPS(1);
10230 10230
10231 return GetEntityParams(GetLinkEntity(m_host, linknumber), rules); 10231 return GetEntityParams(GetLinkEntity(m_host, linknumber), rules);
10232 } 10232 }
10233 10233
10234 public LSL_Vector GetAgentSize(ScenePresence sp) 10234 public LSL_Vector GetAgentSize(ScenePresence sp)
10235 { 10235 {
10236 return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight); 10236 return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight);
10237 } 10237 }
10238 10238
10239 /// <summary> 10239 /// <summary>
10240 /// Gets params for a seated avatar in a linkset. 10240 /// Gets params for a seated avatar in a linkset.
10241 /// </summary> 10241 /// </summary>
10242 /// <returns></returns> 10242 /// <returns></returns>
10243 /// <param name='sp'></param> 10243 /// <param name='sp'></param>
10244 /// <param name='rules'></param> 10244 /// <param name='rules'></param>
10245 /// <param name='res'></param> 10245 /// <param name='res'></param>
10246 public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res) 10246 public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res)
10247 { 10247 {
10248 int idx = 0; 10248 int idx = 0;
10249 while (idx < rules.Length) 10249 while (idx < rules.Length)
10250 { 10250 {
10251 int code = (int)rules.GetLSLIntegerItem(idx++); 10251 int code = (int)rules.GetLSLIntegerItem(idx++);
10252 int remain = rules.Length-idx; 10252 int remain = rules.Length-idx;
10253 10253
10254 switch (code) 10254 switch (code)
10255 { 10255 {
10256 case (int)ScriptBaseClass.PRIM_MATERIAL: 10256 case (int)ScriptBaseClass.PRIM_MATERIAL:
10257 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH)); 10257 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH));
10258 break; 10258 break;
10259 10259
10260 case (int)ScriptBaseClass.PRIM_PHYSICS: 10260 case (int)ScriptBaseClass.PRIM_PHYSICS:
10261 res.Add(ScriptBaseClass.FALSE); 10261 res.Add(ScriptBaseClass.FALSE);
10262 break; 10262 break;
10263 10263
10264 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 10264 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
10265 res.Add(ScriptBaseClass.FALSE); 10265 res.Add(ScriptBaseClass.FALSE);
10266 break; 10266 break;
10267 10267
10268 case (int)ScriptBaseClass.PRIM_PHANTOM: 10268 case (int)ScriptBaseClass.PRIM_PHANTOM:
10269 res.Add(ScriptBaseClass.FALSE); 10269 res.Add(ScriptBaseClass.FALSE);
10270 break; 10270 break;
10271 10271
10272 case (int)ScriptBaseClass.PRIM_POSITION: 10272 case (int)ScriptBaseClass.PRIM_POSITION:
10273 res.Add(new LSL_Vector(sp.AbsolutePosition)); 10273 res.Add(new LSL_Vector(sp.AbsolutePosition));
10274 break; 10274 break;
10275 10275
10276 case (int)ScriptBaseClass.PRIM_SIZE: 10276 case (int)ScriptBaseClass.PRIM_SIZE:
10277 res.Add(GetAgentSize(sp)); 10277 res.Add(GetAgentSize(sp));
10278 break; 10278 break;
10279 10279
10280 case (int)ScriptBaseClass.PRIM_ROTATION: 10280 case (int)ScriptBaseClass.PRIM_ROTATION:
10281 res.Add(sp.GetWorldRotation()); 10281 res.Add(sp.GetWorldRotation());
10282 break; 10282 break;
10283 10283
10284 case (int)ScriptBaseClass.PRIM_TYPE: 10284 case (int)ScriptBaseClass.PRIM_TYPE:
10285 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); 10285 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX));
10286 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); 10286 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT));
10287 res.Add(new LSL_Vector(0, 1, 0)); 10287 res.Add(new LSL_Vector(0, 1, 0));
10288 res.Add(new LSL_Float(0)); 10288 res.Add(new LSL_Float(0));
10289 res.Add(new LSL_Vector(0, 0, 0)); 10289 res.Add(new LSL_Vector(0, 0, 0));
10290 res.Add(new LSL_Vector(1, 1, 0)); 10290 res.Add(new LSL_Vector(1, 1, 0));
10291 res.Add(new LSL_Vector(0, 0, 0)); 10291 res.Add(new LSL_Vector(0, 0, 0));
10292 break; 10292 break;
10293 10293
10294 case (int)ScriptBaseClass.PRIM_TEXTURE: 10294 case (int)ScriptBaseClass.PRIM_TEXTURE:
10295 if (remain < 1) 10295 if (remain < 1)
10296 return null; 10296 return null;
10297 10297
10298 int face = (int)rules.GetLSLIntegerItem(idx++); 10298 int face = (int)rules.GetLSLIntegerItem(idx++);
10299 if (face > 21) 10299 if (face > 21)
10300 break; 10300 break;
10301 10301
10302 res.Add(new LSL_String("")); 10302 res.Add(new LSL_String(""));
10303 res.Add(ScriptBaseClass.ZERO_VECTOR); 10303 res.Add(ScriptBaseClass.ZERO_VECTOR);
10304 res.Add(ScriptBaseClass.ZERO_VECTOR); 10304 res.Add(ScriptBaseClass.ZERO_VECTOR);
10305 res.Add(new LSL_Float(0)); 10305 res.Add(new LSL_Float(0));
10306 break; 10306 break;
10307 10307
10308 case (int)ScriptBaseClass.PRIM_COLOR: 10308 case (int)ScriptBaseClass.PRIM_COLOR:
10309 if (remain < 1) 10309 if (remain < 1)
10310 return null; 10310 return null;
10311 10311
10312 face = (int)rules.GetLSLIntegerItem(idx++); 10312 face = (int)rules.GetLSLIntegerItem(idx++);
10313 if (face > 21) 10313 if (face > 21)
10314 break; 10314 break;
10315 10315
10316 res.Add(ScriptBaseClass.ZERO_VECTOR); 10316 res.Add(ScriptBaseClass.ZERO_VECTOR);
10317 res.Add(new LSL_Float(0)); 10317 res.Add(new LSL_Float(0));
10318 break; 10318 break;
10319 10319
10320 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 10320 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
10321 if (remain < 1) 10321 if (remain < 1)
10322 return null; 10322 return null;
10323 10323
10324 face = (int)rules.GetLSLIntegerItem(idx++); 10324 face = (int)rules.GetLSLIntegerItem(idx++);
10325 if (face > 21) 10325 if (face > 21)
10326 break; 10326 break;
10327 10327
10328 res.Add(ScriptBaseClass.PRIM_SHINY_NONE); 10328 res.Add(ScriptBaseClass.PRIM_SHINY_NONE);
10329 res.Add(ScriptBaseClass.PRIM_BUMP_NONE); 10329 res.Add(ScriptBaseClass.PRIM_BUMP_NONE);
10330 break; 10330 break;
10331 10331
10332 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 10332 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
10333 if (remain < 1) 10333 if (remain < 1)
10334 return null; 10334 return null;
10335 10335
10336 face = (int)rules.GetLSLIntegerItem(idx++); 10336 face = (int)rules.GetLSLIntegerItem(idx++);
10337 if (face > 21) 10337 if (face > 21)
10338 break; 10338 break;
10339 10339
10340 res.Add(ScriptBaseClass.FALSE); 10340 res.Add(ScriptBaseClass.FALSE);
10341 break; 10341 break;
10342 10342
10343 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 10343 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
10344 res.Add(ScriptBaseClass.FALSE); 10344 res.Add(ScriptBaseClass.FALSE);
10345 res.Add(new LSL_Integer(0)); 10345 res.Add(new LSL_Integer(0));
10346 res.Add(new LSL_Float(0)); 10346 res.Add(new LSL_Float(0));
10347 res.Add(new LSL_Float(0)); 10347 res.Add(new LSL_Float(0));
10348 res.Add(new LSL_Float(0)); 10348 res.Add(new LSL_Float(0));
10349 res.Add(new LSL_Float(0)); 10349 res.Add(new LSL_Float(0));
10350 res.Add(ScriptBaseClass.ZERO_VECTOR); 10350 res.Add(ScriptBaseClass.ZERO_VECTOR);
10351 break; 10351 break;
10352 10352
10353 case (int)ScriptBaseClass.PRIM_TEXGEN: 10353 case (int)ScriptBaseClass.PRIM_TEXGEN:
10354 if (remain < 1) 10354 if (remain < 1)
10355 return null; 10355 return null;
10356 10356
10357 face = (int)rules.GetLSLIntegerItem(idx++); 10357 face = (int)rules.GetLSLIntegerItem(idx++);
10358 if (face > 21) 10358 if (face > 21)
10359 break; 10359 break;
10360 10360
10361 res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT); 10361 res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT);
10362 break; 10362 break;
10363 10363
10364 case (int)ScriptBaseClass.PRIM_POINT_LIGHT: 10364 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
10365 res.Add(ScriptBaseClass.FALSE); 10365 res.Add(ScriptBaseClass.FALSE);
10366 res.Add(ScriptBaseClass.ZERO_VECTOR); 10366 res.Add(ScriptBaseClass.ZERO_VECTOR);
10367 res.Add(ScriptBaseClass.ZERO_VECTOR); 10367 res.Add(ScriptBaseClass.ZERO_VECTOR);
10368 break; 10368 break;
10369 10369
10370 case (int)ScriptBaseClass.PRIM_GLOW: 10370 case (int)ScriptBaseClass.PRIM_GLOW:
10371 if (remain < 1) 10371 if (remain < 1)
10372 return null; 10372 return null;
10373 10373
10374 face = (int)rules.GetLSLIntegerItem(idx++); 10374 face = (int)rules.GetLSLIntegerItem(idx++);
10375 if (face > 21) 10375 if (face > 21)
10376 break; 10376 break;
10377 10377
10378 res.Add(new LSL_Float(0)); 10378 res.Add(new LSL_Float(0));
10379 break; 10379 break;
10380 10380
10381 case (int)ScriptBaseClass.PRIM_TEXT: 10381 case (int)ScriptBaseClass.PRIM_TEXT:
10382 res.Add(new LSL_String("")); 10382 res.Add(new LSL_String(""));
10383 res.Add(ScriptBaseClass.ZERO_VECTOR); 10383 res.Add(ScriptBaseClass.ZERO_VECTOR);
10384 res.Add(new LSL_Float(1)); 10384 res.Add(new LSL_Float(1));
10385 break; 10385 break;
10386 10386
10387 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 10387 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
10388 res.Add(new LSL_Rotation(sp.Rotation)); 10388 res.Add(new LSL_Rotation(sp.Rotation));
10389 break; 10389 break;
10390 10390
10391 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 10391 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
10392 res.Add(new LSL_Vector(sp.OffsetPosition)); 10392 res.Add(new LSL_Vector(sp.OffsetPosition));
10393 break; 10393 break;
10394 10394
10395 case (int)ScriptBaseClass.PRIM_SLICE: 10395 case (int)ScriptBaseClass.PRIM_SLICE:
10396 res.Add(new LSL_Vector(0, 1, 0)); 10396 res.Add(new LSL_Vector(0, 1, 0));
10397 break; 10397 break;
10398 10398
10399 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 10399 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
10400 if(remain < 3) 10400 if(remain < 3)
10401 return null; 10401 return null;
10402 10402
10403 return rules.GetSublist(idx, -1); 10403 return rules.GetSublist(idx, -1);
10404 } 10404 }
10405 } 10405 }
10406 10406
10407 return null; 10407 return null;
10408 } 10408 }
10409 10409
10410 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) 10410 public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res)
10411 { 10411 {
10412 int idx = 0; 10412 int idx = 0;
10413 while (idx < rules.Length) 10413 while (idx < rules.Length)
10414 { 10414 {
10415 int code = (int)rules.GetLSLIntegerItem(idx++); 10415 int code = (int)rules.GetLSLIntegerItem(idx++);
10416 int remain = rules.Length - idx; 10416 int remain = rules.Length - idx;
10417 10417
10418 switch (code) 10418 switch (code)
10419 { 10419 {
10420 case (int)ScriptBaseClass.PRIM_MATERIAL: 10420 case (int)ScriptBaseClass.PRIM_MATERIAL:
10421 res.Add(new LSL_Integer(part.Material)); 10421 res.Add(new LSL_Integer(part.Material));
10422 break; 10422 break;
10423 10423
10424 case (int)ScriptBaseClass.PRIM_PHYSICS: 10424 case (int)ScriptBaseClass.PRIM_PHYSICS:
10425 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) 10425 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0)
10426 res.Add(new LSL_Integer(1)); 10426 res.Add(new LSL_Integer(1));
10427 else 10427 else
10428 res.Add(new LSL_Integer(0)); 10428 res.Add(new LSL_Integer(0));
10429 break; 10429 break;
10430 10430
10431 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: 10431 case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ:
10432 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) 10432 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0)
10433 res.Add(new LSL_Integer(1)); 10433 res.Add(new LSL_Integer(1));
10434 else 10434 else
10435 res.Add(new LSL_Integer(0)); 10435 res.Add(new LSL_Integer(0));
10436 break; 10436 break;
10437 10437
10438 case (int)ScriptBaseClass.PRIM_PHANTOM: 10438 case (int)ScriptBaseClass.PRIM_PHANTOM:
10439 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) 10439 if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
10440 res.Add(new LSL_Integer(1)); 10440 res.Add(new LSL_Integer(1));
10441 else 10441 else
10442 res.Add(new LSL_Integer(0)); 10442 res.Add(new LSL_Integer(0));
10443 break; 10443 break;
10444 10444
10445 case (int)ScriptBaseClass.PRIM_POSITION: 10445 case (int)ScriptBaseClass.PRIM_POSITION:
10446 LSL_Vector v = new LSL_Vector(part.AbsolutePosition); 10446 LSL_Vector v = new LSL_Vector(part.AbsolutePosition);
10447 10447
10448 // For some reason, the part.AbsolutePosition.* values do not change if the 10448 // For some reason, the part.AbsolutePosition.* values do not change if the
10449 // linkset is rotated; they always reflect the child prim's world position 10449 // linkset is rotated; they always reflect the child prim's world position
10450 // as though the linkset is unrotated. This is incompatible behavior with SL's 10450 // as though the linkset is unrotated. This is incompatible behavior with SL's
10451 // implementation, so will break scripts imported from there (not to mention it 10451 // implementation, so will break scripts imported from there (not to mention it
10452 // makes it more difficult to determine a child prim's actual inworld position). 10452 // makes it more difficult to determine a child prim's actual inworld position).
10453 if (!part.IsRoot) 10453 if (!part.IsRoot)
10454 { 10454 {
10455 LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition); 10455 LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition);
10456 v = ((v - rootPos) * llGetRootRotation()) + rootPos; 10456 v = ((v - rootPos) * llGetRootRotation()) + rootPos;
10457 } 10457 }
10458 10458
10459 res.Add(v); 10459 res.Add(v);
10460 break; 10460 break;
10461 10461
10462 case (int)ScriptBaseClass.PRIM_SIZE: 10462 case (int)ScriptBaseClass.PRIM_SIZE:
10463 res.Add(new LSL_Vector(part.Scale)); 10463 res.Add(new LSL_Vector(part.Scale));
10464 break; 10464 break;
10465 10465
10466 case (int)ScriptBaseClass.PRIM_ROTATION: 10466 case (int)ScriptBaseClass.PRIM_ROTATION:
10467 res.Add(GetPartRot(part)); 10467 res.Add(GetPartRot(part));
10468 break; 10468 break;
10469 10469
10470 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: 10470 case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE:
10471 res.Add(new LSL_Integer((int)part.PhysicsShapeType)); 10471 res.Add(new LSL_Integer((int)part.PhysicsShapeType));
10472 break; 10472 break;
10473 10473
10474 case (int)ScriptBaseClass.PRIM_TYPE: 10474 case (int)ScriptBaseClass.PRIM_TYPE:
10475 // implementing box 10475 // implementing box
10476 PrimitiveBaseShape Shape = part.Shape; 10476 PrimitiveBaseShape Shape = part.Shape;
10477 int primType = (int)part.GetPrimType(); 10477 int primType = (int)part.GetPrimType();
10478 res.Add(new LSL_Integer(primType)); 10478 res.Add(new LSL_Integer(primType));
10479 double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX 10479 double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX
10480 double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. 10480 double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY.
10481 switch (primType) 10481 switch (primType)
10482 { 10482 {
10483 case ScriptBaseClass.PRIM_TYPE_BOX: 10483 case ScriptBaseClass.PRIM_TYPE_BOX:
10484 case ScriptBaseClass.PRIM_TYPE_CYLINDER: 10484 case ScriptBaseClass.PRIM_TYPE_CYLINDER:
10485 case ScriptBaseClass.PRIM_TYPE_PRISM: 10485 case ScriptBaseClass.PRIM_TYPE_PRISM:
10486 res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. 10486 res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
10487 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); 10487 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
10488 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); 10488 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
10489 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); 10489 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
10490 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); 10490 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
10491 res.Add(new LSL_Vector(topshearx, topsheary, 0)); 10491 res.Add(new LSL_Vector(topshearx, topsheary, 0));
10492 break; 10492 break;
10493 10493
10494 case ScriptBaseClass.PRIM_TYPE_SPHERE: 10494 case ScriptBaseClass.PRIM_TYPE_SPHERE:
10495 res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. 10495 res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
10496 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); 10496 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
10497 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); 10497 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
10498 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); 10498 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
10499 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); 10499 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
10500 break; 10500 break;
10501 10501
10502 case ScriptBaseClass.PRIM_TYPE_SCULPT: 10502 case ScriptBaseClass.PRIM_TYPE_SCULPT:
10503 res.Add(new LSL_String(Shape.SculptTexture.ToString())); 10503 res.Add(new LSL_String(Shape.SculptTexture.ToString()));
10504 res.Add(new LSL_Integer(Shape.SculptType)); 10504 res.Add(new LSL_Integer(Shape.SculptType));
10505 break; 10505 break;
10506 10506
10507 case ScriptBaseClass.PRIM_TYPE_RING: 10507 case ScriptBaseClass.PRIM_TYPE_RING:
10508 case ScriptBaseClass.PRIM_TYPE_TUBE: 10508 case ScriptBaseClass.PRIM_TYPE_TUBE:
10509 case ScriptBaseClass.PRIM_TYPE_TORUS: 10509 case ScriptBaseClass.PRIM_TYPE_TORUS:
10510 // holeshape 10510 // holeshape
10511 res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. 10511 res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble.
10512 10512
10513 // cut 10513 // cut
10514 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); 10514 res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0));
10515 10515
10516 // hollow 10516 // hollow
10517 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); 10517 res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0));
10518 10518
10519 // twist 10519 // twist
10520 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); 10520 res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0));
10521 10521
10522 // vector holesize 10522 // vector holesize
10523 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); 10523 res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0));
10524 10524
10525 // vector topshear 10525 // vector topshear
10526 res.Add(new LSL_Vector(topshearx, topsheary, 0)); 10526 res.Add(new LSL_Vector(topshearx, topsheary, 0));
10527 10527
10528 // vector profilecut 10528 // vector profilecut
10529 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); 10529 res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0));
10530 10530
10531 // vector tapera 10531 // vector tapera
10532 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); 10532 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
10533 10533
10534 // float revolutions 10534 // float revolutions
10535 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); 10535 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
10536 // Slightly inaccurate, because an unsigned byte is being used to represent 10536 // Slightly inaccurate, because an unsigned byte is being used to represent
10537 // the entire range of floating-point values from 1.0 through 4.0 (which is how 10537 // the entire range of floating-point values from 1.0 through 4.0 (which is how
10538 // SL does it). 10538 // SL does it).
10539 // 10539 //
10540 // Using these formulas to store and retrieve PathRevolutions, it is not 10540 // Using these formulas to store and retrieve PathRevolutions, it is not
10541 // possible to use all values between 1.00 and 4.00. For instance, you can't 10541 // possible to use all values between 1.00 and 4.00. For instance, you can't
10542 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you 10542 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
10543 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them 10543 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
10544 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar 10544 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
10545 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. 10545 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
10546 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value 10546 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
10547 // such as 1.10. So, SL must store and retreive the actual user input rather 10547 // such as 1.10. So, SL must store and retreive the actual user input rather
10548 // than only storing the encoded value. 10548 // than only storing the encoded value.
10549 10549
10550 // float radiusoffset 10550 // float radiusoffset
10551 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); 10551 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
10552 10552
10553 // float skew 10553 // float skew
10554 res.Add(new LSL_Float(Shape.PathSkew / 100.0)); 10554 res.Add(new LSL_Float(Shape.PathSkew / 100.0));
10555 break; 10555 break;
10556 } 10556 }
10557 break; 10557 break;
10558 10558
10559 case (int)ScriptBaseClass.PRIM_TEXTURE: 10559 case (int)ScriptBaseClass.PRIM_TEXTURE:
10560 if (remain < 1) 10560 if (remain < 1)
10561 return null; 10561 return null;
10562 10562
10563 int face = (int)rules.GetLSLIntegerItem(idx++); 10563 int face = (int)rules.GetLSLIntegerItem(idx++);
10564 Primitive.TextureEntry tex = part.Shape.Textures; 10564 Primitive.TextureEntry tex = part.Shape.Textures;
10565 if (face == ScriptBaseClass.ALL_SIDES) 10565 if (face == ScriptBaseClass.ALL_SIDES)
10566 { 10566 {
10567 for (face = 0 ; face < GetNumberOfSides(part); face++) 10567 for (face = 0 ; face < GetNumberOfSides(part); face++)
10568 { 10568 {
10569 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10569 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10570 10570
10571 res.Add(new LSL_String(texface.TextureID.ToString())); 10571 res.Add(new LSL_String(texface.TextureID.ToString()));
10572 res.Add(new LSL_Vector(texface.RepeatU, 10572 res.Add(new LSL_Vector(texface.RepeatU,
10573 texface.RepeatV, 10573 texface.RepeatV,
10574 0)); 10574 0));
10575 res.Add(new LSL_Vector(texface.OffsetU, 10575 res.Add(new LSL_Vector(texface.OffsetU,
10576 texface.OffsetV, 10576 texface.OffsetV,
10577 0)); 10577 0));
10578 res.Add(new LSL_Float(texface.Rotation)); 10578 res.Add(new LSL_Float(texface.Rotation));
10579 } 10579 }
10580 } 10580 }
10581 else 10581 else
10582 { 10582 {
10583 if (face >= 0 && face < GetNumberOfSides(part)) 10583 if (face >= 0 && face < GetNumberOfSides(part))
10584 { 10584 {
10585 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10585 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10586 10586
10587 res.Add(new LSL_String(texface.TextureID.ToString())); 10587 res.Add(new LSL_String(texface.TextureID.ToString()));
10588 res.Add(new LSL_Vector(texface.RepeatU, 10588 res.Add(new LSL_Vector(texface.RepeatU,
10589 texface.RepeatV, 10589 texface.RepeatV,
10590 0)); 10590 0));
10591 res.Add(new LSL_Vector(texface.OffsetU, 10591 res.Add(new LSL_Vector(texface.OffsetU,
10592 texface.OffsetV, 10592 texface.OffsetV,
10593 0)); 10593 0));
10594 res.Add(new LSL_Float(texface.Rotation)); 10594 res.Add(new LSL_Float(texface.Rotation));
10595 } 10595 }
10596 } 10596 }
10597 break; 10597 break;
10598 10598
10599 case (int)ScriptBaseClass.PRIM_COLOR: 10599 case (int)ScriptBaseClass.PRIM_COLOR:
10600 if (remain < 1) 10600 if (remain < 1)
10601 return null; 10601 return null;
10602 10602
10603 face=(int)rules.GetLSLIntegerItem(idx++); 10603 face=(int)rules.GetLSLIntegerItem(idx++);
10604 10604
10605 tex = part.Shape.Textures; 10605 tex = part.Shape.Textures;
10606 Color4 texcolor; 10606 Color4 texcolor;
10607 if (face == ScriptBaseClass.ALL_SIDES) 10607 if (face == ScriptBaseClass.ALL_SIDES)
10608 { 10608 {
10609 for (face = 0 ; face < GetNumberOfSides(part); face++) 10609 for (face = 0 ; face < GetNumberOfSides(part); face++)
10610 { 10610 {
10611 texcolor = tex.GetFace((uint)face).RGBA; 10611 texcolor = tex.GetFace((uint)face).RGBA;
10612 res.Add(new LSL_Vector(texcolor.R, 10612 res.Add(new LSL_Vector(texcolor.R,
10613 texcolor.G, 10613 texcolor.G,
10614 texcolor.B)); 10614 texcolor.B));
10615 res.Add(new LSL_Float(texcolor.A)); 10615 res.Add(new LSL_Float(texcolor.A));
10616 } 10616 }
10617 } 10617 }
10618 else 10618 else
10619 { 10619 {
10620 texcolor = tex.GetFace((uint)face).RGBA; 10620 texcolor = tex.GetFace((uint)face).RGBA;
10621 res.Add(new LSL_Vector(texcolor.R, 10621 res.Add(new LSL_Vector(texcolor.R,
10622 texcolor.G, 10622 texcolor.G,
10623 texcolor.B)); 10623 texcolor.B));
10624 res.Add(new LSL_Float(texcolor.A)); 10624 res.Add(new LSL_Float(texcolor.A));
10625 } 10625 }
10626 break; 10626 break;
10627 10627
10628 case (int)ScriptBaseClass.PRIM_BUMP_SHINY: 10628 case (int)ScriptBaseClass.PRIM_BUMP_SHINY:
10629 if (remain < 1) 10629 if (remain < 1)
10630 return null; 10630 return null;
10631 10631
10632 face=(int)rules.GetLSLIntegerItem(idx++); 10632 face=(int)rules.GetLSLIntegerItem(idx++);
10633 10633
10634 tex = part.Shape.Textures; 10634 tex = part.Shape.Textures;
10635 if (face == ScriptBaseClass.ALL_SIDES) 10635 if (face == ScriptBaseClass.ALL_SIDES)
10636 { 10636 {
10637 for (face = 0; face < GetNumberOfSides(part); face++) 10637 for (face = 0; face < GetNumberOfSides(part); face++)
10638 { 10638 {
10639 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10639 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10640 // Convert Shininess to PRIM_SHINY_* 10640 // Convert Shininess to PRIM_SHINY_*
10641 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 10641 res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
10642 // PRIM_BUMP_* 10642 // PRIM_BUMP_*
10643 res.Add(new LSL_Integer((int)texface.Bump)); 10643 res.Add(new LSL_Integer((int)texface.Bump));
10644 } 10644 }
10645 } 10645 }
10646 else 10646 else
10647 { 10647 {
10648 if (face >= 0 && face < GetNumberOfSides(part)) 10648 if (face >= 0 && face < GetNumberOfSides(part))
10649 { 10649 {
10650 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10650 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10651 // Convert Shininess to PRIM_SHINY_* 10651 // Convert Shininess to PRIM_SHINY_*
10652 res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); 10652 res.Add(new LSL_Integer((uint)texface.Shiny >> 6));
10653 // PRIM_BUMP_* 10653 // PRIM_BUMP_*
10654 res.Add(new LSL_Integer((int)texface.Bump)); 10654 res.Add(new LSL_Integer((int)texface.Bump));
10655 } 10655 }
10656 } 10656 }
10657 break; 10657 break;
10658 10658
10659 case (int)ScriptBaseClass.PRIM_FULLBRIGHT: 10659 case (int)ScriptBaseClass.PRIM_FULLBRIGHT:
10660 if (remain < 1) 10660 if (remain < 1)
10661 return null; 10661 return null;
10662 10662
10663 face = (int)rules.GetLSLIntegerItem(idx++); 10663 face = (int)rules.GetLSLIntegerItem(idx++);
10664 10664
10665 tex = part.Shape.Textures; 10665 tex = part.Shape.Textures;
10666 if (face == ScriptBaseClass.ALL_SIDES) 10666 if (face == ScriptBaseClass.ALL_SIDES)
10667 { 10667 {
10668 for (face = 0; face < GetNumberOfSides(part); face++) 10668 for (face = 0; face < GetNumberOfSides(part); face++)
10669 { 10669 {
10670 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10670 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10671 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 10671 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
10672 } 10672 }
10673 } 10673 }
10674 else 10674 else
10675 { 10675 {
10676 if (face >= 0 && face < GetNumberOfSides(part)) 10676 if (face >= 0 && face < GetNumberOfSides(part))
10677 { 10677 {
10678 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10678 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10679 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); 10679 res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0));
10680 } 10680 }
10681 } 10681 }
10682 break; 10682 break;
10683 10683
10684 case (int)ScriptBaseClass.PRIM_FLEXIBLE: 10684 case (int)ScriptBaseClass.PRIM_FLEXIBLE:
10685 PrimitiveBaseShape shape = part.Shape; 10685 PrimitiveBaseShape shape = part.Shape;
10686 10686
10687 if (shape.FlexiEntry) 10687 if (shape.FlexiEntry)
10688 res.Add(new LSL_Integer(1)); // active 10688 res.Add(new LSL_Integer(1)); // active
10689 else 10689 else
10690 res.Add(new LSL_Integer(0)); 10690 res.Add(new LSL_Integer(0));
10691 res.Add(new LSL_Integer(shape.FlexiSoftness));// softness 10691 res.Add(new LSL_Integer(shape.FlexiSoftness));// softness
10692 res.Add(new LSL_Float(shape.FlexiGravity)); // gravity 10692 res.Add(new LSL_Float(shape.FlexiGravity)); // gravity
10693 res.Add(new LSL_Float(shape.FlexiDrag)); // friction 10693 res.Add(new LSL_Float(shape.FlexiDrag)); // friction
10694 res.Add(new LSL_Float(shape.FlexiWind)); // wind 10694 res.Add(new LSL_Float(shape.FlexiWind)); // wind
10695 res.Add(new LSL_Float(shape.FlexiTension)); // tension 10695 res.Add(new LSL_Float(shape.FlexiTension)); // tension
10696 res.Add(new LSL_Vector(shape.FlexiForceX, // force 10696 res.Add(new LSL_Vector(shape.FlexiForceX, // force
10697 shape.FlexiForceY, 10697 shape.FlexiForceY,
10698 shape.FlexiForceZ)); 10698 shape.FlexiForceZ));
10699 break; 10699 break;
10700 10700
10701 case (int)ScriptBaseClass.PRIM_TEXGEN: 10701 case (int)ScriptBaseClass.PRIM_TEXGEN:
10702 if (remain < 1) 10702 if (remain < 1)
10703 return null; 10703 return null;
10704 10704
10705 face=(int)rules.GetLSLIntegerItem(idx++); 10705 face=(int)rules.GetLSLIntegerItem(idx++);
10706 10706
10707 tex = part.Shape.Textures; 10707 tex = part.Shape.Textures;
10708 if (face == ScriptBaseClass.ALL_SIDES) 10708 if (face == ScriptBaseClass.ALL_SIDES)
10709 { 10709 {
10710 for (face = 0; face < GetNumberOfSides(part); face++) 10710 for (face = 0; face < GetNumberOfSides(part); face++)
10711 { 10711 {
10712 MappingType texgen = tex.GetFace((uint)face).TexMapType; 10712 MappingType texgen = tex.GetFace((uint)face).TexMapType;
10713 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. 10713 // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc.
10714 res.Add(new LSL_Integer((uint)texgen >> 1)); 10714 res.Add(new LSL_Integer((uint)texgen >> 1));
10715 } 10715 }
10716 } 10716 }
10717 else 10717 else
10718 { 10718 {
10719 if (face >= 0 && face < GetNumberOfSides(part)) 10719 if (face >= 0 && face < GetNumberOfSides(part))
10720 { 10720 {
10721 MappingType texgen = tex.GetFace((uint)face).TexMapType; 10721 MappingType texgen = tex.GetFace((uint)face).TexMapType;
10722 res.Add(new LSL_Integer((uint)texgen >> 1)); 10722 res.Add(new LSL_Integer((uint)texgen >> 1));
10723 } 10723 }
10724 } 10724 }
10725 break; 10725 break;
10726 10726
10727 case (int)ScriptBaseClass.PRIM_POINT_LIGHT: 10727 case (int)ScriptBaseClass.PRIM_POINT_LIGHT:
10728 shape = part.Shape; 10728 shape = part.Shape;
10729 10729
10730 if (shape.LightEntry) 10730 if (shape.LightEntry)
10731 res.Add(new LSL_Integer(1)); // active 10731 res.Add(new LSL_Integer(1)); // active
10732 else 10732 else
10733 res.Add(new LSL_Integer(0)); 10733 res.Add(new LSL_Integer(0));
10734 res.Add(new LSL_Vector(shape.LightColorR, // color 10734 res.Add(new LSL_Vector(shape.LightColorR, // color
10735 shape.LightColorG, 10735 shape.LightColorG,
10736 shape.LightColorB)); 10736 shape.LightColorB));
10737 res.Add(new LSL_Float(shape.LightIntensity)); // intensity 10737 res.Add(new LSL_Float(shape.LightIntensity)); // intensity
10738 res.Add(new LSL_Float(shape.LightRadius)); // radius 10738 res.Add(new LSL_Float(shape.LightRadius)); // radius
10739 res.Add(new LSL_Float(shape.LightFalloff)); // falloff 10739 res.Add(new LSL_Float(shape.LightFalloff)); // falloff
10740 break; 10740 break;
10741 10741
10742 case (int)ScriptBaseClass.PRIM_GLOW: 10742 case (int)ScriptBaseClass.PRIM_GLOW:
10743 if (remain < 1) 10743 if (remain < 1)
10744 return null; 10744 return null;
10745 10745
10746 face=(int)rules.GetLSLIntegerItem(idx++); 10746 face=(int)rules.GetLSLIntegerItem(idx++);
10747 10747
10748 tex = part.Shape.Textures; 10748 tex = part.Shape.Textures;
10749 if (face == ScriptBaseClass.ALL_SIDES) 10749 if (face == ScriptBaseClass.ALL_SIDES)
10750 { 10750 {
10751 for (face = 0; face < GetNumberOfSides(part); face++) 10751 for (face = 0; face < GetNumberOfSides(part); face++)
10752 { 10752 {
10753 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10753 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10754 res.Add(new LSL_Float(texface.Glow)); 10754 res.Add(new LSL_Float(texface.Glow));
10755 } 10755 }
10756 } 10756 }
10757 else 10757 else
10758 { 10758 {
10759 if (face >= 0 && face < GetNumberOfSides(part)) 10759 if (face >= 0 && face < GetNumberOfSides(part))
10760 { 10760 {
10761 Primitive.TextureEntryFace texface = tex.GetFace((uint)face); 10761 Primitive.TextureEntryFace texface = tex.GetFace((uint)face);
10762 res.Add(new LSL_Float(texface.Glow)); 10762 res.Add(new LSL_Float(texface.Glow));
10763 } 10763 }
10764 } 10764 }
10765 break; 10765 break;
10766 10766
10767 case (int)ScriptBaseClass.PRIM_TEXT: 10767 case (int)ScriptBaseClass.PRIM_TEXT:
10768 Color4 textColor = part.GetTextColor(); 10768 Color4 textColor = part.GetTextColor();
10769 res.Add(new LSL_String(part.Text)); 10769 res.Add(new LSL_String(part.Text));
10770 res.Add(new LSL_Vector(textColor.R, 10770 res.Add(new LSL_Vector(textColor.R,
10771 textColor.G, 10771 textColor.G,
10772 textColor.B)); 10772 textColor.B));
10773 res.Add(new LSL_Float(1.0 - textColor.A)); 10773 res.Add(new LSL_Float(1.0 - textColor.A));
10774 break; 10774 break;
10775 case (int)ScriptBaseClass.PRIM_NAME: 10775 case (int)ScriptBaseClass.PRIM_NAME:
10776 res.Add(new LSL_String(part.Name)); 10776 res.Add(new LSL_String(part.Name));
10777 break; 10777 break;
10778 case (int)ScriptBaseClass.PRIM_DESC: 10778 case (int)ScriptBaseClass.PRIM_DESC:
10779 res.Add(new LSL_String(part.Description)); 10779 res.Add(new LSL_String(part.Description));
10780 break; 10780 break;
10781 case (int)ScriptBaseClass.PRIM_ROT_LOCAL: 10781 case (int)ScriptBaseClass.PRIM_ROT_LOCAL:
10782 res.Add(new LSL_Rotation(part.RotationOffset)); 10782 res.Add(new LSL_Rotation(part.RotationOffset));
10783 break; 10783 break;
10784 case (int)ScriptBaseClass.PRIM_POS_LOCAL: 10784 case (int)ScriptBaseClass.PRIM_POS_LOCAL:
10785 res.Add(new LSL_Vector(GetPartLocalPos(part))); 10785 res.Add(new LSL_Vector(GetPartLocalPos(part)));
10786 break; 10786 break;
10787 case (int)ScriptBaseClass.PRIM_SLICE: 10787 case (int)ScriptBaseClass.PRIM_SLICE:
10788 PrimType prim_type = part.GetPrimType(); 10788 PrimType prim_type = part.GetPrimType();
10789 bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); 10789 bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING);
10790 res.Add(new LSL_Vector( 10790 res.Add(new LSL_Vector(
10791 (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, 10791 (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0,
10792 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, 10792 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0,
10793 0 10793 0
10794 )); 10794 ));
10795 break; 10795 break;
10796 case (int)ScriptBaseClass.PRIM_LINK_TARGET: 10796 case (int)ScriptBaseClass.PRIM_LINK_TARGET:
10797 10797
10798 // TODO: Should be issuing a runtime script warning in this case. 10798 // TODO: Should be issuing a runtime script warning in this case.
10799 if (remain < 2) 10799 if (remain < 2)
10800 return null; 10800 return null;
10801 10801
10802 return rules.GetSublist(idx, -1); 10802 return rules.GetSublist(idx, -1);
10803 } 10803 }
10804 } 10804 }
10805 10805
10806 return null; 10806 return null;
10807 } 10807 }
10808 10808
10809 public LSL_List llGetPrimMediaParams(int face, LSL_List rules) 10809 public LSL_List llGetPrimMediaParams(int face, LSL_List rules)
10810 { 10810 {
10811 m_host.AddScriptLPS(1); 10811 m_host.AddScriptLPS(1);
10812 ScriptSleep(m_sleepMsOnGetPrimMediaParams); 10812 ScriptSleep(m_sleepMsOnGetPrimMediaParams);
10813 return GetPrimMediaParams(m_host, face, rules); 10813 return GetPrimMediaParams(m_host, face, rules);
10814 } 10814 }
10815 10815
10816 public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) 10816 public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
10817 { 10817 {
10818 m_host.AddScriptLPS(1); 10818 m_host.AddScriptLPS(1);
10819 ScriptSleep(m_sleepMsOnGetLinkMedia); 10819 ScriptSleep(m_sleepMsOnGetLinkMedia);
10820 if (link == ScriptBaseClass.LINK_ROOT) 10820 if (link == ScriptBaseClass.LINK_ROOT)
10821 return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); 10821 return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
10822 else if (link == ScriptBaseClass.LINK_THIS) 10822 else if (link == ScriptBaseClass.LINK_THIS)
10823 return GetPrimMediaParams(m_host, face, rules); 10823 return GetPrimMediaParams(m_host, face, rules);
10824 else 10824 else
10825 { 10825 {
10826 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); 10826 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
10827 if (null != part) 10827 if (null != part)
10828 return GetPrimMediaParams(part, face, rules); 10828 return GetPrimMediaParams(part, face, rules);
10829 } 10829 }
10830 10830
10831 return new LSL_List(); 10831 return new LSL_List();
10832 } 10832 }
10833 10833
10834 private LSL_List GetPrimMediaParams(SceneObjectPart part, int face, LSL_List rules) 10834 private LSL_List GetPrimMediaParams(SceneObjectPart part, int face, LSL_List rules)
10835 { 10835 {
10836 // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid 10836 // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid
10837 // TODO: Need to correctly handle case where a face has no media (which gives back an empty list). 10837 // TODO: Need to correctly handle case where a face has no media (which gives back an empty list).
10838 // Assuming silently fail means give back an empty list. Ideally, need to check this. 10838 // Assuming silently fail means give back an empty list. Ideally, need to check this.
10839 if (face < 0 || face > part.GetNumberOfSides() - 1) 10839 if (face < 0 || face > part.GetNumberOfSides() - 1)
10840 return new LSL_List(); 10840 return new LSL_List();
10841 10841
10842 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); 10842 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
10843 if (null == module) 10843 if (null == module)
10844 return new LSL_List(); 10844 return new LSL_List();
10845 10845
10846 MediaEntry me = module.GetMediaEntry(part, face); 10846 MediaEntry me = module.GetMediaEntry(part, face);
10847 10847
10848 // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams 10848 // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams
10849 if (null == me) 10849 if (null == me)
10850 return new LSL_List(); 10850 return new LSL_List();
10851 10851
10852 LSL_List res = new LSL_List(); 10852 LSL_List res = new LSL_List();
10853 10853
10854 for (int i = 0; i < rules.Length; i++) 10854 for (int i = 0; i < rules.Length; i++)
10855 { 10855 {
10856 int code = (int)rules.GetLSLIntegerItem(i); 10856 int code = (int)rules.GetLSLIntegerItem(i);
10857 10857
10858 switch (code) 10858 switch (code)
10859 { 10859 {
10860 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: 10860 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
10861 // Not implemented 10861 // Not implemented
10862 res.Add(new LSL_Integer(0)); 10862 res.Add(new LSL_Integer(0));
10863 break; 10863 break;
10864 10864
10865 case ScriptBaseClass.PRIM_MEDIA_CONTROLS: 10865 case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
10866 if (me.Controls == MediaControls.Standard) 10866 if (me.Controls == MediaControls.Standard)
10867 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD)); 10867 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD));
10868 else 10868 else
10869 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI)); 10869 res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI));
10870 break; 10870 break;
10871 10871
10872 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: 10872 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
10873 res.Add(new LSL_String(me.CurrentURL)); 10873 res.Add(new LSL_String(me.CurrentURL));
10874 break; 10874 break;
10875 10875
10876 case ScriptBaseClass.PRIM_MEDIA_HOME_URL: 10876 case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
10877 res.Add(new LSL_String(me.HomeURL)); 10877 res.Add(new LSL_String(me.HomeURL));
10878 break; 10878 break;
10879 10879
10880 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: 10880 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
10881 res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); 10881 res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
10882 break; 10882 break;
10883 10883
10884 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: 10884 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
10885 res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); 10885 res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
10886 break; 10886 break;
10887 10887
10888 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: 10888 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
10889 res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); 10889 res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
10890 break; 10890 break;
10891 10891
10892 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: 10892 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
10893 res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); 10893 res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
10894 break; 10894 break;
10895 10895
10896 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: 10896 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
10897 res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); 10897 res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
10898 break; 10898 break;
10899 10899
10900 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS: 10900 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
10901 res.Add(new LSL_Integer(me.Width)); 10901 res.Add(new LSL_Integer(me.Width));
10902 break; 10902 break;
10903 10903
10904 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS: 10904 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
10905 res.Add(new LSL_Integer(me.Height)); 10905 res.Add(new LSL_Integer(me.Height));
10906 break; 10906 break;
10907 10907
10908 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE: 10908 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
10909 res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); 10909 res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE);
10910 break; 10910 break;
10911 10911
10912 case ScriptBaseClass.PRIM_MEDIA_WHITELIST: 10912 case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
10913 string[] urls = (string[])me.WhiteList.Clone(); 10913 string[] urls = (string[])me.WhiteList.Clone();
10914 10914
10915 for (int j = 0; j < urls.Length; j++) 10915 for (int j = 0; j < urls.Length; j++)
10916 urls[j] = Uri.EscapeDataString(urls[j]); 10916 urls[j] = Uri.EscapeDataString(urls[j]);
10917 10917
10918 res.Add(new LSL_String(string.Join(", ", urls))); 10918 res.Add(new LSL_String(string.Join(", ", urls)));
10919 break; 10919 break;
10920 10920
10921 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT: 10921 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
10922 res.Add(new LSL_Integer((int)me.InteractPermissions)); 10922 res.Add(new LSL_Integer((int)me.InteractPermissions));
10923 break; 10923 break;
10924 10924
10925 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL: 10925 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
10926 res.Add(new LSL_Integer((int)me.ControlPermissions)); 10926 res.Add(new LSL_Integer((int)me.ControlPermissions));
10927 break; 10927 break;
10928 10928
10929 default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS; 10929 default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS;
10930 } 10930 }
10931 } 10931 }
10932 10932
10933 return res; 10933 return res;
10934 } 10934 }
10935 10935
10936 public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules) 10936 public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules)
10937 { 10937 {
10938 m_host.AddScriptLPS(1); 10938 m_host.AddScriptLPS(1);
10939 ScriptSleep(m_sleepMsOnSetPrimMediaParams); 10939 ScriptSleep(m_sleepMsOnSetPrimMediaParams);
10940 return SetPrimMediaParams(m_host, face, rules); 10940 return SetPrimMediaParams(m_host, face, rules);
10941 } 10941 }
10942 10942
10943 public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) 10943 public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules)
10944 { 10944 {
10945 m_host.AddScriptLPS(1); 10945 m_host.AddScriptLPS(1);
10946 ScriptSleep(m_sleepMsOnSetLinkMedia); 10946 ScriptSleep(m_sleepMsOnSetLinkMedia);
10947 if (link == ScriptBaseClass.LINK_ROOT) 10947 if (link == ScriptBaseClass.LINK_ROOT)
10948 return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); 10948 return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules);
10949 else if (link == ScriptBaseClass.LINK_THIS) 10949 else if (link == ScriptBaseClass.LINK_THIS)
10950 return SetPrimMediaParams(m_host, face, rules); 10950 return SetPrimMediaParams(m_host, face, rules);
10951 else 10951 else
10952 { 10952 {
10953 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); 10953 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
10954 if (null != part) 10954 if (null != part)
10955 return SetPrimMediaParams(part, face, rules); 10955 return SetPrimMediaParams(part, face, rules);
10956 } 10956 }
10957 10957
10958 return ScriptBaseClass.LSL_STATUS_NOT_FOUND; 10958 return ScriptBaseClass.LSL_STATUS_NOT_FOUND;
10959 } 10959 }
10960 10960
10961 private LSL_Integer SetPrimMediaParams(SceneObjectPart part, LSL_Integer face, LSL_List rules) 10961 private LSL_Integer SetPrimMediaParams(SceneObjectPart part, LSL_Integer face, LSL_List rules)
10962 { 10962 {
10963 // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid 10963 // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid
10964 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this. 10964 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
10965 // Don't perform the media check directly 10965 // Don't perform the media check directly
10966 if (face < 0 || face > part.GetNumberOfSides() - 1) 10966 if (face < 0 || face > part.GetNumberOfSides() - 1)
10967 return ScriptBaseClass.LSL_STATUS_NOT_FOUND; 10967 return ScriptBaseClass.LSL_STATUS_NOT_FOUND;
10968 10968
10969 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); 10969 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
10970 if (null == module) 10970 if (null == module)
10971 return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED; 10971 return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED;
10972 10972
10973 MediaEntry me = module.GetMediaEntry(part, face); 10973 MediaEntry me = module.GetMediaEntry(part, face);
10974 if (null == me) 10974 if (null == me)
10975 me = new MediaEntry(); 10975 me = new MediaEntry();
10976 10976
10977 int i = 0; 10977 int i = 0;
10978 10978
10979 while (i < rules.Length - 1) 10979 while (i < rules.Length - 1)
10980 { 10980 {
10981 int code = rules.GetLSLIntegerItem(i++); 10981 int code = rules.GetLSLIntegerItem(i++);
10982 10982
10983 switch (code) 10983 switch (code)
10984 { 10984 {
10985 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: 10985 case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE:
10986 me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false); 10986 me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false);
10987 break; 10987 break;
10988 10988
10989 case ScriptBaseClass.PRIM_MEDIA_CONTROLS: 10989 case ScriptBaseClass.PRIM_MEDIA_CONTROLS:
10990 int v = rules.GetLSLIntegerItem(i++); 10990 int v = rules.GetLSLIntegerItem(i++);
10991 if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v) 10991 if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v)
10992 me.Controls = MediaControls.Standard; 10992 me.Controls = MediaControls.Standard;
10993 else 10993 else
10994 me.Controls = MediaControls.Mini; 10994 me.Controls = MediaControls.Mini;
10995 break; 10995 break;
10996 10996
10997 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: 10997 case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL:
10998 me.CurrentURL = rules.GetLSLStringItem(i++); 10998 me.CurrentURL = rules.GetLSLStringItem(i++);
10999 break; 10999 break;
11000 11000
11001 case ScriptBaseClass.PRIM_MEDIA_HOME_URL: 11001 case ScriptBaseClass.PRIM_MEDIA_HOME_URL:
11002 me.HomeURL = rules.GetLSLStringItem(i++); 11002 me.HomeURL = rules.GetLSLStringItem(i++);
11003 break; 11003 break;
11004 11004
11005 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: 11005 case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP:
11006 me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); 11006 me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11007 break; 11007 break;
11008 11008
11009 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: 11009 case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY:
11010 me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); 11010 me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11011 break; 11011 break;
11012 11012
11013 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: 11013 case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE:
11014 me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); 11014 me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11015 break; 11015 break;
11016 11016
11017 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: 11017 case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM:
11018 me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); 11018 me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11019 break; 11019 break;
11020 11020
11021 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: 11021 case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT:
11022 me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); 11022 me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11023 break; 11023 break;
11024 11024
11025 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS: 11025 case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS:
11026 me.Width = (int)rules.GetLSLIntegerItem(i++); 11026 me.Width = (int)rules.GetLSLIntegerItem(i++);
11027 break; 11027 break;
11028 11028
11029 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS: 11029 case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS:
11030 me.Height = (int)rules.GetLSLIntegerItem(i++); 11030 me.Height = (int)rules.GetLSLIntegerItem(i++);
11031 break; 11031 break;
11032 11032
11033 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE: 11033 case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE:
11034 me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); 11034 me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false);
11035 break; 11035 break;
11036 11036
11037 case ScriptBaseClass.PRIM_MEDIA_WHITELIST: 11037 case ScriptBaseClass.PRIM_MEDIA_WHITELIST:
11038 string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' }); 11038 string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' });
11039 List<string> whiteListUrls = new List<string>(); 11039 List<string> whiteListUrls = new List<string>();
11040 Array.ForEach( 11040 Array.ForEach(
11041 rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); }); 11041 rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); });
11042 me.WhiteList = whiteListUrls.ToArray(); 11042 me.WhiteList = whiteListUrls.ToArray();
11043 break; 11043 break;
11044 11044
11045 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT: 11045 case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT:
11046 me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++); 11046 me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
11047 break; 11047 break;
11048 11048
11049 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL: 11049 case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL:
11050 me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++); 11050 me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++);
11051 break; 11051 break;
11052 11052
11053 default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS; 11053 default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS;
11054 } 11054 }
11055 } 11055 }
11056 11056
11057 module.SetMediaEntry(part, face, me); 11057 module.SetMediaEntry(part, face, me);
11058 11058
11059 return ScriptBaseClass.LSL_STATUS_OK; 11059 return ScriptBaseClass.LSL_STATUS_OK;
11060 } 11060 }
11061 11061
11062 public LSL_Integer llClearPrimMedia(LSL_Integer face) 11062 public LSL_Integer llClearPrimMedia(LSL_Integer face)
11063 { 11063 {
11064 m_host.AddScriptLPS(1); 11064 m_host.AddScriptLPS(1);
11065 ScriptSleep(m_sleepMsOnClearPrimMedia); 11065 ScriptSleep(m_sleepMsOnClearPrimMedia);
11066 return ClearPrimMedia(m_host, face); 11066 return ClearPrimMedia(m_host, face);
11067 } 11067 }
11068 11068
11069 public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face) 11069 public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face)
11070 { 11070 {
11071 m_host.AddScriptLPS(1); 11071 m_host.AddScriptLPS(1);
11072 ScriptSleep(m_sleepMsOnClearLinkMedia); 11072 ScriptSleep(m_sleepMsOnClearLinkMedia);
11073 if (link == ScriptBaseClass.LINK_ROOT) 11073 if (link == ScriptBaseClass.LINK_ROOT)
11074 return ClearPrimMedia(m_host.ParentGroup.RootPart, face); 11074 return ClearPrimMedia(m_host.ParentGroup.RootPart, face);
11075 else if (link == ScriptBaseClass.LINK_THIS) 11075 else if (link == ScriptBaseClass.LINK_THIS)
11076 return ClearPrimMedia(m_host, face); 11076 return ClearPrimMedia(m_host, face);
11077 else 11077 else
11078 { 11078 {
11079 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); 11079 SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link);
11080 if (null != part) 11080 if (null != part)
11081 return ClearPrimMedia(part, face); 11081 return ClearPrimMedia(part, face);
11082 } 11082 }
11083 11083
11084 return ScriptBaseClass.LSL_STATUS_NOT_FOUND; 11084 return ScriptBaseClass.LSL_STATUS_NOT_FOUND;
11085 } 11085 }
11086 11086
11087 private LSL_Integer ClearPrimMedia(SceneObjectPart part, LSL_Integer face) 11087 private LSL_Integer ClearPrimMedia(SceneObjectPart part, LSL_Integer face)
11088 { 11088 {
11089 // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid 11089 // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid
11090 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this. 11090 // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this.
11091 // FIXME: Don't perform the media check directly 11091 // FIXME: Don't perform the media check directly
11092 if (face < 0 || face > part.GetNumberOfSides() - 1) 11092 if (face < 0 || face > part.GetNumberOfSides() - 1)
11093 return ScriptBaseClass.LSL_STATUS_NOT_FOUND; 11093 return ScriptBaseClass.LSL_STATUS_NOT_FOUND;
11094 11094
11095 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); 11095 IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>();
11096 if (null == module) 11096 if (null == module)
11097 return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED; 11097 return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED;
11098 11098
11099 module.ClearMediaEntry(part, face); 11099 module.ClearMediaEntry(part, face);
11100 11100
11101 return ScriptBaseClass.LSL_STATUS_OK; 11101 return ScriptBaseClass.LSL_STATUS_OK;
11102 } 11102 }
11103 11103
11104 // <remarks> 11104 // <remarks>
11105 // <para> 11105 // <para>
11106 // The .NET definition of base 64 is: 11106 // The .NET definition of base 64 is:
11107 // <list> 11107 // <list>
11108 // <item> 11108 // <item>
11109 // Significant: A-Z a-z 0-9 + - 11109 // Significant: A-Z a-z 0-9 + -
11110 // </item> 11110 // </item>
11111 // <item> 11111 // <item>
11112 // Whitespace: \t \n \r ' ' 11112 // Whitespace: \t \n \r ' '
11113 // </item> 11113 // </item>
11114 // <item> 11114 // <item>
11115 // Valueless: = 11115 // Valueless: =
11116 // </item> 11116 // </item>
11117 // <item> 11117 // <item>
11118 // End-of-string: \0 or '==' 11118 // End-of-string: \0 or '=='
11119 // </item> 11119 // </item>
11120 // </list> 11120 // </list>
11121 // </para> 11121 // </para>
11122 // <para> 11122 // <para>
11123 // Each point in a base-64 string represents 11123 // Each point in a base-64 string represents
11124 // a 6 bit value. A 32-bit integer can be 11124 // a 6 bit value. A 32-bit integer can be
11125 // represented using 6 characters (with some 11125 // represented using 6 characters (with some
11126 // redundancy). 11126 // redundancy).
11127 // </para> 11127 // </para>
11128 // <para> 11128 // <para>
11129 // LSL requires a base64 string to be 8 11129 // LSL requires a base64 string to be 8
11130 // characters in length. LSL also uses '/' 11130 // characters in length. LSL also uses '/'
11131 // rather than '-' (MIME compliant). 11131 // rather than '-' (MIME compliant).
11132 // </para> 11132 // </para>
11133 // <para> 11133 // <para>
11134 // RFC 1341 used as a reference (as specified 11134 // RFC 1341 used as a reference (as specified
11135 // by the SecondLife Wiki). 11135 // by the SecondLife Wiki).
11136 // </para> 11136 // </para>
11137 // <para> 11137 // <para>
11138 // SL do not record any kind of exception for 11138 // SL do not record any kind of exception for
11139 // these functions, so the string to integer 11139 // these functions, so the string to integer
11140 // conversion returns '0' if an invalid 11140 // conversion returns '0' if an invalid
11141 // character is encountered during conversion. 11141 // character is encountered during conversion.
11142 // </para> 11142 // </para>
11143 // <para> 11143 // <para>
11144 // References 11144 // References
11145 // <list> 11145 // <list>
11146 // <item> 11146 // <item>
11147 // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64 11147 // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64
11148 // </item> 11148 // </item>
11149 // <item> 11149 // <item>
11150 // </item> 11150 // </item>
11151 // </list> 11151 // </list>
11152 // </para> 11152 // </para>
11153 // </remarks> 11153 // </remarks>
11154 11154
11155 // <summary> 11155 // <summary>
11156 // Table for converting 6-bit integers into 11156 // Table for converting 6-bit integers into
11157 // base-64 characters 11157 // base-64 characters
11158 // </summary> 11158 // </summary>
11159 11159
11160 protected static readonly char[] i2ctable = 11160 protected static readonly char[] i2ctable =
11161 { 11161 {
11162 'A','B','C','D','E','F','G','H', 11162 'A','B','C','D','E','F','G','H',
11163 'I','J','K','L','M','N','O','P', 11163 'I','J','K','L','M','N','O','P',
11164 'Q','R','S','T','U','V','W','X', 11164 'Q','R','S','T','U','V','W','X',
11165 'Y','Z', 11165 'Y','Z',
11166 'a','b','c','d','e','f','g','h', 11166 'a','b','c','d','e','f','g','h',
11167 'i','j','k','l','m','n','o','p', 11167 'i','j','k','l','m','n','o','p',
11168 'q','r','s','t','u','v','w','x', 11168 'q','r','s','t','u','v','w','x',
11169 'y','z', 11169 'y','z',
11170 '0','1','2','3','4','5','6','7', 11170 '0','1','2','3','4','5','6','7',
11171 '8','9', 11171 '8','9',
11172 '+','/' 11172 '+','/'
11173 }; 11173 };
11174 11174
11175 // <summary> 11175 // <summary>
11176 // Table for converting base-64 characters 11176 // Table for converting base-64 characters
11177 // into 6-bit integers. 11177 // into 6-bit integers.
11178 // </summary> 11178 // </summary>
11179 11179
11180 protected static readonly int[] c2itable = 11180 protected static readonly int[] c2itable =
11181 { 11181 {
11182 -1,-1,-1,-1,-1,-1,-1,-1, // 0x 11182 -1,-1,-1,-1,-1,-1,-1,-1, // 0x
11183 -1,-1,-1,-1,-1,-1,-1,-1, 11183 -1,-1,-1,-1,-1,-1,-1,-1,
11184 -1,-1,-1,-1,-1,-1,-1,-1, // 1x 11184 -1,-1,-1,-1,-1,-1,-1,-1, // 1x
11185 -1,-1,-1,-1,-1,-1,-1,-1, 11185 -1,-1,-1,-1,-1,-1,-1,-1,
11186 -1,-1,-1,-1,-1,-1,-1,-1, // 2x 11186 -1,-1,-1,-1,-1,-1,-1,-1, // 2x
11187 -1,-1,-1,63,-1,-1,-1,64, 11187 -1,-1,-1,63,-1,-1,-1,64,
11188 53,54,55,56,57,58,59,60, // 3x 11188 53,54,55,56,57,58,59,60, // 3x
11189 61,62,-1,-1,-1,0,-1,-1, 11189 61,62,-1,-1,-1,0,-1,-1,
11190 -1,1,2,3,4,5,6,7, // 4x 11190 -1,1,2,3,4,5,6,7, // 4x
11191 8,9,10,11,12,13,14,15, 11191 8,9,10,11,12,13,14,15,
11192 16,17,18,19,20,21,22,23, // 5x 11192 16,17,18,19,20,21,22,23, // 5x
11193 24,25,26,-1,-1,-1,-1,-1, 11193 24,25,26,-1,-1,-1,-1,-1,
11194 -1,27,28,29,30,31,32,33, // 6x 11194 -1,27,28,29,30,31,32,33, // 6x
11195 34,35,36,37,38,39,40,41, 11195 34,35,36,37,38,39,40,41,
11196 42,43,44,45,46,47,48,49, // 7x 11196 42,43,44,45,46,47,48,49, // 7x
11197 50,51,52,-1,-1,-1,-1,-1, 11197 50,51,52,-1,-1,-1,-1,-1,
11198 -1,-1,-1,-1,-1,-1,-1,-1, // 8x 11198 -1,-1,-1,-1,-1,-1,-1,-1, // 8x
11199 -1,-1,-1,-1,-1,-1,-1,-1, 11199 -1,-1,-1,-1,-1,-1,-1,-1,
11200 -1,-1,-1,-1,-1,-1,-1,-1, // 9x 11200 -1,-1,-1,-1,-1,-1,-1,-1, // 9x
11201 -1,-1,-1,-1,-1,-1,-1,-1, 11201 -1,-1,-1,-1,-1,-1,-1,-1,
11202 -1,-1,-1,-1,-1,-1,-1,-1, // Ax 11202 -1,-1,-1,-1,-1,-1,-1,-1, // Ax
11203 -1,-1,-1,-1,-1,-1,-1,-1, 11203 -1,-1,-1,-1,-1,-1,-1,-1,
11204 -1,-1,-1,-1,-1,-1,-1,-1, // Bx 11204 -1,-1,-1,-1,-1,-1,-1,-1, // Bx
11205 -1,-1,-1,-1,-1,-1,-1,-1, 11205 -1,-1,-1,-1,-1,-1,-1,-1,
11206 -1,-1,-1,-1,-1,-1,-1,-1, // Cx 11206 -1,-1,-1,-1,-1,-1,-1,-1, // Cx
11207 -1,-1,-1,-1,-1,-1,-1,-1, 11207 -1,-1,-1,-1,-1,-1,-1,-1,
11208 -1,-1,-1,-1,-1,-1,-1,-1, // Dx 11208 -1,-1,-1,-1,-1,-1,-1,-1, // Dx
11209 -1,-1,-1,-1,-1,-1,-1,-1, 11209 -1,-1,-1,-1,-1,-1,-1,-1,
11210 -1,-1,-1,-1,-1,-1,-1,-1, // Ex 11210 -1,-1,-1,-1,-1,-1,-1,-1, // Ex
11211 -1,-1,-1,-1,-1,-1,-1,-1, 11211 -1,-1,-1,-1,-1,-1,-1,-1,
11212 -1,-1,-1,-1,-1,-1,-1,-1, // Fx 11212 -1,-1,-1,-1,-1,-1,-1,-1, // Fx
11213 -1,-1,-1,-1,-1,-1,-1,-1 11213 -1,-1,-1,-1,-1,-1,-1,-1
11214 }; 11214 };
11215 11215
11216 // <summary> 11216 // <summary>
11217 // Converts a 32-bit integer into a Base64 11217 // Converts a 32-bit integer into a Base64
11218 // character string. Base64 character strings 11218 // character string. Base64 character strings
11219 // are always 8 characters long. All iinteger 11219 // are always 8 characters long. All iinteger
11220 // values are acceptable. 11220 // values are acceptable.
11221 // </summary> 11221 // </summary>
11222 // <param name="number"> 11222 // <param name="number">
11223 // 32-bit integer to be converted. 11223 // 32-bit integer to be converted.
11224 // </param> 11224 // </param>
11225 // <returns> 11225 // <returns>
11226 // 8 character string. The 1st six characters 11226 // 8 character string. The 1st six characters
11227 // contain the encoded number, the last two 11227 // contain the encoded number, the last two
11228 // characters are padded with "=". 11228 // characters are padded with "=".
11229 // </returns> 11229 // </returns>
11230 11230
11231 public LSL_String llIntegerToBase64(int number) 11231 public LSL_String llIntegerToBase64(int number)
11232 { 11232 {
11233 // uninitialized string 11233 // uninitialized string
11234 11234
11235 char[] imdt = new char[8]; 11235 char[] imdt = new char[8];
11236 11236
11237 m_host.AddScriptLPS(1); 11237 m_host.AddScriptLPS(1);
11238 11238
11239 // Manually unroll the loop 11239 // Manually unroll the loop
11240 11240
11241 imdt[7] = '='; 11241 imdt[7] = '=';
11242 imdt[6] = '='; 11242 imdt[6] = '=';
11243 imdt[5] = i2ctable[number<<4 & 0x3F]; 11243 imdt[5] = i2ctable[number<<4 & 0x3F];
11244 imdt[4] = i2ctable[number>>2 & 0x3F]; 11244 imdt[4] = i2ctable[number>>2 & 0x3F];
11245 imdt[3] = i2ctable[number>>8 & 0x3F]; 11245 imdt[3] = i2ctable[number>>8 & 0x3F];
11246 imdt[2] = i2ctable[number>>14 & 0x3F]; 11246 imdt[2] = i2ctable[number>>14 & 0x3F];
11247 imdt[1] = i2ctable[number>>20 & 0x3F]; 11247 imdt[1] = i2ctable[number>>20 & 0x3F];
11248 imdt[0] = i2ctable[number>>26 & 0x3F]; 11248 imdt[0] = i2ctable[number>>26 & 0x3F];
11249 11249
11250 return new string(imdt); 11250 return new string(imdt);
11251 } 11251 }
11252 11252
11253 // <summary> 11253 // <summary>
11254 // Converts an eight character base-64 string 11254 // Converts an eight character base-64 string
11255 // into a 32-bit integer. 11255 // into a 32-bit integer.
11256 // </summary> 11256 // </summary>
11257 // <param name="str"> 11257 // <param name="str">
11258 // 8 characters string to be converted. Other 11258 // 8 characters string to be converted. Other
11259 // length strings return zero. 11259 // length strings return zero.
11260 // </param> 11260 // </param>
11261 // <returns> 11261 // <returns>
11262 // Returns an integer representing the 11262 // Returns an integer representing the
11263 // encoded value providedint he 1st 6 11263 // encoded value providedint he 1st 6
11264 // characters of the string. 11264 // characters of the string.
11265 // </returns> 11265 // </returns>
11266 // <remarks> 11266 // <remarks>
11267 // This is coded to behave like LSL's 11267 // This is coded to behave like LSL's
11268 // implementation (I think), based upon the 11268 // implementation (I think), based upon the
11269 // information available at the Wiki. 11269 // information available at the Wiki.
11270 // If more than 8 characters are supplied, 11270 // If more than 8 characters are supplied,
11271 // zero is returned. 11271 // zero is returned.
11272 // If a NULL string is supplied, zero will 11272 // If a NULL string is supplied, zero will
11273 // be returned. 11273 // be returned.
11274 // If fewer than 6 characters are supplied, then 11274 // If fewer than 6 characters are supplied, then
11275 // the answer will reflect a partial 11275 // the answer will reflect a partial
11276 // accumulation. 11276 // accumulation.
11277 // <para> 11277 // <para>
11278 // The 6-bit segments are 11278 // The 6-bit segments are
11279 // extracted left-to-right in big-endian mode, 11279 // extracted left-to-right in big-endian mode,
11280 // which means that segment 6 only contains the 11280 // which means that segment 6 only contains the
11281 // two low-order bits of the 32 bit integer as 11281 // two low-order bits of the 32 bit integer as
11282 // its high order 2 bits. A short string therefore 11282 // its high order 2 bits. A short string therefore
11283 // means loss of low-order information. E.g. 11283 // means loss of low-order information. E.g.
11284 // 11284 //
11285 // |<---------------------- 32-bit integer ----------------------->|<-Pad->| 11285 // |<---------------------- 32-bit integer ----------------------->|<-Pad->|
11286 // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->| 11286 // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->|
11287 // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P| 11287 // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P|
11288 // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P| 11288 // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P|
11289 // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] | 11289 // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] |
11290 // 11290 //
11291 // </para> 11291 // </para>
11292 // </remarks> 11292 // </remarks>
11293 11293
11294 public LSL_Integer llBase64ToInteger(string str) 11294 public LSL_Integer llBase64ToInteger(string str)
11295 { 11295 {
11296 int number = 0; 11296 int number = 0;
11297 int digit; 11297 int digit;
11298 11298
11299 m_host.AddScriptLPS(1); 11299 m_host.AddScriptLPS(1);
11300 11300
11301 // Require a well-fromed base64 string 11301 // Require a well-fromed base64 string
11302 11302
11303 if (str.Length > 8) 11303 if (str.Length > 8)
11304 return 0; 11304 return 0;
11305 11305
11306 // The loop is unrolled in the interests 11306 // The loop is unrolled in the interests
11307 // of performance and simple necessity. 11307 // of performance and simple necessity.
11308 // 11308 //
11309 // MUST find 6 digits to be well formed 11309 // MUST find 6 digits to be well formed
11310 // -1 == invalid 11310 // -1 == invalid
11311 // 0 == padding 11311 // 0 == padding
11312 11312
11313 if ((digit = c2itable[str[0]]) <= 0) 11313 if ((digit = c2itable[str[0]]) <= 0)
11314 { 11314 {
11315 return digit < 0 ? (int)0 : number; 11315 return digit < 0 ? (int)0 : number;
11316 } 11316 }
11317 number += --digit<<26; 11317 number += --digit<<26;
11318 11318
11319 if ((digit = c2itable[str[1]]) <= 0) 11319 if ((digit = c2itable[str[1]]) <= 0)
11320 { 11320 {
11321 return digit < 0 ? (int)0 : number; 11321 return digit < 0 ? (int)0 : number;
11322 } 11322 }
11323 number += --digit<<20; 11323 number += --digit<<20;
11324 11324
11325 if ((digit = c2itable[str[2]]) <= 0) 11325 if ((digit = c2itable[str[2]]) <= 0)
11326 { 11326 {
11327 return digit < 0 ? (int)0 : number; 11327 return digit < 0 ? (int)0 : number;
11328 } 11328 }
11329 number += --digit<<14; 11329 number += --digit<<14;
11330 11330
11331 if ((digit = c2itable[str[3]]) <= 0) 11331 if ((digit = c2itable[str[3]]) <= 0)
11332 { 11332 {
11333 return digit < 0 ? (int)0 : number; 11333 return digit < 0 ? (int)0 : number;
11334 } 11334 }
11335 number += --digit<<8; 11335 number += --digit<<8;
11336 11336
11337 if ((digit = c2itable[str[4]]) <= 0) 11337 if ((digit = c2itable[str[4]]) <= 0)
11338 { 11338 {
11339 return digit < 0 ? (int)0 : number; 11339 return digit < 0 ? (int)0 : number;
11340 } 11340 }
11341 number += --digit<<2; 11341 number += --digit<<2;
11342 11342
11343 if ((digit = c2itable[str[5]]) <= 0) 11343 if ((digit = c2itable[str[5]]) <= 0)
11344 { 11344 {
11345 return digit < 0 ? (int)0 : number; 11345 return digit < 0 ? (int)0 : number;
11346 } 11346 }
11347 number += --digit>>4; 11347 number += --digit>>4;
11348 11348
11349 // ignore trailing padding 11349 // ignore trailing padding
11350 11350
11351 return number; 11351 return number;
11352 } 11352 }
11353 11353
11354 public LSL_Float llGetGMTclock() 11354 public LSL_Float llGetGMTclock()
11355 { 11355 {
11356 m_host.AddScriptLPS(1); 11356 m_host.AddScriptLPS(1);
11357 return DateTime.UtcNow.TimeOfDay.TotalSeconds; 11357 return DateTime.UtcNow.TimeOfDay.TotalSeconds;
11358 } 11358 }
11359 11359
11360 public LSL_String llGetHTTPHeader(LSL_Key request_id, string header) 11360 public LSL_String llGetHTTPHeader(LSL_Key request_id, string header)
11361 { 11361 {
11362 m_host.AddScriptLPS(1); 11362 m_host.AddScriptLPS(1);
11363 11363
11364 if (m_UrlModule != null) 11364 if (m_UrlModule != null)
11365 return m_UrlModule.GetHttpHeader(new UUID(request_id), header); 11365 return m_UrlModule.GetHttpHeader(new UUID(request_id), header);
11366 return String.Empty; 11366 return String.Empty;
11367 } 11367 }
11368 11368
11369 11369
11370 public LSL_String llGetSimulatorHostname() 11370 public LSL_String llGetSimulatorHostname()
11371 { 11371 {
11372 m_host.AddScriptLPS(1); 11372 m_host.AddScriptLPS(1);
11373 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); 11373 IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>();
11374 return UrlModule.ExternalHostNameForLSL; 11374 return UrlModule.ExternalHostNameForLSL;
11375 } 11375 }
11376 11376
11377 // <summary> 11377 // <summary>
11378 // Scan the string supplied in 'src' and 11378 // Scan the string supplied in 'src' and
11379 // tokenize it based upon two sets of 11379 // tokenize it based upon two sets of
11380 // tokenizers provided in two lists, 11380 // tokenizers provided in two lists,
11381 // separators and spacers. 11381 // separators and spacers.
11382 // </summary> 11382 // </summary>
11383 // 11383 //
11384 // <remarks> 11384 // <remarks>
11385 // Separators demarcate tokens and are 11385 // Separators demarcate tokens and are
11386 // elided as they are encountered. Spacers 11386 // elided as they are encountered. Spacers
11387 // also demarcate tokens, but are themselves 11387 // also demarcate tokens, but are themselves
11388 // retained as tokens. 11388 // retained as tokens.
11389 // 11389 //
11390 // Both separators and spacers may be arbitrarily 11390 // Both separators and spacers may be arbitrarily
11391 // long strings. i.e. ":::". 11391 // long strings. i.e. ":::".
11392 // 11392 //
11393 // The function returns an ordered list 11393 // The function returns an ordered list
11394 // representing the tokens found in the supplied 11394 // representing the tokens found in the supplied
11395 // sources string. If two successive tokenizers 11395 // sources string. If two successive tokenizers
11396 // are encountered, then a NULL entry is added 11396 // are encountered, then a NULL entry is added
11397 // to the list. 11397 // to the list.
11398 // 11398 //
11399 // It is a precondition that the source and 11399 // It is a precondition that the source and
11400 // toekizer lisst are non-null. If they are null, 11400 // toekizer lisst are non-null. If they are null,
11401 // then a null pointer exception will be thrown 11401 // then a null pointer exception will be thrown
11402 // while their lengths are being determined. 11402 // while their lengths are being determined.
11403 // 11403 //
11404 // A small amount of working memoryis required 11404 // A small amount of working memoryis required
11405 // of approximately 8*#tokenizers. 11405 // of approximately 8*#tokenizers.
11406 // 11406 //
11407 // There are many ways in which this function 11407 // There are many ways in which this function
11408 // can be implemented, this implementation is 11408 // can be implemented, this implementation is
11409 // fairly naive and assumes that when the 11409 // fairly naive and assumes that when the
11410 // function is invooked with a short source 11410 // function is invooked with a short source
11411 // string and/or short lists of tokenizers, then 11411 // string and/or short lists of tokenizers, then
11412 // performance will not be an issue. 11412 // performance will not be an issue.
11413 // 11413 //
11414 // In order to minimize the perofrmance 11414 // In order to minimize the perofrmance
11415 // effects of long strings, or large numbers 11415 // effects of long strings, or large numbers
11416 // of tokeizers, the function skips as far as 11416 // of tokeizers, the function skips as far as
11417 // possible whenever a toekenizer is found, 11417 // possible whenever a toekenizer is found,
11418 // and eliminates redundant tokenizers as soon 11418 // and eliminates redundant tokenizers as soon
11419 // as is possible. 11419 // as is possible.
11420 // 11420 //
11421 // The implementation tries to avoid any copying 11421 // The implementation tries to avoid any copying
11422 // of arrays or other objects. 11422 // of arrays or other objects.
11423 // </remarks> 11423 // </remarks>
11424 11424
11425 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) 11425 private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls)
11426 { 11426 {
11427 int beginning = 0; 11427 int beginning = 0;
11428 int srclen = src.Length; 11428 int srclen = src.Length;
11429 int seplen = separators.Length; 11429 int seplen = separators.Length;
11430 object[] separray = separators.Data; 11430 object[] separray = separators.Data;
11431 int spclen = spacers.Length; 11431 int spclen = spacers.Length;
11432 object[] spcarray = spacers.Data; 11432 object[] spcarray = spacers.Data;
11433 int mlen = seplen+spclen; 11433 int mlen = seplen+spclen;
11434 11434
11435 int[] offset = new int[mlen+1]; 11435 int[] offset = new int[mlen+1];
11436 bool[] active = new bool[mlen]; 11436 bool[] active = new bool[mlen];
11437 11437
11438 int best; 11438 int best;
11439 int j; 11439 int j;
11440 11440
11441 // Initial capacity reduces resize cost 11441 // Initial capacity reduces resize cost
11442 11442
11443 LSL_List tokens = new LSL_List(); 11443 LSL_List tokens = new LSL_List();
11444 11444
11445 // All entries are initially valid 11445 // All entries are initially valid
11446 11446
11447 for (int i = 0; i < mlen; i++) 11447 for (int i = 0; i < mlen; i++)
11448 active[i] = true; 11448 active[i] = true;
11449 11449
11450 offset[mlen] = srclen; 11450 offset[mlen] = srclen;
11451 11451
11452 while (beginning < srclen) 11452 while (beginning < srclen)
11453 { 11453 {
11454 11454
11455 best = mlen; // as bad as it gets 11455 best = mlen; // as bad as it gets
11456 11456
11457 // Scan for separators 11457 // Scan for separators
11458 11458
11459 for (j = 0; j < seplen; j++) 11459 for (j = 0; j < seplen; j++)
11460 { 11460 {
11461 if (separray[j].ToString() == String.Empty) 11461 if (separray[j].ToString() == String.Empty)
11462 active[j] = false; 11462 active[j] = false;
11463 11463
11464 if (active[j]) 11464 if (active[j])
11465 { 11465 {
11466 // scan all of the markers 11466 // scan all of the markers
11467 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) 11467 if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1)
11468 { 11468 {
11469 // not present at all 11469 // not present at all
11470 active[j] = false; 11470 active[j] = false;
11471 } 11471 }
11472 else 11472 else
11473 { 11473 {
11474 // present and correct 11474 // present and correct
11475 if (offset[j] < offset[best]) 11475 if (offset[j] < offset[best])
11476 { 11476 {
11477 // closest so far 11477 // closest so far
11478 best = j; 11478 best = j;
11479 if (offset[best] == beginning) 11479 if (offset[best] == beginning)
11480 break; 11480 break;
11481 } 11481 }
11482 } 11482 }
11483 } 11483 }
11484 } 11484 }
11485 11485
11486 // Scan for spacers 11486 // Scan for spacers
11487 11487
11488 if (offset[best] != beginning) 11488 if (offset[best] != beginning)
11489 { 11489 {
11490 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) 11490 for (j = seplen; (j < mlen) && (offset[best] > beginning); j++)
11491 { 11491 {
11492 if (spcarray[j-seplen].ToString() == String.Empty) 11492 if (spcarray[j-seplen].ToString() == String.Empty)
11493 active[j] = false; 11493 active[j] = false;
11494 11494
11495 if (active[j]) 11495 if (active[j])
11496 { 11496 {
11497 // scan all of the markers 11497 // scan all of the markers
11498 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1) 11498 if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1)
11499 { 11499 {
11500 // not present at all 11500 // not present at all
11501 active[j] = false; 11501 active[j] = false;
11502 } 11502 }
11503 else 11503 else
11504 { 11504 {
11505 // present and correct 11505 // present and correct
11506 if (offset[j] < offset[best]) 11506 if (offset[j] < offset[best])
11507 { 11507 {
11508 // closest so far 11508 // closest so far
11509 best = j; 11509 best = j;
11510 } 11510 }
11511 } 11511 }
11512 } 11512 }
11513 } 11513 }
11514 } 11514 }
11515 11515
11516 // This is the normal exit from the scanning loop 11516 // This is the normal exit from the scanning loop
11517 11517
11518 if (best == mlen) 11518 if (best == mlen)
11519 { 11519 {
11520 // no markers were found on this pass 11520 // no markers were found on this pass
11521 // so we're pretty much done 11521 // so we're pretty much done
11522 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0)) 11522 if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0))
11523 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning))); 11523 tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning)));
11524 break; 11524 break;
11525 } 11525 }
11526 11526
11527 // Otherwise we just add the newly delimited token 11527 // Otherwise we just add the newly delimited token
11528 // and recalculate where the search should continue. 11528 // and recalculate where the search should continue.
11529 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) 11529 if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0))
11530 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); 11530 tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning)));
11531 11531
11532 if (best < seplen) 11532 if (best < seplen)
11533 { 11533 {
11534 beginning = offset[best] + (separray[best].ToString()).Length; 11534 beginning = offset[best] + (separray[best].ToString()).Length;
11535 } 11535 }
11536 else 11536 else
11537 { 11537 {
11538 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length; 11538 beginning = offset[best] + (spcarray[best - seplen].ToString()).Length;
11539 string str = spcarray[best - seplen].ToString(); 11539 string str = spcarray[best - seplen].ToString();
11540 if ((keepNulls) || ((!keepNulls) && (str.Length > 0))) 11540 if ((keepNulls) || ((!keepNulls) && (str.Length > 0)))
11541 tokens.Add(new LSL_String(str)); 11541 tokens.Add(new LSL_String(str));
11542 } 11542 }
11543 } 11543 }
11544 11544
11545 // This an awkward an not very intuitive boundary case. If the 11545 // This an awkward an not very intuitive boundary case. If the
11546 // last substring is a tokenizer, then there is an implied trailing 11546 // last substring is a tokenizer, then there is an implied trailing
11547 // null list entry. Hopefully the single comparison will not be too 11547 // null list entry. Hopefully the single comparison will not be too
11548 // arduous. Alternatively the 'break' could be replced with a return 11548 // arduous. Alternatively the 'break' could be replced with a return
11549 // but that's shabby programming. 11549 // but that's shabby programming.
11550 11550
11551 if ((beginning == srclen) && (keepNulls)) 11551 if ((beginning == srclen) && (keepNulls))
11552 { 11552 {
11553 if (srclen != 0) 11553 if (srclen != 0)
11554 tokens.Add(new LSL_String("")); 11554 tokens.Add(new LSL_String(""));
11555 } 11555 }
11556 11556
11557 return tokens; 11557 return tokens;
11558 } 11558 }
11559 11559
11560 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers) 11560 public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers)
11561 { 11561 {
11562 m_host.AddScriptLPS(1); 11562 m_host.AddScriptLPS(1);
11563 return this.ParseString(src, separators, spacers, false); 11563 return this.ParseString(src, separators, spacers, false);
11564 } 11564 }
11565 11565
11566 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) 11566 public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers)
11567 { 11567 {
11568 m_host.AddScriptLPS(1); 11568 m_host.AddScriptLPS(1);
11569 return this.ParseString(src, separators, spacers, true); 11569 return this.ParseString(src, separators, spacers, true);
11570 } 11570 }
11571 11571
11572 public LSL_Integer llGetObjectPermMask(int mask) 11572 public LSL_Integer llGetObjectPermMask(int mask)
11573 { 11573 {
11574 m_host.AddScriptLPS(1); 11574 m_host.AddScriptLPS(1);
11575 11575
11576 int permmask = 0; 11576 int permmask = 0;
11577 11577
11578 if (mask == ScriptBaseClass.MASK_BASE)//0 11578 if (mask == ScriptBaseClass.MASK_BASE)//0
11579 { 11579 {
11580 permmask = (int)m_host.BaseMask; 11580 permmask = (int)m_host.BaseMask;
11581 } 11581 }
11582 11582
11583 else if (mask == ScriptBaseClass.MASK_OWNER)//1 11583 else if (mask == ScriptBaseClass.MASK_OWNER)//1
11584 { 11584 {
11585 permmask = (int)m_host.OwnerMask; 11585 permmask = (int)m_host.OwnerMask;
11586 } 11586 }
11587 11587
11588 else if (mask == ScriptBaseClass.MASK_GROUP)//2 11588 else if (mask == ScriptBaseClass.MASK_GROUP)//2
11589 { 11589 {
11590 permmask = (int)m_host.GroupMask; 11590 permmask = (int)m_host.GroupMask;
11591 } 11591 }
11592 11592
11593 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 11593 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
11594 { 11594 {
11595 permmask = (int)m_host.EveryoneMask; 11595 permmask = (int)m_host.EveryoneMask;
11596 } 11596 }
11597 11597
11598 else if (mask == ScriptBaseClass.MASK_NEXT)//4 11598 else if (mask == ScriptBaseClass.MASK_NEXT)//4
11599 { 11599 {
11600 permmask = (int)m_host.NextOwnerMask; 11600 permmask = (int)m_host.NextOwnerMask;
11601 } 11601 }
11602 11602
11603 return permmask; 11603 return permmask;
11604 } 11604 }
11605 11605
11606 public void llSetObjectPermMask(int mask, int value) 11606 public void llSetObjectPermMask(int mask, int value)
11607 { 11607 {
11608 m_host.AddScriptLPS(1); 11608 m_host.AddScriptLPS(1);
11609 11609
11610 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) 11610 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
11611 { 11611 {
11612 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) 11612 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
11613 { 11613 {
11614 if (mask == ScriptBaseClass.MASK_BASE)//0 11614 if (mask == ScriptBaseClass.MASK_BASE)//0
11615 { 11615 {
11616 m_host.BaseMask = (uint)value; 11616 m_host.BaseMask = (uint)value;
11617 } 11617 }
11618 11618
11619 else if (mask == ScriptBaseClass.MASK_OWNER)//1 11619 else if (mask == ScriptBaseClass.MASK_OWNER)//1
11620 { 11620 {
11621 m_host.OwnerMask = (uint)value; 11621 m_host.OwnerMask = (uint)value;
11622 } 11622 }
11623 11623
11624 else if (mask == ScriptBaseClass.MASK_GROUP)//2 11624 else if (mask == ScriptBaseClass.MASK_GROUP)//2
11625 { 11625 {
11626 m_host.GroupMask = (uint)value; 11626 m_host.GroupMask = (uint)value;
11627 } 11627 }
11628 11628
11629 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 11629 else if (mask == ScriptBaseClass.MASK_EVERYONE)//3
11630 { 11630 {
11631 m_host.EveryoneMask = (uint)value; 11631 m_host.EveryoneMask = (uint)value;
11632 } 11632 }
11633 11633
11634 else if (mask == ScriptBaseClass.MASK_NEXT)//4 11634 else if (mask == ScriptBaseClass.MASK_NEXT)//4
11635 { 11635 {
11636 m_host.NextOwnerMask = (uint)value; 11636 m_host.NextOwnerMask = (uint)value;
11637 } 11637 }
11638 } 11638 }
11639 } 11639 }
11640 } 11640 }
11641 11641
11642 public LSL_Integer llGetInventoryPermMask(string itemName, int mask) 11642 public LSL_Integer llGetInventoryPermMask(string itemName, int mask)
11643 { 11643 {
11644 m_host.AddScriptLPS(1); 11644 m_host.AddScriptLPS(1);
11645 11645
11646 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); 11646 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
11647 11647
11648 if (item == null) 11648 if (item == null)
11649 return -1; 11649 return -1;
11650 11650
11651 switch (mask) 11651 switch (mask)
11652 { 11652 {
11653 case 0: 11653 case 0:
11654 return (int)item.BasePermissions; 11654 return (int)item.BasePermissions;
11655 case 1: 11655 case 1:
11656 return (int)item.CurrentPermissions; 11656 return (int)item.CurrentPermissions;
11657 case 2: 11657 case 2:
11658 return (int)item.GroupPermissions; 11658 return (int)item.GroupPermissions;
11659 case 3: 11659 case 3:
11660 return (int)item.EveryonePermissions; 11660 return (int)item.EveryonePermissions;
11661 case 4: 11661 case 4:
11662 return (int)item.NextPermissions; 11662 return (int)item.NextPermissions;
11663 } 11663 }
11664 11664
11665 return -1; 11665 return -1;
11666 } 11666 }
11667 11667
11668 public void llSetInventoryPermMask(string itemName, int mask, int value) 11668 public void llSetInventoryPermMask(string itemName, int mask, int value)
11669 { 11669 {
11670 m_host.AddScriptLPS(1); 11670 m_host.AddScriptLPS(1);
11671 11671
11672 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) 11672 if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false))
11673 { 11673 {
11674 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) 11674 if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID))
11675 { 11675 {
11676 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); 11676 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
11677 11677
11678 if (item != null) 11678 if (item != null)
11679 { 11679 {
11680 switch (mask) 11680 switch (mask)
11681 { 11681 {
11682 case 0: 11682 case 0:
11683 item.BasePermissions = (uint)value; 11683 item.BasePermissions = (uint)value;
11684 break; 11684 break;
11685 case 1: 11685 case 1:
11686 item.CurrentPermissions = (uint)value; 11686 item.CurrentPermissions = (uint)value;
11687 break; 11687 break;
11688 case 2: 11688 case 2:
11689 item.GroupPermissions = (uint)value; 11689 item.GroupPermissions = (uint)value;
11690 break; 11690 break;
11691 case 3: 11691 case 3:
11692 item.EveryonePermissions = (uint)value; 11692 item.EveryonePermissions = (uint)value;
11693 break; 11693 break;
11694 case 4: 11694 case 4:
11695 item.NextPermissions = (uint)value; 11695 item.NextPermissions = (uint)value;
11696 break; 11696 break;
11697 } 11697 }
11698 } 11698 }
11699 } 11699 }
11700 } 11700 }
11701 } 11701 }
11702 11702
11703 public LSL_String llGetInventoryCreator(string itemName) 11703 public LSL_String llGetInventoryCreator(string itemName)
11704 { 11704 {
11705 m_host.AddScriptLPS(1); 11705 m_host.AddScriptLPS(1);
11706 11706
11707 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); 11707 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName);
11708 11708
11709 if (item == null) 11709 if (item == null)
11710 { 11710 {
11711 Error("llGetInventoryCreator", "Can't find item '" + item + "'"); 11711 Error("llGetInventoryCreator", "Can't find item '" + item + "'");
11712 11712
11713 return String.Empty; 11713 return String.Empty;
11714 } 11714 }
11715 11715
11716 return item.CreatorID.ToString(); 11716 return item.CreatorID.ToString();
11717 } 11717 }
11718 11718
11719 public void llOwnerSay(string msg) 11719 public void llOwnerSay(string msg)
11720 { 11720 {
11721 m_host.AddScriptLPS(1); 11721 m_host.AddScriptLPS(1);
11722 11722
11723 World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, 11723 World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0,
11724 m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); 11724 m_host.AbsolutePosition, m_host.Name, m_host.UUID, false);
11725// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 11725// IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
11726// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg); 11726// wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg);
11727 } 11727 }
11728 11728
11729 public LSL_String llRequestSecureURL() 11729 public LSL_String llRequestSecureURL()
11730 { 11730 {
11731 m_host.AddScriptLPS(1); 11731 m_host.AddScriptLPS(1);
11732 if (m_UrlModule != null) 11732 if (m_UrlModule != null)
11733 return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); 11733 return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString();
11734 return UUID.Zero.ToString(); 11734 return UUID.Zero.ToString();
11735 } 11735 }
11736 11736
11737 public LSL_String llRequestSimulatorData(string simulator, int data) 11737 public LSL_String llRequestSimulatorData(string simulator, int data)
11738 { 11738 {
11739 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 11739 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL");
11740 11740
11741 try 11741 try
11742 { 11742 {
11743 m_host.AddScriptLPS(1); 11743 m_host.AddScriptLPS(1);
11744 11744
11745 string reply = String.Empty; 11745 string reply = String.Empty;
11746 11746
11747 GridRegion info; 11747 GridRegion info;
11748 11748
11749 if (World.RegionInfo.RegionName == simulator) 11749 if (World.RegionInfo.RegionName == simulator)
11750 info = new GridRegion(World.RegionInfo); 11750 info = new GridRegion(World.RegionInfo);
11751 else 11751 else
11752 info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); 11752 info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator);
11753 11753
11754 switch (data) 11754 switch (data)
11755 { 11755 {
11756 case ScriptBaseClass.DATA_SIM_POS: 11756 case ScriptBaseClass.DATA_SIM_POS:
11757 if (info == null) 11757 if (info == null)
11758 { 11758 {
11759 ScriptSleep(m_sleepMsOnRequestSimulatorData); 11759 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11760 return UUID.Zero.ToString(); 11760 return UUID.Zero.ToString();
11761 } 11761 }
11762 11762
11763 bool isHypergridRegion = false; 11763 bool isHypergridRegion = false;
11764 11764
11765 if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") 11765 if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "")
11766 { 11766 {
11767 // Hypergrid is currently placing real destination region co-ords into RegionSecret. 11767 // Hypergrid is currently placing real destination region co-ords into RegionSecret.
11768 // But other code can also use this field for a genuine RegionSecret! Therefore, if 11768 // But other code can also use this field for a genuine RegionSecret! Therefore, if
11769 // anything is present we need to disambiguate. 11769 // anything is present we need to disambiguate.
11770 // 11770 //
11771 // FIXME: Hypergrid should be storing this data in a different field. 11771 // FIXME: Hypergrid should be storing this data in a different field.
11772 RegionFlags regionFlags 11772 RegionFlags regionFlags
11773 = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( 11773 = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags(
11774 info.ScopeID, info.RegionID); 11774 info.ScopeID, info.RegionID);
11775 isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; 11775 isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0;
11776 } 11776 }
11777 11777
11778 if (isHypergridRegion) 11778 if (isHypergridRegion)
11779 { 11779 {
11780 uint rx = 0, ry = 0; 11780 uint rx = 0, ry = 0;
11781 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); 11781 Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry);
11782 11782
11783 reply = new LSL_Vector( 11783 reply = new LSL_Vector(
11784 rx, 11784 rx,
11785 ry, 11785 ry,
11786 0).ToString(); 11786 0).ToString();
11787 } 11787 }
11788 else 11788 else
11789 { 11789 {
11790 // Local grid co-oridnates 11790 // Local grid co-oridnates
11791 reply = new LSL_Vector( 11791 reply = new LSL_Vector(
11792 info.RegionLocX, 11792 info.RegionLocX,
11793 info.RegionLocY, 11793 info.RegionLocY,
11794 0).ToString(); 11794 0).ToString();
11795 } 11795 }
11796 break; 11796 break;
11797 case ScriptBaseClass.DATA_SIM_STATUS: 11797 case ScriptBaseClass.DATA_SIM_STATUS:
11798 if (info != null) 11798 if (info != null)
11799 reply = "up"; // Duh! 11799 reply = "up"; // Duh!
11800 else 11800 else
11801 reply = "unknown"; 11801 reply = "unknown";
11802 break; 11802 break;
11803 case ScriptBaseClass.DATA_SIM_RATING: 11803 case ScriptBaseClass.DATA_SIM_RATING:
11804 if (info == null) 11804 if (info == null)
11805 { 11805 {
11806 ScriptSleep(m_sleepMsOnRequestSimulatorData); 11806 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11807 return UUID.Zero.ToString(); 11807 return UUID.Zero.ToString();
11808 } 11808 }
11809 int access = info.Maturity; 11809 int access = info.Maturity;
11810 if (access == 0) 11810 if (access == 0)
11811 reply = "PG"; 11811 reply = "PG";
11812 else if (access == 1) 11812 else if (access == 1)
11813 reply = "MATURE"; 11813 reply = "MATURE";
11814 else if (access == 2) 11814 else if (access == 2)
11815 reply = "ADULT"; 11815 reply = "ADULT";
11816 else 11816 else
11817 reply = "UNKNOWN"; 11817 reply = "UNKNOWN";
11818 break; 11818 break;
11819 case ScriptBaseClass.DATA_SIM_RELEASE: 11819 case ScriptBaseClass.DATA_SIM_RELEASE:
11820 if (ossl != null) 11820 if (ossl != null)
11821 ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData"); 11821 ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData");
11822 reply = "OpenSim"; 11822 reply = "OpenSim";
11823 break; 11823 break;
11824 default: 11824 default:
11825 ScriptSleep(m_sleepMsOnRequestSimulatorData); 11825 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11826 return UUID.Zero.ToString(); // Raise no event 11826 return UUID.Zero.ToString(); // Raise no event
11827 } 11827 }
11828 UUID rq = UUID.Random(); 11828 UUID rq = UUID.Random();
11829 11829
11830 UUID tid = AsyncCommands. 11830 UUID tid = AsyncCommands.
11831 DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); 11831 DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
11832 11832
11833 AsyncCommands. 11833 AsyncCommands.
11834 DataserverPlugin.DataserverReply(rq.ToString(), reply); 11834 DataserverPlugin.DataserverReply(rq.ToString(), reply);
11835 11835
11836 ScriptSleep(m_sleepMsOnRequestSimulatorData); 11836 ScriptSleep(m_sleepMsOnRequestSimulatorData);
11837 return tid.ToString(); 11837 return tid.ToString();
11838 } 11838 }
11839 catch(Exception) 11839 catch(Exception)
11840 { 11840 {
11841 //m_log.Error("[LSL_API]: llRequestSimulatorData" + e.ToString()); 11841 //m_log.Error("[LSL_API]: llRequestSimulatorData" + e.ToString());
11842 return UUID.Zero.ToString(); 11842 return UUID.Zero.ToString();
11843 } 11843 }
11844 } 11844 }
11845 11845
11846 public LSL_String llRequestURL() 11846 public LSL_String llRequestURL()
11847 { 11847 {
11848 m_host.AddScriptLPS(1); 11848 m_host.AddScriptLPS(1);
11849 11849
11850 if (m_UrlModule != null) 11850 if (m_UrlModule != null)
11851 return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); 11851 return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString();
11852 return UUID.Zero.ToString(); 11852 return UUID.Zero.ToString();
11853 } 11853 }
11854 11854
11855 public void llForceMouselook(int mouselook) 11855 public void llForceMouselook(int mouselook)
11856 { 11856 {
11857 m_host.AddScriptLPS(1); 11857 m_host.AddScriptLPS(1);
11858 m_host.SetForceMouselook(mouselook != 0); 11858 m_host.SetForceMouselook(mouselook != 0);
11859 } 11859 }
11860 11860
11861 public LSL_Float llGetObjectMass(string id) 11861 public LSL_Float llGetObjectMass(string id)
11862 { 11862 {
11863 m_host.AddScriptLPS(1); 11863 m_host.AddScriptLPS(1);
11864 UUID key = new UUID(); 11864 UUID key = new UUID();
11865 if (UUID.TryParse(id, out key)) 11865 if (UUID.TryParse(id, out key))
11866 { 11866 {
11867 try 11867 try
11868 { 11868 {
11869 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); 11869 SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId);
11870 if (obj != null) 11870 if (obj != null)
11871 return (double)obj.GetMass(); 11871 return (double)obj.GetMass();
11872 // the object is null so the key is for an avatar 11872 // the object is null so the key is for an avatar
11873 ScenePresence avatar = World.GetScenePresence(key); 11873 ScenePresence avatar = World.GetScenePresence(key);
11874 if (avatar != null) 11874 if (avatar != null)
11875 if (avatar.IsChildAgent) 11875 if (avatar.IsChildAgent)
11876 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass 11876 // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass
11877 // child agents have a mass of 1.0 11877 // child agents have a mass of 1.0
11878 return 1; 11878 return 1;
11879 else 11879 else
11880 return (double)avatar.GetMass(); 11880 return (double)avatar.GetMass();
11881 } 11881 }
11882 catch (KeyNotFoundException) 11882 catch (KeyNotFoundException)
11883 { 11883 {
11884 return 0; // The Object/Agent not in the region so just return zero 11884 return 0; // The Object/Agent not in the region so just return zero
11885 } 11885 }
11886 } 11886 }
11887 return 0; 11887 return 0;
11888 } 11888 }
11889 11889
11890 /// <summary> 11890 /// <summary>
11891 /// illListReplaceList removes the sub-list defined by the inclusive indices 11891 /// illListReplaceList removes the sub-list defined by the inclusive indices
11892 /// start and end and inserts the src list in its place. The inclusive 11892 /// start and end and inserts the src list in its place. The inclusive
11893 /// nature of the indices means that at least one element must be deleted 11893 /// nature of the indices means that at least one element must be deleted
11894 /// if the indices are within the bounds of the existing list. I.e. 2,2 11894 /// if the indices are within the bounds of the existing list. I.e. 2,2
11895 /// will remove the element at index 2 and replace it with the source 11895 /// will remove the element at index 2 and replace it with the source
11896 /// list. Both indices may be negative, with the usual interpretation. An 11896 /// list. Both indices may be negative, with the usual interpretation. An
11897 /// interesting case is where end is lower than start. As these indices 11897 /// interesting case is where end is lower than start. As these indices
11898 /// bound the list to be removed, then 0->end, and start->lim are removed 11898 /// bound the list to be removed, then 0->end, and start->lim are removed
11899 /// and the source list is added as a suffix. 11899 /// and the source list is added as a suffix.
11900 /// </summary> 11900 /// </summary>
11901 11901
11902 public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) 11902 public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end)
11903 { 11903 {
11904 LSL_List pref = null; 11904 LSL_List pref = null;
11905 11905
11906 m_host.AddScriptLPS(1); 11906 m_host.AddScriptLPS(1);
11907 11907
11908 // Note that although we have normalized, both 11908 // Note that although we have normalized, both
11909 // indices could still be negative. 11909 // indices could still be negative.
11910 if (start < 0) 11910 if (start < 0)
11911 { 11911 {
11912 start = start+dest.Length; 11912 start = start+dest.Length;
11913 } 11913 }
11914 11914
11915 if (end < 0) 11915 if (end < 0)
11916 { 11916 {
11917 end = end+dest.Length; 11917 end = end+dest.Length;
11918 } 11918 }
11919 // The comventional case, remove a sequence starting with 11919 // The comventional case, remove a sequence starting with
11920 // start and ending with end. And then insert the source 11920 // start and ending with end. And then insert the source
11921 // list. 11921 // list.
11922 if (start <= end) 11922 if (start <= end)
11923 { 11923 {
11924 // If greater than zero, then there is going to be a 11924 // If greater than zero, then there is going to be a
11925 // surviving prefix. Otherwise the inclusive nature 11925 // surviving prefix. Otherwise the inclusive nature
11926 // of the indices mean that we're going to add the 11926 // of the indices mean that we're going to add the
11927 // source list as a prefix. 11927 // source list as a prefix.
11928 if (start > 0) 11928 if (start > 0)
11929 { 11929 {
11930 pref = dest.GetSublist(0,start-1); 11930 pref = dest.GetSublist(0,start-1);
11931 // Only add a suffix if there is something 11931 // Only add a suffix if there is something
11932 // beyond the end index (it's inclusive too). 11932 // beyond the end index (it's inclusive too).
11933 if (end + 1 < dest.Length) 11933 if (end + 1 < dest.Length)
11934 { 11934 {
11935 return pref + src + dest.GetSublist(end + 1, -1); 11935 return pref + src + dest.GetSublist(end + 1, -1);
11936 } 11936 }
11937 else 11937 else
11938 { 11938 {
11939 return pref + src; 11939 return pref + src;
11940 } 11940 }
11941 } 11941 }
11942 // If start is less than or equal to zero, then 11942 // If start is less than or equal to zero, then
11943 // the new list is simply a prefix. We still need to 11943 // the new list is simply a prefix. We still need to
11944 // figure out any necessary surgery to the destination 11944 // figure out any necessary surgery to the destination
11945 // based upon end. Note that if end exceeds the upper 11945 // based upon end. Note that if end exceeds the upper
11946 // bound in this case, the entire destination list 11946 // bound in this case, the entire destination list
11947 // is removed. 11947 // is removed.
11948 else 11948 else
11949 { 11949 {
11950 if (end + 1 < dest.Length) 11950 if (end + 1 < dest.Length)
11951 { 11951 {
11952 return src + dest.GetSublist(end + 1, -1); 11952 return src + dest.GetSublist(end + 1, -1);
11953 } 11953 }
11954 else 11954 else
11955 { 11955 {
11956 return src; 11956 return src;
11957 } 11957 }
11958 } 11958 }
11959 } 11959 }
11960 // Finally, if start > end, we strip away a prefix and 11960 // Finally, if start > end, we strip away a prefix and
11961 // a suffix, to leave the list that sits <between> ens 11961 // a suffix, to leave the list that sits <between> ens
11962 // and start, and then tag on the src list. AT least 11962 // and start, and then tag on the src list. AT least
11963 // that's my interpretation. We can get sublist to do 11963 // that's my interpretation. We can get sublist to do
11964 // this for us. Note that one, or both of the indices 11964 // this for us. Note that one, or both of the indices
11965 // might have been negative. 11965 // might have been negative.
11966 else 11966 else
11967 { 11967 {
11968 return dest.GetSublist(end + 1, start - 1) + src; 11968 return dest.GetSublist(end + 1, start - 1) + src;
11969 } 11969 }
11970 } 11970 }
11971 11971
11972 public void llLoadURL(string avatar_id, string message, string url) 11972 public void llLoadURL(string avatar_id, string message, string url)
11973 { 11973 {
11974 m_host.AddScriptLPS(1); 11974 m_host.AddScriptLPS(1);
11975 11975
11976 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 11976 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
11977 if (null != dm) 11977 if (null != dm)
11978 dm.SendUrlToUser( 11978 dm.SendUrlToUser(
11979 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url); 11979 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
11980 11980
11981 ScriptSleep(m_sleepMsOnLoadURL); 11981 ScriptSleep(m_sleepMsOnLoadURL);
11982 } 11982 }
11983 11983
11984 public void llParcelMediaCommandList(LSL_List commandList) 11984 public void llParcelMediaCommandList(LSL_List commandList)
11985 { 11985 {
11986 // TODO: Not implemented yet (missing in libomv?): 11986 // TODO: Not implemented yet (missing in libomv?):
11987 // PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) 11987 // PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
11988 11988
11989 m_host.AddScriptLPS(1); 11989 m_host.AddScriptLPS(1);
11990 11990
11991 // according to the docs, this command only works if script owner and land owner are the same 11991 // according to the docs, this command only works if script owner and land owner are the same
11992 // lets add estate owners and gods, too, and use the generic permission check. 11992 // lets add estate owners and gods, too, and use the generic permission check.
11993 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 11993 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
11994 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; 11994 if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return;
11995 11995
11996 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? 11996 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
11997 byte loop = 0; 11997 byte loop = 0;
11998 11998
11999 LandData landData = landObject.LandData; 11999 LandData landData = landObject.LandData;
12000 string url = landData.MediaURL; 12000 string url = landData.MediaURL;
12001 string texture = landData.MediaID.ToString(); 12001 string texture = landData.MediaID.ToString();
12002 bool autoAlign = landData.MediaAutoScale != 0; 12002 bool autoAlign = landData.MediaAutoScale != 0;
12003 string mediaType = ""; // TODO these have to be added as soon as LandData supports it 12003 string mediaType = ""; // TODO these have to be added as soon as LandData supports it
12004 string description = ""; 12004 string description = "";
12005 int width = 0; 12005 int width = 0;
12006 int height = 0; 12006 int height = 0;
12007 12007
12008 ParcelMediaCommandEnum? commandToSend = null; 12008 ParcelMediaCommandEnum? commandToSend = null;
12009 float time = 0.0f; // default is from start 12009 float time = 0.0f; // default is from start
12010 12010
12011 ScenePresence presence = null; 12011 ScenePresence presence = null;
12012 12012
12013 for (int i = 0; i < commandList.Data.Length; i++) 12013 for (int i = 0; i < commandList.Data.Length; i++)
12014 { 12014 {
12015 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; 12015 ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i];
12016 switch (command) 12016 switch (command)
12017 { 12017 {
12018 case ParcelMediaCommandEnum.Agent: 12018 case ParcelMediaCommandEnum.Agent:
12019 // we send only to one agent 12019 // we send only to one agent
12020 if ((i + 1) < commandList.Length) 12020 if ((i + 1) < commandList.Length)
12021 { 12021 {
12022 if (commandList.Data[i + 1] is LSL_String) 12022 if (commandList.Data[i + 1] is LSL_String)
12023 { 12023 {
12024 UUID agentID; 12024 UUID agentID;
12025 if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID)) 12025 if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID))
12026 { 12026 {
12027 presence = World.GetScenePresence(agentID); 12027 presence = World.GetScenePresence(agentID);
12028 } 12028 }
12029 } 12029 }
12030 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); 12030 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key");
12031 ++i; 12031 ++i;
12032 } 12032 }
12033 break; 12033 break;
12034 12034
12035 case ParcelMediaCommandEnum.Loop: 12035 case ParcelMediaCommandEnum.Loop:
12036 loop = 1; 12036 loop = 1;
12037 commandToSend = command; 12037 commandToSend = command;
12038 update = true; //need to send the media update packet to set looping 12038 update = true; //need to send the media update packet to set looping
12039 break; 12039 break;
12040 12040
12041 case ParcelMediaCommandEnum.Play: 12041 case ParcelMediaCommandEnum.Play:
12042 loop = 0; 12042 loop = 0;
12043 commandToSend = command; 12043 commandToSend = command;
12044 update = true; //need to send the media update packet to make sure it doesn't loop 12044 update = true; //need to send the media update packet to make sure it doesn't loop
12045 break; 12045 break;
12046 12046
12047 case ParcelMediaCommandEnum.Pause: 12047 case ParcelMediaCommandEnum.Pause:
12048 case ParcelMediaCommandEnum.Stop: 12048 case ParcelMediaCommandEnum.Stop:
12049 case ParcelMediaCommandEnum.Unload: 12049 case ParcelMediaCommandEnum.Unload:
12050 commandToSend = command; 12050 commandToSend = command;
12051 break; 12051 break;
12052 12052
12053 case ParcelMediaCommandEnum.Url: 12053 case ParcelMediaCommandEnum.Url:
12054 if ((i + 1) < commandList.Length) 12054 if ((i + 1) < commandList.Length)
12055 { 12055 {
12056 if (commandList.Data[i + 1] is LSL_String) 12056 if (commandList.Data[i + 1] is LSL_String)
12057 { 12057 {
12058 url = (LSL_String)commandList.Data[i + 1]; 12058 url = (LSL_String)commandList.Data[i + 1];
12059 update = true; 12059 update = true;
12060 } 12060 }
12061 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string"); 12061 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string");
12062 ++i; 12062 ++i;
12063 } 12063 }
12064 break; 12064 break;
12065 12065
12066 case ParcelMediaCommandEnum.Texture: 12066 case ParcelMediaCommandEnum.Texture:
12067 if ((i + 1) < commandList.Length) 12067 if ((i + 1) < commandList.Length)
12068 { 12068 {
12069 if (commandList.Data[i + 1] is LSL_String) 12069 if (commandList.Data[i + 1] is LSL_String)
12070 { 12070 {
12071 texture = (LSL_String)commandList.Data[i + 1]; 12071 texture = (LSL_String)commandList.Data[i + 1];
12072 update = true; 12072 update = true;
12073 } 12073 }
12074 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key"); 12074 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key");
12075 ++i; 12075 ++i;
12076 } 12076 }
12077 break; 12077 break;
12078 12078
12079 case ParcelMediaCommandEnum.Time: 12079 case ParcelMediaCommandEnum.Time:
12080 if ((i + 1) < commandList.Length) 12080 if ((i + 1) < commandList.Length)
12081 { 12081 {
12082 if (commandList.Data[i + 1] is LSL_Float) 12082 if (commandList.Data[i + 1] is LSL_Float)
12083 { 12083 {
12084 time = (float)(LSL_Float)commandList.Data[i + 1]; 12084 time = (float)(LSL_Float)commandList.Data[i + 1];
12085 } 12085 }
12086 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float"); 12086 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float");
12087 ++i; 12087 ++i;
12088 } 12088 }
12089 break; 12089 break;
12090 12090
12091 case ParcelMediaCommandEnum.AutoAlign: 12091 case ParcelMediaCommandEnum.AutoAlign:
12092 if ((i + 1) < commandList.Length) 12092 if ((i + 1) < commandList.Length)
12093 { 12093 {
12094 if (commandList.Data[i + 1] is LSL_Integer) 12094 if (commandList.Data[i + 1] is LSL_Integer)
12095 { 12095 {
12096 autoAlign = (LSL_Integer)commandList.Data[i + 1]; 12096 autoAlign = (LSL_Integer)commandList.Data[i + 1];
12097 update = true; 12097 update = true;
12098 } 12098 }
12099 12099
12100 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer"); 12100 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer");
12101 ++i; 12101 ++i;
12102 } 12102 }
12103 break; 12103 break;
12104 12104
12105 case ParcelMediaCommandEnum.Type: 12105 case ParcelMediaCommandEnum.Type:
12106 if ((i + 1) < commandList.Length) 12106 if ((i + 1) < commandList.Length)
12107 { 12107 {
12108 if (commandList.Data[i + 1] is LSL_String) 12108 if (commandList.Data[i + 1] is LSL_String)
12109 { 12109 {
12110 mediaType = (LSL_String)commandList.Data[i + 1]; 12110 mediaType = (LSL_String)commandList.Data[i + 1];
12111 update = true; 12111 update = true;
12112 } 12112 }
12113 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string"); 12113 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string");
12114 ++i; 12114 ++i;
12115 } 12115 }
12116 break; 12116 break;
12117 12117
12118 case ParcelMediaCommandEnum.Desc: 12118 case ParcelMediaCommandEnum.Desc:
12119 if ((i + 1) < commandList.Length) 12119 if ((i + 1) < commandList.Length)
12120 { 12120 {
12121 if (commandList.Data[i + 1] is LSL_String) 12121 if (commandList.Data[i + 1] is LSL_String)
12122 { 12122 {
12123 description = (LSL_String)commandList.Data[i + 1]; 12123 description = (LSL_String)commandList.Data[i + 1];
12124 update = true; 12124 update = true;
12125 } 12125 }
12126 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string"); 12126 else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string");
12127 ++i; 12127 ++i;
12128 } 12128 }
12129 break; 12129 break;
12130 12130
12131 case ParcelMediaCommandEnum.Size: 12131 case ParcelMediaCommandEnum.Size:
12132 if ((i + 2) < commandList.Length) 12132 if ((i + 2) < commandList.Length)
12133 { 12133 {
12134 if (commandList.Data[i + 1] is LSL_Integer) 12134 if (commandList.Data[i + 1] is LSL_Integer)
12135 { 12135 {
12136 if (commandList.Data[i + 2] is LSL_Integer) 12136 if (commandList.Data[i + 2] is LSL_Integer)
12137 { 12137 {
12138 width = (LSL_Integer)commandList.Data[i + 1]; 12138 width = (LSL_Integer)commandList.Data[i + 1];
12139 height = (LSL_Integer)commandList.Data[i + 2]; 12139 height = (LSL_Integer)commandList.Data[i + 2];
12140 update = true; 12140 update = true;
12141 } 12141 }
12142 else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); 12142 else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
12143 } 12143 }
12144 else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); 12144 else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer");
12145 i += 2; 12145 i += 2;
12146 } 12146 }
12147 break; 12147 break;
12148 12148
12149 default: 12149 default:
12150 NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString()); 12150 NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString());
12151 break; 12151 break;
12152 }//end switch 12152 }//end switch
12153 }//end for 12153 }//end for
12154 12154
12155 // if we didn't get a presence, we send to all and change the url 12155 // if we didn't get a presence, we send to all and change the url
12156 // if we did get a presence, we only send to the agent specified, and *don't change the land settings*! 12156 // if we did get a presence, we only send to the agent specified, and *don't change the land settings*!
12157 12157
12158 // did something important change or do we only start/stop/pause? 12158 // did something important change or do we only start/stop/pause?
12159 if (update) 12159 if (update)
12160 { 12160 {
12161 if (presence == null) 12161 if (presence == null)
12162 { 12162 {
12163 // we send to all 12163 // we send to all
12164 landData.MediaID = new UUID(texture); 12164 landData.MediaID = new UUID(texture);
12165 landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0; 12165 landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0;
12166 landData.MediaWidth = width; 12166 landData.MediaWidth = width;
12167 landData.MediaHeight = height; 12167 landData.MediaHeight = height;
12168 landData.MediaType = mediaType; 12168 landData.MediaType = mediaType;
12169 12169
12170 // do that one last, it will cause a ParcelPropertiesUpdate 12170 // do that one last, it will cause a ParcelPropertiesUpdate
12171 landObject.SetMediaUrl(url); 12171 landObject.SetMediaUrl(url);
12172 12172
12173 // now send to all (non-child) agents in the parcel 12173 // now send to all (non-child) agents in the parcel
12174 World.ForEachRootScenePresence(delegate(ScenePresence sp) 12174 World.ForEachRootScenePresence(delegate(ScenePresence sp)
12175 { 12175 {
12176 if (sp.currentParcelUUID == landData.GlobalID) 12176 if (sp.currentParcelUUID == landData.GlobalID)
12177 { 12177 {
12178 sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, 12178 sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL,
12179 landData.MediaID, 12179 landData.MediaID,
12180 landData.MediaAutoScale, 12180 landData.MediaAutoScale,
12181 mediaType, 12181 mediaType,
12182 description, 12182 description,
12183 width, height, 12183 width, height,
12184 loop); 12184 loop);
12185 } 12185 }
12186 }); 12186 });
12187 } 12187 }
12188 else if (!presence.IsChildAgent) 12188 else if (!presence.IsChildAgent)
12189 { 12189 {
12190 // we only send to one (root) agent 12190 // we only send to one (root) agent
12191 presence.ControllingClient.SendParcelMediaUpdate(url, 12191 presence.ControllingClient.SendParcelMediaUpdate(url,
12192 new UUID(texture), 12192 new UUID(texture),
12193 autoAlign ? (byte)1 : (byte)0, 12193 autoAlign ? (byte)1 : (byte)0,
12194 mediaType, 12194 mediaType,
12195 description, 12195 description,
12196 width, height, 12196 width, height,
12197 loop); 12197 loop);
12198 } 12198 }
12199 } 12199 }
12200 12200
12201 if (commandToSend != null) 12201 if (commandToSend != null)
12202 { 12202 {
12203 // the commandList contained a start/stop/... command, too 12203 // the commandList contained a start/stop/... command, too
12204 if (presence == null) 12204 if (presence == null)
12205 { 12205 {
12206 // send to all (non-child) agents in the parcel 12206 // send to all (non-child) agents in the parcel
12207 World.ForEachRootScenePresence(delegate(ScenePresence sp) 12207 World.ForEachRootScenePresence(delegate(ScenePresence sp)
12208 { 12208 {
12209 if (sp.currentParcelUUID == landData.GlobalID) 12209 if (sp.currentParcelUUID == landData.GlobalID)
12210 { 12210 {
12211 sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? 12211 sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12212 (ParcelMediaCommandEnum)commandToSend, 12212 (ParcelMediaCommandEnum)commandToSend,
12213 time); 12213 time);
12214 } 12214 }
12215 }); 12215 });
12216 } 12216 }
12217 else if (!presence.IsChildAgent) 12217 else if (!presence.IsChildAgent)
12218 { 12218 {
12219 presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? 12219 presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this?
12220 (ParcelMediaCommandEnum)commandToSend, 12220 (ParcelMediaCommandEnum)commandToSend,
12221 time); 12221 time);
12222 } 12222 }
12223 } 12223 }
12224 ScriptSleep(m_sleepMsOnParcelMediaCommandList); 12224 ScriptSleep(m_sleepMsOnParcelMediaCommandList);
12225 } 12225 }
12226 12226
12227 public LSL_List llParcelMediaQuery(LSL_List aList) 12227 public LSL_List llParcelMediaQuery(LSL_List aList)
12228 { 12228 {
12229 m_host.AddScriptLPS(1); 12229 m_host.AddScriptLPS(1);
12230 LSL_List list = new LSL_List(); 12230 LSL_List list = new LSL_List();
12231 //TO DO: make the implementation for the missing commands 12231 //TO DO: make the implementation for the missing commands
12232 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) 12232 //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later)
12233 for (int i = 0; i < aList.Data.Length; i++) 12233 for (int i = 0; i < aList.Data.Length; i++)
12234 { 12234 {
12235 12235
12236 if (aList.Data[i] != null) 12236 if (aList.Data[i] != null)
12237 { 12237 {
12238 switch ((ParcelMediaCommandEnum) aList.Data[i]) 12238 switch ((ParcelMediaCommandEnum) aList.Data[i])
12239 { 12239 {
12240 case ParcelMediaCommandEnum.Url: 12240 case ParcelMediaCommandEnum.Url:
12241 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); 12241 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL));
12242 break; 12242 break;
12243 case ParcelMediaCommandEnum.Desc: 12243 case ParcelMediaCommandEnum.Desc:
12244 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); 12244 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description));
12245 break; 12245 break;
12246 case ParcelMediaCommandEnum.Texture: 12246 case ParcelMediaCommandEnum.Texture:
12247 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); 12247 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString()));
12248 break; 12248 break;
12249 case ParcelMediaCommandEnum.Type: 12249 case ParcelMediaCommandEnum.Type:
12250 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); 12250 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType));
12251 break; 12251 break;
12252 case ParcelMediaCommandEnum.Size: 12252 case ParcelMediaCommandEnum.Size:
12253 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); 12253 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth));
12254 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); 12254 list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight));
12255 break; 12255 break;
12256 default: 12256 default:
12257 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; 12257 ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url;
12258 NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); 12258 NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString());
12259 break; 12259 break;
12260 } 12260 }
12261 12261
12262 } 12262 }
12263 } 12263 }
12264 ScriptSleep(m_sleepMsOnParcelMediaQuery); 12264 ScriptSleep(m_sleepMsOnParcelMediaQuery);
12265 return list; 12265 return list;
12266 } 12266 }
12267 12267
12268 public LSL_Integer llModPow(int a, int b, int c) 12268 public LSL_Integer llModPow(int a, int b, int c)
12269 { 12269 {
12270 m_host.AddScriptLPS(1); 12270 m_host.AddScriptLPS(1);
12271 Int64 tmp = 0; 12271 Int64 tmp = 0;
12272 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); 12272 Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp);
12273 ScriptSleep(m_sleepMsOnModPow); 12273 ScriptSleep(m_sleepMsOnModPow);
12274 return Convert.ToInt32(tmp); 12274 return Convert.ToInt32(tmp);
12275 } 12275 }
12276 12276
12277 public LSL_Integer llGetInventoryType(string name) 12277 public LSL_Integer llGetInventoryType(string name)
12278 { 12278 {
12279 m_host.AddScriptLPS(1); 12279 m_host.AddScriptLPS(1);
12280 12280
12281 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 12281 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
12282 12282
12283 if (item == null) 12283 if (item == null)
12284 return -1; 12284 return -1;
12285 12285
12286 return item.Type; 12286 return item.Type;
12287 } 12287 }
12288 12288
12289 public void llSetPayPrice(int price, LSL_List quick_pay_buttons) 12289 public void llSetPayPrice(int price, LSL_List quick_pay_buttons)
12290 { 12290 {
12291 m_host.AddScriptLPS(1); 12291 m_host.AddScriptLPS(1);
12292 12292
12293 if (quick_pay_buttons.Data.Length < 4) 12293 if (quick_pay_buttons.Data.Length < 4)
12294 { 12294 {
12295 Error("llSetPayPrice", "List must have at least 4 elements"); 12295 Error("llSetPayPrice", "List must have at least 4 elements");
12296 return; 12296 return;
12297 } 12297 }
12298 m_host.ParentGroup.RootPart.PayPrice[0]=price; 12298 m_host.ParentGroup.RootPart.PayPrice[0]=price;
12299 12299
12300 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; 12300 m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0];
12301 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; 12301 m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1];
12302 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; 12302 m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2];
12303 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; 12303 m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3];
12304 m_host.ParentGroup.HasGroupChanged = true; 12304 m_host.ParentGroup.HasGroupChanged = true;
12305 } 12305 }
12306 12306
12307 public LSL_Vector llGetCameraPos() 12307 public LSL_Vector llGetCameraPos()
12308 { 12308 {
12309 m_host.AddScriptLPS(1); 12309 m_host.AddScriptLPS(1);
12310 12310
12311 if (m_item.PermsGranter == UUID.Zero) 12311 if (m_item.PermsGranter == UUID.Zero)
12312 return Vector3.Zero; 12312 return Vector3.Zero;
12313 12313
12314 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 12314 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
12315 { 12315 {
12316 Error("llGetCameraPos", "No permissions to track the camera"); 12316 Error("llGetCameraPos", "No permissions to track the camera");
12317 return Vector3.Zero; 12317 return Vector3.Zero;
12318 } 12318 }
12319 12319
12320 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12320 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12321 if (presence != null) 12321 if (presence != null)
12322 { 12322 {
12323 LSL_Vector pos = new LSL_Vector(presence.CameraPosition); 12323 LSL_Vector pos = new LSL_Vector(presence.CameraPosition);
12324 return pos; 12324 return pos;
12325 } 12325 }
12326 12326
12327 return Vector3.Zero; 12327 return Vector3.Zero;
12328 } 12328 }
12329 12329
12330 public LSL_Rotation llGetCameraRot() 12330 public LSL_Rotation llGetCameraRot()
12331 { 12331 {
12332 m_host.AddScriptLPS(1); 12332 m_host.AddScriptLPS(1);
12333 12333
12334 if (m_item.PermsGranter == UUID.Zero) 12334 if (m_item.PermsGranter == UUID.Zero)
12335 return Quaternion.Identity; 12335 return Quaternion.Identity;
12336 12336
12337 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) 12337 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0)
12338 { 12338 {
12339 Error("llGetCameraRot", "No permissions to track the camera"); 12339 Error("llGetCameraRot", "No permissions to track the camera");
12340 return Quaternion.Identity; 12340 return Quaternion.Identity;
12341 } 12341 }
12342 12342
12343 ScenePresence presence = World.GetScenePresence(m_host.OwnerID); 12343 ScenePresence presence = World.GetScenePresence(m_host.OwnerID);
12344 if (presence != null) 12344 if (presence != null)
12345 { 12345 {
12346 return new LSL_Rotation(presence.CameraRotation); 12346 return new LSL_Rotation(presence.CameraRotation);
12347 } 12347 }
12348 12348
12349 return Quaternion.Identity; 12349 return Quaternion.Identity;
12350 } 12350 }
12351 12351
12352 public void llSetPrimURL(string url) 12352 public void llSetPrimURL(string url)
12353 { 12353 {
12354 m_host.AddScriptLPS(1); 12354 m_host.AddScriptLPS(1);
12355 Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead"); 12355 Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead");
12356 ScriptSleep(m_sleepMsOnSetPrimURL); 12356 ScriptSleep(m_sleepMsOnSetPrimURL);
12357 } 12357 }
12358 12358
12359 public void llRefreshPrimURL() 12359 public void llRefreshPrimURL()
12360 { 12360 {
12361 m_host.AddScriptLPS(1); 12361 m_host.AddScriptLPS(1);
12362 Deprecated("llRefreshPrimURL"); 12362 Deprecated("llRefreshPrimURL");
12363 ScriptSleep(m_sleepMsOnRefreshPrimURL); 12363 ScriptSleep(m_sleepMsOnRefreshPrimURL);
12364 } 12364 }
12365 12365
12366 public LSL_String llEscapeURL(string url) 12366 public LSL_String llEscapeURL(string url)
12367 { 12367 {
12368 m_host.AddScriptLPS(1); 12368 m_host.AddScriptLPS(1);
12369 try 12369 try
12370 { 12370 {
12371 return Uri.EscapeDataString(url); 12371 return Uri.EscapeDataString(url);
12372 } 12372 }
12373 catch (Exception ex) 12373 catch (Exception ex)
12374 { 12374 {
12375 return "llEscapeURL: " + ex.ToString(); 12375 return "llEscapeURL: " + ex.ToString();
12376 } 12376 }
12377 } 12377 }
12378 12378
12379 public LSL_String llUnescapeURL(string url) 12379 public LSL_String llUnescapeURL(string url)
12380 { 12380 {
12381 m_host.AddScriptLPS(1); 12381 m_host.AddScriptLPS(1);
12382 try 12382 try
12383 { 12383 {
12384 return Uri.UnescapeDataString(url); 12384 return Uri.UnescapeDataString(url);
12385 } 12385 }
12386 catch (Exception ex) 12386 catch (Exception ex)
12387 { 12387 {
12388 return "llUnescapeURL: " + ex.ToString(); 12388 return "llUnescapeURL: " + ex.ToString();
12389 } 12389 }
12390 } 12390 }
12391 12391
12392 public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt) 12392 public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt)
12393 { 12393 {
12394 m_host.AddScriptLPS(1); 12394 m_host.AddScriptLPS(1);
12395 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); 12395 DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0);
12396 if (detectedParams == null) return; // only works on the first detected avatar 12396 if (detectedParams == null) return; // only works on the first detected avatar
12397 12397
12398 ScenePresence avatar = World.GetScenePresence(detectedParams.Key); 12398 ScenePresence avatar = World.GetScenePresence(detectedParams.Key);
12399 if (avatar != null) 12399 if (avatar != null)
12400 { 12400 {
12401 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, 12401 avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name,
12402 simname, pos, lookAt); 12402 simname, pos, lookAt);
12403 } 12403 }
12404 ScriptSleep(m_sleepMsOnMapDestination); 12404 ScriptSleep(m_sleepMsOnMapDestination);
12405 } 12405 }
12406 12406
12407 public void llAddToLandBanList(string avatar, double hours) 12407 public void llAddToLandBanList(string avatar, double hours)
12408 { 12408 {
12409 m_host.AddScriptLPS(1); 12409 m_host.AddScriptLPS(1);
12410 UUID key; 12410 UUID key;
12411 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12411 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12412 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 12412 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
12413 { 12413 {
12414 int expires = 0; 12414 int expires = 0;
12415 if (hours != 0) 12415 if (hours != 0)
12416 expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours); 12416 expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours);
12417 12417
12418 if (UUID.TryParse(avatar, out key)) 12418 if (UUID.TryParse(avatar, out key))
12419 { 12419 {
12420 int idx = land.LandData.ParcelAccessList.FindIndex( 12420 int idx = land.LandData.ParcelAccessList.FindIndex(
12421 delegate(LandAccessEntry e) 12421 delegate(LandAccessEntry e)
12422 { 12422 {
12423 if (e.AgentID == key && e.Flags == AccessList.Ban) 12423 if (e.AgentID == key && e.Flags == AccessList.Ban)
12424 return true; 12424 return true;
12425 return false; 12425 return false;
12426 }); 12426 });
12427 12427
12428 if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires))) 12428 if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires)))
12429 return; 12429 return;
12430 12430
12431 if (idx != -1) 12431 if (idx != -1)
12432 land.LandData.ParcelAccessList.RemoveAt(idx); 12432 land.LandData.ParcelAccessList.RemoveAt(idx);
12433 12433
12434 LandAccessEntry entry = new LandAccessEntry(); 12434 LandAccessEntry entry = new LandAccessEntry();
12435 12435
12436 entry.AgentID = key; 12436 entry.AgentID = key;
12437 entry.Flags = AccessList.Ban; 12437 entry.Flags = AccessList.Ban;
12438 entry.Expires = expires; 12438 entry.Expires = expires;
12439 12439
12440 land.LandData.ParcelAccessList.Add(entry); 12440 land.LandData.ParcelAccessList.Add(entry);
12441 12441
12442 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 12442 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
12443 } 12443 }
12444 } 12444 }
12445 ScriptSleep(m_sleepMsOnAddToLandBanList); 12445 ScriptSleep(m_sleepMsOnAddToLandBanList);
12446 } 12446 }
12447 12447
12448 public void llRemoveFromLandPassList(string avatar) 12448 public void llRemoveFromLandPassList(string avatar)
12449 { 12449 {
12450 m_host.AddScriptLPS(1); 12450 m_host.AddScriptLPS(1);
12451 UUID key; 12451 UUID key;
12452 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12452 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12453 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) 12453 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed))
12454 { 12454 {
12455 if (UUID.TryParse(avatar, out key)) 12455 if (UUID.TryParse(avatar, out key))
12456 { 12456 {
12457 int idx = land.LandData.ParcelAccessList.FindIndex( 12457 int idx = land.LandData.ParcelAccessList.FindIndex(
12458 delegate(LandAccessEntry e) 12458 delegate(LandAccessEntry e)
12459 { 12459 {
12460 if (e.AgentID == key && e.Flags == AccessList.Access) 12460 if (e.AgentID == key && e.Flags == AccessList.Access)
12461 return true; 12461 return true;
12462 return false; 12462 return false;
12463 }); 12463 });
12464 12464
12465 if (idx != -1) 12465 if (idx != -1)
12466 { 12466 {
12467 land.LandData.ParcelAccessList.RemoveAt(idx); 12467 land.LandData.ParcelAccessList.RemoveAt(idx);
12468 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 12468 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
12469 } 12469 }
12470 } 12470 }
12471 } 12471 }
12472 ScriptSleep(m_sleepMsOnRemoveFromLandPassList); 12472 ScriptSleep(m_sleepMsOnRemoveFromLandPassList);
12473 } 12473 }
12474 12474
12475 public void llRemoveFromLandBanList(string avatar) 12475 public void llRemoveFromLandBanList(string avatar)
12476 { 12476 {
12477 m_host.AddScriptLPS(1); 12477 m_host.AddScriptLPS(1);
12478 UUID key; 12478 UUID key;
12479 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); 12479 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition);
12480 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) 12480 if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned))
12481 { 12481 {
12482 if (UUID.TryParse(avatar, out key)) 12482 if (UUID.TryParse(avatar, out key))
12483 { 12483 {
12484 int idx = land.LandData.ParcelAccessList.FindIndex( 12484 int idx = land.LandData.ParcelAccessList.FindIndex(
12485 delegate(LandAccessEntry e) 12485 delegate(LandAccessEntry e)
12486 { 12486 {
12487 if (e.AgentID == key && e.Flags == AccessList.Ban) 12487 if (e.AgentID == key && e.Flags == AccessList.Ban)
12488 return true; 12488 return true;
12489 return false; 12489 return false;
12490 }); 12490 });
12491 12491
12492 if (idx != -1) 12492 if (idx != -1)
12493 { 12493 {
12494 land.LandData.ParcelAccessList.RemoveAt(idx); 12494 land.LandData.ParcelAccessList.RemoveAt(idx);
12495 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); 12495 World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land);
12496 } 12496 }
12497 } 12497 }
12498 } 12498 }
12499 ScriptSleep(m_sleepMsOnRemoveFromLandBanList); 12499 ScriptSleep(m_sleepMsOnRemoveFromLandBanList);
12500 } 12500 }
12501 12501
12502 public void llSetCameraParams(LSL_List rules) 12502 public void llSetCameraParams(LSL_List rules)
12503 { 12503 {
12504 m_host.AddScriptLPS(1); 12504 m_host.AddScriptLPS(1);
12505 12505
12506 // the object we are in 12506 // the object we are in
12507 UUID objectID = m_host.ParentUUID; 12507 UUID objectID = m_host.ParentUUID;
12508 if (objectID == UUID.Zero) 12508 if (objectID == UUID.Zero)
12509 return; 12509 return;
12510 12510
12511 // we need the permission first, to know which avatar we want to set the camera for 12511 // we need the permission first, to know which avatar we want to set the camera for
12512 UUID agentID = m_item.PermsGranter; 12512 UUID agentID = m_item.PermsGranter;
12513 12513
12514 if (agentID == UUID.Zero) 12514 if (agentID == UUID.Zero)
12515 return; 12515 return;
12516 12516
12517 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) 12517 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
12518 return; 12518 return;
12519 12519
12520 ScenePresence presence = World.GetScenePresence(agentID); 12520 ScenePresence presence = World.GetScenePresence(agentID);
12521 12521
12522 // we are not interested in child-agents 12522 // we are not interested in child-agents
12523 if (presence.IsChildAgent) return; 12523 if (presence.IsChildAgent) return;
12524 12524
12525 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); 12525 SortedDictionary<int, float> parameters = new SortedDictionary<int, float>();
12526 object[] data = rules.Data; 12526 object[] data = rules.Data;
12527 for (int i = 0; i < data.Length; ++i) 12527 for (int i = 0; i < data.Length; ++i)
12528 { 12528 {
12529 int type; 12529 int type;
12530 try 12530 try
12531 { 12531 {
12532 type = Convert.ToInt32(data[i++].ToString()); 12532 type = Convert.ToInt32(data[i++].ToString());
12533 } 12533 }
12534 catch 12534 catch
12535 { 12535 {
12536 Error("llSetCameraParams", string.Format("Invalid camera param type {0}", data[i - 1])); 12536 Error("llSetCameraParams", string.Format("Invalid camera param type {0}", data[i - 1]));
12537 return; 12537 return;
12538 } 12538 }
12539 if (i >= data.Length) break; // odd number of entries => ignore the last 12539 if (i >= data.Length) break; // odd number of entries => ignore the last
12540 12540
12541 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) 12541 // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3)
12542 switch (type) 12542 switch (type)
12543 { 12543 {
12544 case ScriptBaseClass.CAMERA_FOCUS: 12544 case ScriptBaseClass.CAMERA_FOCUS:
12545 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 12545 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12546 case ScriptBaseClass.CAMERA_POSITION: 12546 case ScriptBaseClass.CAMERA_POSITION:
12547 LSL_Vector v = (LSL_Vector)data[i]; 12547 LSL_Vector v = (LSL_Vector)data[i];
12548 try 12548 try
12549 { 12549 {
12550 parameters.Add(type + 1, (float)v.x); 12550 parameters.Add(type + 1, (float)v.x);
12551 } 12551 }
12552 catch 12552 catch
12553 { 12553 {
12554 switch(type) 12554 switch(type)
12555 { 12555 {
12556 case ScriptBaseClass.CAMERA_FOCUS: 12556 case ScriptBaseClass.CAMERA_FOCUS:
12557 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter x is invalid"); 12557 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter x is invalid");
12558 return; 12558 return;
12559 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 12559 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12560 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter x is invalid"); 12560 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter x is invalid");
12561 return; 12561 return;
12562 case ScriptBaseClass.CAMERA_POSITION: 12562 case ScriptBaseClass.CAMERA_POSITION:
12563 Error("llSetCameraParams", "CAMERA_POSITION: Parameter x is invalid"); 12563 Error("llSetCameraParams", "CAMERA_POSITION: Parameter x is invalid");
12564 return; 12564 return;
12565 } 12565 }
12566 } 12566 }
12567 try 12567 try
12568 { 12568 {
12569 parameters.Add(type + 2, (float)v.y); 12569 parameters.Add(type + 2, (float)v.y);
12570 } 12570 }
12571 catch 12571 catch
12572 { 12572 {
12573 switch(type) 12573 switch(type)
12574 { 12574 {
12575 case ScriptBaseClass.CAMERA_FOCUS: 12575 case ScriptBaseClass.CAMERA_FOCUS:
12576 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter y is invalid"); 12576 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter y is invalid");
12577 return; 12577 return;
12578 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 12578 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12579 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter y is invalid"); 12579 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter y is invalid");
12580 return; 12580 return;
12581 case ScriptBaseClass.CAMERA_POSITION: 12581 case ScriptBaseClass.CAMERA_POSITION:
12582 Error("llSetCameraParams", "CAMERA_POSITION: Parameter y is invalid"); 12582 Error("llSetCameraParams", "CAMERA_POSITION: Parameter y is invalid");
12583 return; 12583 return;
12584 } 12584 }
12585 } 12585 }
12586 try 12586 try
12587 { 12587 {
12588 parameters.Add(type + 3, (float)v.z); 12588 parameters.Add(type + 3, (float)v.z);
12589 } 12589 }
12590 catch 12590 catch
12591 { 12591 {
12592 switch(type) 12592 switch(type)
12593 { 12593 {
12594 case ScriptBaseClass.CAMERA_FOCUS: 12594 case ScriptBaseClass.CAMERA_FOCUS:
12595 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter z is invalid"); 12595 Error("llSetCameraParams", "CAMERA_FOCUS: Parameter z is invalid");
12596 return; 12596 return;
12597 case ScriptBaseClass.CAMERA_FOCUS_OFFSET: 12597 case ScriptBaseClass.CAMERA_FOCUS_OFFSET:
12598 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter z is invalid"); 12598 Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter z is invalid");
12599 return; 12599 return;
12600 case ScriptBaseClass.CAMERA_POSITION: 12600 case ScriptBaseClass.CAMERA_POSITION:
12601 Error("llSetCameraParams", "CAMERA_POSITION: Parameter z is invalid"); 12601 Error("llSetCameraParams", "CAMERA_POSITION: Parameter z is invalid");
12602 return; 12602 return;
12603 } 12603 }
12604 } 12604 }
12605 break; 12605 break;
12606 default: 12606 default:
12607 // TODO: clean that up as soon as the implicit casts are in 12607 // TODO: clean that up as soon as the implicit casts are in
12608 if (data[i] is LSL_Float) 12608 if (data[i] is LSL_Float)
12609 parameters.Add(type, (float)((LSL_Float)data[i]).value); 12609 parameters.Add(type, (float)((LSL_Float)data[i]).value);
12610 else if (data[i] is LSL_Integer) 12610 else if (data[i] is LSL_Integer)
12611 parameters.Add(type, (float)((LSL_Integer)data[i]).value); 12611 parameters.Add(type, (float)((LSL_Integer)data[i]).value);
12612 else 12612 else
12613 { 12613 {
12614 try 12614 try
12615 { 12615 {
12616 parameters.Add(type, Convert.ToSingle(data[i])); 12616 parameters.Add(type, Convert.ToSingle(data[i]));
12617 } 12617 }
12618 catch 12618 catch
12619 { 12619 {
12620 Error("llSetCameraParams", string.Format("{0}: Parameter is invalid", type)); 12620 Error("llSetCameraParams", string.Format("{0}: Parameter is invalid", type));
12621 } 12621 }
12622 } 12622 }
12623 break; 12623 break;
12624 } 12624 }
12625 } 12625 }
12626 if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters); 12626 if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters);
12627 } 12627 }
12628 12628
12629 public void llClearCameraParams() 12629 public void llClearCameraParams()
12630 { 12630 {
12631 m_host.AddScriptLPS(1); 12631 m_host.AddScriptLPS(1);
12632 12632
12633 // the object we are in 12633 // the object we are in
12634 UUID objectID = m_host.ParentUUID; 12634 UUID objectID = m_host.ParentUUID;
12635 if (objectID == UUID.Zero) 12635 if (objectID == UUID.Zero)
12636 return; 12636 return;
12637 12637
12638 // we need the permission first, to know which avatar we want to clear the camera for 12638 // we need the permission first, to know which avatar we want to clear the camera for
12639 UUID agentID = m_item.PermsGranter; 12639 UUID agentID = m_item.PermsGranter;
12640 12640
12641 if (agentID == UUID.Zero) 12641 if (agentID == UUID.Zero)
12642 return; 12642 return;
12643 12643
12644 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) 12644 if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0)
12645 return; 12645 return;
12646 12646
12647 ScenePresence presence = World.GetScenePresence(agentID); 12647 ScenePresence presence = World.GetScenePresence(agentID);
12648 12648
12649 // we are not interested in child-agents 12649 // we are not interested in child-agents
12650 if (presence.IsChildAgent) 12650 if (presence.IsChildAgent)
12651 return; 12651 return;
12652 12652
12653 presence.ControllingClient.SendClearFollowCamProperties(objectID); 12653 presence.ControllingClient.SendClearFollowCamProperties(objectID);
12654 } 12654 }
12655 12655
12656 public LSL_Float llListStatistics(int operation, LSL_List src) 12656 public LSL_Float llListStatistics(int operation, LSL_List src)
12657 { 12657 {
12658 m_host.AddScriptLPS(1); 12658 m_host.AddScriptLPS(1);
12659 switch (operation) 12659 switch (operation)
12660 { 12660 {
12661 case ScriptBaseClass.LIST_STAT_RANGE: 12661 case ScriptBaseClass.LIST_STAT_RANGE:
12662 return src.Range(); 12662 return src.Range();
12663 case ScriptBaseClass.LIST_STAT_MIN: 12663 case ScriptBaseClass.LIST_STAT_MIN:
12664 return src.Min(); 12664 return src.Min();
12665 case ScriptBaseClass.LIST_STAT_MAX: 12665 case ScriptBaseClass.LIST_STAT_MAX:
12666 return src.Max(); 12666 return src.Max();
12667 case ScriptBaseClass.LIST_STAT_MEAN: 12667 case ScriptBaseClass.LIST_STAT_MEAN:
12668 return src.Mean(); 12668 return src.Mean();
12669 case ScriptBaseClass.LIST_STAT_MEDIAN: 12669 case ScriptBaseClass.LIST_STAT_MEDIAN:
12670 return LSL_List.ToDoubleList(src).Median(); 12670 return LSL_List.ToDoubleList(src).Median();
12671 case ScriptBaseClass.LIST_STAT_NUM_COUNT: 12671 case ScriptBaseClass.LIST_STAT_NUM_COUNT:
12672 return src.NumericLength(); 12672 return src.NumericLength();
12673 case ScriptBaseClass.LIST_STAT_STD_DEV: 12673 case ScriptBaseClass.LIST_STAT_STD_DEV:
12674 return src.StdDev(); 12674 return src.StdDev();
12675 case ScriptBaseClass.LIST_STAT_SUM: 12675 case ScriptBaseClass.LIST_STAT_SUM:
12676 return src.Sum(); 12676 return src.Sum();
12677 case ScriptBaseClass.LIST_STAT_SUM_SQUARES: 12677 case ScriptBaseClass.LIST_STAT_SUM_SQUARES:
12678 return src.SumSqrs(); 12678 return src.SumSqrs();
12679 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: 12679 case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN:
12680 return src.GeometricMean(); 12680 return src.GeometricMean();
12681 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: 12681 case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN:
12682 return src.HarmonicMean(); 12682 return src.HarmonicMean();
12683 default: 12683 default:
12684 return 0.0; 12684 return 0.0;
12685 } 12685 }
12686 } 12686 }
12687 12687
12688 public LSL_Integer llGetUnixTime() 12688 public LSL_Integer llGetUnixTime()
12689 { 12689 {
12690 m_host.AddScriptLPS(1); 12690 m_host.AddScriptLPS(1);
12691 return Util.UnixTimeSinceEpoch(); 12691 return Util.UnixTimeSinceEpoch();
12692 } 12692 }
12693 12693
12694 public LSL_Integer llGetParcelFlags(LSL_Vector pos) 12694 public LSL_Integer llGetParcelFlags(LSL_Vector pos)
12695 { 12695 {
12696 m_host.AddScriptLPS(1); 12696 m_host.AddScriptLPS(1);
12697 return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).LandData.Flags; 12697 return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).LandData.Flags;
12698 } 12698 }
12699 12699
12700 public LSL_Integer llGetRegionFlags() 12700 public LSL_Integer llGetRegionFlags()
12701 { 12701 {
12702 m_host.AddScriptLPS(1); 12702 m_host.AddScriptLPS(1);
12703 IEstateModule estate = World.RequestModuleInterface<IEstateModule>(); 12703 IEstateModule estate = World.RequestModuleInterface<IEstateModule>();
12704 if (estate == null) 12704 if (estate == null)
12705 return 67108864; 12705 return 67108864;
12706 return (int)estate.GetRegionFlags(); 12706 return (int)estate.GetRegionFlags();
12707 } 12707 }
12708 12708
12709 public LSL_String llXorBase64StringsCorrect(string str1, string str2) 12709 public LSL_String llXorBase64StringsCorrect(string str1, string str2)
12710 { 12710 {
12711 m_host.AddScriptLPS(1); 12711 m_host.AddScriptLPS(1);
12712 string ret = String.Empty; 12712 string ret = String.Empty;
12713 string src1 = llBase64ToString(str1); 12713 string src1 = llBase64ToString(str1);
12714 string src2 = llBase64ToString(str2); 12714 string src2 = llBase64ToString(str2);
12715 int c = 0; 12715 int c = 0;
12716 for (int i = 0; i < src1.Length; i++) 12716 for (int i = 0; i < src1.Length; i++)
12717 { 12717 {
12718 ret += (char) (src1[i] ^ src2[c]); 12718 ret += (char) (src1[i] ^ src2[c]);
12719 12719
12720 c++; 12720 c++;
12721 if (c >= src2.Length) 12721 if (c >= src2.Length)
12722 c = 0; 12722 c = 0;
12723 } 12723 }
12724 return llStringToBase64(ret); 12724 return llStringToBase64(ret);
12725 } 12725 }
12726 12726
12727 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) 12727 public LSL_String llHTTPRequest(string url, LSL_List parameters, string body)
12728 { 12728 {
12729 // Partial implementation: support for parameter flags needed 12729 // Partial implementation: support for parameter flags needed
12730 // see http://wiki.secondlife.com/wiki/LlHTTPRequest 12730 // see http://wiki.secondlife.com/wiki/LlHTTPRequest
12731 // parameter flags support are implemented in ScriptsHttpRequests.cs 12731 // parameter flags support are implemented in ScriptsHttpRequests.cs
12732 // in StartHttpRequest 12732 // in StartHttpRequest
12733 12733
12734 m_host.AddScriptLPS(1); 12734 m_host.AddScriptLPS(1);
12735 IHttpRequestModule httpScriptMod = 12735 IHttpRequestModule httpScriptMod =
12736 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); 12736 m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>();
12737 List<string> param = new List<string>(); 12737 List<string> param = new List<string>();
12738 bool ok; 12738 bool ok;
12739 Int32 flag; 12739 Int32 flag;
12740 12740
12741 for (int i = 0; i < parameters.Data.Length; i += 2) 12741 for (int i = 0; i < parameters.Data.Length; i += 2)
12742 { 12742 {
12743 ok = Int32.TryParse(parameters.Data[i].ToString(), out flag); 12743 ok = Int32.TryParse(parameters.Data[i].ToString(), out flag);
12744 if (!ok || flag < 0 || 12744 if (!ok || flag < 0 ||
12745 flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE) 12745 flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE)
12746 { 12746 {
12747 Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag"); 12747 Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag");
12748 } 12748 }
12749 12749
12750 param.Add(parameters.Data[i].ToString()); //Add parameter flag 12750 param.Add(parameters.Data[i].ToString()); //Add parameter flag
12751 12751
12752 if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER) 12752 if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER)
12753 { 12753 {
12754 param.Add(parameters.Data[i+1].ToString()); //Add parameter value 12754 param.Add(parameters.Data[i+1].ToString()); //Add parameter value
12755 } 12755 }
12756 else 12756 else
12757 { 12757 {
12758 //Parameters are in pairs and custom header takes 12758 //Parameters are in pairs and custom header takes
12759 //arguments in pairs so adjust for header marker. 12759 //arguments in pairs so adjust for header marker.
12760 ++i; 12760 ++i;
12761 12761
12762 //Maximum of 8 headers are allowed based on the 12762 //Maximum of 8 headers are allowed based on the
12763 //Second Life documentation for llHTTPRequest. 12763 //Second Life documentation for llHTTPRequest.
12764 for (int count = 1; count <= 8; ++count) 12764 for (int count = 1; count <= 8; ++count)
12765 { 12765 {
12766 //Enough parameters remaining for (another) header? 12766 //Enough parameters remaining for (another) header?
12767 if (parameters.Data.Length - i < 2) 12767 if (parameters.Data.Length - i < 2)
12768 { 12768 {
12769 //There must be at least one name/value pair for custom header 12769 //There must be at least one name/value pair for custom header
12770 if (count == 1) 12770 if (count == 1)
12771 Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString()); 12771 Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString());
12772 break; 12772 break;
12773 } 12773 }
12774 12774
12775 if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase)) 12775 if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase))
12776 Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString()); 12776 Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString());
12777 12777
12778 param.Add(parameters.Data[i].ToString()); 12778 param.Add(parameters.Data[i].ToString());
12779 param.Add(parameters.Data[i+1].ToString()); 12779 param.Add(parameters.Data[i+1].ToString());
12780 12780
12781 //Have we reached the end of the list of headers? 12781 //Have we reached the end of the list of headers?
12782 //End is marked by a string with a single digit. 12782 //End is marked by a string with a single digit.
12783 if (i+2 >= parameters.Data.Length || 12783 if (i+2 >= parameters.Data.Length ||
12784 Char.IsDigit(parameters.Data[i].ToString()[0])) 12784 Char.IsDigit(parameters.Data[i].ToString()[0]))
12785 { 12785 {
12786 break; 12786 break;
12787 } 12787 }
12788 12788
12789 i += 2; 12789 i += 2;
12790 } 12790 }
12791 } 12791 }
12792 } 12792 }
12793 12793
12794 Vector3 position = m_host.AbsolutePosition; 12794 Vector3 position = m_host.AbsolutePosition;
12795 Vector3 velocity = m_host.Velocity; 12795 Vector3 velocity = m_host.Velocity;
12796 Quaternion rotation = m_host.RotationOffset; 12796 Quaternion rotation = m_host.RotationOffset;
12797 string ownerName = String.Empty; 12797 string ownerName = String.Empty;
12798 ScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID); 12798 ScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID);
12799 if (scenePresence == null) 12799 if (scenePresence == null)
12800 ownerName = resolveName(m_host.OwnerID); 12800 ownerName = resolveName(m_host.OwnerID);
12801 else 12801 else
12802 ownerName = scenePresence.Name; 12802 ownerName = scenePresence.Name;
12803 12803
12804 RegionInfo regionInfo = World.RegionInfo; 12804 RegionInfo regionInfo = World.RegionInfo;
12805 12805
12806 Dictionary<string, string> httpHeaders = new Dictionary<string, string>(); 12806 Dictionary<string, string> httpHeaders = new Dictionary<string, string>();
12807 12807
12808 string shard = "OpenSim"; 12808 string shard = "OpenSim";
12809 IConfigSource config = m_ScriptEngine.ConfigSource; 12809 IConfigSource config = m_ScriptEngine.ConfigSource;
12810 if (config.Configs["Network"] != null) 12810 if (config.Configs["Network"] != null)
12811 { 12811 {
12812 shard = config.Configs["Network"].GetString("shard", shard); 12812 shard = config.Configs["Network"].GetString("shard", shard);
12813 } 12813 }
12814 12814
12815 httpHeaders["X-SecondLife-Shard"] = shard; 12815 httpHeaders["X-SecondLife-Shard"] = shard;
12816 httpHeaders["X-SecondLife-Object-Name"] = m_host.Name; 12816 httpHeaders["X-SecondLife-Object-Name"] = m_host.Name;
12817 httpHeaders["X-SecondLife-Object-Key"] = m_host.UUID.ToString(); 12817 httpHeaders["X-SecondLife-Object-Key"] = m_host.UUID.ToString();
12818 httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY); 12818 httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY);
12819 httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z); 12819 httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z);
12820 httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z); 12820 httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
12821 httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W); 12821 httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
12822 httpHeaders["X-SecondLife-Owner-Name"] = ownerName; 12822 httpHeaders["X-SecondLife-Owner-Name"] = ownerName;
12823 httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString(); 12823 httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString();
12824 string userAgent = config.Configs["Network"].GetString("user_agent", null); 12824 string userAgent = config.Configs["Network"].GetString("user_agent", null);
12825 if (userAgent != null) 12825 if (userAgent != null)
12826 httpHeaders["User-Agent"] = userAgent; 12826 httpHeaders["User-Agent"] = userAgent;
12827 12827
12828 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; 12828 string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$";
12829 Regex r = new Regex(authregex); 12829 Regex r = new Regex(authregex);
12830 int[] gnums = r.GetGroupNumbers(); 12830 int[] gnums = r.GetGroupNumbers();
12831 Match m = r.Match(url); 12831 Match m = r.Match(url);
12832 if (m.Success) { 12832 if (m.Success) {
12833 for (int i = 1; i < gnums.Length; i++) { 12833 for (int i = 1; i < gnums.Length; i++) {
12834 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; 12834 //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]];
12835 //CaptureCollection cc = g.Captures; 12835 //CaptureCollection cc = g.Captures;
12836 } 12836 }
12837 if (m.Groups.Count == 5) { 12837 if (m.Groups.Count == 5) {
12838 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); 12838 httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString())));
12839 url = m.Groups[1].ToString() + m.Groups[4].ToString(); 12839 url = m.Groups[1].ToString() + m.Groups[4].ToString();
12840 } 12840 }
12841 } 12841 }
12842 12842
12843 HttpInitialRequestStatus status; 12843 HttpInitialRequestStatus status;
12844 UUID reqID 12844 UUID reqID
12845 = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status); 12845 = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status);
12846 12846
12847 if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER) 12847 if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER)
12848 Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url)); 12848 Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url));
12849 12849
12850 if (reqID != UUID.Zero) 12850 if (reqID != UUID.Zero)
12851 return reqID.ToString(); 12851 return reqID.ToString();
12852 else 12852 else
12853 return null; 12853 return null;
12854 } 12854 }
12855 12855
12856 12856
12857 public void llHTTPResponse(LSL_Key id, int status, string body) 12857 public void llHTTPResponse(LSL_Key id, int status, string body)
12858 { 12858 {
12859 // Partial implementation: support for parameter flags needed 12859 // Partial implementation: support for parameter flags needed
12860 // see http://wiki.secondlife.com/wiki/llHTTPResponse 12860 // see http://wiki.secondlife.com/wiki/llHTTPResponse
12861 12861
12862 m_host.AddScriptLPS(1); 12862 m_host.AddScriptLPS(1);
12863 12863
12864 if (m_UrlModule != null) 12864 if (m_UrlModule != null)
12865 m_UrlModule.HttpResponse(new UUID(id), status,body); 12865 m_UrlModule.HttpResponse(new UUID(id), status,body);
12866 } 12866 }
12867 12867
12868 public void llResetLandBanList() 12868 public void llResetLandBanList()
12869 { 12869 {
12870 m_host.AddScriptLPS(1); 12870 m_host.AddScriptLPS(1);
12871 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; 12871 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData;
12872 if (land.OwnerID == m_host.OwnerID) 12872 if (land.OwnerID == m_host.OwnerID)
12873 { 12873 {
12874 foreach (LandAccessEntry entry in land.ParcelAccessList) 12874 foreach (LandAccessEntry entry in land.ParcelAccessList)
12875 { 12875 {
12876 if (entry.Flags == AccessList.Ban) 12876 if (entry.Flags == AccessList.Ban)
12877 { 12877 {
12878 land.ParcelAccessList.Remove(entry); 12878 land.ParcelAccessList.Remove(entry);
12879 } 12879 }
12880 } 12880 }
12881 } 12881 }
12882 ScriptSleep(m_sleepMsOnResetLandBanList); 12882 ScriptSleep(m_sleepMsOnResetLandBanList);
12883 } 12883 }
12884 12884
12885 public void llResetLandPassList() 12885 public void llResetLandPassList()
12886 { 12886 {
12887 m_host.AddScriptLPS(1); 12887 m_host.AddScriptLPS(1);
12888 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; 12888 LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData;
12889 if (land.OwnerID == m_host.OwnerID) 12889 if (land.OwnerID == m_host.OwnerID)
12890 { 12890 {
12891 foreach (LandAccessEntry entry in land.ParcelAccessList) 12891 foreach (LandAccessEntry entry in land.ParcelAccessList)
12892 { 12892 {
12893 if (entry.Flags == AccessList.Access) 12893 if (entry.Flags == AccessList.Access)
12894 { 12894 {
12895 land.ParcelAccessList.Remove(entry); 12895 land.ParcelAccessList.Remove(entry);
12896 } 12896 }
12897 } 12897 }
12898 } 12898 }
12899 ScriptSleep(m_sleepMsOnResetLandPassList); 12899 ScriptSleep(m_sleepMsOnResetLandPassList);
12900 } 12900 }
12901 12901
12902 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) 12902 public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide)
12903 { 12903 {
12904 m_host.AddScriptLPS(1); 12904 m_host.AddScriptLPS(1);
12905 12905
12906 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); 12906 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
12907 12907
12908 if (lo == null) 12908 if (lo == null)
12909 return 0; 12909 return 0;
12910 12910
12911 IPrimCounts pc = lo.PrimCounts; 12911 IPrimCounts pc = lo.PrimCounts;
12912 12912
12913 if (sim_wide != ScriptBaseClass.FALSE) 12913 if (sim_wide != ScriptBaseClass.FALSE)
12914 { 12914 {
12915 if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL) 12915 if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL)
12916 { 12916 {
12917 return pc.Simulator; 12917 return pc.Simulator;
12918 } 12918 }
12919 else 12919 else
12920 { 12920 {
12921 // counts not implemented yet 12921 // counts not implemented yet
12922 return 0; 12922 return 0;
12923 } 12923 }
12924 } 12924 }
12925 else 12925 else
12926 { 12926 {
12927 if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL) 12927 if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL)
12928 return pc.Total; 12928 return pc.Total;
12929 else if (category == ScriptBaseClass.PARCEL_COUNT_OWNER) 12929 else if (category == ScriptBaseClass.PARCEL_COUNT_OWNER)
12930 return pc.Owner; 12930 return pc.Owner;
12931 else if (category == ScriptBaseClass.PARCEL_COUNT_GROUP) 12931 else if (category == ScriptBaseClass.PARCEL_COUNT_GROUP)
12932 return pc.Group; 12932 return pc.Group;
12933 else if (category == ScriptBaseClass.PARCEL_COUNT_OTHER) 12933 else if (category == ScriptBaseClass.PARCEL_COUNT_OTHER)
12934 return pc.Others; 12934 return pc.Others;
12935 else if (category == ScriptBaseClass.PARCEL_COUNT_SELECTED) 12935 else if (category == ScriptBaseClass.PARCEL_COUNT_SELECTED)
12936 return pc.Selected; 12936 return pc.Selected;
12937 else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP) 12937 else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP)
12938 return 0; // counts not implemented yet 12938 return 0; // counts not implemented yet
12939 } 12939 }
12940 12940
12941 return 0; 12941 return 0;
12942 } 12942 }
12943 12943
12944 public LSL_List llGetParcelPrimOwners(LSL_Vector pos) 12944 public LSL_List llGetParcelPrimOwners(LSL_Vector pos)
12945 { 12945 {
12946 m_host.AddScriptLPS(1); 12946 m_host.AddScriptLPS(1);
12947 LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); 12947 LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
12948 LSL_List ret = new LSL_List(); 12948 LSL_List ret = new LSL_List();
12949 if (land != null) 12949 if (land != null)
12950 { 12950 {
12951 foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners()) 12951 foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners())
12952 { 12952 {
12953 ret.Add(new LSL_String(detectedParams.Key.ToString())); 12953 ret.Add(new LSL_String(detectedParams.Key.ToString()));
12954 ret.Add(new LSL_Integer(detectedParams.Value)); 12954 ret.Add(new LSL_Integer(detectedParams.Value));
12955 } 12955 }
12956 } 12956 }
12957 ScriptSleep(m_sleepMsOnGetParcelPrimOwners); 12957 ScriptSleep(m_sleepMsOnGetParcelPrimOwners);
12958 return ret; 12958 return ret;
12959 } 12959 }
12960 12960
12961 public LSL_Integer llGetObjectPrimCount(string object_id) 12961 public LSL_Integer llGetObjectPrimCount(string object_id)
12962 { 12962 {
12963 m_host.AddScriptLPS(1); 12963 m_host.AddScriptLPS(1);
12964 SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id)); 12964 SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id));
12965 if (part == null) 12965 if (part == null)
12966 { 12966 {
12967 return 0; 12967 return 0;
12968 } 12968 }
12969 else 12969 else
12970 { 12970 {
12971 return part.ParentGroup.PrimCount; 12971 return part.ParentGroup.PrimCount;
12972 } 12972 }
12973 } 12973 }
12974 12974
12975 public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide) 12975 public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide)
12976 { 12976 {
12977 m_host.AddScriptLPS(1); 12977 m_host.AddScriptLPS(1);
12978 12978
12979 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); 12979 ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y);
12980 12980
12981 if (lo == null) 12981 if (lo == null)
12982 return 0; 12982 return 0;
12983 12983
12984 if (sim_wide != 0) 12984 if (sim_wide != 0)
12985 return lo.GetSimulatorMaxPrimCount(); 12985 return lo.GetSimulatorMaxPrimCount();
12986 else 12986 else
12987 return lo.GetParcelMaxPrimCount(); 12987 return lo.GetParcelMaxPrimCount();
12988 } 12988 }
12989 12989
12990 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) 12990 public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param)
12991 { 12991 {
12992 m_host.AddScriptLPS(1); 12992 m_host.AddScriptLPS(1);
12993 LandData land = World.GetLandData(pos); 12993 LandData land = World.GetLandData(pos);
12994 if (land == null) 12994 if (land == null)
12995 { 12995 {
12996 return new LSL_List(0); 12996 return new LSL_List(0);
12997 } 12997 }
12998 LSL_List ret = new LSL_List(); 12998 LSL_List ret = new LSL_List();
12999 foreach (object o in param.Data) 12999 foreach (object o in param.Data)
13000 { 13000 {
13001 switch (o.ToString()) 13001 switch (o.ToString())
13002 { 13002 {
13003 case "0": 13003 case "0":
13004 ret.Add(new LSL_String(land.Name)); 13004 ret.Add(new LSL_String(land.Name));
13005 break; 13005 break;
13006 case "1": 13006 case "1":
13007 ret.Add(new LSL_String(land.Description)); 13007 ret.Add(new LSL_String(land.Description));
13008 break; 13008 break;
13009 case "2": 13009 case "2":
13010 ret.Add(new LSL_Key(land.OwnerID.ToString())); 13010 ret.Add(new LSL_Key(land.OwnerID.ToString()));
13011 break; 13011 break;
13012 case "3": 13012 case "3":
13013 ret.Add(new LSL_Key(land.GroupID.ToString())); 13013 ret.Add(new LSL_Key(land.GroupID.ToString()));
13014 break; 13014 break;
13015 case "4": 13015 case "4":
13016 ret.Add(new LSL_Integer(land.Area)); 13016 ret.Add(new LSL_Integer(land.Area));
13017 break; 13017 break;
13018 case "5": 13018 case "5":
13019 ret.Add(new LSL_Key(land.GlobalID.ToString())); 13019 ret.Add(new LSL_Key(land.GlobalID.ToString()));
13020 break; 13020 break;
13021 default: 13021 default:
13022 ret.Add(new LSL_Integer(0)); 13022 ret.Add(new LSL_Integer(0));
13023 break; 13023 break;
13024 } 13024 }
13025 } 13025 }
13026 return ret; 13026 return ret;
13027 } 13027 }
13028 13028
13029 public LSL_String llStringTrim(string src, int type) 13029 public LSL_String llStringTrim(string src, int type)
13030 { 13030 {
13031 m_host.AddScriptLPS(1); 13031 m_host.AddScriptLPS(1);
13032 if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } 13032 if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); }
13033 if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } 13033 if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); }
13034 if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); } 13034 if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); }
13035 return src; 13035 return src;
13036 } 13036 }
13037 13037
13038 public LSL_List llGetObjectDetails(string id, LSL_List args) 13038 public LSL_List llGetObjectDetails(string id, LSL_List args)
13039 { 13039 {
13040 m_host.AddScriptLPS(1); 13040 m_host.AddScriptLPS(1);
13041 13041
13042 LSL_List ret = new LSL_List(); 13042 LSL_List ret = new LSL_List();
13043 UUID key = new UUID(); 13043 UUID key = new UUID();
13044 if (UUID.TryParse(id, out key)) 13044 if (UUID.TryParse(id, out key))
13045 { 13045 {
13046 ScenePresence av = World.GetScenePresence(key); 13046 ScenePresence av = World.GetScenePresence(key);
13047 13047
13048 if (av != null) 13048 if (av != null)
13049 { 13049 {
13050 foreach (object o in args.Data) 13050 foreach (object o in args.Data)
13051 { 13051 {
13052 switch (int.Parse(o.ToString())) 13052 switch (int.Parse(o.ToString()))
13053 { 13053 {
13054 case ScriptBaseClass.OBJECT_NAME: 13054 case ScriptBaseClass.OBJECT_NAME:
13055 ret.Add(new LSL_String(av.Firstname + " " + av.Lastname)); 13055 ret.Add(new LSL_String(av.Firstname + " " + av.Lastname));
13056 break; 13056 break;
13057 case ScriptBaseClass.OBJECT_DESC: 13057 case ScriptBaseClass.OBJECT_DESC:
13058 ret.Add(new LSL_String("")); 13058 ret.Add(new LSL_String(""));
13059 break; 13059 break;
13060 case ScriptBaseClass.OBJECT_POS: 13060 case ScriptBaseClass.OBJECT_POS:
13061 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); 13061 ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z));
13062 break; 13062 break;
13063 case ScriptBaseClass.OBJECT_ROT: 13063 case ScriptBaseClass.OBJECT_ROT:
13064 ret.Add(new LSL_Rotation(av.GetWorldRotation())); 13064 ret.Add(new LSL_Rotation(av.GetWorldRotation()));
13065 break; 13065 break;
13066 case ScriptBaseClass.OBJECT_VELOCITY: 13066 case ScriptBaseClass.OBJECT_VELOCITY:
13067 ret.Add(new LSL_Vector(av.GetWorldVelocity())); 13067 ret.Add(new LSL_Vector(av.GetWorldVelocity()));
13068 break; 13068 break;
13069 case ScriptBaseClass.OBJECT_OWNER: 13069 case ScriptBaseClass.OBJECT_OWNER:
13070 ret.Add(new LSL_String(id)); 13070 ret.Add(new LSL_String(id));
13071 break; 13071 break;
13072 case ScriptBaseClass.OBJECT_GROUP: 13072 case ScriptBaseClass.OBJECT_GROUP:
13073 ret.Add(new LSL_String(UUID.Zero.ToString())); 13073 ret.Add(new LSL_String(UUID.Zero.ToString()));
13074 break; 13074 break;
13075 case ScriptBaseClass.OBJECT_CREATOR: 13075 case ScriptBaseClass.OBJECT_CREATOR:
13076 ret.Add(new LSL_String(UUID.Zero.ToString())); 13076 ret.Add(new LSL_String(UUID.Zero.ToString()));
13077 break; 13077 break;
13078 // For the following 8 see the Object version below 13078 // For the following 8 see the Object version below
13079 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: 13079 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
13080 ret.Add(new LSL_Integer(av.RunningScriptCount())); 13080 ret.Add(new LSL_Integer(av.RunningScriptCount()));
13081 break; 13081 break;
13082 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: 13082 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
13083 ret.Add(new LSL_Integer(av.ScriptCount())); 13083 ret.Add(new LSL_Integer(av.ScriptCount()));
13084 break; 13084 break;
13085 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: 13085 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
13086 ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384)); 13086 ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384));
13087 break; 13087 break;
13088 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 13088 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
13089 ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f)); 13089 ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f));
13090 break; 13090 break;
13091 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 13091 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
13092 ret.Add(new LSL_Integer(1)); 13092 ret.Add(new LSL_Integer(1));
13093 break; 13093 break;
13094 case ScriptBaseClass.OBJECT_SERVER_COST: 13094 case ScriptBaseClass.OBJECT_SERVER_COST:
13095 ret.Add(new LSL_Float(0)); 13095 ret.Add(new LSL_Float(0));
13096 break; 13096 break;
13097 case ScriptBaseClass.OBJECT_STREAMING_COST: 13097 case ScriptBaseClass.OBJECT_STREAMING_COST:
13098 ret.Add(new LSL_Float(0)); 13098 ret.Add(new LSL_Float(0));
13099 break; 13099 break;
13100 case ScriptBaseClass.OBJECT_PHYSICS_COST: 13100 case ScriptBaseClass.OBJECT_PHYSICS_COST:
13101 ret.Add(new LSL_Float(0)); 13101 ret.Add(new LSL_Float(0));
13102 break; 13102 break;
13103 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding 13103 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
13104 ret.Add(new LSL_Float(0)); 13104 ret.Add(new LSL_Float(0));
13105 break; 13105 break;
13106 case ScriptBaseClass.OBJECT_ROOT: 13106 case ScriptBaseClass.OBJECT_ROOT:
13107 SceneObjectPart p = av.ParentPart; 13107 SceneObjectPart p = av.ParentPart;
13108 if (p != null) 13108 if (p != null)
13109 { 13109 {
13110 ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString())); 13110 ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString()));
13111 } 13111 }
13112 else 13112 else
13113 { 13113 {
13114 ret.Add(new LSL_String(id)); 13114 ret.Add(new LSL_String(id));
13115 } 13115 }
13116 break; 13116 break;
13117 case ScriptBaseClass.OBJECT_ATTACHED_POINT: 13117 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
13118 ret.Add(new LSL_Integer(0)); 13118 ret.Add(new LSL_Integer(0));
13119 break; 13119 break;
13120 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding 13120 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding
13121 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR)); 13121 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR));
13122 break; 13122 break;
13123 case ScriptBaseClass.OBJECT_PHYSICS: 13123 case ScriptBaseClass.OBJECT_PHYSICS:
13124 ret.Add(new LSL_Integer(0)); 13124 ret.Add(new LSL_Integer(0));
13125 break; 13125 break;
13126 case ScriptBaseClass.OBJECT_PHANTOM: 13126 case ScriptBaseClass.OBJECT_PHANTOM:
13127 ret.Add(new LSL_Integer(0)); 13127 ret.Add(new LSL_Integer(0));
13128 break; 13128 break;
13129 case ScriptBaseClass.OBJECT_TEMP_ON_REZ: 13129 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
13130 ret.Add(new LSL_Integer(0)); 13130 ret.Add(new LSL_Integer(0));
13131 break; 13131 break;
13132 case ScriptBaseClass.OBJECT_RENDER_WEIGHT: 13132 case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13133 ret.Add(new LSL_Integer(-1)); 13133 ret.Add(new LSL_Integer(-1));
13134 break; 13134 break;
13135 case ScriptBaseClass.OBJECT_HOVER_HEIGHT: 13135 case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13136 ret.Add(new LSL_Float(0)); 13136 ret.Add(new LSL_Float(0));
13137 break; 13137 break;
13138 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: 13138 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13139 LSL_Float shapeType; 13139 LSL_Float shapeType;
13140 if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0) 13140 if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0)
13141 shapeType = new LSL_Float(1); 13141 shapeType = new LSL_Float(1);
13142 else 13142 else
13143 shapeType = new LSL_Float(0); 13143 shapeType = new LSL_Float(0);
13144 ret.Add(shapeType); 13144 ret.Add(shapeType);
13145 break; 13145 break;
13146 case ScriptBaseClass.OBJECT_LAST_OWNER_ID: 13146 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13147 ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY)); 13147 ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY));
13148 break; 13148 break;
13149 default: 13149 default:
13150 // Invalid or unhandled constant. 13150 // Invalid or unhandled constant.
13151 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 13151 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
13152 break; 13152 break;
13153 } 13153 }
13154 } 13154 }
13155 13155
13156 return ret; 13156 return ret;
13157 } 13157 }
13158 13158
13159 SceneObjectPart obj = World.GetSceneObjectPart(key); 13159 SceneObjectPart obj = World.GetSceneObjectPart(key);
13160 if (obj != null) 13160 if (obj != null)
13161 { 13161 {
13162 foreach (object o in args.Data) 13162 foreach (object o in args.Data)
13163 { 13163 {
13164 switch (int.Parse(o.ToString())) 13164 switch (int.Parse(o.ToString()))
13165 { 13165 {
13166 case ScriptBaseClass.OBJECT_NAME: 13166 case ScriptBaseClass.OBJECT_NAME:
13167 ret.Add(new LSL_String(obj.Name)); 13167 ret.Add(new LSL_String(obj.Name));
13168 break; 13168 break;
13169 case ScriptBaseClass.OBJECT_DESC: 13169 case ScriptBaseClass.OBJECT_DESC:
13170 ret.Add(new LSL_String(obj.Description)); 13170 ret.Add(new LSL_String(obj.Description));
13171 break; 13171 break;
13172 case ScriptBaseClass.OBJECT_POS: 13172 case ScriptBaseClass.OBJECT_POS:
13173 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); 13173 ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z));
13174 break; 13174 break;
13175 case ScriptBaseClass.OBJECT_ROT: 13175 case ScriptBaseClass.OBJECT_ROT:
13176 Quaternion rot = Quaternion.Identity; 13176 Quaternion rot = Quaternion.Identity;
13177 13177
13178 if (obj.ParentGroup.IsAttachment) 13178 if (obj.ParentGroup.IsAttachment)
13179 { 13179 {
13180 ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); 13180 ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar);
13181 13181
13182 if (sp != null) 13182 if (sp != null)
13183 rot = sp.GetWorldRotation(); 13183 rot = sp.GetWorldRotation();
13184 } 13184 }
13185 else 13185 else
13186 { 13186 {
13187 if (obj.ParentGroup.RootPart == obj) 13187 if (obj.ParentGroup.RootPart == obj)
13188 rot = obj.ParentGroup.GroupRotation; 13188 rot = obj.ParentGroup.GroupRotation;
13189 else 13189 else
13190 rot = obj.GetWorldRotation(); 13190 rot = obj.GetWorldRotation();
13191 } 13191 }
13192 13192
13193 LSL_Rotation objrot = new LSL_Rotation(rot); 13193 LSL_Rotation objrot = new LSL_Rotation(rot);
13194 ret.Add(objrot); 13194 ret.Add(objrot);
13195 13195
13196 break; 13196 break;
13197 case ScriptBaseClass.OBJECT_VELOCITY: 13197 case ScriptBaseClass.OBJECT_VELOCITY:
13198 Vector3 vel = Vector3.Zero; 13198 Vector3 vel = Vector3.Zero;
13199 13199
13200 if (obj.ParentGroup.IsAttachment) 13200 if (obj.ParentGroup.IsAttachment)
13201 { 13201 {
13202 ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); 13202 ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar);
13203 13203
13204 if (sp != null) 13204 if (sp != null)
13205 vel = sp.GetWorldVelocity(); 13205 vel = sp.GetWorldVelocity();
13206 } 13206 }
13207 else 13207 else
13208 { 13208 {
13209 vel = obj.Velocity; 13209 vel = obj.Velocity;
13210 } 13210 }
13211 13211
13212 ret.Add(vel); 13212 ret.Add(vel);
13213 break; 13213 break;
13214 case ScriptBaseClass.OBJECT_OWNER: 13214 case ScriptBaseClass.OBJECT_OWNER:
13215 ret.Add(new LSL_String(obj.OwnerID.ToString())); 13215 ret.Add(new LSL_String(obj.OwnerID.ToString()));
13216 break; 13216 break;
13217 case ScriptBaseClass.OBJECT_GROUP: 13217 case ScriptBaseClass.OBJECT_GROUP:
13218 ret.Add(new LSL_String(obj.GroupID.ToString())); 13218 ret.Add(new LSL_String(obj.GroupID.ToString()));
13219 break; 13219 break;
13220 case ScriptBaseClass.OBJECT_CREATOR: 13220 case ScriptBaseClass.OBJECT_CREATOR:
13221 ret.Add(new LSL_String(obj.CreatorID.ToString())); 13221 ret.Add(new LSL_String(obj.CreatorID.ToString()));
13222 break; 13222 break;
13223 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: 13223 case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT:
13224 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount())); 13224 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount()));
13225 break; 13225 break;
13226 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: 13226 case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT:
13227 ret.Add(new LSL_Integer(obj.ParentGroup.ScriptCount())); 13227 ret.Add(new LSL_Integer(obj.ParentGroup.ScriptCount()));
13228 break; 13228 break;
13229 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: 13229 case ScriptBaseClass.OBJECT_SCRIPT_MEMORY:
13230 // The value returned in SL for mono scripts is 65536 * number of active scripts 13230 // The value returned in SL for mono scripts is 65536 * number of active scripts
13231 // and 16384 * number of active scripts for LSO. since llGetFreememory 13231 // and 16384 * number of active scripts for LSO. since llGetFreememory
13232 // is coded to give the LSO value use it here 13232 // is coded to give the LSO value use it here
13233 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384)); 13233 ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384));
13234 break; 13234 break;
13235 case ScriptBaseClass.OBJECT_SCRIPT_TIME: 13235 case ScriptBaseClass.OBJECT_SCRIPT_TIME:
13236 // Average cpu time in seconds per simulator frame expended on all scripts in the object 13236 // Average cpu time in seconds per simulator frame expended on all scripts in the object
13237 ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f)); 13237 ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f));
13238 break; 13238 break;
13239 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: 13239 case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE:
13240 // according to the SL wiki A prim or linkset will have prim 13240 // according to the SL wiki A prim or linkset will have prim
13241 // equivalent of the number of prims in a linkset if it does not 13241 // equivalent of the number of prims in a linkset if it does not
13242 // contain a mesh anywhere in the link set or is not a normal prim 13242 // contain a mesh anywhere in the link set or is not a normal prim
13243 // The value returned in SL for normal prims is prim count 13243 // The value returned in SL for normal prims is prim count
13244 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); 13244 ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount));
13245 break; 13245 break;
13246 // The following 3 costs I have intentionaly coded to return zero. They are part of 13246 // The following 3 costs I have intentionaly coded to return zero. They are part of
13247 // "Land Impact" calculations. These calculations are probably not applicable 13247 // "Land Impact" calculations. These calculations are probably not applicable
13248 // to OpenSim and are not yet complete in SL 13248 // to OpenSim and are not yet complete in SL
13249 case ScriptBaseClass.OBJECT_SERVER_COST: 13249 case ScriptBaseClass.OBJECT_SERVER_COST:
13250 // The linden calculation is here 13250 // The linden calculation is here
13251 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight 13251 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight
13252 // The value returned in SL for normal prims looks like the prim count 13252 // The value returned in SL for normal prims looks like the prim count
13253 ret.Add(new LSL_Float(0)); 13253 ret.Add(new LSL_Float(0));
13254 break; 13254 break;
13255 case ScriptBaseClass.OBJECT_STREAMING_COST: 13255 case ScriptBaseClass.OBJECT_STREAMING_COST:
13256 // The linden calculation is here 13256 // The linden calculation is here
13257 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost 13257 // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost
13258 // The value returned in SL for normal prims looks like the prim count * 0.06 13258 // The value returned in SL for normal prims looks like the prim count * 0.06
13259 ret.Add(new LSL_Float(0)); 13259 ret.Add(new LSL_Float(0));
13260 break; 13260 break;
13261 case ScriptBaseClass.OBJECT_PHYSICS_COST: 13261 case ScriptBaseClass.OBJECT_PHYSICS_COST:
13262 // The linden calculation is here 13262 // The linden calculation is here
13263 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics 13263 // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics
13264 // The value returned in SL for normal prims looks like the prim count 13264 // The value returned in SL for normal prims looks like the prim count
13265 ret.Add(new LSL_Float(0)); 13265 ret.Add(new LSL_Float(0));
13266 break; 13266 break;
13267 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding 13267 case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding
13268 ret.Add(new LSL_Float(0)); 13268 ret.Add(new LSL_Float(0));
13269 break; 13269 break;
13270 case ScriptBaseClass.OBJECT_ROOT: 13270 case ScriptBaseClass.OBJECT_ROOT:
13271 ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString())); 13271 ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString()));
13272 break; 13272 break;
13273 case ScriptBaseClass.OBJECT_ATTACHED_POINT: 13273 case ScriptBaseClass.OBJECT_ATTACHED_POINT:
13274 ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint)); 13274 ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint));
13275 break; 13275 break;
13276 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: 13276 case ScriptBaseClass.OBJECT_PATHFINDING_TYPE:
13277 byte pcode = obj.Shape.PCode; 13277 byte pcode = obj.Shape.PCode;
13278 if (obj.ParentGroup.AttachmentPoint != 0 13278 if (obj.ParentGroup.AttachmentPoint != 0
13279 || pcode == (byte)PCode.Grass 13279 || pcode == (byte)PCode.Grass
13280 || pcode == (byte)PCode.Tree 13280 || pcode == (byte)PCode.Tree
13281 || pcode == (byte)PCode.NewTree) 13281 || pcode == (byte)PCode.NewTree)
13282 { 13282 {
13283 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER)); 13283 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER));
13284 } 13284 }
13285 else 13285 else
13286 { 13286 {
13287 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET)); 13287 ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET));
13288 } 13288 }
13289 break; 13289 break;
13290 case ScriptBaseClass.OBJECT_PHYSICS: 13290 case ScriptBaseClass.OBJECT_PHYSICS:
13291 if (obj.ParentGroup.AttachmentPoint != 0) 13291 if (obj.ParentGroup.AttachmentPoint != 0)
13292 { 13292 {
13293 ret.Add(new LSL_Integer(0)); // Always false if attached 13293 ret.Add(new LSL_Integer(0)); // Always false if attached
13294 } 13294 }
13295 else 13295 else
13296 { 13296 {
13297 ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0)); 13297 ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0));
13298 } 13298 }
13299 break; 13299 break;
13300 case ScriptBaseClass.OBJECT_PHANTOM: 13300 case ScriptBaseClass.OBJECT_PHANTOM:
13301 if (obj.ParentGroup.AttachmentPoint != 0) 13301 if (obj.ParentGroup.AttachmentPoint != 0)
13302 { 13302 {
13303 ret.Add(new LSL_Integer(0)); // Always false if attached 13303 ret.Add(new LSL_Integer(0)); // Always false if attached
13304 } 13304 }
13305 else 13305 else
13306 { 13306 {
13307 ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0)); 13307 ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0));
13308 } 13308 }
13309 break; 13309 break;
13310 case ScriptBaseClass.OBJECT_TEMP_ON_REZ: 13310 case ScriptBaseClass.OBJECT_TEMP_ON_REZ:
13311 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); 13311 ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0));
13312 break; 13312 break;
13313 case ScriptBaseClass.OBJECT_RENDER_WEIGHT: 13313 case ScriptBaseClass.OBJECT_RENDER_WEIGHT:
13314 ret.Add(new LSL_Integer(0)); 13314 ret.Add(new LSL_Integer(0));
13315 break; 13315 break;
13316 case ScriptBaseClass.OBJECT_HOVER_HEIGHT: 13316 case ScriptBaseClass.OBJECT_HOVER_HEIGHT:
13317 ret.Add(new LSL_Float(0)); 13317 ret.Add(new LSL_Float(0));
13318 break; 13318 break;
13319 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: 13319 case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE:
13320 ret.Add(new LSL_Float(-1)); 13320 ret.Add(new LSL_Float(-1));
13321 break; 13321 break;
13322 case ScriptBaseClass.OBJECT_LAST_OWNER_ID: 13322 case ScriptBaseClass.OBJECT_LAST_OWNER_ID:
13323 ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString())); 13323 ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString()));
13324 break; 13324 break;
13325 default: 13325 default:
13326 // Invalid or unhandled constant. 13326 // Invalid or unhandled constant.
13327 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); 13327 ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL));
13328 break; 13328 break;
13329 } 13329 }
13330 } 13330 }
13331 13331
13332 return ret; 13332 return ret;
13333 } 13333 }
13334 } 13334 }
13335 13335
13336 return new LSL_List(); 13336 return new LSL_List();
13337 } 13337 }
13338 13338
13339 internal UUID GetScriptByName(string name) 13339 internal UUID GetScriptByName(string name)
13340 { 13340 {
13341 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 13341 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
13342 13342
13343 if (item == null || item.Type != 10) 13343 if (item == null || item.Type != 10)
13344 return UUID.Zero; 13344 return UUID.Zero;
13345 13345
13346 return item.ItemID; 13346 return item.ItemID;
13347 } 13347 }
13348 13348
13349 /// <summary> 13349 /// <summary>
13350 /// Reports the script error in the viewer's Script Warning/Error dialog and shouts it on the debug channel. 13350 /// Reports the script error in the viewer's Script Warning/Error dialog and shouts it on the debug channel.
13351 /// </summary> 13351 /// </summary>
13352 /// <param name="command">The name of the command that generated the error.</param> 13352 /// <param name="command">The name of the command that generated the error.</param>
13353 /// <param name="message">The error message to report to the user.</param> 13353 /// <param name="message">The error message to report to the user.</param>
13354 internal void Error(string command, string message) 13354 internal void Error(string command, string message)
13355 { 13355 {
13356 string text = command + ": " + message; 13356 string text = command + ": " + message;
13357 if (text.Length > 1023) 13357 if (text.Length > 1023)
13358 { 13358 {
13359 text = text.Substring(0, 1023); 13359 text = text.Substring(0, 1023);
13360 } 13360 }
13361 13361
13362 World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL, 13362 World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL,
13363 m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); 13363 m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false);
13364 13364
13365 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); 13365 IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
13366 if (wComm != null) 13366 if (wComm != null)
13367 { 13367 {
13368 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text); 13368 wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text);
13369 } 13369 }
13370 } 13370 }
13371 13371
13372 /// <summary> 13372 /// <summary>
13373 /// Reports that the command is not implemented as a script error. 13373 /// Reports that the command is not implemented as a script error.
13374 /// </summary> 13374 /// </summary>
13375 /// <param name="command">The name of the command that is not implemented.</param> 13375 /// <param name="command">The name of the command that is not implemented.</param>
13376 /// <param name="message">Additional information to report to the user. (Optional)</param> 13376 /// <param name="message">Additional information to report to the user. (Optional)</param>
13377 internal void NotImplemented(string command, string message = "") 13377 internal void NotImplemented(string command, string message = "")
13378 { 13378 {
13379 if (throwErrorOnNotImplemented) 13379 if (throwErrorOnNotImplemented)
13380 { 13380 {
13381 if (message != "") 13381 if (message != "")
13382 { 13382 {
13383 message = " - " + message; 13383 message = " - " + message;
13384 } 13384 }
13385 13385
13386 throw new NotImplementedException("Command not implemented: " + command + message); 13386 throw new NotImplementedException("Command not implemented: " + command + message);
13387 } 13387 }
13388 else 13388 else
13389 { 13389 {
13390 string text = "Command not implemented"; 13390 string text = "Command not implemented";
13391 if (message != "") 13391 if (message != "")
13392 { 13392 {
13393 text = text + " - " + message; 13393 text = text + " - " + message;
13394 } 13394 }
13395 13395
13396 Error(command, text); 13396 Error(command, text);
13397 } 13397 }
13398 } 13398 }
13399 13399
13400 /// <summary> 13400 /// <summary>
13401 /// Reports that the command is deprecated as a script error. 13401 /// Reports that the command is deprecated as a script error.
13402 /// </summary> 13402 /// </summary>
13403 /// <param name="command">The name of the command that is deprecated.</param> 13403 /// <param name="command">The name of the command that is deprecated.</param>
13404 /// <param name="message">Additional information to report to the user. (Optional)</param> 13404 /// <param name="message">Additional information to report to the user. (Optional)</param>
13405 internal void Deprecated(string command, string message = "") 13405 internal void Deprecated(string command, string message = "")
13406 { 13406 {
13407 string text = "Command deprecated"; 13407 string text = "Command deprecated";
13408 if (message != "") 13408 if (message != "")
13409 { 13409 {
13410 text = text + " - " + message; 13410 text = text + " - " + message;
13411 } 13411 }
13412 13412
13413 Error(command, text); 13413 Error(command, text);
13414 } 13414 }
13415 13415
13416 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); 13416 public delegate void AssetRequestCallback(UUID assetID, AssetBase asset);
13417 protected void WithNotecard(UUID assetID, AssetRequestCallback cb) 13417 protected void WithNotecard(UUID assetID, AssetRequestCallback cb)
13418 { 13418 {
13419 World.AssetService.Get(assetID.ToString(), this, 13419 World.AssetService.Get(assetID.ToString(), this,
13420 delegate(string i, object sender, AssetBase a) 13420 delegate(string i, object sender, AssetBase a)
13421 { 13421 {
13422 UUID uuid = UUID.Zero; 13422 UUID uuid = UUID.Zero;
13423 UUID.TryParse(i, out uuid); 13423 UUID.TryParse(i, out uuid);
13424 cb(uuid, a); 13424 cb(uuid, a);
13425 }); 13425 });
13426 } 13426 }
13427 13427
13428 public LSL_String llGetNumberOfNotecardLines(string name) 13428 public LSL_String llGetNumberOfNotecardLines(string name)
13429 { 13429 {
13430 m_host.AddScriptLPS(1); 13430 m_host.AddScriptLPS(1);
13431 13431
13432 UUID assetID = UUID.Zero; 13432 UUID assetID = UUID.Zero;
13433 13433
13434 if (!UUID.TryParse(name, out assetID)) 13434 if (!UUID.TryParse(name, out assetID))
13435 { 13435 {
13436 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 13436 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
13437 13437
13438 if (item != null && item.Type == 7) 13438 if (item != null && item.Type == 7)
13439 assetID = item.AssetID; 13439 assetID = item.AssetID;
13440 } 13440 }
13441 13441
13442 if (assetID == UUID.Zero) 13442 if (assetID == UUID.Zero)
13443 { 13443 {
13444 // => complain loudly, as specified by the LSL docs 13444 // => complain loudly, as specified by the LSL docs
13445 Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); 13445 Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
13446 13446
13447 return UUID.Zero.ToString(); 13447 return UUID.Zero.ToString();
13448 } 13448 }
13449 13449
13450 string reqIdentifier = UUID.Random().ToString(); 13450 string reqIdentifier = UUID.Random().ToString();
13451 13451
13452 // was: UUID tid = tid = AsyncCommands. 13452 // was: UUID tid = tid = AsyncCommands.
13453 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); 13453 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
13454 13454
13455 if (NotecardCache.IsCached(assetID)) 13455 if (NotecardCache.IsCached(assetID))
13456 { 13456 {
13457 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString()); 13457 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString());
13458 13458
13459 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); 13459 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
13460 return tid.ToString(); 13460 return tid.ToString();
13461 } 13461 }
13462 13462
13463 WithNotecard(assetID, delegate (UUID id, AssetBase a) 13463 WithNotecard(assetID, delegate (UUID id, AssetBase a)
13464 { 13464 {
13465 if (a == null || a.Type != 7) 13465 if (a == null || a.Type != 7)
13466 { 13466 {
13467 Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); 13467 Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'");
13468 return; 13468 return;
13469 } 13469 }
13470 13470
13471 NotecardCache.Cache(id, a.Data); 13471 NotecardCache.Cache(id, a.Data);
13472 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString()); 13472 AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString());
13473 }); 13473 });
13474 13474
13475 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); 13475 ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines);
13476 return tid.ToString(); 13476 return tid.ToString();
13477 } 13477 }
13478 13478
13479 public LSL_String llGetNotecardLine(string name, int line) 13479 public LSL_String llGetNotecardLine(string name, int line)
13480 { 13480 {
13481 m_host.AddScriptLPS(1); 13481 m_host.AddScriptLPS(1);
13482 13482
13483 UUID assetID = UUID.Zero; 13483 UUID assetID = UUID.Zero;
13484 13484
13485 if (!UUID.TryParse(name, out assetID)) 13485 if (!UUID.TryParse(name, out assetID))
13486 { 13486 {
13487 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); 13487 TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name);
13488 13488
13489 if (item != null && item.Type == 7) 13489 if (item != null && item.Type == 7)
13490 assetID = item.AssetID; 13490 assetID = item.AssetID;
13491 } 13491 }
13492 13492
13493 if (assetID == UUID.Zero) 13493 if (assetID == UUID.Zero)
13494 { 13494 {
13495 // => complain loudly, as specified by the LSL docs 13495 // => complain loudly, as specified by the LSL docs
13496 Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); 13496 Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
13497 13497
13498 return UUID.Zero.ToString(); 13498 return UUID.Zero.ToString();
13499 } 13499 }
13500 13500
13501 string reqIdentifier = UUID.Random().ToString(); 13501 string reqIdentifier = UUID.Random().ToString();
13502 13502
13503 // was: UUID tid = tid = AsyncCommands. 13503 // was: UUID tid = tid = AsyncCommands.
13504 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); 13504 UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier);
13505 13505
13506 if (NotecardCache.IsCached(assetID)) 13506 if (NotecardCache.IsCached(assetID))
13507 { 13507 {
13508 AsyncCommands.DataserverPlugin.DataserverReply( 13508 AsyncCommands.DataserverPlugin.DataserverReply(
13509 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); 13509 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
13510 13510
13511 ScriptSleep(m_sleepMsOnGetNotecardLine); 13511 ScriptSleep(m_sleepMsOnGetNotecardLine);
13512 return tid.ToString(); 13512 return tid.ToString();
13513 } 13513 }
13514 13514
13515 WithNotecard(assetID, delegate (UUID id, AssetBase a) 13515 WithNotecard(assetID, delegate (UUID id, AssetBase a)
13516 { 13516 {
13517 if (a == null || a.Type != 7) 13517 if (a == null || a.Type != 7)
13518 { 13518 {
13519 Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); 13519 Error("llGetNotecardLine", "Can't find notecard '" + name + "'");
13520 return; 13520 return;
13521 } 13521 }
13522 13522
13523 string data = Encoding.UTF8.GetString(a.Data); 13523 string data = Encoding.UTF8.GetString(a.Data);
13524 //m_log.Debug(data); 13524 //m_log.Debug(data);
13525 NotecardCache.Cache(id, a.Data); 13525 NotecardCache.Cache(id, a.Data);
13526 AsyncCommands.DataserverPlugin.DataserverReply( 13526 AsyncCommands.DataserverPlugin.DataserverReply(
13527 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); 13527 reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax));
13528 }); 13528 });
13529 13529
13530 ScriptSleep(m_sleepMsOnGetNotecardLine); 13530 ScriptSleep(m_sleepMsOnGetNotecardLine);
13531 return tid.ToString(); 13531 return tid.ToString();
13532 } 13532 }
13533 13533
13534 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) 13534 public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc)
13535 { 13535 {
13536 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 13536 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
13537 if (obj == null) 13537 if (obj == null)
13538 return; 13538 return;
13539 13539
13540 if (obj.OwnerID != m_host.OwnerID) 13540 if (obj.OwnerID != m_host.OwnerID)
13541 return; 13541 return;
13542 13542
13543 SetEntityParams(new List<ISceneEntity>() { obj }, rules, originFunc); 13543 SetEntityParams(new List<ISceneEntity>() { obj }, rules, originFunc);
13544 } 13544 }
13545 13545
13546 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) 13546 public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules)
13547 { 13547 {
13548 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); 13548 SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim));
13549 13549
13550 if (obj != null && obj.OwnerID == m_host.OwnerID) 13550 if (obj != null && obj.OwnerID == m_host.OwnerID)
13551 return GetEntityParams(obj, rules); 13551 return GetEntityParams(obj, rules);
13552 13552
13553 return new LSL_List(); 13553 return new LSL_List();
13554 } 13554 }
13555 13555
13556 public void print(string str) 13556 public void print(string str)
13557 { 13557 {
13558 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print 13558 // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print
13559 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); 13559 IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL");
13560 if (ossl != null) 13560 if (ossl != null)
13561 { 13561 {
13562 ossl.CheckThreatLevel(ThreatLevel.High, "print"); 13562 ossl.CheckThreatLevel(ThreatLevel.High, "print");
13563 m_log.Info("LSL print():" + str); 13563 m_log.Info("LSL print():" + str);
13564 } 13564 }
13565 } 13565 }
13566 13566
13567 private string Name2Username(string name) 13567 private string Name2Username(string name)
13568 { 13568 {
13569 string[] parts = name.Split(new char[] {' '}); 13569 string[] parts = name.Split(new char[] {' '});
13570 if (parts.Length < 2) 13570 if (parts.Length < 2)
13571 return name.ToLower(); 13571 return name.ToLower();
13572 if (parts[1] == "Resident") 13572 if (parts[1] == "Resident")
13573 return parts[0].ToLower(); 13573 return parts[0].ToLower();
13574 13574
13575 return name.Replace(" ", ".").ToLower(); 13575 return name.Replace(" ", ".").ToLower();
13576 } 13576 }
13577 13577
13578 public LSL_String llGetUsername(string id) 13578 public LSL_String llGetUsername(string id)
13579 { 13579 {
13580 return Name2Username(llKey2Name(id)); 13580 return Name2Username(llKey2Name(id));
13581 } 13581 }
13582 13582
13583 public LSL_String llRequestUsername(string id) 13583 public LSL_String llRequestUsername(string id)
13584 { 13584 {
13585 UUID rq = UUID.Random(); 13585 UUID rq = UUID.Random();
13586 13586
13587 AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); 13587 AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
13588 13588
13589 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id))); 13589 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id)));
13590 13590
13591 return rq.ToString(); 13591 return rq.ToString();
13592 } 13592 }
13593 13593
13594 public LSL_String llGetDisplayName(string id) 13594 public LSL_String llGetDisplayName(string id)
13595 { 13595 {
13596 return llKey2Name(id); 13596 return llKey2Name(id);
13597 } 13597 }
13598 13598
13599 public LSL_String llRequestDisplayName(string id) 13599 public LSL_String llRequestDisplayName(string id)
13600 { 13600 {
13601 UUID rq = UUID.Random(); 13601 UUID rq = UUID.Random();
13602 13602
13603 AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); 13603 AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString());
13604 13604
13605 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id)); 13605 AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id));
13606 13606
13607 return rq.ToString(); 13607 return rq.ToString();
13608 } 13608 }
13609 13609
13610 private struct Tri 13610 private struct Tri
13611 { 13611 {
13612 public Vector3 p1; 13612 public Vector3 p1;
13613 public Vector3 p2; 13613 public Vector3 p2;
13614 public Vector3 p3; 13614 public Vector3 p3;
13615 } 13615 }
13616 13616
13617 private bool InBoundingBox(ScenePresence avatar, Vector3 point) 13617 private bool InBoundingBox(ScenePresence avatar, Vector3 point)
13618 { 13618 {
13619 float height = avatar.Appearance.AvatarHeight; 13619 float height = avatar.Appearance.AvatarHeight;
13620 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2); 13620 Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2);
13621 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2); 13621 Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2);
13622 13622
13623 if (point.X > b1.X && point.X < b2.X && 13623 if (point.X > b1.X && point.X < b2.X &&
13624 point.Y > b1.Y && point.Y < b2.Y && 13624 point.Y > b1.Y && point.Y < b2.Y &&
13625 point.Z > b1.Z && point.Z < b2.Z) 13625 point.Z > b1.Z && point.Z < b2.Z)
13626 return true; 13626 return true;
13627 return false; 13627 return false;
13628 } 13628 }
13629 13629
13630 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd) 13630 private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd)
13631 { 13631 {
13632 List<ContactResult> contacts = new List<ContactResult>(); 13632 List<ContactResult> contacts = new List<ContactResult>();
13633 13633
13634 Vector3 ab = rayEnd - rayStart; 13634 Vector3 ab = rayEnd - rayStart;
13635 13635
13636 World.ForEachScenePresence(delegate(ScenePresence sp) 13636 World.ForEachScenePresence(delegate(ScenePresence sp)
13637 { 13637 {
13638 Vector3 ac = sp.AbsolutePosition - rayStart; 13638 Vector3 ac = sp.AbsolutePosition - rayStart;
13639// Vector3 bc = sp.AbsolutePosition - rayEnd; 13639// Vector3 bc = sp.AbsolutePosition - rayEnd;
13640 13640
13641 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 13641 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
13642 13642
13643 if (d > 1.5) 13643 if (d > 1.5)
13644 return; 13644 return;
13645 13645
13646 double d2 = Vector3.Dot(Vector3.Negate(ab), ac); 13646 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
13647 13647
13648 if (d2 > 0) 13648 if (d2 > 0)
13649 return; 13649 return;
13650 13650
13651 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d); 13651 double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d);
13652 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab)); 13652 Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab));
13653 13653
13654 if (!InBoundingBox(sp, p)) 13654 if (!InBoundingBox(sp, p))
13655 return; 13655 return;
13656 13656
13657 ContactResult result = new ContactResult (); 13657 ContactResult result = new ContactResult ();
13658 result.ConsumerID = sp.LocalId; 13658 result.ConsumerID = sp.LocalId;
13659 result.Depth = Vector3.Distance(rayStart, p); 13659 result.Depth = Vector3.Distance(rayStart, p);
13660 result.Normal = Vector3.Zero; 13660 result.Normal = Vector3.Zero;
13661 result.Pos = p; 13661 result.Pos = p;
13662 13662
13663 contacts.Add(result); 13663 contacts.Add(result);
13664 }); 13664 });
13665 13665
13666 return contacts.ToArray(); 13666 return contacts.ToArray();
13667 } 13667 }
13668 13668
13669 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom) 13669 private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom)
13670 { 13670 {
13671 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); 13671 Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
13672 List<ContactResult> contacts = new List<ContactResult>(); 13672 List<ContactResult> contacts = new List<ContactResult>();
13673 13673
13674 Vector3 ab = rayEnd - rayStart; 13674 Vector3 ab = rayEnd - rayStart;
13675 13675
13676 World.ForEachSOG(delegate(SceneObjectGroup group) 13676 World.ForEachSOG(delegate(SceneObjectGroup group)
13677 { 13677 {
13678 if (m_host.ParentGroup == group) 13678 if (m_host.ParentGroup == group)
13679 return; 13679 return;
13680 13680
13681 if (group.IsAttachment) 13681 if (group.IsAttachment)
13682 return; 13682 return;
13683 13683
13684 if (group.RootPart.PhysActor == null) 13684 if (group.RootPart.PhysActor == null)
13685 { 13685 {
13686 if (!includePhantom) 13686 if (!includePhantom)
13687 return; 13687 return;
13688 } 13688 }
13689 else 13689 else
13690 { 13690 {
13691 if (group.RootPart.PhysActor.IsPhysical) 13691 if (group.RootPart.PhysActor.IsPhysical)
13692 { 13692 {
13693 if (!includePhysical) 13693 if (!includePhysical)
13694 return; 13694 return;
13695 } 13695 }
13696 else 13696 else
13697 { 13697 {
13698 if (!includeNonPhysical) 13698 if (!includeNonPhysical)
13699 return; 13699 return;
13700 } 13700 }
13701 } 13701 }
13702 13702
13703 // Find the radius ouside of which we don't even need to hit test 13703 // Find the radius ouside of which we don't even need to hit test
13704 float minX; 13704 float minX;
13705 float maxX; 13705 float maxX;
13706 float minY; 13706 float minY;
13707 float maxY; 13707 float maxY;
13708 float minZ; 13708 float minZ;
13709 float maxZ; 13709 float maxZ;
13710 13710
13711 float radius = 0.0f; 13711 float radius = 0.0f;
13712 13712
13713 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ); 13713 group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ);
13714 13714
13715 if (Math.Abs(minX) > radius) 13715 if (Math.Abs(minX) > radius)
13716 radius = Math.Abs(minX); 13716 radius = Math.Abs(minX);
13717 if (Math.Abs(minY) > radius) 13717 if (Math.Abs(minY) > radius)
13718 radius = Math.Abs(minY); 13718 radius = Math.Abs(minY);
13719 if (Math.Abs(minZ) > radius) 13719 if (Math.Abs(minZ) > radius)
13720 radius = Math.Abs(minZ); 13720 radius = Math.Abs(minZ);
13721 if (Math.Abs(maxX) > radius) 13721 if (Math.Abs(maxX) > radius)
13722 radius = Math.Abs(maxX); 13722 radius = Math.Abs(maxX);
13723 if (Math.Abs(maxY) > radius) 13723 if (Math.Abs(maxY) > radius)
13724 radius = Math.Abs(maxY); 13724 radius = Math.Abs(maxY);
13725 if (Math.Abs(maxZ) > radius) 13725 if (Math.Abs(maxZ) > radius)
13726 radius = Math.Abs(maxZ); 13726 radius = Math.Abs(maxZ);
13727 radius = radius*1.413f; 13727 radius = radius*1.413f;
13728 Vector3 ac = group.AbsolutePosition - rayStart; 13728 Vector3 ac = group.AbsolutePosition - rayStart;
13729// Vector3 bc = group.AbsolutePosition - rayEnd; 13729// Vector3 bc = group.AbsolutePosition - rayEnd;
13730 13730
13731 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); 13731 double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd));
13732 13732
13733 // Too far off ray, don't bother 13733 // Too far off ray, don't bother
13734 if (d > radius) 13734 if (d > radius)
13735 return; 13735 return;
13736 13736
13737 // Behind ray, drop 13737 // Behind ray, drop
13738 double d2 = Vector3.Dot(Vector3.Negate(ab), ac); 13738 double d2 = Vector3.Dot(Vector3.Negate(ab), ac);
13739 if (d2 > 0) 13739 if (d2 > 0)
13740 return; 13740 return;
13741 13741
13742 ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); 13742 ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart));
13743 EntityIntersection intersection = group.TestIntersection(ray, true, false); 13743 EntityIntersection intersection = group.TestIntersection(ray, true, false);
13744 // Miss. 13744 // Miss.
13745 if (!intersection.HitTF) 13745 if (!intersection.HitTF)
13746 return; 13746 return;
13747 13747
13748 Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ); 13748 Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ);
13749 Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ); 13749 Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ);
13750 //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z); 13750 //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z);
13751 if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X && 13751 if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X &&
13752 intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y && 13752 intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y &&
13753 intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z)) 13753 intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z))
13754 return; 13754 return;
13755 13755
13756 ContactResult result = new ContactResult (); 13756 ContactResult result = new ContactResult ();
13757 result.ConsumerID = group.LocalId; 13757 result.ConsumerID = group.LocalId;
13758 result.Depth = intersection.distance; 13758 result.Depth = intersection.distance;
13759 result.Normal = intersection.normal; 13759 result.Normal = intersection.normal;
13760 result.Pos = intersection.ipoint; 13760 result.Pos = intersection.ipoint;
13761 13761
13762 contacts.Add(result); 13762 contacts.Add(result);
13763 }); 13763 });
13764 13764
13765 return contacts.ToArray(); 13765 return contacts.ToArray();
13766 } 13766 }
13767 13767
13768 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd) 13768 private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd)
13769 { 13769 {
13770 double[,] heightfield = World.Heightmap.GetDoubles(); 13770 double[,] heightfield = World.Heightmap.GetDoubles();
13771 List<ContactResult> contacts = new List<ContactResult>(); 13771 List<ContactResult> contacts = new List<ContactResult>();
13772 13772
13773 double min = 2048.0; 13773 double min = 2048.0;
13774 double max = 0.0; 13774 double max = 0.0;
13775 13775
13776 // Find the min and max of the heightfield 13776 // Find the min and max of the heightfield
13777 for (int x = 0 ; x < World.Heightmap.Width ; x++) 13777 for (int x = 0 ; x < World.Heightmap.Width ; x++)
13778 { 13778 {
13779 for (int y = 0 ; y < World.Heightmap.Height ; y++) 13779 for (int y = 0 ; y < World.Heightmap.Height ; y++)
13780 { 13780 {
13781 if (heightfield[x, y] > max) 13781 if (heightfield[x, y] > max)
13782 max = heightfield[x, y]; 13782 max = heightfield[x, y];
13783 if (heightfield[x, y] < min) 13783 if (heightfield[x, y] < min)
13784 min = heightfield[x, y]; 13784 min = heightfield[x, y];
13785 } 13785 }
13786 } 13786 }
13787 13787
13788 13788
13789 // A ray extends past rayEnd, but doesn't go back before 13789 // A ray extends past rayEnd, but doesn't go back before
13790 // rayStart. If the start is above the highest point of the ground 13790 // rayStart. If the start is above the highest point of the ground
13791 // and the ray goes up, we can't hit the ground. Ever. 13791 // and the ray goes up, we can't hit the ground. Ever.
13792 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z) 13792 if (rayStart.Z > max && rayEnd.Z >= rayStart.Z)
13793 return null; 13793 return null;
13794 13794
13795 // Same for going down 13795 // Same for going down
13796 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z) 13796 if (rayStart.Z < min && rayEnd.Z <= rayStart.Z)
13797 return null; 13797 return null;
13798 13798
13799 List<Tri> trilist = new List<Tri>(); 13799 List<Tri> trilist = new List<Tri>();
13800 13800
13801 // Create our triangle list 13801 // Create our triangle list
13802 for (int x = 1 ; x < World.Heightmap.Width ; x++) 13802 for (int x = 1 ; x < World.Heightmap.Width ; x++)
13803 { 13803 {
13804 for (int y = 1 ; y < World.Heightmap.Height ; y++) 13804 for (int y = 1 ; y < World.Heightmap.Height ; y++)
13805 { 13805 {
13806 Tri t1 = new Tri(); 13806 Tri t1 = new Tri();
13807 Tri t2 = new Tri(); 13807 Tri t2 = new Tri();
13808 13808
13809 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]); 13809 Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]);
13810 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]); 13810 Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]);
13811 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]); 13811 Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]);
13812 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]); 13812 Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]);
13813 13813
13814 t1.p1 = p1; 13814 t1.p1 = p1;
13815 t1.p2 = p2; 13815 t1.p2 = p2;
13816 t1.p3 = p3; 13816 t1.p3 = p3;
13817 13817
13818 t2.p1 = p3; 13818 t2.p1 = p3;
13819 t2.p2 = p4; 13819 t2.p2 = p4;
13820 t2.p3 = p1; 13820 t2.p3 = p1;
13821 13821
13822 trilist.Add(t1); 13822 trilist.Add(t1);
13823 trilist.Add(t2); 13823 trilist.Add(t2);
13824 } 13824 }
13825 } 13825 }
13826 13826
13827 // Ray direction 13827 // Ray direction
13828 Vector3 rayDirection = rayEnd - rayStart; 13828 Vector3 rayDirection = rayEnd - rayStart;
13829 13829
13830 foreach (Tri t in trilist) 13830 foreach (Tri t in trilist)
13831 { 13831 {
13832 // Compute triangle plane normal and edges 13832 // Compute triangle plane normal and edges
13833 Vector3 u = t.p2 - t.p1; 13833 Vector3 u = t.p2 - t.p1;
13834 Vector3 v = t.p3 - t.p1; 13834 Vector3 v = t.p3 - t.p1;
13835 Vector3 n = Vector3.Cross(u, v); 13835 Vector3 n = Vector3.Cross(u, v);
13836 13836
13837 if (n == Vector3.Zero) 13837 if (n == Vector3.Zero)
13838 continue; 13838 continue;
13839 13839
13840 Vector3 w0 = rayStart - t.p1; 13840 Vector3 w0 = rayStart - t.p1;
13841 double a = -Vector3.Dot(n, w0); 13841 double a = -Vector3.Dot(n, w0);
13842 double b = Vector3.Dot(n, rayDirection); 13842 double b = Vector3.Dot(n, rayDirection);
13843 13843
13844 // Not intersecting the plane, or in plane (same thing) 13844 // Not intersecting the plane, or in plane (same thing)
13845 // Ignoring this MAY cause the ground to not be detected 13845 // Ignoring this MAY cause the ground to not be detected
13846 // sometimes 13846 // sometimes
13847 if (Math.Abs(b) < 0.000001) 13847 if (Math.Abs(b) < 0.000001)
13848 continue; 13848 continue;
13849 13849
13850 double r = a / b; 13850 double r = a / b;
13851 13851
13852 // ray points away from plane 13852 // ray points away from plane
13853 if (r < 0.0) 13853 if (r < 0.0)
13854 continue; 13854 continue;
13855 13855
13856 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r); 13856 Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r);
13857 13857
13858 float uu = Vector3.Dot(u, u); 13858 float uu = Vector3.Dot(u, u);
13859 float uv = Vector3.Dot(u, v); 13859 float uv = Vector3.Dot(u, v);
13860 float vv = Vector3.Dot(v, v); 13860 float vv = Vector3.Dot(v, v);
13861 Vector3 w = ip - t.p1; 13861 Vector3 w = ip - t.p1;
13862 float wu = Vector3.Dot(w, u); 13862 float wu = Vector3.Dot(w, u);
13863 float wv = Vector3.Dot(w, v); 13863 float wv = Vector3.Dot(w, v);
13864 float d = uv * uv - uu * vv; 13864 float d = uv * uv - uu * vv;
13865 13865
13866 float cs = (uv * wv - vv * wu) / d; 13866 float cs = (uv * wv - vv * wu) / d;
13867 if (cs < 0 || cs > 1.0) 13867 if (cs < 0 || cs > 1.0)
13868 continue; 13868 continue;
13869 float ct = (uv * wu - uu * wv) / d; 13869 float ct = (uv * wu - uu * wv) / d;
13870 if (ct < 0 || (cs + ct) > 1.0) 13870 if (ct < 0 || (cs + ct) > 1.0)
13871 continue; 13871 continue;
13872 13872
13873 // Add contact point 13873 // Add contact point
13874 ContactResult result = new ContactResult (); 13874 ContactResult result = new ContactResult ();
13875 result.ConsumerID = 0; 13875 result.ConsumerID = 0;
13876 result.Depth = Vector3.Distance(rayStart, ip); 13876 result.Depth = Vector3.Distance(rayStart, ip);
13877 result.Normal = n; 13877 result.Normal = n;
13878 result.Pos = ip; 13878 result.Pos = ip;
13879 13879
13880 contacts.Add(result); 13880 contacts.Add(result);
13881 } 13881 }
13882 13882
13883 if (contacts.Count == 0) 13883 if (contacts.Count == 0)
13884 return null; 13884 return null;
13885 13885
13886 contacts.Sort(delegate(ContactResult a, ContactResult b) 13886 contacts.Sort(delegate(ContactResult a, ContactResult b)
13887 { 13887 {
13888 return (int)(a.Depth - b.Depth); 13888 return (int)(a.Depth - b.Depth);
13889 }); 13889 });
13890 13890
13891 return contacts[0]; 13891 return contacts[0];
13892 } 13892 }
13893 13893
13894 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) 13894 public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options)
13895 { 13895 {
13896 // Use llCastRay V3 if configured 13896 // Use llCastRay V3 if configured
13897 if (m_useCastRayV3) 13897 if (m_useCastRayV3)
13898 return llCastRayV3(start, end, options); 13898 return llCastRayV3(start, end, options);
13899 13899
13900 LSL_List list = new LSL_List(); 13900 LSL_List list = new LSL_List();
13901 13901
13902 m_host.AddScriptLPS(1); 13902 m_host.AddScriptLPS(1);
13903 13903
13904 Vector3 rayStart = start; 13904 Vector3 rayStart = start;
13905 Vector3 rayEnd = end; 13905 Vector3 rayEnd = end;
13906 Vector3 dir = rayEnd - rayStart; 13906 Vector3 dir = rayEnd - rayStart;
13907 13907
13908 float dist = Vector3.Mag(dir); 13908 float dist = Vector3.Mag(dir);
13909 13909
13910 int count = 1; 13910 int count = 1;
13911 bool detectPhantom = false; 13911 bool detectPhantom = false;
13912 int dataFlags = 0; 13912 int dataFlags = 0;
13913 int rejectTypes = 0; 13913 int rejectTypes = 0;
13914 13914
13915 for (int i = 0; i < options.Length; i += 2) 13915 for (int i = 0; i < options.Length; i += 2)
13916 { 13916 {
13917 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 13917 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
13918 count = options.GetLSLIntegerItem(i + 1); 13918 count = options.GetLSLIntegerItem(i + 1);
13919 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 13919 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
13920 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0); 13920 detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0);
13921 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 13921 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
13922 dataFlags = options.GetLSLIntegerItem(i + 1); 13922 dataFlags = options.GetLSLIntegerItem(i + 1);
13923 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 13923 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
13924 rejectTypes = options.GetLSLIntegerItem(i + 1); 13924 rejectTypes = options.GetLSLIntegerItem(i + 1);
13925 } 13925 }
13926 13926
13927 if (count > 16) 13927 if (count > 16)
13928 count = 16; 13928 count = 16;
13929 13929
13930 List<ContactResult> results = new List<ContactResult>(); 13930 List<ContactResult> results = new List<ContactResult>();
13931 13931
13932 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); 13932 bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND);
13933 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); 13933 bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS);
13934 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); 13934 bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL);
13935 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); 13935 bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL);
13936 13936
13937 13937
13938 if (World.SupportsRayCastFiltered()) 13938 if (World.SupportsRayCastFiltered())
13939 { 13939 {
13940 if (dist == 0) 13940 if (dist == 0)
13941 return list; 13941 return list;
13942 13942
13943 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull; 13943 RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull;
13944 if (checkTerrain) 13944 if (checkTerrain)
13945 rayfilter |= RayFilterFlags.land; 13945 rayfilter |= RayFilterFlags.land;
13946// if (checkAgents) 13946// if (checkAgents)
13947// rayfilter |= RayFilterFlags.agent; 13947// rayfilter |= RayFilterFlags.agent;
13948 if (checkPhysical) 13948 if (checkPhysical)
13949 rayfilter |= RayFilterFlags.physical; 13949 rayfilter |= RayFilterFlags.physical;
13950 if (checkNonPhysical) 13950 if (checkNonPhysical)
13951 rayfilter |= RayFilterFlags.nonphysical; 13951 rayfilter |= RayFilterFlags.nonphysical;
13952 if (detectPhantom) 13952 if (detectPhantom)
13953 rayfilter |= RayFilterFlags.LSLPhantom; 13953 rayfilter |= RayFilterFlags.LSLPhantom;
13954 13954
13955 Vector3 direction = dir * ( 1/dist); 13955 Vector3 direction = dir * ( 1/dist);
13956 13956
13957 if(rayfilter == 0) 13957 if(rayfilter == 0)
13958 { 13958 {
13959 list.Add(new LSL_Integer(0)); 13959 list.Add(new LSL_Integer(0));
13960 return list; 13960 return list;
13961 } 13961 }
13962 13962
13963 // get some more contacts to sort ??? 13963 // get some more contacts to sort ???
13964 int physcount = 4 * count; 13964 int physcount = 4 * count;
13965 if (physcount > 20) 13965 if (physcount > 20)
13966 physcount = 20; 13966 physcount = 20;
13967 13967
13968 object physresults; 13968 object physresults;
13969 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter); 13969 physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter);
13970 13970
13971 if (physresults == null) 13971 if (physresults == null)
13972 { 13972 {
13973 list.Add(new LSL_Integer(-3)); // timeout error 13973 list.Add(new LSL_Integer(-3)); // timeout error
13974 return list; 13974 return list;
13975 } 13975 }
13976 13976
13977 results = (List<ContactResult>)physresults; 13977 results = (List<ContactResult>)physresults;
13978 13978
13979 // for now physics doesn't detect sitted avatars so do it outside physics 13979 // for now physics doesn't detect sitted avatars so do it outside physics
13980 if (checkAgents) 13980 if (checkAgents)
13981 { 13981 {
13982 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 13982 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
13983 foreach (ContactResult r in agentHits) 13983 foreach (ContactResult r in agentHits)
13984 results.Add(r); 13984 results.Add(r);
13985 } 13985 }
13986 13986
13987 // TODO: Replace this with a better solution. ObjectIntersection can only 13987 // TODO: Replace this with a better solution. ObjectIntersection can only
13988 // detect nonphysical phantoms. They are detected by virtue of being 13988 // detect nonphysical phantoms. They are detected by virtue of being
13989 // nonphysical (e.g. no PhysActor) so will not conflict with detecting 13989 // nonphysical (e.g. no PhysActor) so will not conflict with detecting
13990 // physicsl phantoms as done by the physics scene 13990 // physicsl phantoms as done by the physics scene
13991 // We don't want anything else but phantoms here. 13991 // We don't want anything else but phantoms here.
13992 if (detectPhantom) 13992 if (detectPhantom)
13993 { 13993 {
13994 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true); 13994 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true);
13995 foreach (ContactResult r in objectHits) 13995 foreach (ContactResult r in objectHits)
13996 results.Add(r); 13996 results.Add(r);
13997 } 13997 }
13998 } 13998 }
13999 else 13999 else
14000 { 14000 {
14001 if (checkAgents) 14001 if (checkAgents)
14002 { 14002 {
14003 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); 14003 ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd);
14004 foreach (ContactResult r in agentHits) 14004 foreach (ContactResult r in agentHits)
14005 results.Add(r); 14005 results.Add(r);
14006 } 14006 }
14007 14007
14008 if (checkPhysical || checkNonPhysical || detectPhantom) 14008 if (checkPhysical || checkNonPhysical || detectPhantom)
14009 { 14009 {
14010 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); 14010 ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom);
14011 for (int iter = 0; iter < objectHits.Length; iter++) 14011 for (int iter = 0; iter < objectHits.Length; iter++)
14012 { 14012 {
14013 // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler. 14013 // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler.
14014 objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart); 14014 objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart);
14015 results.Add(objectHits[iter]); 14015 results.Add(objectHits[iter]);
14016 } 14016 }
14017 } 14017 }
14018 } 14018 }
14019 14019
14020 if (checkTerrain) 14020 if (checkTerrain)
14021 { 14021 {
14022 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); 14022 ContactResult? groundContact = GroundIntersection(rayStart, rayEnd);
14023 if (groundContact != null) 14023 if (groundContact != null)
14024 results.Add((ContactResult)groundContact); 14024 results.Add((ContactResult)groundContact);
14025 } 14025 }
14026 14026
14027 results.Sort(delegate(ContactResult a, ContactResult b) 14027 results.Sort(delegate(ContactResult a, ContactResult b)
14028 { 14028 {
14029 return a.Depth.CompareTo(b.Depth); 14029 return a.Depth.CompareTo(b.Depth);
14030 }); 14030 });
14031 14031
14032 int values = 0; 14032 int values = 0;
14033 SceneObjectGroup thisgrp = m_host.ParentGroup; 14033 SceneObjectGroup thisgrp = m_host.ParentGroup;
14034 14034
14035 foreach (ContactResult result in results) 14035 foreach (ContactResult result in results)
14036 { 14036 {
14037 if (result.Depth > dist) 14037 if (result.Depth > dist)
14038 continue; 14038 continue;
14039 14039
14040 // physics ray can return colisions with host prim 14040 // physics ray can return colisions with host prim
14041 if (m_host.LocalId == result.ConsumerID) 14041 if (m_host.LocalId == result.ConsumerID)
14042 continue; 14042 continue;
14043 14043
14044 UUID itemID = UUID.Zero; 14044 UUID itemID = UUID.Zero;
14045 int linkNum = 0; 14045 int linkNum = 0;
14046 14046
14047 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID); 14047 SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID);
14048 // It's a prim! 14048 // It's a prim!
14049 if (part != null) 14049 if (part != null)
14050 { 14050 {
14051 // dont detect members of same object ??? 14051 // dont detect members of same object ???
14052 if (part.ParentGroup == thisgrp) 14052 if (part.ParentGroup == thisgrp)
14053 continue; 14053 continue;
14054 14054
14055 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY) 14055 if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY)
14056 itemID = part.ParentGroup.UUID; 14056 itemID = part.ParentGroup.UUID;
14057 else 14057 else
14058 itemID = part.UUID; 14058 itemID = part.UUID;
14059 14059
14060 linkNum = part.LinkNum; 14060 linkNum = part.LinkNum;
14061 } 14061 }
14062 else 14062 else
14063 { 14063 {
14064 ScenePresence sp = World.GetScenePresence(result.ConsumerID); 14064 ScenePresence sp = World.GetScenePresence(result.ConsumerID);
14065 /// It it a boy? a girl? 14065 /// It it a boy? a girl?
14066 if (sp != null) 14066 if (sp != null)
14067 itemID = sp.UUID; 14067 itemID = sp.UUID;
14068 } 14068 }
14069 14069
14070 list.Add(new LSL_String(itemID.ToString())); 14070 list.Add(new LSL_String(itemID.ToString()));
14071 list.Add(new LSL_String(result.Pos.ToString())); 14071 list.Add(new LSL_String(result.Pos.ToString()));
14072 14072
14073 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) 14073 if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM)
14074 list.Add(new LSL_Integer(linkNum)); 14074 list.Add(new LSL_Integer(linkNum));
14075 14075
14076 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) 14076 if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL)
14077 list.Add(new LSL_Vector(result.Normal)); 14077 list.Add(new LSL_Vector(result.Normal));
14078 14078
14079 values++; 14079 values++;
14080 if (values >= count) 14080 if (values >= count)
14081 break; 14081 break;
14082 } 14082 }
14083 14083
14084 list.Add(new LSL_Integer(values)); 14084 list.Add(new LSL_Integer(values));
14085 14085
14086 return list; 14086 return list;
14087 } 14087 }
14088 14088
14089 /// <summary> 14089 /// <summary>
14090 /// Implementation of llCastRay similar to SL 2015-04-21. 14090 /// Implementation of llCastRay similar to SL 2015-04-21.
14091 /// http://wiki.secondlife.com/wiki/LlCastRay 14091 /// http://wiki.secondlife.com/wiki/LlCastRay
14092 /// Uses pure geometry, bounding shapes, meshing and no physics 14092 /// Uses pure geometry, bounding shapes, meshing and no physics
14093 /// for prims, sculpts, meshes, avatars and terrain. 14093 /// for prims, sculpts, meshes, avatars and terrain.
14094 /// Implements all flags, reject types and data flags. 14094 /// Implements all flags, reject types and data flags.
14095 /// Can handle both objects/groups and prims/parts, by config. 14095 /// Can handle both objects/groups and prims/parts, by config.
14096 /// May sometimes be inaccurate owing to calculation precision, 14096 /// May sometimes be inaccurate owing to calculation precision,
14097 /// meshing detail level and a bug in libopenmetaverse PrimMesher. 14097 /// meshing detail level and a bug in libopenmetaverse PrimMesher.
14098 /// </summary> 14098 /// </summary>
14099 public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options) 14099 public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options)
14100 { 14100 {
14101 m_host.AddScriptLPS(1); 14101 m_host.AddScriptLPS(1);
14102 LSL_List result = new LSL_List(); 14102 LSL_List result = new LSL_List();
14103 14103
14104 // Prepare throttle data 14104 // Prepare throttle data
14105 int calledMs = Environment.TickCount; 14105 int calledMs = Environment.TickCount;
14106 Stopwatch stopWatch = new Stopwatch(); 14106 Stopwatch stopWatch = new Stopwatch();
14107 stopWatch.Start(); 14107 stopWatch.Start();
14108 UUID regionId = World.RegionInfo.RegionID; 14108 UUID regionId = World.RegionInfo.RegionID;
14109 UUID userId = UUID.Zero; 14109 UUID userId = UUID.Zero;
14110 int msAvailable = 0; 14110 int msAvailable = 0;
14111 // Throttle per owner when attachment or "vehicle" (sat upon) 14111 // Throttle per owner when attachment or "vehicle" (sat upon)
14112 if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0) 14112 if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0)
14113 { 14113 {
14114 userId = m_host.OwnerID; 14114 userId = m_host.OwnerID;
14115 msAvailable = m_msPerAvatarInCastRay; 14115 msAvailable = m_msPerAvatarInCastRay;
14116 } 14116 }
14117 // Throttle per parcel when not attachment or vehicle 14117 // Throttle per parcel when not attachment or vehicle
14118 else 14118 else
14119 { 14119 {
14120 LandData land = World.GetLandData(m_host.GetWorldPosition()); 14120 LandData land = World.GetLandData(m_host.GetWorldPosition());
14121 if (land != null) 14121 if (land != null)
14122 msAvailable = m_msPerRegionInCastRay * land.Area / 65536; 14122 msAvailable = m_msPerRegionInCastRay * land.Area / 65536;
14123 } 14123 }
14124 // Clamp for "oversized" parcels on varregions 14124 // Clamp for "oversized" parcels on varregions
14125 if (msAvailable > m_msMaxInCastRay) 14125 if (msAvailable > m_msMaxInCastRay)
14126 msAvailable = m_msMaxInCastRay; 14126 msAvailable = m_msMaxInCastRay;
14127 14127
14128 // Check throttle data 14128 // Check throttle data
14129 int fromCalledMs = calledMs - m_msThrottleInCastRay; 14129 int fromCalledMs = calledMs - m_msThrottleInCastRay;
14130 lock (m_castRayCalls) 14130 lock (m_castRayCalls)
14131 { 14131 {
14132 for (int i = m_castRayCalls.Count - 1; i >= 0; i--) 14132 for (int i = m_castRayCalls.Count - 1; i >= 0; i--)
14133 { 14133 {
14134 // Delete old calls from throttle data 14134 // Delete old calls from throttle data
14135 if (m_castRayCalls[i].CalledMs < fromCalledMs) 14135 if (m_castRayCalls[i].CalledMs < fromCalledMs)
14136 m_castRayCalls.RemoveAt(i); 14136 m_castRayCalls.RemoveAt(i);
14137 // Use current region (in multi-region sims) 14137 // Use current region (in multi-region sims)
14138 else if (m_castRayCalls[i].RegionId == regionId) 14138 else if (m_castRayCalls[i].RegionId == regionId)
14139 { 14139 {
14140 // Reduce available time with recent calls 14140 // Reduce available time with recent calls
14141 if (m_castRayCalls[i].UserId == userId) 14141 if (m_castRayCalls[i].UserId == userId)
14142 msAvailable -= m_castRayCalls[i].UsedMs; 14142 msAvailable -= m_castRayCalls[i].UsedMs;
14143 } 14143 }
14144 } 14144 }
14145 } 14145 }
14146 14146
14147 // Return failure if not enough available time 14147 // Return failure if not enough available time
14148 if (msAvailable < m_msMinInCastRay) 14148 if (msAvailable < m_msMinInCastRay)
14149 { 14149 {
14150 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED)); 14150 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED));
14151 return result; 14151 return result;
14152 } 14152 }
14153 14153
14154 // Initialize 14154 // Initialize
14155 List<RayHit> rayHits = new List<RayHit>(); 14155 List<RayHit> rayHits = new List<RayHit>();
14156 float tol = m_floatToleranceInCastRay; 14156 float tol = m_floatToleranceInCastRay;
14157 Vector3 pos1Ray = start; 14157 Vector3 pos1Ray = start;
14158 Vector3 pos2Ray = end; 14158 Vector3 pos2Ray = end;
14159 14159
14160 // Get input options 14160 // Get input options
14161 int rejectTypes = 0; 14161 int rejectTypes = 0;
14162 int dataFlags = 0; 14162 int dataFlags = 0;
14163 int maxHits = 1; 14163 int maxHits = 1;
14164 bool detectPhantom = false; 14164 bool detectPhantom = false;
14165 for (int i = 0; i < options.Length; i += 2) 14165 for (int i = 0; i < options.Length; i += 2)
14166 { 14166 {
14167 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) 14167 if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES)
14168 rejectTypes = options.GetLSLIntegerItem(i + 1); 14168 rejectTypes = options.GetLSLIntegerItem(i + 1);
14169 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) 14169 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS)
14170 dataFlags = options.GetLSLIntegerItem(i + 1); 14170 dataFlags = options.GetLSLIntegerItem(i + 1);
14171 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) 14171 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS)
14172 maxHits = options.GetLSLIntegerItem(i + 1); 14172 maxHits = options.GetLSLIntegerItem(i + 1);
14173 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) 14173 else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM)
14174 detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0); 14174 detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0);
14175 } 14175 }
14176 if (maxHits > m_maxHitsInCastRay) 14176 if (maxHits > m_maxHitsInCastRay)
14177 maxHits = m_maxHitsInCastRay; 14177 maxHits = m_maxHitsInCastRay;
14178 bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0); 14178 bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0);
14179 bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0); 14179 bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0);
14180 bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0); 14180 bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0);
14181 bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0); 14181 bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0);
14182 bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0); 14182 bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0);
14183 bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0); 14183 bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0);
14184 bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); 14184 bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0);
14185 14185
14186 // Calculate some basic parameters 14186 // Calculate some basic parameters
14187 Vector3 vecRay = pos2Ray - pos1Ray; 14187 Vector3 vecRay = pos2Ray - pos1Ray;
14188 float rayLength = vecRay.Length(); 14188 float rayLength = vecRay.Length();
14189 14189
14190 // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits 14190 // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits
14191 IRendering primMesher = null; 14191 IRendering primMesher = null;
14192 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); 14192 List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory());
14193 if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) 14193 if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1)
14194 { 14194 {
14195 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); 14195 result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN));
14196 return result; 14196 return result;
14197 } 14197 }
14198 primMesher = RenderingLoader.LoadRenderer(renderers[0]); 14198 primMesher = RenderingLoader.LoadRenderer(renderers[0]);
14199 14199
14200 // Iterate over all objects/groups and prims/parts in region 14200 // Iterate over all objects/groups and prims/parts in region
14201 World.ForEachSOG( 14201 World.ForEachSOG(
14202 delegate(SceneObjectGroup group) 14202 delegate(SceneObjectGroup group)
14203 { 14203 {
14204 // Check group filters unless part filters are configured 14204 // Check group filters unless part filters are configured
14205 bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical); 14205 bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical);
14206 bool isNonphysical = !isPhysical; 14206 bool isNonphysical = !isPhysical;
14207 bool isPhantom = group.IsPhantom || group.IsVolumeDetect; 14207 bool isPhantom = group.IsPhantom || group.IsVolumeDetect;
14208 bool isAttachment = group.IsAttachment; 14208 bool isAttachment = group.IsAttachment;
14209 bool doGroup = true; 14209 bool doGroup = true;
14210 if (isPhysical && rejectPhysical) 14210 if (isPhysical && rejectPhysical)
14211 doGroup = false; 14211 doGroup = false;
14212 if (isNonphysical && rejectNonphysical) 14212 if (isNonphysical && rejectNonphysical)
14213 doGroup = false; 14213 doGroup = false;
14214 if (isPhantom && detectPhantom) 14214 if (isPhantom && detectPhantom)
14215 doGroup = true; 14215 doGroup = true;
14216 if (m_filterPartsInCastRay) 14216 if (m_filterPartsInCastRay)
14217 doGroup = true; 14217 doGroup = true;
14218 if (isAttachment && !m_doAttachmentsInCastRay) 14218 if (isAttachment && !m_doAttachmentsInCastRay)
14219 doGroup = false; 14219 doGroup = false;
14220 // Parse object/group if passed filters 14220 // Parse object/group if passed filters
14221 if (doGroup) 14221 if (doGroup)
14222 { 14222 {
14223 // Iterate over all prims/parts in object/group 14223 // Iterate over all prims/parts in object/group
14224 foreach(SceneObjectPart part in group.Parts) 14224 foreach(SceneObjectPart part in group.Parts)
14225 { 14225 {
14226 // Check part filters if configured 14226 // Check part filters if configured
14227 if (m_filterPartsInCastRay) 14227 if (m_filterPartsInCastRay)
14228 { 14228 {
14229 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical); 14229 isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical);
14230 isNonphysical = !isPhysical; 14230 isNonphysical = !isPhysical;
14231 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive); 14231 isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive);
14232 bool doPart = true; 14232 bool doPart = true;
14233 if (isPhysical && rejectPhysical) 14233 if (isPhysical && rejectPhysical)
14234 doPart = false; 14234 doPart = false;
14235 if (isNonphysical && rejectNonphysical) 14235 if (isNonphysical && rejectNonphysical)
14236 doPart = false; 14236 doPart = false;
14237 if (isPhantom && detectPhantom) 14237 if (isPhantom && detectPhantom)
14238 doPart = true; 14238 doPart = true;
14239 if (!doPart) 14239 if (!doPart)
14240 continue; 14240 continue;
14241 } 14241 }
14242 14242
14243 // Parse prim/part and project ray if passed filters 14243 // Parse prim/part and project ray if passed filters
14244 Vector3 scalePart = part.Scale; 14244 Vector3 scalePart = part.Scale;
14245 Vector3 posPart = part.GetWorldPosition(); 14245 Vector3 posPart = part.GetWorldPosition();
14246 Quaternion rotPart = part.GetWorldRotation(); 14246 Quaternion rotPart = part.GetWorldRotation();
14247 Quaternion rotPartInv = Quaternion.Inverse(rotPart); 14247 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14248 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; 14248 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14249 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; 14249 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14250 14250
14251 // Filter parts by shape bounding boxes 14251 // Filter parts by shape bounding boxes
14252 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f); 14252 Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f);
14253 if (!part.Shape.SculptEntry) 14253 if (!part.Shape.SculptEntry)
14254 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); 14254 shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ));
14255 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol)); 14255 shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol));
14256 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) 14256 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14257 { 14257 {
14258 // Prepare data needed to check for ray hits 14258 // Prepare data needed to check for ray hits
14259 RayTrans rayTrans = new RayTrans(); 14259 RayTrans rayTrans = new RayTrans();
14260 rayTrans.PartId = part.UUID; 14260 rayTrans.PartId = part.UUID;
14261 rayTrans.GroupId = part.ParentGroup.UUID; 14261 rayTrans.GroupId = part.ParentGroup.UUID;
14262 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; 14262 rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0;
14263 rayTrans.ScalePart = scalePart; 14263 rayTrans.ScalePart = scalePart;
14264 rayTrans.PositionPart = posPart; 14264 rayTrans.PositionPart = posPart;
14265 rayTrans.RotationPart = rotPart; 14265 rayTrans.RotationPart = rotPart;
14266 rayTrans.ShapeNeedsEnds = true; 14266 rayTrans.ShapeNeedsEnds = true;
14267 rayTrans.Position1Ray = pos1Ray; 14267 rayTrans.Position1Ray = pos1Ray;
14268 rayTrans.Position1RayProj = pos1RayProj; 14268 rayTrans.Position1RayProj = pos1RayProj;
14269 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; 14269 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14270 14270
14271 // Get detail level depending on type 14271 // Get detail level depending on type
14272 int lod = 0; 14272 int lod = 0;
14273 // Mesh detail level 14273 // Mesh detail level
14274 if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) 14274 if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14275 lod = (int)m_meshLodInCastRay; 14275 lod = (int)m_meshLodInCastRay;
14276 // Sculpt detail level 14276 // Sculpt detail level
14277 else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) 14277 else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh)
14278 lod = (int)m_sculptLodInCastRay; 14278 lod = (int)m_sculptLodInCastRay;
14279 // Shape detail level 14279 // Shape detail level
14280 else if (!part.Shape.SculptEntry) 14280 else if (!part.Shape.SculptEntry)
14281 lod = (int)m_primLodInCastRay; 14281 lod = (int)m_primLodInCastRay;
14282 14282
14283 // Try to get cached mesh if configured 14283 // Try to get cached mesh if configured
14284 ulong meshKey = 0; 14284 ulong meshKey = 0;
14285 FacetedMesh mesh = null; 14285 FacetedMesh mesh = null;
14286 if (m_useMeshCacheInCastRay) 14286 if (m_useMeshCacheInCastRay)
14287 { 14287 {
14288 meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); 14288 meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod));
14289 lock (m_cachedMeshes) 14289 lock (m_cachedMeshes)
14290 { 14290 {
14291 m_cachedMeshes.TryGetValue(meshKey, out mesh); 14291 m_cachedMeshes.TryGetValue(meshKey, out mesh);
14292 } 14292 }
14293 } 14293 }
14294 14294
14295 // Create mesh if no cached mesh 14295 // Create mesh if no cached mesh
14296 if (mesh == null) 14296 if (mesh == null)
14297 { 14297 {
14298 // Make an OMV prim to be able to mesh part 14298 // Make an OMV prim to be able to mesh part
14299 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); 14299 Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart);
14300 byte[] sculptAsset = null; 14300 byte[] sculptAsset = null;
14301 if (omvPrim.Sculpt != null) 14301 if (omvPrim.Sculpt != null)
14302 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); 14302 sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString());
14303 14303
14304 // When part is mesh, get mesh 14304 // When part is mesh, get mesh
14305 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) 14305 if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null)
14306 { 14306 {
14307 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); 14307 AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset);
14308 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); 14308 FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh);
14309 meshAsset = null; 14309 meshAsset = null;
14310 } 14310 }
14311 14311
14312 // When part is sculpt, create mesh 14312 // When part is sculpt, create mesh
14313 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. 14313 // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt.
14314 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) 14314 else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null)
14315 { 14315 {
14316 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); 14316 IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>();
14317 if (imgDecoder != null) 14317 if (imgDecoder != null)
14318 { 14318 {
14319 Image sculpt = imgDecoder.DecodeToImage(sculptAsset); 14319 Image sculpt = imgDecoder.DecodeToImage(sculptAsset);
14320 if (sculpt != null) 14320 if (sculpt != null)
14321 { 14321 {
14322 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); 14322 mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay);
14323 sculpt.Dispose(); 14323 sculpt.Dispose();
14324 } 14324 }
14325 } 14325 }
14326 } 14326 }
14327 14327
14328 // When part is shape, create mesh 14328 // When part is shape, create mesh
14329 else if (omvPrim.Sculpt == null) 14329 else if (omvPrim.Sculpt == null)
14330 { 14330 {
14331 if ( 14331 if (
14332 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && 14332 omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 &&
14333 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && 14333 omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 &&
14334 omvPrim.PrimData.PathSkew == 0.0 && 14334 omvPrim.PrimData.PathSkew == 0.0 &&
14335 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 14335 omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0
14336 ) 14336 )
14337 rayTrans.ShapeNeedsEnds = false; 14337 rayTrans.ShapeNeedsEnds = false;
14338 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); 14338 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay);
14339 } 14339 }
14340 14340
14341 // Cache mesh if configured 14341 // Cache mesh if configured
14342 if (m_useMeshCacheInCastRay && mesh != null) 14342 if (m_useMeshCacheInCastRay && mesh != null)
14343 { 14343 {
14344 lock(m_cachedMeshes) 14344 lock(m_cachedMeshes)
14345 { 14345 {
14346 if (!m_cachedMeshes.ContainsKey(meshKey)) 14346 if (!m_cachedMeshes.ContainsKey(meshKey))
14347 m_cachedMeshes.Add(meshKey, mesh); 14347 m_cachedMeshes.Add(meshKey, mesh);
14348 } 14348 }
14349 } 14349 }
14350 } 14350 }
14351 // Check mesh for ray hits 14351 // Check mesh for ray hits
14352 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); 14352 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14353 mesh = null; 14353 mesh = null;
14354 } 14354 }
14355 } 14355 }
14356 } 14356 }
14357 } 14357 }
14358 ); 14358 );
14359 14359
14360 // Check avatar filter 14360 // Check avatar filter
14361 if (!rejectAgents) 14361 if (!rejectAgents)
14362 { 14362 {
14363 // Iterate over all avatars in region 14363 // Iterate over all avatars in region
14364 World.ForEachRootScenePresence( 14364 World.ForEachRootScenePresence(
14365 delegate (ScenePresence sp) 14365 delegate (ScenePresence sp)
14366 { 14366 {
14367 // Get bounding box 14367 // Get bounding box
14368 Vector3 lower; 14368 Vector3 lower;
14369 Vector3 upper; 14369 Vector3 upper;
14370 BoundingBoxOfScenePresence(sp, out lower, out upper); 14370 BoundingBoxOfScenePresence(sp, out lower, out upper);
14371 // Parse avatar 14371 // Parse avatar
14372 Vector3 scalePart = upper - lower; 14372 Vector3 scalePart = upper - lower;
14373 Vector3 posPart = sp.AbsolutePosition; 14373 Vector3 posPart = sp.AbsolutePosition;
14374 Quaternion rotPart = sp.GetWorldRotation(); 14374 Quaternion rotPart = sp.GetWorldRotation();
14375 Quaternion rotPartInv = Quaternion.Inverse(rotPart); 14375 Quaternion rotPartInv = Quaternion.Inverse(rotPart);
14376 posPart = posPart + (lower + upper) * 0.5f * rotPart; 14376 posPart = posPart + (lower + upper) * 0.5f * rotPart;
14377 // Project ray 14377 // Project ray
14378 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; 14378 Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart;
14379 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; 14379 Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart;
14380 14380
14381 // Filter avatars by shape bounding boxes 14381 // Filter avatars by shape bounding boxes
14382 Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol); 14382 Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol);
14383 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) 14383 if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax))
14384 { 14384 {
14385 // Prepare data needed to check for ray hits 14385 // Prepare data needed to check for ray hits
14386 RayTrans rayTrans = new RayTrans(); 14386 RayTrans rayTrans = new RayTrans();
14387 rayTrans.PartId = sp.UUID; 14387 rayTrans.PartId = sp.UUID;
14388 rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; 14388 rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID;
14389 rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; 14389 rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0;
14390 rayTrans.ScalePart = scalePart; 14390 rayTrans.ScalePart = scalePart;
14391 rayTrans.PositionPart = posPart; 14391 rayTrans.PositionPart = posPart;
14392 rayTrans.RotationPart = rotPart; 14392 rayTrans.RotationPart = rotPart;
14393 rayTrans.ShapeNeedsEnds = false; 14393 rayTrans.ShapeNeedsEnds = false;
14394 rayTrans.Position1Ray = pos1Ray; 14394 rayTrans.Position1Ray = pos1Ray;
14395 rayTrans.Position1RayProj = pos1RayProj; 14395 rayTrans.Position1RayProj = pos1RayProj;
14396 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; 14396 rayTrans.VectorRayProj = pos2RayProj - pos1RayProj;
14397 14397
14398 // Try to get cached mesh if configured 14398 // Try to get cached mesh if configured
14399 PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); 14399 PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere();
14400 int lod = (int)m_avatarLodInCastRay; 14400 int lod = (int)m_avatarLodInCastRay;
14401 ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod)); 14401 ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod));
14402 FacetedMesh mesh = null; 14402 FacetedMesh mesh = null;
14403 if (m_useMeshCacheInCastRay) 14403 if (m_useMeshCacheInCastRay)
14404 { 14404 {
14405 lock (m_cachedMeshes) 14405 lock (m_cachedMeshes)
14406 { 14406 {
14407 m_cachedMeshes.TryGetValue(meshKey, out mesh); 14407 m_cachedMeshes.TryGetValue(meshKey, out mesh);
14408 } 14408 }
14409 } 14409 }
14410 14410
14411 // Create mesh if no cached mesh 14411 // Create mesh if no cached mesh
14412 if (mesh == null) 14412 if (mesh == null)
14413 { 14413 {
14414 // Make OMV prim and create mesh 14414 // Make OMV prim and create mesh
14415 prim.Scale = scalePart; 14415 prim.Scale = scalePart;
14416 Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); 14416 Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart);
14417 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay); 14417 mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay);
14418 14418
14419 // Cache mesh if configured 14419 // Cache mesh if configured
14420 if (m_useMeshCacheInCastRay && mesh != null) 14420 if (m_useMeshCacheInCastRay && mesh != null)
14421 { 14421 {
14422 lock(m_cachedMeshes) 14422 lock(m_cachedMeshes)
14423 { 14423 {
14424 if (!m_cachedMeshes.ContainsKey(meshKey)) 14424 if (!m_cachedMeshes.ContainsKey(meshKey))
14425 m_cachedMeshes.Add(meshKey, mesh); 14425 m_cachedMeshes.Add(meshKey, mesh);
14426 } 14426 }
14427 } 14427 }
14428 } 14428 }
14429 14429
14430 // Check mesh for ray hits 14430 // Check mesh for ray hits
14431 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); 14431 AddRayInFacetedMesh(mesh, rayTrans, ref rayHits);
14432 mesh = null; 14432 mesh = null;
14433 } 14433 }
14434 } 14434 }
14435 ); 14435 );
14436 } 14436 }
14437 14437
14438 // Check terrain filter 14438 // Check terrain filter
14439 if (!rejectLand) 14439 if (!rejectLand)
14440 { 14440 {
14441 // Parse terrain 14441 // Parse terrain
14442 14442
14443 // Mesh terrain and check bounding box 14443 // Mesh terrain and check bounding box
14444 Vector3 lower; 14444 Vector3 lower;
14445 Vector3 upper; 14445 Vector3 upper;
14446 List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper); 14446 List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper);
14447 lower.Z -= tol; 14447 lower.Z -= tol;
14448 upper.Z += tol; 14448 upper.Z += tol;
14449 if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z)) 14449 if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z))
14450 { 14450 {
14451 // Prepare data needed to check for ray hits 14451 // Prepare data needed to check for ray hits
14452 RayTrans rayTrans = new RayTrans(); 14452 RayTrans rayTrans = new RayTrans();
14453 rayTrans.PartId = UUID.Zero; 14453 rayTrans.PartId = UUID.Zero;
14454 rayTrans.GroupId = UUID.Zero; 14454 rayTrans.GroupId = UUID.Zero;
14455 rayTrans.Link = 0; 14455 rayTrans.Link = 0;
14456 rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f); 14456 rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f);
14457 rayTrans.PositionPart = Vector3.Zero; 14457 rayTrans.PositionPart = Vector3.Zero;
14458 rayTrans.RotationPart = Quaternion.Identity; 14458 rayTrans.RotationPart = Quaternion.Identity;
14459 rayTrans.ShapeNeedsEnds = true; 14459 rayTrans.ShapeNeedsEnds = true;
14460 rayTrans.Position1Ray = pos1Ray; 14460 rayTrans.Position1Ray = pos1Ray;
14461 rayTrans.Position1RayProj = pos1Ray; 14461 rayTrans.Position1RayProj = pos1Ray;
14462 rayTrans.VectorRayProj = vecRay; 14462 rayTrans.VectorRayProj = vecRay;
14463 14463
14464 // Check mesh 14464 // Check mesh
14465 AddRayInTris(triangles, rayTrans, ref rayHits); 14465 AddRayInTris(triangles, rayTrans, ref rayHits);
14466 triangles = null; 14466 triangles = null;
14467 } 14467 }
14468 } 14468 }
14469 14469
14470 // Sort hits by ascending distance 14470 // Sort hits by ascending distance
14471 rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance)); 14471 rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance));
14472 14472
14473 // Check excess hits per part and group 14473 // Check excess hits per part and group
14474 for (int t = 0; t < 2; t++) 14474 for (int t = 0; t < 2; t++)
14475 { 14475 {
14476 int maxHitsPerType = 0; 14476 int maxHitsPerType = 0;
14477 UUID id = UUID.Zero; 14477 UUID id = UUID.Zero;
14478 if (t == 0) 14478 if (t == 0)
14479 maxHitsPerType = m_maxHitsPerPrimInCastRay; 14479 maxHitsPerType = m_maxHitsPerPrimInCastRay;
14480 else 14480 else
14481 maxHitsPerType = m_maxHitsPerObjectInCastRay; 14481 maxHitsPerType = m_maxHitsPerObjectInCastRay;
14482 14482
14483 // Handle excess hits only when needed 14483 // Handle excess hits only when needed
14484 if (maxHitsPerType < m_maxHitsInCastRay) 14484 if (maxHitsPerType < m_maxHitsInCastRay)
14485 { 14485 {
14486 // Find excess hits 14486 // Find excess hits
14487 Hashtable hits = new Hashtable(); 14487 Hashtable hits = new Hashtable();
14488 for (int i = rayHits.Count - 1; i >= 0; i--) 14488 for (int i = rayHits.Count - 1; i >= 0; i--)
14489 { 14489 {
14490 if (t == 0) 14490 if (t == 0)
14491 id = rayHits[i].PartId; 14491 id = rayHits[i].PartId;
14492 else 14492 else
14493 id = rayHits[i].GroupId; 14493 id = rayHits[i].GroupId;
14494 if (hits.ContainsKey(id)) 14494 if (hits.ContainsKey(id))
14495 hits[id] = (int)hits[id] + 1; 14495 hits[id] = (int)hits[id] + 1;
14496 else 14496 else
14497 hits[id] = 1; 14497 hits[id] = 1;
14498 } 14498 }
14499 14499
14500 // Remove excess hits 14500 // Remove excess hits
14501 for (int i = rayHits.Count - 1; i >= 0; i--) 14501 for (int i = rayHits.Count - 1; i >= 0; i--)
14502 { 14502 {
14503 if (t == 0) 14503 if (t == 0)
14504 id = rayHits[i].PartId; 14504 id = rayHits[i].PartId;
14505 else 14505 else
14506 id = rayHits[i].GroupId; 14506 id = rayHits[i].GroupId;
14507 int hit = (int)hits[id]; 14507 int hit = (int)hits[id];
14508 if (hit > m_maxHitsPerPrimInCastRay) 14508 if (hit > m_maxHitsPerPrimInCastRay)
14509 { 14509 {
14510 rayHits.RemoveAt(i); 14510 rayHits.RemoveAt(i);
14511 hit--; 14511 hit--;
14512 hits[id] = hit; 14512 hits[id] = hit;
14513 } 14513 }
14514 } 14514 }
14515 } 14515 }
14516 } 14516 }
14517 14517
14518 // Parse hits into result list according to data flags 14518 // Parse hits into result list according to data flags
14519 int hitCount = rayHits.Count; 14519 int hitCount = rayHits.Count;
14520 if (hitCount > maxHits) 14520 if (hitCount > maxHits)
14521 hitCount = maxHits; 14521 hitCount = maxHits;
14522 for (int i = 0; i < hitCount; i++) 14522 for (int i = 0; i < hitCount; i++)
14523 { 14523 {
14524 RayHit rayHit = rayHits[i]; 14524 RayHit rayHit = rayHits[i];
14525 if (getRootKey) 14525 if (getRootKey)
14526 result.Add(new LSL_Key(rayHit.GroupId.ToString())); 14526 result.Add(new LSL_Key(rayHit.GroupId.ToString()));
14527 else 14527 else
14528 result.Add(new LSL_Key(rayHit.PartId.ToString())); 14528 result.Add(new LSL_Key(rayHit.PartId.ToString()));
14529 result.Add(new LSL_Vector(rayHit.Position)); 14529 result.Add(new LSL_Vector(rayHit.Position));
14530 if (getLinkNum) 14530 if (getLinkNum)
14531 result.Add(new LSL_Integer(rayHit.Link)); 14531 result.Add(new LSL_Integer(rayHit.Link));
14532 if (getNormal) 14532 if (getNormal)
14533 result.Add(new LSL_Vector(rayHit.Normal)); 14533 result.Add(new LSL_Vector(rayHit.Normal));
14534 } 14534 }
14535 result.Add(new LSL_Integer(hitCount)); 14535 result.Add(new LSL_Integer(hitCount));
14536 14536
14537 // Add to throttle data 14537 // Add to throttle data
14538 stopWatch.Stop(); 14538 stopWatch.Stop();
14539 CastRayCall castRayCall = new CastRayCall(); 14539 CastRayCall castRayCall = new CastRayCall();
14540 castRayCall.RegionId = regionId; 14540 castRayCall.RegionId = regionId;
14541 castRayCall.UserId = userId; 14541 castRayCall.UserId = userId;
14542 castRayCall.CalledMs = calledMs; 14542 castRayCall.CalledMs = calledMs;
14543 castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds; 14543 castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds;
14544 lock (m_castRayCalls) 14544 lock (m_castRayCalls)
14545 { 14545 {
14546 m_castRayCalls.Add(castRayCall); 14546 m_castRayCalls.Add(castRayCall);
14547 } 14547 }
14548 14548
14549 // Return hits 14549 // Return hits
14550 return result; 14550 return result;
14551 } 14551 }
14552 14552
14553 /// <summary> 14553 /// <summary>
14554 /// Struct for transmitting parameters required for finding llCastRay ray hits. 14554 /// Struct for transmitting parameters required for finding llCastRay ray hits.
14555 /// </summary> 14555 /// </summary>
14556 public struct RayTrans 14556 public struct RayTrans
14557 { 14557 {
14558 public UUID PartId; 14558 public UUID PartId;
14559 public UUID GroupId; 14559 public UUID GroupId;
14560 public int Link; 14560 public int Link;
14561 public Vector3 ScalePart; 14561 public Vector3 ScalePart;
14562 public Vector3 PositionPart; 14562 public Vector3 PositionPart;
14563 public Quaternion RotationPart; 14563 public Quaternion RotationPart;
14564 public bool ShapeNeedsEnds; 14564 public bool ShapeNeedsEnds;
14565 public Vector3 Position1Ray; 14565 public Vector3 Position1Ray;
14566 public Vector3 Position1RayProj; 14566 public Vector3 Position1RayProj;
14567 public Vector3 VectorRayProj; 14567 public Vector3 VectorRayProj;
14568 } 14568 }
14569 14569
14570 /// <summary> 14570 /// <summary>
14571 /// Struct for llCastRay ray hits. 14571 /// Struct for llCastRay ray hits.
14572 /// </summary> 14572 /// </summary>
14573 public struct RayHit 14573 public struct RayHit
14574 { 14574 {
14575 public UUID PartId; 14575 public UUID PartId;
14576 public UUID GroupId; 14576 public UUID GroupId;
14577 public int Link; 14577 public int Link;
14578 public Vector3 Position; 14578 public Vector3 Position;
14579 public Vector3 Normal; 14579 public Vector3 Normal;
14580 public float Distance; 14580 public float Distance;
14581 } 14581 }
14582 14582
14583 /// <summary> 14583 /// <summary>
14584 /// Struct for llCastRay throttle data. 14584 /// Struct for llCastRay throttle data.
14585 /// </summary> 14585 /// </summary>
14586 public struct CastRayCall 14586 public struct CastRayCall
14587 { 14587 {
14588 public UUID RegionId; 14588 public UUID RegionId;
14589 public UUID UserId; 14589 public UUID UserId;
14590 public int CalledMs; 14590 public int CalledMs;
14591 public int UsedMs; 14591 public int UsedMs;
14592 } 14592 }
14593 14593
14594 /// <summary> 14594 /// <summary>
14595 /// Helper to check if a ray intersects a shape bounding box. 14595 /// Helper to check if a ray intersects a shape bounding box.
14596 /// </summary> 14596 /// </summary>
14597 private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax) 14597 private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax)
14598 { 14598 {
14599 // Skip if ray can't intersect bounding box; 14599 // Skip if ray can't intersect bounding box;
14600 Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj); 14600 Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj);
14601 Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj); 14601 Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj);
14602 if ( 14602 if (
14603 rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z || 14603 rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z ||
14604 rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z 14604 rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z
14605 ) 14605 )
14606 return false; 14606 return false;
14607 14607
14608 // Check if ray intersect any bounding box side 14608 // Check if ray intersect any bounding box side
14609 int sign = 0; 14609 int sign = 0;
14610 float dist = 0.0f; 14610 float dist = 0.0f;
14611 Vector3 posProj = Vector3.Zero; 14611 Vector3 posProj = Vector3.Zero;
14612 Vector3 vecRayProj = pos2RayProj - pos1RayProj; 14612 Vector3 vecRayProj = pos2RayProj - pos1RayProj;
14613 14613
14614 // Check both X sides unless ray is parallell to them 14614 // Check both X sides unless ray is parallell to them
14615 if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay) 14615 if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay)
14616 { 14616 {
14617 for (sign = -1; sign <= 1; sign += 2) 14617 for (sign = -1; sign <= 1; sign += 2)
14618 { 14618 {
14619 dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X; 14619 dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X;
14620 posProj = pos1RayProj + vecRayProj * dist; 14620 posProj = pos1RayProj + vecRayProj * dist;
14621 if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z) 14621 if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14622 return true; 14622 return true;
14623 } 14623 }
14624 } 14624 }
14625 14625
14626 // Check both Y sides unless ray is parallell to them 14626 // Check both Y sides unless ray is parallell to them
14627 if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay) 14627 if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay)
14628 { 14628 {
14629 for (sign = -1; sign <= 1; sign += 2) 14629 for (sign = -1; sign <= 1; sign += 2)
14630 { 14630 {
14631 dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y; 14631 dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y;
14632 posProj = pos1RayProj + vecRayProj * dist; 14632 posProj = pos1RayProj + vecRayProj * dist;
14633 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z) 14633 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z)
14634 return true; 14634 return true;
14635 } 14635 }
14636 } 14636 }
14637 14637
14638 // Check both Z sides unless ray is parallell to them 14638 // Check both Z sides unless ray is parallell to them
14639 if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay) 14639 if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay)
14640 { 14640 {
14641 for (sign = -1; sign <= 1; sign += 2) 14641 for (sign = -1; sign <= 1; sign += 2)
14642 { 14642 {
14643 dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z; 14643 dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z;
14644 posProj = pos1RayProj + vecRayProj * dist; 14644 posProj = pos1RayProj + vecRayProj * dist;
14645 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y) 14645 if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y)
14646 return true; 14646 return true;
14647 } 14647 }
14648 } 14648 }
14649 14649
14650 // No hits on bounding box so return false 14650 // No hits on bounding box so return false
14651 return false; 14651 return false;
14652 } 14652 }
14653 14653
14654 /// <summary> 14654 /// <summary>
14655 /// Helper to parse FacetedMesh for ray hits. 14655 /// Helper to parse FacetedMesh for ray hits.
14656 /// </summary> 14656 /// </summary>
14657 private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits) 14657 private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits)
14658 { 14658 {
14659 if (mesh != null) 14659 if (mesh != null)
14660 { 14660 {
14661 foreach (Face face in mesh.Faces) 14661 foreach (Face face in mesh.Faces)
14662 { 14662 {
14663 for (int i = 0; i < face.Indices.Count; i += 3) 14663 for (int i = 0; i < face.Indices.Count; i += 3)
14664 { 14664 {
14665 Tri triangle = new Tri(); 14665 Tri triangle = new Tri();
14666 triangle.p1 = face.Vertices[face.Indices[i]].Position; 14666 triangle.p1 = face.Vertices[face.Indices[i]].Position;
14667 triangle.p2 = face.Vertices[face.Indices[i + 1]].Position; 14667 triangle.p2 = face.Vertices[face.Indices[i + 1]].Position;
14668 triangle.p3 = face.Vertices[face.Indices[i + 2]].Position; 14668 triangle.p3 = face.Vertices[face.Indices[i + 2]].Position;
14669 AddRayInTri(triangle, rayTrans, ref rayHits); 14669 AddRayInTri(triangle, rayTrans, ref rayHits);
14670 } 14670 }
14671 } 14671 }
14672 } 14672 }
14673 } 14673 }
14674 14674
14675 /// <summary> 14675 /// <summary>
14676 /// Helper to parse Tri (triangle) List for ray hits. 14676 /// Helper to parse Tri (triangle) List for ray hits.
14677 /// </summary> 14677 /// </summary>
14678 private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits) 14678 private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits)
14679 { 14679 {
14680 foreach (Tri triangle in triangles) 14680 foreach (Tri triangle in triangles)
14681 { 14681 {
14682 AddRayInTri(triangle, rayTrans, ref rayHits); 14682 AddRayInTri(triangle, rayTrans, ref rayHits);
14683 } 14683 }
14684 } 14684 }
14685 14685
14686 /// <summary> 14686 /// <summary>
14687 /// Helper to add ray hit in a Tri (triangle). 14687 /// Helper to add ray hit in a Tri (triangle).
14688 /// </summary> 14688 /// </summary>
14689 private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits) 14689 private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits)
14690 { 14690 {
14691 // Check for hit in triangle 14691 // Check for hit in triangle
14692 Vector3 posHitProj; 14692 Vector3 posHitProj;
14693 Vector3 normalProj; 14693 Vector3 normalProj;
14694 if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj)) 14694 if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj))
14695 { 14695 {
14696 // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center 14696 // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center
14697 if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds) 14697 if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds)
14698 return; 14698 return;
14699 14699
14700 // Transform hit and normal to region coordinate system 14700 // Transform hit and normal to region coordinate system
14701 Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart; 14701 Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart;
14702 Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart); 14702 Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart);
14703 14703
14704 // Remove duplicate hits at triangle intersections 14704 // Remove duplicate hits at triangle intersections
14705 float distance = Vector3.Distance(rayTrans.Position1Ray, posHit); 14705 float distance = Vector3.Distance(rayTrans.Position1Ray, posHit);
14706 for (int i = rayHits.Count - 1; i >= 0; i--) 14706 for (int i = rayHits.Count - 1; i >= 0; i--)
14707 { 14707 {
14708 if (rayHits[i].PartId != rayTrans.PartId) 14708 if (rayHits[i].PartId != rayTrans.PartId)
14709 break; 14709 break;
14710 if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay) 14710 if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay)
14711 return; 14711 return;
14712 } 14712 }
14713 14713
14714 // Build result data set 14714 // Build result data set
14715 RayHit rayHit = new RayHit(); 14715 RayHit rayHit = new RayHit();
14716 rayHit.PartId = rayTrans.PartId; 14716 rayHit.PartId = rayTrans.PartId;
14717 rayHit.GroupId = rayTrans.GroupId; 14717 rayHit.GroupId = rayTrans.GroupId;
14718 rayHit.Link = rayTrans.Link; 14718 rayHit.Link = rayTrans.Link;
14719 rayHit.Position = posHit; 14719 rayHit.Position = posHit;
14720 rayHit.Normal = normal; 14720 rayHit.Normal = normal;
14721 rayHit.Distance = distance; 14721 rayHit.Distance = distance;
14722 rayHits.Add(rayHit); 14722 rayHits.Add(rayHit);
14723 } 14723 }
14724 } 14724 }
14725 14725
14726 /// <summary> 14726 /// <summary>
14727 /// Helper to find ray hit in triangle 14727 /// Helper to find ray hit in triangle
14728 /// </summary> 14728 /// </summary>
14729 bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj) 14729 bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj)
14730 { 14730 {
14731 float tol = m_floatToleranceInCastRay; 14731 float tol = m_floatToleranceInCastRay;
14732 posHitProj = Vector3.Zero; 14732 posHitProj = Vector3.Zero;
14733 14733
14734 // Calculate triangle edge vectors 14734 // Calculate triangle edge vectors
14735 Vector3 vec1Proj = triProj.p2 - triProj.p1; 14735 Vector3 vec1Proj = triProj.p2 - triProj.p1;
14736 Vector3 vec2Proj = triProj.p3 - triProj.p2; 14736 Vector3 vec2Proj = triProj.p3 - triProj.p2;
14737 Vector3 vec3Proj = triProj.p1 - triProj.p3; 14737 Vector3 vec3Proj = triProj.p1 - triProj.p3;
14738 14738
14739 // Calculate triangle normal 14739 // Calculate triangle normal
14740 normalProj = Vector3.Cross(vec1Proj, vec2Proj); 14740 normalProj = Vector3.Cross(vec1Proj, vec2Proj);
14741 14741
14742 // Skip if degenerate triangle or ray parallell with triangle plane 14742 // Skip if degenerate triangle or ray parallell with triangle plane
14743 float divisor = Vector3.Dot(vecRayProj, normalProj); 14743 float divisor = Vector3.Dot(vecRayProj, normalProj);
14744 if (Math.Abs(divisor) < tol) 14744 if (Math.Abs(divisor) < tol)
14745 return false; 14745 return false;
14746 14746
14747 // Skip if exit and not configured to detect 14747 // Skip if exit and not configured to detect
14748 if (divisor > tol && !m_detectExitsInCastRay) 14748 if (divisor > tol && !m_detectExitsInCastRay)
14749 return false; 14749 return false;
14750 14750
14751 // Skip if outside ray ends 14751 // Skip if outside ray ends
14752 float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor; 14752 float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor;
14753 if (distanceProj < -tol || distanceProj > 1 + tol) 14753 if (distanceProj < -tol || distanceProj > 1 + tol)
14754 return false; 14754 return false;
14755 14755
14756 // Calculate hit position in triangle 14756 // Calculate hit position in triangle
14757 posHitProj = pos1RayProj + vecRayProj * distanceProj; 14757 posHitProj = pos1RayProj + vecRayProj * distanceProj;
14758 14758
14759 // Skip if outside triangle bounding box 14759 // Skip if outside triangle bounding box
14760 Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3); 14760 Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3);
14761 Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3); 14761 Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3);
14762 if ( 14762 if (
14763 posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol || 14763 posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol ||
14764 posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol 14764 posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol
14765 ) 14765 )
14766 return false; 14766 return false;
14767 14767
14768 // Skip if outside triangle 14768 // Skip if outside triangle
14769 if ( 14769 if (
14770 Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol || 14770 Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol ||
14771 Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol || 14771 Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol ||
14772 Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol 14772 Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol
14773 ) 14773 )
14774 return false; 14774 return false;
14775 14775
14776 // Return hit 14776 // Return hit
14777 return true; 14777 return true;
14778 } 14778 }
14779 14779
14780 /// <summary> 14780 /// <summary>
14781 /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box. 14781 /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box.
14782 /// </summary> 14782 /// </summary>
14783 private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper) 14783 private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper)
14784 { 14784 {
14785 // Get bounding X-Y rectangle of terrain under ray 14785 // Get bounding X-Y rectangle of terrain under ray
14786 lower = Vector3.Min(posStart, posEnd); 14786 lower = Vector3.Min(posStart, posEnd);
14787 upper = Vector3.Max(posStart, posEnd); 14787 upper = Vector3.Max(posStart, posEnd);
14788 lower.X = (float)Math.Floor(lower.X); 14788 lower.X = (float)Math.Floor(lower.X);
14789 lower.Y = (float)Math.Floor(lower.Y); 14789 lower.Y = (float)Math.Floor(lower.Y);
14790 float zLower = float.MaxValue; 14790 float zLower = float.MaxValue;
14791 upper.X = (float)Math.Ceiling(upper.X); 14791 upper.X = (float)Math.Ceiling(upper.X);
14792 upper.Y = (float)Math.Ceiling(upper.Y); 14792 upper.Y = (float)Math.Ceiling(upper.Y);
14793 float zUpper = float.MinValue; 14793 float zUpper = float.MinValue;
14794 14794
14795 // Initialize Tri (triangle) List 14795 // Initialize Tri (triangle) List
14796 List<Tri> triangles = new List<Tri>(); 14796 List<Tri> triangles = new List<Tri>();
14797 14797
14798 // Set parsing lane direction to major ray X-Y axis 14798 // Set parsing lane direction to major ray X-Y axis
14799 Vector3 vec = posEnd - posStart; 14799 Vector3 vec = posEnd - posStart;
14800 float xAbs = Math.Abs(vec.X); 14800 float xAbs = Math.Abs(vec.X);
14801 float yAbs = Math.Abs(vec.Y); 14801 float yAbs = Math.Abs(vec.Y);
14802 bool bigX = true; 14802 bool bigX = true;
14803 if (yAbs > xAbs) 14803 if (yAbs > xAbs)
14804 { 14804 {
14805 bigX = false; 14805 bigX = false;
14806 vec = vec / yAbs; 14806 vec = vec / yAbs;
14807 } 14807 }
14808 else if (xAbs > yAbs || xAbs > 0.0f) 14808 else if (xAbs > yAbs || xAbs > 0.0f)
14809 vec = vec / xAbs; 14809 vec = vec / xAbs;
14810 else 14810 else
14811 vec = new Vector3(1.0f, 1.0f, 0.0f); 14811 vec = new Vector3(1.0f, 1.0f, 0.0f);
14812 14812
14813 // Simplify by start parsing in lower end of lane 14813 // Simplify by start parsing in lower end of lane
14814 if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f)) 14814 if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f))
14815 { 14815 {
14816 Vector3 posTemp = posStart; 14816 Vector3 posTemp = posStart;
14817 posStart = posEnd; 14817 posStart = posEnd;
14818 posEnd = posTemp; 14818 posEnd = posTemp;
14819 vec = vec * -1.0f; 14819 vec = vec * -1.0f;
14820 } 14820 }
14821 14821
14822 // First 1x1 rectangle under ray 14822 // First 1x1 rectangle under ray
14823 float xFloorOld = 0.0f; 14823 float xFloorOld = 0.0f;
14824 float yFloorOld = 0.0f; 14824 float yFloorOld = 0.0f;
14825 Vector3 pos = posStart; 14825 Vector3 pos = posStart;
14826 float xFloor = (float)Math.Floor(pos.X); 14826 float xFloor = (float)Math.Floor(pos.X);
14827 float yFloor = (float)Math.Floor(pos.Y); 14827 float yFloor = (float)Math.Floor(pos.Y);
14828 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); 14828 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
14829 14829
14830 // Parse every remaining 1x1 rectangle under ray 14830 // Parse every remaining 1x1 rectangle under ray
14831 while (pos != posEnd) 14831 while (pos != posEnd)
14832 { 14832 {
14833 // Next 1x1 rectangle under ray 14833 // Next 1x1 rectangle under ray
14834 xFloorOld = xFloor; 14834 xFloorOld = xFloor;
14835 yFloorOld = yFloor; 14835 yFloorOld = yFloor;
14836 pos = pos + vec; 14836 pos = pos + vec;
14837 14837
14838 // Clip position to 1x1 rectangle border 14838 // Clip position to 1x1 rectangle border
14839 xFloor = (float)Math.Floor(pos.X); 14839 xFloor = (float)Math.Floor(pos.X);
14840 yFloor = (float)Math.Floor(pos.Y); 14840 yFloor = (float)Math.Floor(pos.Y);
14841 if (bigX && pos.X > xFloor) 14841 if (bigX && pos.X > xFloor)
14842 { 14842 {
14843 pos.Y -= vec.Y * (pos.X - xFloor); 14843 pos.Y -= vec.Y * (pos.X - xFloor);
14844 pos.X = xFloor; 14844 pos.X = xFloor;
14845 } 14845 }
14846 else if (!bigX && pos.Y > yFloor) 14846 else if (!bigX && pos.Y > yFloor)
14847 { 14847 {
14848 pos.X -= vec.X * (pos.Y - yFloor); 14848 pos.X -= vec.X * (pos.Y - yFloor);
14849 pos.Y = yFloor; 14849 pos.Y = yFloor;
14850 } 14850 }
14851 14851
14852 // Last 1x1 rectangle under ray 14852 // Last 1x1 rectangle under ray
14853 if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y)) 14853 if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y))
14854 { 14854 {
14855 pos = posEnd; 14855 pos = posEnd;
14856 xFloor = (float)Math.Floor(pos.X); 14856 xFloor = (float)Math.Floor(pos.X);
14857 yFloor = (float)Math.Floor(pos.Y); 14857 yFloor = (float)Math.Floor(pos.Y);
14858 } 14858 }
14859 14859
14860 // Add new 1x1 rectangle in lane 14860 // Add new 1x1 rectangle in lane
14861 if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld)) 14861 if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld))
14862 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); 14862 AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper);
14863 // Add last 1x1 rectangle in old lane at lane shift 14863 // Add last 1x1 rectangle in old lane at lane shift
14864 if (bigX && yFloor != yFloorOld) 14864 if (bigX && yFloor != yFloorOld)
14865 AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper); 14865 AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper);
14866 if (!bigX && xFloor != xFloorOld) 14866 if (!bigX && xFloor != xFloorOld)
14867 AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper); 14867 AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper);
14868 } 14868 }
14869 14869
14870 // Finalize bounding box Z 14870 // Finalize bounding box Z
14871 lower.Z = zLower; 14871 lower.Z = zLower;
14872 upper.Z = zUpper; 14872 upper.Z = zUpper;
14873 14873
14874 // Done and returning Tri (triangle)List 14874 // Done and returning Tri (triangle)List
14875 return triangles; 14875 return triangles;
14876 } 14876 }
14877 14877
14878 /// <summary> 14878 /// <summary>
14879 /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box. 14879 /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box.
14880 /// </summary> 14880 /// </summary>
14881 private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper) 14881 private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper)
14882 { 14882 {
14883 int xInt = (int)xPos; 14883 int xInt = (int)xPos;
14884 int yInt = (int)yPos; 14884 int yInt = (int)yPos;
14885 14885
14886 // Corner 1 of 1x1 rectangle 14886 // Corner 1 of 1x1 rectangle
14887 int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); 14887 int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
14888 int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); 14888 int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
14889 Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]); 14889 Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14890 // Adjust bounding box 14890 // Adjust bounding box
14891 zLower = Math.Min(zLower, pos1.Z); 14891 zLower = Math.Min(zLower, pos1.Z);
14892 zUpper = Math.Max(zUpper, pos1.Z); 14892 zUpper = Math.Max(zUpper, pos1.Z);
14893 14893
14894 // Corner 2 of 1x1 rectangle 14894 // Corner 2 of 1x1 rectangle
14895 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); 14895 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
14896 y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); 14896 y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1);
14897 Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); 14897 Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14898 // Adjust bounding box 14898 // Adjust bounding box
14899 zLower = Math.Min(zLower, pos2.Z); 14899 zLower = Math.Min(zLower, pos2.Z);
14900 zUpper = Math.Max(zUpper, pos2.Z); 14900 zUpper = Math.Max(zUpper, pos2.Z);
14901 14901
14902 // Corner 3 of 1x1 rectangle 14902 // Corner 3 of 1x1 rectangle
14903 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); 14903 x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1);
14904 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); 14904 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14905 Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); 14905 Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14906 // Adjust bounding box 14906 // Adjust bounding box
14907 zLower = Math.Min(zLower, pos3.Z); 14907 zLower = Math.Min(zLower, pos3.Z);
14908 zUpper = Math.Max(zUpper, pos3.Z); 14908 zUpper = Math.Max(zUpper, pos3.Z);
14909 14909
14910 // Corner 4 of 1x1 rectangle 14910 // Corner 4 of 1x1 rectangle
14911 x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); 14911 x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1);
14912 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); 14912 y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1);
14913 Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); 14913 Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]);
14914 // Adjust bounding box 14914 // Adjust bounding box
14915 zLower = Math.Min(zLower, pos4.Z); 14915 zLower = Math.Min(zLower, pos4.Z);
14916 zUpper = Math.Max(zUpper, pos4.Z); 14916 zUpper = Math.Max(zUpper, pos4.Z);
14917 14917
14918 // Add triangle 1 14918 // Add triangle 1
14919 Tri triangle1 = new Tri(); 14919 Tri triangle1 = new Tri();
14920 triangle1.p1 = pos1; 14920 triangle1.p1 = pos1;
14921 triangle1.p2 = pos2; 14921 triangle1.p2 = pos2;
14922 triangle1.p3 = pos3; 14922 triangle1.p3 = pos3;
14923 triangles.Add(triangle1); 14923 triangles.Add(triangle1);
14924 14924
14925 // Add triangle 2 14925 // Add triangle 2
14926 Tri triangle2 = new Tri(); 14926 Tri triangle2 = new Tri();
14927 triangle2.p1 = pos3; 14927 triangle2.p1 = pos3;
14928 triangle2.p2 = pos4; 14928 triangle2.p2 = pos4;
14929 triangle2.p3 = pos1; 14929 triangle2.p3 = pos1;
14930 triangles.Add(triangle2); 14930 triangles.Add(triangle2);
14931 } 14931 }
14932 14932
14933 /// <summary> 14933 /// <summary>
14934 /// Helper to get link number for a UUID. 14934 /// Helper to get link number for a UUID.
14935 /// </summary> 14935 /// </summary>
14936 private int UUID2LinkNumber(SceneObjectPart part, UUID id) 14936 private int UUID2LinkNumber(SceneObjectPart part, UUID id)
14937 { 14937 {
14938 SceneObjectGroup group = part.ParentGroup; 14938 SceneObjectGroup group = part.ParentGroup;
14939 if (group != null) 14939 if (group != null)
14940 { 14940 {
14941 // Parse every link for UUID 14941 // Parse every link for UUID
14942 int linkCount = group.PrimCount + group.GetSittingAvatarsCount(); 14942 int linkCount = group.PrimCount + group.GetSittingAvatarsCount();
14943 for (int link = linkCount; link > 0; link--) 14943 for (int link = linkCount; link > 0; link--)
14944 { 14944 {
14945 ISceneEntity entity = GetLinkEntity(part, link); 14945 ISceneEntity entity = GetLinkEntity(part, link);
14946 // Return link number if UUID match 14946 // Return link number if UUID match
14947 if (entity != null && entity.UUID == id) 14947 if (entity != null && entity.UUID == id)
14948 return link; 14948 return link;
14949 } 14949 }
14950 } 14950 }
14951 // Return link number 0 if no links or UUID matches 14951 // Return link number 0 if no links or UUID matches
14952 return 0; 14952 return 0;
14953 } 14953 }
14954 14954
14955 public LSL_Integer llManageEstateAccess(int action, string avatar) 14955 public LSL_Integer llManageEstateAccess(int action, string avatar)
14956 { 14956 {
14957 m_host.AddScriptLPS(1); 14957 m_host.AddScriptLPS(1);
14958 EstateSettings estate = World.RegionInfo.EstateSettings; 14958 EstateSettings estate = World.RegionInfo.EstateSettings;
14959 bool isAccount = false; 14959 bool isAccount = false;
14960 bool isGroup = false; 14960 bool isGroup = false;
14961 14961
14962 if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID)) 14962 if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID))
14963 return 0; 14963 return 0;
14964 14964
14965 UUID id = new UUID(); 14965 UUID id = new UUID();
14966 if (!UUID.TryParse(avatar, out id)) 14966 if (!UUID.TryParse(avatar, out id))
14967 return 0; 14967 return 0;
14968 14968
14969 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, id); 14969 UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, id);
14970 isAccount = account != null ? true : false; 14970 isAccount = account != null ? true : false;
14971 if (!isAccount) 14971 if (!isAccount)
14972 { 14972 {
14973 IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>(); 14973 IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>();
14974 if (groups != null) 14974 if (groups != null)
14975 { 14975 {
14976 GroupRecord group = groups.GetGroupRecord(id); 14976 GroupRecord group = groups.GetGroupRecord(id);
14977 isGroup = group != null ? true : false; 14977 isGroup = group != null ? true : false;
14978 if (!isGroup) 14978 if (!isGroup)
14979 return 0; 14979 return 0;
14980 } 14980 }
14981 else 14981 else
14982 return 0; 14982 return 0;
14983 } 14983 }
14984 14984
14985 switch (action) 14985 switch (action)
14986 { 14986 {
14987 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: 14987 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD:
14988 if (!isAccount) return 0; 14988 if (!isAccount) return 0;
14989 if (estate.HasAccess(id)) return 1; 14989 if (estate.HasAccess(id)) return 1;
14990 if (estate.IsBanned(id)) 14990 if (estate.IsBanned(id))
14991 estate.RemoveBan(id); 14991 estate.RemoveBan(id);
14992 estate.AddEstateUser(id); 14992 estate.AddEstateUser(id);
14993 break; 14993 break;
14994 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_REMOVE: 14994 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_REMOVE:
14995 if (!isAccount || !estate.HasAccess(id)) return 0; 14995 if (!isAccount || !estate.HasAccess(id)) return 0;
14996 estate.RemoveEstateUser(id); 14996 estate.RemoveEstateUser(id);
14997 break; 14997 break;
14998 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_ADD: 14998 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_ADD:
14999 if (!isGroup) return 0; 14999 if (!isGroup) return 0;
15000 if (estate.GroupAccess(id)) return 1; 15000 if (estate.GroupAccess(id)) return 1;
15001 estate.AddEstateGroup(id); 15001 estate.AddEstateGroup(id);
15002 break; 15002 break;
15003 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_REMOVE: 15003 case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_REMOVE:
15004 if (!isGroup || !estate.GroupAccess(id)) return 0; 15004 if (!isGroup || !estate.GroupAccess(id)) return 0;
15005 estate.RemoveEstateGroup(id); 15005 estate.RemoveEstateGroup(id);
15006 break; 15006 break;
15007 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: 15007 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD:
15008 if (!isAccount) return 0; 15008 if (!isAccount) return 0;
15009 if (estate.IsBanned(id)) return 1; 15009 if (estate.IsBanned(id)) return 1;
15010 EstateBan ban = new EstateBan(); 15010 EstateBan ban = new EstateBan();
15011 ban.EstateID = estate.EstateID; 15011 ban.EstateID = estate.EstateID;
15012 ban.BannedUserID = id; 15012 ban.BannedUserID = id;
15013 estate.AddBan(ban); 15013 estate.AddBan(ban);
15014 break; 15014 break;
15015 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: 15015 case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE:
15016 if (!isAccount || !estate.IsBanned(id)) return 0; 15016 if (!isAccount || !estate.IsBanned(id)) return 0;
15017 estate.RemoveBan(id); 15017 estate.RemoveBan(id);
15018 break; 15018 break;
15019 default: return 0; 15019 default: return 0;
15020 } 15020 }
15021 return 1; 15021 return 1;
15022 } 15022 }
15023 15023
15024 public LSL_Integer llGetMemoryLimit() 15024 public LSL_Integer llGetMemoryLimit()
15025 { 15025 {
15026 m_host.AddScriptLPS(1); 15026 m_host.AddScriptLPS(1);
15027 // The value returned for Mono scripts in SL 15027 // The value returned for Mono scripts in SL
15028 return 65536; 15028 return 65536;
15029 } 15029 }
15030 15030
15031 public LSL_Integer llSetMemoryLimit(LSL_Integer limit) 15031 public LSL_Integer llSetMemoryLimit(LSL_Integer limit)
15032 { 15032 {
15033 m_host.AddScriptLPS(1); 15033 m_host.AddScriptLPS(1);
15034 // Treat as an LSO script 15034 // Treat as an LSO script
15035 return ScriptBaseClass.FALSE; 15035 return ScriptBaseClass.FALSE;
15036 } 15036 }
15037 15037
15038 public LSL_Integer llGetSPMaxMemory() 15038 public LSL_Integer llGetSPMaxMemory()
15039 { 15039 {
15040 m_host.AddScriptLPS(1); 15040 m_host.AddScriptLPS(1);
15041 // The value returned for Mono scripts in SL 15041 // The value returned for Mono scripts in SL
15042 return 65536; 15042 return 65536;
15043 } 15043 }
15044 15044
15045 public virtual LSL_Integer llGetUsedMemory() 15045 public virtual LSL_Integer llGetUsedMemory()
15046 { 15046 {
15047 m_host.AddScriptLPS(1); 15047 m_host.AddScriptLPS(1);
15048 // The value returned for Mono scripts in SL 15048 // The value returned for Mono scripts in SL
15049 return 65536; 15049 return 65536;
15050 } 15050 }
15051 15051
15052 public void llScriptProfiler(LSL_Integer flags) 15052 public void llScriptProfiler(LSL_Integer flags)
15053 { 15053 {
15054 m_host.AddScriptLPS(1); 15054 m_host.AddScriptLPS(1);
15055 // This does nothing for LSO scripts in SL 15055 // This does nothing for LSO scripts in SL
15056 } 15056 }
15057 15057
15058 #region Not Implemented 15058 #region Not Implemented
15059 // 15059 //
15060 // Listing the unimplemented lsl functions here, please move 15060 // Listing the unimplemented lsl functions here, please move
15061 // them from this region as they are completed 15061 // them from this region as they are completed
15062 // 15062 //
15063 15063
15064 public void llSetSoundQueueing(int queue) 15064 public void llSetSoundQueueing(int queue)
15065 { 15065 {
15066 m_host.AddScriptLPS(1); 15066 m_host.AddScriptLPS(1);
15067 15067
15068 if (m_SoundModule != null) 15068 if (m_SoundModule != null)
15069 m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value); 15069 m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value);
15070 } 15070 }
15071 15071
15072 public void llCollisionSprite(string impact_sprite) 15072 public void llCollisionSprite(string impact_sprite)
15073 { 15073 {
15074 m_host.AddScriptLPS(1); 15074 m_host.AddScriptLPS(1);
15075 NotImplemented("llCollisionSprite"); 15075 NotImplemented("llCollisionSprite");
15076 } 15076 }
15077 15077
15078 public void llGodLikeRezObject(string inventory, LSL_Vector pos) 15078 public void llGodLikeRezObject(string inventory, LSL_Vector pos)
15079 { 15079 {
15080 m_host.AddScriptLPS(1); 15080 m_host.AddScriptLPS(1);
15081 NotImplemented("llGodLikeRezObject"); 15081 NotImplemented("llGodLikeRezObject");
15082 } 15082 }
15083 15083
15084 public LSL_String llTransferLindenDollars(string destination, int amount) 15084 public LSL_String llTransferLindenDollars(string destination, int amount)
15085 { 15085 {
15086 UUID txn = UUID.Random(); 15086 UUID txn = UUID.Random();
15087 15087
15088 Util.FireAndForget(delegate(object x) 15088 Util.FireAndForget(delegate(object x)
15089 { 15089 {
15090 int replycode = 0; 15090 int replycode = 0;
15091 string replydata = destination + "," + amount.ToString(); 15091 string replydata = destination + "," + amount.ToString();
15092 15092
15093 try 15093 try
15094 { 15094 {
15095 TaskInventoryItem item = m_item; 15095 TaskInventoryItem item = m_item;
15096 if (item == null) 15096 if (item == null)
15097 { 15097 {
15098 replydata = "SERVICE_ERROR"; 15098 replydata = "SERVICE_ERROR";
15099 return; 15099 return;
15100 } 15100 }
15101 15101
15102 m_host.AddScriptLPS(1); 15102 m_host.AddScriptLPS(1);
15103 15103
15104 if (item.PermsGranter == UUID.Zero) 15104 if (item.PermsGranter == UUID.Zero)
15105 { 15105 {
15106 replydata = "MISSING_PERMISSION_DEBIT"; 15106 replydata = "MISSING_PERMISSION_DEBIT";
15107 return; 15107 return;
15108 } 15108 }
15109 15109
15110 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) 15110 if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0)
15111 { 15111 {
15112 replydata = "MISSING_PERMISSION_DEBIT"; 15112 replydata = "MISSING_PERMISSION_DEBIT";
15113 return; 15113 return;
15114 } 15114 }
15115 15115
15116 UUID toID = new UUID(); 15116 UUID toID = new UUID();
15117 15117
15118 if (!UUID.TryParse(destination, out toID)) 15118 if (!UUID.TryParse(destination, out toID))
15119 { 15119 {
15120 replydata = "INVALID_AGENT"; 15120 replydata = "INVALID_AGENT";
15121 return; 15121 return;
15122 } 15122 }
15123 15123
15124 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); 15124 IMoneyModule money = World.RequestModuleInterface<IMoneyModule>();
15125 15125
15126 if (money == null) 15126 if (money == null)
15127 { 15127 {
15128 replydata = "TRANSFERS_DISABLED"; 15128 replydata = "TRANSFERS_DISABLED";
15129 return; 15129 return;
15130 } 15130 }
15131 15131
15132 bool result = money.ObjectGiveMoney( 15132 bool result = money.ObjectGiveMoney(
15133 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); 15133 m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount);
15134 15134
15135 if (result) 15135 if (result)
15136 { 15136 {
15137 replycode = 1; 15137 replycode = 1;
15138 return; 15138 return;
15139 } 15139 }
15140 15140
15141 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS"; 15141 replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS";
15142 } 15142 }
15143 finally 15143 finally
15144 { 15144 {
15145 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( 15145 m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams(
15146 "transaction_result", new Object[] { 15146 "transaction_result", new Object[] {
15147 new LSL_String(txn.ToString()), 15147 new LSL_String(txn.ToString()),
15148 new LSL_Integer(replycode), 15148 new LSL_Integer(replycode),
15149 new LSL_String(replydata) }, 15149 new LSL_String(replydata) },
15150 new DetectParams[0])); 15150 new DetectParams[0]));
15151 } 15151 }
15152 }, null, "LSL_Api.llTransferLindenDollars"); 15152 }, null, "LSL_Api.llTransferLindenDollars");
15153 15153
15154 return txn.ToString(); 15154 return txn.ToString();
15155 } 15155 }
15156 15156
15157 #endregion 15157 #endregion
15158 } 15158 }
15159 15159
15160 public class NotecardCache 15160 public class NotecardCache
15161 { 15161 {
15162 protected class Notecard 15162 protected class Notecard
15163 { 15163 {
15164 public string[] text; 15164 public string[] text;
15165 public DateTime lastRef; 15165 public DateTime lastRef;
15166 } 15166 }
15167 15167
15168 private static Dictionary<UUID, Notecard> m_Notecards = 15168 private static Dictionary<UUID, Notecard> m_Notecards =
15169 new Dictionary<UUID, Notecard>(); 15169 new Dictionary<UUID, Notecard>();
15170 15170
15171 public static void Cache(UUID assetID, byte[] text) 15171 public static void Cache(UUID assetID, byte[] text)
15172 { 15172 {
15173 CheckCache(); 15173 CheckCache();
15174 15174
15175 lock (m_Notecards) 15175 lock (m_Notecards)
15176 { 15176 {
15177 if (m_Notecards.ContainsKey(assetID)) 15177 if (m_Notecards.ContainsKey(assetID))
15178 return; 15178 return;
15179 15179
15180 Notecard nc = new Notecard(); 15180 Notecard nc = new Notecard();
15181 nc.lastRef = DateTime.Now; 15181 nc.lastRef = DateTime.Now;
15182 try 15182 try
15183 { 15183 {
15184 nc.text = SLUtil.ParseNotecardToArray(text); 15184 nc.text = SLUtil.ParseNotecardToArray(text);
15185 } 15185 }
15186 catch(SLUtil.NotANotecardFormatException) 15186 catch(SLUtil.NotANotecardFormatException)
15187 { 15187 {
15188 nc.text = new string[0]; 15188 nc.text = new string[0];
15189 } 15189 }
15190 m_Notecards[assetID] = nc; 15190 m_Notecards[assetID] = nc;
15191 } 15191 }
15192 } 15192 }
15193 15193
15194 public static bool IsCached(UUID assetID) 15194 public static bool IsCached(UUID assetID)
15195 { 15195 {
15196 lock (m_Notecards) 15196 lock (m_Notecards)
15197 { 15197 {
15198 return m_Notecards.ContainsKey(assetID); 15198 return m_Notecards.ContainsKey(assetID);
15199 } 15199 }
15200 } 15200 }
15201 15201
15202 public static int GetLines(UUID assetID) 15202 public static int GetLines(UUID assetID)
15203 { 15203 {
15204 if (!IsCached(assetID)) 15204 if (!IsCached(assetID))
15205 return -1; 15205 return -1;
15206 15206
15207 lock (m_Notecards) 15207 lock (m_Notecards)
15208 { 15208 {
15209 m_Notecards[assetID].lastRef = DateTime.Now; 15209 m_Notecards[assetID].lastRef = DateTime.Now;
15210 return m_Notecards[assetID].text.Length; 15210 return m_Notecards[assetID].text.Length;
15211 } 15211 }
15212 } 15212 }
15213 15213
15214 /// <summary> 15214 /// <summary>
15215 /// Get a notecard line. 15215 /// Get a notecard line.
15216 /// </summary> 15216 /// </summary>
15217 /// <param name="assetID"></param> 15217 /// <param name="assetID"></param>
15218 /// <param name="lineNumber">Lines start at index 0</param> 15218 /// <param name="lineNumber">Lines start at index 0</param>
15219 /// <returns></returns> 15219 /// <returns></returns>
15220 public static string GetLine(UUID assetID, int lineNumber) 15220 public static string GetLine(UUID assetID, int lineNumber)
15221 { 15221 {
15222 if (lineNumber < 0) 15222 if (lineNumber < 0)
15223 return ""; 15223 return "";
15224 15224
15225 string data; 15225 string data;
15226 15226
15227 if (!IsCached(assetID)) 15227 if (!IsCached(assetID))
15228 return ""; 15228 return "";
15229 15229
15230 lock (m_Notecards) 15230 lock (m_Notecards)
15231 { 15231 {
15232 m_Notecards[assetID].lastRef = DateTime.Now; 15232 m_Notecards[assetID].lastRef = DateTime.Now;
15233 15233
15234 if (lineNumber >= m_Notecards[assetID].text.Length) 15234 if (lineNumber >= m_Notecards[assetID].text.Length)
15235 return "\n\n\n"; 15235 return "\n\n\n";
15236 15236
15237 data = m_Notecards[assetID].text[lineNumber]; 15237 data = m_Notecards[assetID].text[lineNumber];
15238 15238
15239 return data; 15239 return data;
15240 } 15240 }
15241 } 15241 }
15242 15242
15243 /// <summary> 15243 /// <summary>
15244 /// Get a notecard line. 15244 /// Get a notecard line.
15245 /// </summary> 15245 /// </summary>
15246 /// <param name="assetID"></param> 15246 /// <param name="assetID"></param>
15247 /// <param name="lineNumber">Lines start at index 0</param> 15247 /// <param name="lineNumber">Lines start at index 0</param>
15248 /// <param name="maxLength"> 15248 /// <param name="maxLength">
15249 /// Maximum length of the returned line. 15249 /// Maximum length of the returned line.
15250 /// </param> 15250 /// </param>
15251 /// <returns> 15251 /// <returns>
15252 /// If the line length is longer than <paramref name="maxLength"/>, 15252 /// If the line length is longer than <paramref name="maxLength"/>,
15253 /// the return string will be truncated. 15253 /// the return string will be truncated.
15254 /// </returns> 15254 /// </returns>
15255 public static string GetLine(UUID assetID, int lineNumber, int maxLength) 15255 public static string GetLine(UUID assetID, int lineNumber, int maxLength)
15256 { 15256 {
15257 string line = GetLine(assetID, lineNumber); 15257 string line = GetLine(assetID, lineNumber);
15258 15258
15259 if (line.Length > maxLength) 15259 if (line.Length > maxLength)
15260 line = line.Substring(0, maxLength); 15260 line = line.Substring(0, maxLength);
15261 15261
15262 return line; 15262 return line;
15263 } 15263 }
15264 15264
15265 public static void CheckCache() 15265 public static void CheckCache()
15266 { 15266 {
15267 lock (m_Notecards) 15267 lock (m_Notecards)
15268 { 15268 {
15269 foreach (UUID key in new List<UUID>(m_Notecards.Keys)) 15269 foreach (UUID key in new List<UUID>(m_Notecards.Keys))
15270 { 15270 {
15271 Notecard nc = m_Notecards[key]; 15271 Notecard nc = m_Notecards[key];
15272 if (nc.lastRef.AddSeconds(30) < DateTime.Now) 15272 if (nc.lastRef.AddSeconds(30) < DateTime.Now)
15273 m_Notecards.Remove(key); 15273 m_Notecards.Remove(key);
15274 } 15274 }
15275 } 15275 }
15276 } 15276 }
15277 } 15277 }
15278} 15278}