diff options
author | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
---|---|---|
committer | David Walter Seikel | 2016-11-03 21:44:39 +1000 |
commit | 134f86e8d5c414409631b25b8c6f0ee45fbd8631 (patch) | |
tree | 216b89d3fb89acfb81be1e440c25c41ab09fa96d /OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |
parent | More changing to production grid. Double oops. (diff) | |
download | opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.zip opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.gz opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.bz2 opensim-SC_OLD-134f86e8d5c414409631b25b8c6f0ee45fbd8631.tar.xz |
Initial update to OpenSim 0.8.2.1 source code.
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 5807 |
1 files changed, 4705 insertions, 1102 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1ab107a..4eda443 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -28,6 +28,9 @@ | |||
28 | using System; | 28 | using System; |
29 | using System.Collections; | 29 | using System.Collections; |
30 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
31 | using System.Diagnostics; | ||
32 | using System.Drawing; | ||
33 | using System.Drawing.Imaging; | ||
31 | using System.Runtime.Remoting.Lifetime; | 34 | using System.Runtime.Remoting.Lifetime; |
32 | using System.Text; | 35 | using System.Text; |
33 | using System.Threading; | 36 | using System.Threading; |
@@ -35,7 +38,9 @@ using System.Text.RegularExpressions; | |||
35 | using Nini.Config; | 38 | using Nini.Config; |
36 | using log4net; | 39 | using log4net; |
37 | using OpenMetaverse; | 40 | using OpenMetaverse; |
41 | using OpenMetaverse.Assets; | ||
38 | using OpenMetaverse.Packets; | 42 | using OpenMetaverse.Packets; |
43 | using OpenMetaverse.Rendering; | ||
39 | using OpenSim; | 44 | using OpenSim; |
40 | using OpenSim.Framework; | 45 | using OpenSim.Framework; |
41 | 46 | ||
@@ -45,7 +50,8 @@ using OpenSim.Region.CoreModules.World.Terrain; | |||
45 | using OpenSim.Region.Framework.Interfaces; | 50 | using OpenSim.Region.Framework.Interfaces; |
46 | using OpenSim.Region.Framework.Scenes; | 51 | using OpenSim.Region.Framework.Scenes; |
47 | using OpenSim.Region.Framework.Scenes.Animation; | 52 | using OpenSim.Region.Framework.Scenes.Animation; |
48 | using OpenSim.Region.Physics.Manager; | 53 | using OpenSim.Region.Framework.Scenes.Scripting; |
54 | using OpenSim.Region.PhysicsModules.SharedBase; | ||
49 | using OpenSim.Region.ScriptEngine.Shared; | 55 | using OpenSim.Region.ScriptEngine.Shared; |
50 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; | 56 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; |
51 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | 57 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
@@ -66,6 +72,8 @@ using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | |||
66 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | 72 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
67 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | 73 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; |
68 | using System.Reflection; | 74 | using System.Reflection; |
75 | using System.Linq; | ||
76 | using PermissionMask = OpenSim.Framework.PermissionMask; | ||
69 | 77 | ||
70 | namespace OpenSim.Region.ScriptEngine.Shared.Api | 78 | namespace OpenSim.Region.ScriptEngine.Shared.Api |
71 | { | 79 | { |
@@ -83,15 +91,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
83 | public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi | 91 | public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi |
84 | { | 92 | { |
85 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 93 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
94 | |||
95 | public int LlRequestAgentDataCacheTimeoutMs { get; set; } | ||
96 | |||
86 | protected IScriptEngine m_ScriptEngine; | 97 | protected IScriptEngine m_ScriptEngine; |
87 | protected SceneObjectPart m_host; | 98 | protected SceneObjectPart m_host; |
88 | 99 | ||
89 | /// <summary> | 100 | /// <summary> |
101 | /// Used for script sleeps when we are using co-operative script termination. | ||
102 | /// </summary> | ||
103 | /// <remarks>null if co-operative script termination is not active</remarks> | ||
104 | /// <summary> | ||
90 | /// The item that hosts this script | 105 | /// The item that hosts this script |
91 | /// </summary> | 106 | /// </summary> |
92 | protected TaskInventoryItem m_item; | 107 | protected TaskInventoryItem m_item; |
93 | 108 | ||
94 | protected bool throwErrorOnNotImplemented = true; | 109 | protected bool throwErrorOnNotImplemented = false; |
95 | protected AsyncCommandManager AsyncCommands = null; | 110 | protected AsyncCommandManager AsyncCommands = null; |
96 | protected float m_ScriptDelayFactor = 1.0f; | 111 | protected float m_ScriptDelayFactor = 1.0f; |
97 | protected float m_ScriptDistanceFactor = 1.0f; | 112 | protected float m_ScriptDistanceFactor = 1.0f; |
@@ -108,49 +123,260 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
108 | protected IUrlModule m_UrlModule = null; | 123 | protected IUrlModule m_UrlModule = null; |
109 | protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); | 124 | protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); |
110 | protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. | 125 | protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. |
126 | protected int m_sleepMsOnSetTexture = 200; | ||
127 | protected int m_sleepMsOnSetLinkTexture = 200; | ||
128 | protected int m_sleepMsOnScaleTexture = 200; | ||
129 | protected int m_sleepMsOnOffsetTexture = 200; | ||
130 | protected int m_sleepMsOnRotateTexture = 200; | ||
131 | protected int m_sleepMsOnSetPos = 200; | ||
132 | protected int m_sleepMsOnSetRot = 200; | ||
133 | protected int m_sleepMsOnSetLocalRot = 200; | ||
134 | protected int m_sleepMsOnPreloadSound = 1000; | ||
135 | protected int m_sleepMsOnMakeExplosion = 100; | ||
136 | protected int m_sleepMsOnMakeFountain = 100; | ||
137 | protected int m_sleepMsOnMakeSmoke = 100; | ||
138 | protected int m_sleepMsOnMakeFire = 100; | ||
139 | protected int m_sleepMsOnRezAtRoot = 100; | ||
140 | protected int m_sleepMsOnInstantMessage = 2000; | ||
141 | protected int m_sleepMsOnEmail = 20000; | ||
142 | protected int m_sleepMsOnCreateLink = 1000; | ||
143 | protected int m_sleepMsOnGiveInventory = 3000; | ||
144 | protected int m_sleepMsOnRequestAgentData = 100; | ||
145 | protected int m_sleepMsOnRequestInventoryData = 1000; | ||
146 | protected int m_sleepMsOnSetDamage = 5000; | ||
147 | protected int m_sleepMsOnTextBox = 1000; | ||
148 | protected int m_sleepMsOnAdjustSoundVolume = 100; | ||
149 | protected int m_sleepMsOnEjectFromLand = 5000; | ||
150 | protected int m_sleepMsOnAddToLandPassList = 100; | ||
151 | protected int m_sleepMsOnDialog = 1000; | ||
152 | protected int m_sleepMsOnRemoteLoadScript = 3000; | ||
153 | protected int m_sleepMsOnRemoteLoadScriptPin = 3000; | ||
154 | protected int m_sleepMsOnOpenRemoteDataChannel = 1000; | ||
155 | protected int m_sleepMsOnSendRemoteData = 3000; | ||
156 | protected int m_sleepMsOnRemoteDataReply = 3000; | ||
157 | protected int m_sleepMsOnCloseRemoteDataChannel = 1000; | ||
158 | protected int m_sleepMsOnSetPrimitiveParams = 200; | ||
159 | protected int m_sleepMsOnSetLinkPrimitiveParams = 200; | ||
160 | protected int m_sleepMsOnXorBase64Strings = 300; | ||
161 | protected int m_sleepMsOnSetParcelMusicURL = 2000; | ||
162 | protected int m_sleepMsOnGetPrimMediaParams = 1000; | ||
163 | protected int m_sleepMsOnGetLinkMedia = 1000; | ||
164 | protected int m_sleepMsOnSetPrimMediaParams = 1000; | ||
165 | protected int m_sleepMsOnSetLinkMedia = 1000; | ||
166 | protected int m_sleepMsOnClearPrimMedia = 1000; | ||
167 | protected int m_sleepMsOnClearLinkMedia = 1000; | ||
168 | protected int m_sleepMsOnRequestSimulatorData = 1000; | ||
169 | protected int m_sleepMsOnLoadURL = 10000; | ||
170 | protected int m_sleepMsOnParcelMediaCommandList = 2000; | ||
171 | protected int m_sleepMsOnParcelMediaQuery = 2000; | ||
172 | protected int m_sleepMsOnModPow = 1000; | ||
173 | protected int m_sleepMsOnSetPrimURL = 2000; | ||
174 | protected int m_sleepMsOnRefreshPrimURL = 20000; | ||
175 | protected int m_sleepMsOnMapDestination = 1000; | ||
176 | protected int m_sleepMsOnAddToLandBanList = 100; | ||
177 | protected int m_sleepMsOnRemoveFromLandPassList = 100; | ||
178 | protected int m_sleepMsOnRemoveFromLandBanList = 100; | ||
179 | protected int m_sleepMsOnResetLandBanList = 100; | ||
180 | protected int m_sleepMsOnResetLandPassList = 100; | ||
181 | protected int m_sleepMsOnGetParcelPrimOwners = 2000; | ||
182 | protected int m_sleepMsOnGetNumberOfNotecardLines = 100; | ||
183 | protected int m_sleepMsOnGetNotecardLine = 100; | ||
184 | protected string m_internalObjectHost = "lsl.opensim.local"; | ||
185 | protected bool m_restrictEmail = false; | ||
111 | protected ISoundModule m_SoundModule = null; | 186 | protected ISoundModule m_SoundModule = null; |
112 | 187 | ||
113 | public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) | 188 | protected float m_avatarHeightCorrection = 0.2f; |
189 | protected bool m_useSimpleBoxesInGetBoundingBox = false; | ||
190 | protected bool m_addStatsInGetBoundingBox = false; | ||
191 | |||
192 | //LSL Avatar Bounding Box (lABB), lower (1) and upper (2), | ||
193 | //standing (Std), Groundsitting (Grs), Sitting (Sit), | ||
194 | //along X, Y and Z axes, constants (0) and coefficients (1) | ||
195 | protected float m_lABB1StdX0 = -0.275f; | ||
196 | protected float m_lABB2StdX0 = 0.275f; | ||
197 | protected float m_lABB1StdY0 = -0.35f; | ||
198 | protected float m_lABB2StdY0 = 0.35f; | ||
199 | protected float m_lABB1StdZ0 = -0.1f; | ||
200 | protected float m_lABB1StdZ1 = -0.5f; | ||
201 | protected float m_lABB2StdZ0 = 0.1f; | ||
202 | protected float m_lABB2StdZ1 = 0.5f; | ||
203 | protected float m_lABB1GrsX0 = -0.3875f; | ||
204 | protected float m_lABB2GrsX0 = 0.3875f; | ||
205 | protected float m_lABB1GrsY0 = -0.5f; | ||
206 | protected float m_lABB2GrsY0 = 0.5f; | ||
207 | protected float m_lABB1GrsZ0 = -0.05f; | ||
208 | protected float m_lABB1GrsZ1 = -0.375f; | ||
209 | protected float m_lABB2GrsZ0 = 0.5f; | ||
210 | protected float m_lABB2GrsZ1 = 0.0f; | ||
211 | protected float m_lABB1SitX0 = -0.5875f; | ||
212 | protected float m_lABB2SitX0 = 0.1875f; | ||
213 | protected float m_lABB1SitY0 = -0.35f; | ||
214 | protected float m_lABB2SitY0 = 0.35f; | ||
215 | protected float m_lABB1SitZ0 = -0.35f; | ||
216 | protected float m_lABB1SitZ1 = -0.375f; | ||
217 | protected float m_lABB2SitZ0 = -0.25f; | ||
218 | protected float m_lABB2SitZ1 = 0.25f; | ||
219 | |||
220 | protected float m_primSafetyCoeffX = 2.414214f; | ||
221 | protected float m_primSafetyCoeffY = 2.414214f; | ||
222 | protected float m_primSafetyCoeffZ = 1.618034f; | ||
223 | protected bool m_useCastRayV3 = false; | ||
224 | protected float m_floatToleranceInCastRay = 0.00001f; | ||
225 | protected float m_floatTolerance2InCastRay = 0.001f; | ||
226 | protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; | ||
227 | protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; | ||
228 | protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; | ||
229 | protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium; | ||
230 | protected int m_maxHitsInCastRay = 16; | ||
231 | protected int m_maxHitsPerPrimInCastRay = 16; | ||
232 | protected int m_maxHitsPerObjectInCastRay = 16; | ||
233 | protected bool m_detectExitsInCastRay = false; | ||
234 | protected bool m_filterPartsInCastRay = false; | ||
235 | protected bool m_doAttachmentsInCastRay = false; | ||
236 | protected int m_msThrottleInCastRay = 200; | ||
237 | protected int m_msPerRegionInCastRay = 40; | ||
238 | protected int m_msPerAvatarInCastRay = 10; | ||
239 | protected int m_msMinInCastRay = 2; | ||
240 | protected int m_msMaxInCastRay = 40; | ||
241 | protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>(); | ||
242 | protected bool m_useMeshCacheInCastRay = true; | ||
243 | protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); | ||
244 | |||
245 | //An array of HTTP/1.1 headers that are not allowed to be used | ||
246 | //as custom headers by llHTTPRequest. | ||
247 | private string[] HttpStandardHeaders = | ||
248 | { | ||
249 | "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", | ||
250 | "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control", | ||
251 | "Connection", "Content-Encoding", "Content-Language", | ||
252 | "Content-Length", "Content-Location", "Content-MD5", | ||
253 | "Content-Range", "Content-Type", "Date", "ETag", "Expect", | ||
254 | "Expires", "From", "Host", "If-Match", "If-Modified-Since", | ||
255 | "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", | ||
256 | "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate", | ||
257 | "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server", | ||
258 | "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent", | ||
259 | "Vary", "Via", "Warning", "WWW-Authenticate" | ||
260 | }; | ||
261 | |||
262 | public void Initialize( | ||
263 | IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item) | ||
114 | { | 264 | { |
115 | m_ScriptEngine = ScriptEngine; | 265 | m_ScriptEngine = scriptEngine; |
116 | m_host = host; | 266 | m_host = host; |
117 | m_item = item; | 267 | m_item = item; |
118 | 268 | ||
119 | LoadLimits(); // read script limits from config. | 269 | LoadConfig(); |
120 | 270 | ||
121 | m_TransferModule = | 271 | m_TransferModule = |
122 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); | 272 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); |
123 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); | 273 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); |
124 | m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); | 274 | m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); |
125 | 275 | ||
126 | AsyncCommands = new AsyncCommandManager(ScriptEngine); | 276 | AsyncCommands = new AsyncCommandManager(m_ScriptEngine); |
127 | } | 277 | } |
128 | 278 | ||
129 | /* load configuration items that affect script, object and run-time behavior. */ | 279 | /// <summary> |
130 | private void LoadLimits() | 280 | /// Load configuration items that affect script, object and run-time behavior. */ |
281 | /// </summary> | ||
282 | private void LoadConfig() | ||
131 | { | 283 | { |
132 | m_ScriptDelayFactor = | 284 | LlRequestAgentDataCacheTimeoutMs = 20000; |
133 | m_ScriptEngine.Config.GetFloat("ScriptDelayFactor", 1.0f); | 285 | |
134 | m_ScriptDistanceFactor = | 286 | IConfig seConfig = m_ScriptEngine.Config; |
135 | m_ScriptEngine.Config.GetFloat("ScriptDistanceLimitFactor", 1.0f); | 287 | |
136 | m_MinTimerInterval = | 288 | if (seConfig != null) |
137 | m_ScriptEngine.Config.GetFloat("MinTimerInterval", 0.5f); | 289 | { |
138 | m_automaticLinkPermission = | 290 | m_ScriptDelayFactor = |
139 | m_ScriptEngine.Config.GetBoolean("AutomaticLinkPermission", false); | 291 | seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor); |
140 | m_notecardLineReadCharsMax = | 292 | m_ScriptDistanceFactor = |
141 | m_ScriptEngine.Config.GetInt("NotecardLineReadCharsMax", 255); | 293 | seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor); |
294 | m_MinTimerInterval = | ||
295 | seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval); | ||
296 | m_automaticLinkPermission = | ||
297 | seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission); | ||
298 | m_notecardLineReadCharsMax = | ||
299 | seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax); | ||
300 | |||
301 | // Rezzing an object with a velocity can create recoil. This feature seems to have been | ||
302 | // removed from recent versions of SL. The code computes recoil (vel*mass) and scales | ||
303 | // it by this factor. May be zero to turn off recoil all together. | ||
304 | m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor); | ||
305 | } | ||
306 | |||
142 | if (m_notecardLineReadCharsMax > 65535) | 307 | if (m_notecardLineReadCharsMax > 65535) |
143 | m_notecardLineReadCharsMax = 65535; | 308 | m_notecardLineReadCharsMax = 65535; |
309 | |||
144 | // load limits for particular subsystems. | 310 | // load limits for particular subsystems. |
145 | IConfig SMTPConfig; | 311 | IConfigSource seConfigSource = m_ScriptEngine.ConfigSource; |
146 | if ((SMTPConfig = m_ScriptEngine.ConfigSource.Configs["SMTP"]) != null) { | 312 | |
147 | // there's an smtp config, so load in the snooze time. | 313 | if (seConfigSource != null) |
148 | EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); | 314 | { |
149 | } | 315 | IConfig lslConfig = seConfigSource.Configs["LL-Functions"]; |
150 | // Rezzing an object with a velocity can create recoil. This feature seems to have been | 316 | if (lslConfig != null) |
151 | // removed from recent versions of SL. The code computes recoil (vel*mass) and scales | 317 | { |
152 | // it by this factor. May be zero to turn off recoil all together. | 318 | m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); |
153 | m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor); | 319 | m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection); |
320 | m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox); | ||
321 | m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox); | ||
322 | m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0); | ||
323 | m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0); | ||
324 | m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0); | ||
325 | m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0); | ||
326 | m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0); | ||
327 | m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1); | ||
328 | m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0); | ||
329 | m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1); | ||
330 | m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0); | ||
331 | m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0); | ||
332 | m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0); | ||
333 | m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0); | ||
334 | m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0); | ||
335 | m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1); | ||
336 | m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0); | ||
337 | m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1); | ||
338 | m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0); | ||
339 | m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0); | ||
340 | m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0); | ||
341 | m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0); | ||
342 | m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0); | ||
343 | m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1); | ||
344 | m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0); | ||
345 | m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1); | ||
346 | m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); | ||
347 | m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); | ||
348 | m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); | ||
349 | m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3); | ||
350 | m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); | ||
351 | m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); | ||
352 | m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay); | ||
353 | m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay); | ||
354 | m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay); | ||
355 | m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay); | ||
356 | m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); | ||
357 | m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); | ||
358 | m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); | ||
359 | m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); | ||
360 | m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); | ||
361 | m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); | ||
362 | m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay); | ||
363 | m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay); | ||
364 | m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay); | ||
365 | m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay); | ||
366 | m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay); | ||
367 | m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay); | ||
368 | } | ||
369 | |||
370 | IConfig smtpConfig = seConfigSource.Configs["SMTP"]; | ||
371 | if (smtpConfig != null) | ||
372 | { | ||
373 | // there's an smtp config, so load in the snooze time. | ||
374 | EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); | ||
375 | |||
376 | m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost); | ||
377 | } | ||
378 | } | ||
379 | m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000; | ||
154 | } | 380 | } |
155 | 381 | ||
156 | public override Object InitializeLifetimeService() | 382 | public override Object InitializeLifetimeService() |
@@ -171,9 +397,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
171 | delay = (int)((float)delay * m_ScriptDelayFactor); | 397 | delay = (int)((float)delay * m_ScriptDelayFactor); |
172 | if (delay == 0) | 398 | if (delay == 0) |
173 | return; | 399 | return; |
174 | System.Threading.Thread.Sleep(delay); | 400 | |
401 | Sleep(delay); | ||
175 | } | 402 | } |
176 | 403 | ||
404 | protected virtual void Sleep(int delay) | ||
405 | { | ||
406 | if (m_item == null) // Some unit tests don't set this | ||
407 | { | ||
408 | Thread.Sleep(delay); | ||
409 | return; | ||
410 | } | ||
411 | |||
412 | m_ScriptEngine.SleepScript(m_item.ItemID, delay); | ||
413 | } | ||
414 | |||
415 | /// <summary> | ||
416 | /// Check for co-operative termination. | ||
417 | /// </summary> | ||
418 | /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param> | ||
419 | |||
177 | public Scene World | 420 | public Scene World |
178 | { | 421 | { |
179 | get { return m_ScriptEngine.World; } | 422 | get { return m_ScriptEngine.World; } |
@@ -209,7 +452,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
209 | if ((item = GetScriptByName(name)) != UUID.Zero) | 452 | if ((item = GetScriptByName(name)) != UUID.Zero) |
210 | m_ScriptEngine.ResetScript(item); | 453 | m_ScriptEngine.ResetScript(item); |
211 | else | 454 | else |
212 | ShoutError("llResetOtherScript: script "+name+" not found"); | 455 | Error("llResetOtherScript", "Can't find script '" + name + "'"); |
213 | } | 456 | } |
214 | 457 | ||
215 | public LSL_Integer llGetScriptState(string name) | 458 | public LSL_Integer llGetScriptState(string name) |
@@ -223,7 +466,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
223 | return m_ScriptEngine.GetScriptState(item) ?1:0; | 466 | return m_ScriptEngine.GetScriptState(item) ?1:0; |
224 | } | 467 | } |
225 | 468 | ||
226 | ShoutError("llGetScriptState: script "+name+" not found"); | 469 | Error("llGetScriptState", "Can't find script '" + name + "'"); |
227 | 470 | ||
228 | // If we didn't find it, then it's safe to | 471 | // If we didn't find it, then it's safe to |
229 | // assume it is not running. | 472 | // assume it is not running. |
@@ -246,7 +489,78 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
246 | } | 489 | } |
247 | else | 490 | else |
248 | { | 491 | { |
249 | ShoutError("llSetScriptState: script "+name+" not found"); | 492 | Error("llSetScriptState", "Can't find script '" + name + "'"); |
493 | } | ||
494 | } | ||
495 | |||
496 | /// <summary> | ||
497 | /// Get a given link entity from a linkset (linked objects and any sitting avatars). | ||
498 | /// </summary> | ||
499 | /// <remarks> | ||
500 | /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then | ||
501 | /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset. | ||
502 | /// The ScenePresences receive linknums in the order in which they sat. | ||
503 | /// </remarks> | ||
504 | /// <returns> | ||
505 | /// The link entity. null if not found. | ||
506 | /// </returns> | ||
507 | /// <param name='part'></param> | ||
508 | /// <param name='linknum'> | ||
509 | /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4). | ||
510 | /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned. | ||
511 | /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned. If any | ||
512 | /// positive integer is given in this case then null is returned. | ||
513 | /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number | ||
514 | /// of entities, then the entity which corresponds to that linknum is returned. | ||
515 | /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then | ||
516 | /// null is returned. | ||
517 | /// </param> | ||
518 | public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum) | ||
519 | { | ||
520 | if (linknum < 0) | ||
521 | { | ||
522 | if (linknum == ScriptBaseClass.LINK_THIS) | ||
523 | return part; | ||
524 | else | ||
525 | return null; | ||
526 | } | ||
527 | |||
528 | int actualPrimCount = part.ParentGroup.PrimCount; | ||
529 | List<ScenePresence> sittingAvatars = part.ParentGroup.GetSittingAvatars(); | ||
530 | int adjustedPrimCount = actualPrimCount + sittingAvatars.Count; | ||
531 | |||
532 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single | ||
533 | // prim that has any avatars sat upon it (in which case the root prim is link 1). | ||
534 | if (linknum == 0) | ||
535 | { | ||
536 | if (actualPrimCount == 1 && sittingAvatars.Count == 0) | ||
537 | return part; | ||
538 | |||
539 | return null; | ||
540 | } | ||
541 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but | ||
542 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). | ||
543 | else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1) | ||
544 | { | ||
545 | if (sittingAvatars.Count > 0) | ||
546 | return part.ParentGroup.RootPart; | ||
547 | else | ||
548 | return null; | ||
549 | } | ||
550 | else if (linknum <= adjustedPrimCount) | ||
551 | { | ||
552 | if (linknum <= actualPrimCount) | ||
553 | { | ||
554 | return part.ParentGroup.GetLinkNumPart(linknum); | ||
555 | } | ||
556 | else | ||
557 | { | ||
558 | return sittingAvatars[linknum - actualPrimCount - 1]; | ||
559 | } | ||
560 | } | ||
561 | else | ||
562 | { | ||
563 | return null; | ||
250 | } | 564 | } |
251 | } | 565 | } |
252 | 566 | ||
@@ -301,77 +615,52 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
301 | } | 615 | } |
302 | } | 616 | } |
303 | 617 | ||
304 | protected UUID InventoryKey(string name, int type) | 618 | public List<ISceneEntity> GetLinkEntities(int linkType) |
305 | { | 619 | { |
306 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 620 | return GetLinkEntities(m_host, linkType); |
307 | |||
308 | if (item != null && item.Type == type) | ||
309 | return item.AssetID; | ||
310 | else | ||
311 | return UUID.Zero; | ||
312 | } | 621 | } |
313 | 622 | ||
314 | /// <summary> | 623 | public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType) |
315 | /// accepts a valid UUID, -or- a name of an inventory item. | ||
316 | /// Returns a valid UUID or UUID.Zero if key invalid and item not found | ||
317 | /// in prim inventory. | ||
318 | /// </summary> | ||
319 | /// <param name="k"></param> | ||
320 | /// <returns></returns> | ||
321 | protected UUID KeyOrName(string k) | ||
322 | { | 624 | { |
323 | UUID key; | 625 | List<ISceneEntity> ret; |
324 | 626 | ||
325 | // if we can parse the string as a key, use it. | 627 | switch (linkType) |
326 | // else try to locate the name in inventory of object. found returns key, | ||
327 | // not found returns UUID.Zero | ||
328 | if (!UUID.TryParse(k, out key)) | ||
329 | { | 628 | { |
330 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); | 629 | case ScriptBaseClass.LINK_SET: |
630 | return new List<ISceneEntity>(part.ParentGroup.Parts); | ||
331 | 631 | ||
332 | if (item != null) | 632 | case ScriptBaseClass.LINK_ROOT: |
333 | key = item.AssetID; | 633 | return new List<ISceneEntity>() { part.ParentGroup.RootPart }; |
334 | else | ||
335 | key = UUID.Zero; | ||
336 | } | ||
337 | 634 | ||
338 | return key; | 635 | case ScriptBaseClass.LINK_ALL_OTHERS: |
339 | } | 636 | ret = new List<ISceneEntity>(part.ParentGroup.Parts); |
340 | 637 | ||
341 | /// <summary> | 638 | if (ret.Contains(part)) |
342 | /// Return the UUID of the asset matching the specified key or name | 639 | ret.Remove(part); |
343 | /// and asset type. | ||
344 | /// </summary> | ||
345 | /// <param name="k"></param> | ||
346 | /// <param name="type"></param> | ||
347 | /// <returns></returns> | ||
348 | protected UUID KeyOrName(string k, AssetType type) | ||
349 | { | ||
350 | UUID key; | ||
351 | 640 | ||
352 | if (!UUID.TryParse(k, out key)) | 641 | return ret; |
353 | { | 642 | |
354 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); | 643 | case ScriptBaseClass.LINK_ALL_CHILDREN: |
355 | if (item != null && item.Type == (int)type) | 644 | ret = new List<ISceneEntity>(part.ParentGroup.Parts); |
356 | key = item.AssetID; | ||
357 | } | ||
358 | else | ||
359 | { | ||
360 | lock (m_host.TaskInventory) | ||
361 | { | ||
362 | foreach (KeyValuePair<UUID, TaskInventoryItem> item in m_host.TaskInventory) | ||
363 | { | ||
364 | if (item.Value.Type == (int)type && item.Value.Name == k) | ||
365 | { | ||
366 | key = item.Value.ItemID; | ||
367 | break; | ||
368 | } | ||
369 | } | ||
370 | } | ||
371 | } | ||
372 | 645 | ||
646 | if (ret.Contains(part.ParentGroup.RootPart)) | ||
647 | ret.Remove(part.ParentGroup.RootPart); | ||
373 | 648 | ||
374 | return key; | 649 | return ret; |
650 | |||
651 | case ScriptBaseClass.LINK_THIS: | ||
652 | return new List<ISceneEntity>() { part }; | ||
653 | |||
654 | default: | ||
655 | if (linkType < 0) | ||
656 | return new List<ISceneEntity>(); | ||
657 | |||
658 | ISceneEntity target = GetLinkEntity(part, linkType); | ||
659 | if (target == null) | ||
660 | return new List<ISceneEntity>(); | ||
661 | |||
662 | return new List<ISceneEntity>() { target }; | ||
663 | } | ||
375 | } | 664 | } |
376 | 665 | ||
377 | //These are the implementations of the various ll-functions used by the LSL scripts. | 666 | //These are the implementations of the various ll-functions used by the LSL scripts. |
@@ -430,10 +719,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
430 | public LSL_Float llFrand(double mag) | 719 | public LSL_Float llFrand(double mag) |
431 | { | 720 | { |
432 | m_host.AddScriptLPS(1); | 721 | m_host.AddScriptLPS(1); |
433 | lock (Util.RandomClass) | 722 | |
434 | { | 723 | return Util.RandomClass.NextDouble() * mag; |
435 | return Util.RandomClass.NextDouble() * mag; | ||
436 | } | ||
437 | } | 724 | } |
438 | 725 | ||
439 | public LSL_Integer llFloor(double f) | 726 | public LSL_Integer llFloor(double f) |
@@ -837,7 +1124,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
837 | { | 1124 | { |
838 | if (channelID == 0) | 1125 | if (channelID == 0) |
839 | { | 1126 | { |
840 | LSLError("Cannot use llRegionSay() on channel 0"); | 1127 | Error("llRegionSay", "Cannot use on channel 0"); |
841 | return; | 1128 | return; |
842 | } | 1129 | } |
843 | 1130 | ||
@@ -846,6 +1133,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
846 | 1133 | ||
847 | m_host.AddScriptLPS(1); | 1134 | m_host.AddScriptLPS(1); |
848 | 1135 | ||
1136 | World.SimChat(Utils.StringToBytes(text), | ||
1137 | ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
1138 | |||
849 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1139 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
850 | if (wComm != null) | 1140 | if (wComm != null) |
851 | wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); | 1141 | wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); |
@@ -866,6 +1156,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
866 | UUID TargetID; | 1156 | UUID TargetID; |
867 | UUID.TryParse(target, out TargetID); | 1157 | UUID.TryParse(target, out TargetID); |
868 | 1158 | ||
1159 | World.SimChatToAgent(TargetID, Utils.StringToBytes(msg), | ||
1160 | channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); | ||
1161 | |||
869 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1162 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
870 | if (wComm != null) | 1163 | if (wComm != null) |
871 | wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); | 1164 | wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); |
@@ -1255,12 +1548,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1255 | } | 1548 | } |
1256 | 1549 | ||
1257 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) | 1550 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) |
1258 | { | 1551 | m_host.BlockGrab = value != 0; |
1259 | if (value != 0) | 1552 | |
1260 | m_host.SetBlockGrab(true); | 1553 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) |
1261 | else | 1554 | m_host.ParentGroup.BlockGrabOverride = value != 0; |
1262 | m_host.SetBlockGrab(false); | ||
1263 | } | ||
1264 | 1555 | ||
1265 | if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) | 1556 | if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) |
1266 | { | 1557 | { |
@@ -1321,10 +1612,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1321 | return 0; | 1612 | return 0; |
1322 | 1613 | ||
1323 | case ScriptBaseClass.STATUS_BLOCK_GRAB: | 1614 | case ScriptBaseClass.STATUS_BLOCK_GRAB: |
1324 | if (m_host.GetBlockGrab()) | 1615 | return m_host.BlockGrab ? 1 : 0; |
1325 | return 1; | 1616 | |
1326 | else | 1617 | case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT: |
1327 | return 0; | 1618 | return m_host.ParentGroup.BlockGrabOverride ? 1 : 0; |
1328 | 1619 | ||
1329 | case ScriptBaseClass.STATUS_DIE_AT_EDGE: | 1620 | case ScriptBaseClass.STATUS_DIE_AT_EDGE: |
1330 | if (m_host.GetDieAtEdge()) | 1621 | if (m_host.GetDieAtEdge()) |
@@ -1427,6 +1718,73 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1427 | m_host.SetFaceColorAlpha(face, color, null); | 1718 | m_host.SetFaceColorAlpha(face, color, null); |
1428 | } | 1719 | } |
1429 | 1720 | ||
1721 | public void llSetContentType(LSL_Key id, LSL_Integer type) | ||
1722 | { | ||
1723 | m_host.AddScriptLPS(1); | ||
1724 | |||
1725 | if (m_UrlModule == null) | ||
1726 | return; | ||
1727 | |||
1728 | // Make sure the content type is text/plain to start with | ||
1729 | m_UrlModule.HttpContentType(new UUID(id), "text/plain"); | ||
1730 | |||
1731 | // Is the object owner online and in the region | ||
1732 | ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID); | ||
1733 | if (agent == null || agent.IsChildAgent) | ||
1734 | return; // Fail if the owner is not in the same region | ||
1735 | |||
1736 | // Is it the embeded browser? | ||
1737 | string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent"); | ||
1738 | if (userAgent.IndexOf("SecondLife") < 0) | ||
1739 | return; // Not the embedded browser. Is this check good enough? | ||
1740 | |||
1741 | // Use the IP address of the client and check against the request | ||
1742 | // seperate logins from the same IP will allow all of them to get non-text/plain as long | ||
1743 | // as the owner is in the region. Same as SL! | ||
1744 | string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString(); | ||
1745 | string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr"); | ||
1746 | //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'"); | ||
1747 | if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "") | ||
1748 | return; | ||
1749 | if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "") | ||
1750 | return; | ||
1751 | |||
1752 | // If the request isnt from the same IP address then the request cannot be from the owner | ||
1753 | if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim())) | ||
1754 | return; | ||
1755 | |||
1756 | switch (type) | ||
1757 | { | ||
1758 | case ScriptBaseClass.CONTENT_TYPE_HTML: | ||
1759 | m_UrlModule.HttpContentType(new UUID(id), "text/html"); | ||
1760 | break; | ||
1761 | case ScriptBaseClass.CONTENT_TYPE_XML: | ||
1762 | m_UrlModule.HttpContentType(new UUID(id), "application/xml"); | ||
1763 | break; | ||
1764 | case ScriptBaseClass.CONTENT_TYPE_XHTML: | ||
1765 | m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml"); | ||
1766 | break; | ||
1767 | case ScriptBaseClass.CONTENT_TYPE_ATOM: | ||
1768 | m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml"); | ||
1769 | break; | ||
1770 | case ScriptBaseClass.CONTENT_TYPE_JSON: | ||
1771 | m_UrlModule.HttpContentType(new UUID(id), "application/json"); | ||
1772 | break; | ||
1773 | case ScriptBaseClass.CONTENT_TYPE_LLSD: | ||
1774 | m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml"); | ||
1775 | break; | ||
1776 | case ScriptBaseClass.CONTENT_TYPE_FORM: | ||
1777 | m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded"); | ||
1778 | break; | ||
1779 | case ScriptBaseClass.CONTENT_TYPE_RSS: | ||
1780 | m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml"); | ||
1781 | break; | ||
1782 | default: | ||
1783 | m_UrlModule.HttpContentType(new UUID(id), "text/plain"); | ||
1784 | break; | ||
1785 | } | ||
1786 | } | ||
1787 | |||
1430 | public void SetTexGen(SceneObjectPart part, int face,int style) | 1788 | public void SetTexGen(SceneObjectPart part, int face,int style) |
1431 | { | 1789 | { |
1432 | Primitive.TextureEntry tex = part.Shape.Textures; | 1790 | Primitive.TextureEntry tex = part.Shape.Textures; |
@@ -1522,7 +1880,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1522 | if (tex.FaceTextures[i] != null) | 1880 | if (tex.FaceTextures[i] != null) |
1523 | { | 1881 | { |
1524 | tex.FaceTextures[i].Shiny = sval; | 1882 | tex.FaceTextures[i].Shiny = sval; |
1525 | tex.FaceTextures[i].Bump = bump;; | 1883 | tex.FaceTextures[i].Bump = bump; |
1526 | } | 1884 | } |
1527 | tex.DefaultTexture.Shiny = sval; | 1885 | tex.DefaultTexture.Shiny = sval; |
1528 | tex.DefaultTexture.Bump = bump; | 1886 | tex.DefaultTexture.Bump = bump; |
@@ -1631,7 +1989,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1631 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | 1989 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); |
1632 | tex.DefaultTexture.RGBA = texcolor; | 1990 | tex.DefaultTexture.RGBA = texcolor; |
1633 | } | 1991 | } |
1634 | 1992 | ||
1635 | part.UpdateTextureEntry(tex.GetBytes()); | 1993 | part.UpdateTextureEntry(tex.GetBytes()); |
1636 | return; | 1994 | return; |
1637 | } | 1995 | } |
@@ -1703,9 +2061,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1703 | part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); | 2061 | part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); |
1704 | part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); | 2062 | part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); |
1705 | part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); | 2063 | part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); |
1706 | part.Shape.LightIntensity = intensity; | 2064 | part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f); |
1707 | part.Shape.LightRadius = radius; | 2065 | part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f); |
1708 | part.Shape.LightFalloff = falloff; | 2066 | part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f); |
1709 | } | 2067 | } |
1710 | else | 2068 | else |
1711 | { | 2069 | { |
@@ -1752,7 +2110,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1752 | rgb.x = texcolor.R; | 2110 | rgb.x = texcolor.R; |
1753 | rgb.y = texcolor.G; | 2111 | rgb.y = texcolor.G; |
1754 | rgb.z = texcolor.B; | 2112 | rgb.z = texcolor.B; |
1755 | 2113 | ||
1756 | return rgb; | 2114 | return rgb; |
1757 | } | 2115 | } |
1758 | else | 2116 | else |
@@ -1765,7 +2123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1765 | { | 2123 | { |
1766 | m_host.AddScriptLPS(1); | 2124 | m_host.AddScriptLPS(1); |
1767 | SetTexture(m_host, texture, face); | 2125 | SetTexture(m_host, texture, face); |
1768 | ScriptSleep(200); | 2126 | ScriptSleep(m_sleepMsOnSetTexture); |
1769 | } | 2127 | } |
1770 | 2128 | ||
1771 | public void llSetLinkTexture(int linknumber, string texture, int face) | 2129 | public void llSetLinkTexture(int linknumber, string texture, int face) |
@@ -1777,19 +2135,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1777 | foreach (SceneObjectPart part in parts) | 2135 | foreach (SceneObjectPart part in parts) |
1778 | SetTexture(part, texture, face); | 2136 | SetTexture(part, texture, face); |
1779 | 2137 | ||
1780 | ScriptSleep(200); | 2138 | ScriptSleep(m_sleepMsOnSetLinkTexture); |
1781 | } | 2139 | } |
1782 | 2140 | ||
1783 | protected void SetTexture(SceneObjectPart part, string texture, int face) | 2141 | protected void SetTexture(SceneObjectPart part, string texture, int face) |
1784 | { | 2142 | { |
1785 | UUID textureID = new UUID(); | 2143 | UUID textureID = new UUID(); |
1786 | 2144 | ||
1787 | textureID = InventoryKey(texture, (int)AssetType.Texture); | 2145 | textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); |
1788 | if (textureID == UUID.Zero) | 2146 | if (textureID == UUID.Zero) |
1789 | { | 2147 | { |
1790 | if (!UUID.TryParse(texture, out textureID)) | 2148 | if (!UUID.TryParse(texture, out textureID)) |
1791 | return; | 2149 | return; |
1792 | } | 2150 | } |
1793 | 2151 | ||
1794 | Primitive.TextureEntry tex = part.Shape.Textures; | 2152 | Primitive.TextureEntry tex = part.Shape.Textures; |
1795 | 2153 | ||
@@ -1821,7 +2179,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1821 | m_host.AddScriptLPS(1); | 2179 | m_host.AddScriptLPS(1); |
1822 | 2180 | ||
1823 | ScaleTexture(m_host, u, v, face); | 2181 | ScaleTexture(m_host, u, v, face); |
1824 | ScriptSleep(200); | 2182 | ScriptSleep(m_sleepMsOnScaleTexture); |
1825 | } | 2183 | } |
1826 | 2184 | ||
1827 | protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) | 2185 | protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) |
@@ -1857,7 +2215,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1857 | { | 2215 | { |
1858 | m_host.AddScriptLPS(1); | 2216 | m_host.AddScriptLPS(1); |
1859 | OffsetTexture(m_host, u, v, face); | 2217 | OffsetTexture(m_host, u, v, face); |
1860 | ScriptSleep(200); | 2218 | ScriptSleep(m_sleepMsOnOffsetTexture); |
1861 | } | 2219 | } |
1862 | 2220 | ||
1863 | protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) | 2221 | protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) |
@@ -1893,7 +2251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1893 | { | 2251 | { |
1894 | m_host.AddScriptLPS(1); | 2252 | m_host.AddScriptLPS(1); |
1895 | RotateTexture(m_host, rotation, face); | 2253 | RotateTexture(m_host, rotation, face); |
1896 | ScriptSleep(200); | 2254 | ScriptSleep(m_sleepMsOnRotateTexture); |
1897 | } | 2255 | } |
1898 | 2256 | ||
1899 | protected void RotateTexture(SceneObjectPart part, double rotation, int face) | 2257 | protected void RotateTexture(SceneObjectPart part, double rotation, int face) |
@@ -1968,7 +2326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1968 | 2326 | ||
1969 | SetPos(m_host, pos, true); | 2327 | SetPos(m_host, pos, true); |
1970 | 2328 | ||
1971 | ScriptSleep(200); | 2329 | ScriptSleep(m_sleepMsOnSetPos); |
1972 | } | 2330 | } |
1973 | 2331 | ||
1974 | /// <summary> | 2332 | /// <summary> |
@@ -1986,8 +2344,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1986 | // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. | 2344 | // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. |
1987 | // | 2345 | // |
1988 | // This workaround is to prevent silent failure of this function. | 2346 | // This workaround is to prevent silent failure of this function. |
1989 | // According to the specification on the SL Wiki, providing a position outside of the | 2347 | // According to the specification on the SL Wiki, providing a position outside of the |
1990 | if (pos.x < 0 || pos.x > Constants.RegionSize || pos.y < 0 || pos.y > Constants.RegionSize) | 2348 | if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY) |
1991 | { | 2349 | { |
1992 | return 0; | 2350 | return 0; |
1993 | } | 2351 | } |
@@ -1997,9 +2355,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
1997 | m_host.ParentGroup.IsAttachment || // return FALSE if attachment | 2355 | m_host.ParentGroup.IsAttachment || // return FALSE if attachment |
1998 | ( | 2356 | ( |
1999 | pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. | 2357 | pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. |
2000 | pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. | 2358 | pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region. |
2001 | pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. | 2359 | pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. |
2002 | pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. | 2360 | pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region. |
2003 | pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m | 2361 | pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m |
2004 | ) | 2362 | ) |
2005 | ) | 2363 | ) |
@@ -2151,14 +2509,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2151 | } | 2509 | } |
2152 | } | 2510 | } |
2153 | 2511 | ||
2154 | ScriptSleep(200); | 2512 | ScriptSleep(m_sleepMsOnSetRot); |
2155 | } | 2513 | } |
2156 | 2514 | ||
2157 | public void llSetLocalRot(LSL_Rotation rot) | 2515 | public void llSetLocalRot(LSL_Rotation rot) |
2158 | { | 2516 | { |
2159 | m_host.AddScriptLPS(1); | 2517 | m_host.AddScriptLPS(1); |
2160 | SetRot(m_host, rot); | 2518 | SetRot(m_host, rot); |
2161 | ScriptSleep(200); | 2519 | ScriptSleep(m_sleepMsOnSetLocalRot); |
2162 | } | 2520 | } |
2163 | 2521 | ||
2164 | protected void SetRot(SceneObjectPart part, Quaternion rot) | 2522 | protected void SetRot(SceneObjectPart part, Quaternion rot) |
@@ -2195,7 +2553,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2195 | { | 2553 | { |
2196 | return llGetRootRotation(); | 2554 | return llGetRootRotation(); |
2197 | } | 2555 | } |
2198 | 2556 | ||
2199 | m_host.AddScriptLPS(1); | 2557 | m_host.AddScriptLPS(1); |
2200 | Quaternion q = m_host.GetWorldRotation(); | 2558 | Quaternion q = m_host.GetWorldRotation(); |
2201 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 2559 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); |
@@ -2214,23 +2572,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2214 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) | 2572 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) |
2215 | q = avatar.CameraRotation; // Mouselook | 2573 | q = avatar.CameraRotation; // Mouselook |
2216 | else | 2574 | else |
2217 | q = avatar.Rotation; // Currently infrequently updated so may be inaccurate | 2575 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate |
2218 | } | 2576 | } |
2219 | else | 2577 | else |
2220 | q = part.ParentGroup.GroupRotation; // Likely never get here but just in case | 2578 | q = part.ParentGroup.GroupRotation; // Likely never get here but just in case |
2221 | } | 2579 | } |
2222 | else | 2580 | else |
2223 | q = part.ParentGroup.GroupRotation; // just the group rotation | 2581 | q = part.ParentGroup.GroupRotation; // just the group rotation |
2224 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 2582 | |
2583 | return new LSL_Rotation(q); | ||
2225 | } | 2584 | } |
2226 | q = part.GetWorldRotation(); | 2585 | |
2227 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 2586 | return new LSL_Rotation(part.GetWorldRotation()); |
2228 | } | 2587 | } |
2229 | 2588 | ||
2230 | public LSL_Rotation llGetLocalRot() | 2589 | public LSL_Rotation llGetLocalRot() |
2231 | { | 2590 | { |
2232 | m_host.AddScriptLPS(1); | 2591 | m_host.AddScriptLPS(1); |
2233 | return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); | 2592 | |
2593 | return new LSL_Rotation(m_host.RotationOffset); | ||
2234 | } | 2594 | } |
2235 | 2595 | ||
2236 | public void llSetForce(LSL_Vector force, int local) | 2596 | public void llSetForce(LSL_Vector force, int local) |
@@ -2260,6 +2620,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2260 | return force; | 2620 | return force; |
2261 | } | 2621 | } |
2262 | 2622 | ||
2623 | public void llSetVelocity(LSL_Vector velocity, int local) | ||
2624 | { | ||
2625 | m_host.AddScriptLPS(1); | ||
2626 | |||
2627 | if (!m_host.ParentGroup.IsDeleted) | ||
2628 | { | ||
2629 | if (local != 0) | ||
2630 | velocity *= llGetRot(); | ||
2631 | |||
2632 | m_host.ParentGroup.RootPart.Velocity = velocity; | ||
2633 | } | ||
2634 | } | ||
2635 | |||
2636 | public void llSetAngularVelocity(LSL_Vector angularVelocity, int local) | ||
2637 | { | ||
2638 | m_host.AddScriptLPS(1); | ||
2639 | |||
2640 | if (!m_host.ParentGroup.IsDeleted) | ||
2641 | { | ||
2642 | if (local != 0) | ||
2643 | angularVelocity *= llGetRot(); | ||
2644 | |||
2645 | m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity; | ||
2646 | } | ||
2647 | } | ||
2648 | |||
2263 | public LSL_Integer llTarget(LSL_Vector position, double range) | 2649 | public LSL_Integer llTarget(LSL_Vector position, double range) |
2264 | { | 2650 | { |
2265 | m_host.AddScriptLPS(1); | 2651 | m_host.AddScriptLPS(1); |
@@ -2325,8 +2711,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2325 | public LSL_Vector llGetTorque() | 2711 | public LSL_Vector llGetTorque() |
2326 | { | 2712 | { |
2327 | m_host.AddScriptLPS(1); | 2713 | m_host.AddScriptLPS(1); |
2328 | Vector3 torque = m_host.ParentGroup.GetTorque(); | 2714 | |
2329 | return new LSL_Vector(torque.X,torque.Y,torque.Z); | 2715 | return new LSL_Vector(m_host.ParentGroup.GetTorque()); |
2330 | } | 2716 | } |
2331 | 2717 | ||
2332 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) | 2718 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) |
@@ -2345,26 +2731,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2345 | if (m_host.ParentGroup.IsAttachment) | 2731 | if (m_host.ParentGroup.IsAttachment) |
2346 | { | 2732 | { |
2347 | ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); | 2733 | ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); |
2348 | vel = avatar.Velocity; | 2734 | vel = avatar.GetWorldVelocity(); |
2349 | } | 2735 | } |
2350 | else | 2736 | else |
2351 | { | 2737 | { |
2352 | vel = m_host.Velocity; | 2738 | vel = m_host.Velocity; |
2353 | } | 2739 | } |
2354 | 2740 | ||
2355 | return new LSL_Vector(vel.X, vel.Y, vel.Z); | 2741 | return new LSL_Vector(vel); |
2356 | } | 2742 | } |
2357 | 2743 | ||
2358 | public LSL_Vector llGetAccel() | 2744 | public LSL_Vector llGetAccel() |
2359 | { | 2745 | { |
2360 | m_host.AddScriptLPS(1); | 2746 | m_host.AddScriptLPS(1); |
2361 | return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); | 2747 | |
2748 | return new LSL_Vector(m_host.Acceleration); | ||
2362 | } | 2749 | } |
2363 | 2750 | ||
2364 | public LSL_Vector llGetOmega() | 2751 | public LSL_Vector llGetOmega() |
2365 | { | 2752 | { |
2366 | m_host.AddScriptLPS(1); | 2753 | m_host.AddScriptLPS(1); |
2367 | return new LSL_Vector(m_host.AngularVelocity.X, m_host.AngularVelocity.Y, m_host.AngularVelocity.Z); | 2754 | |
2755 | return new LSL_Vector(m_host.AngularVelocity); | ||
2368 | } | 2756 | } |
2369 | 2757 | ||
2370 | public LSL_Float llGetTimeOfDay() | 2758 | public LSL_Float llGetTimeOfDay() |
@@ -2403,9 +2791,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2403 | public void llSound(string sound, double volume, int queue, int loop) | 2791 | public void llSound(string sound, double volume, int queue, int loop) |
2404 | { | 2792 | { |
2405 | m_host.AddScriptLPS(1); | 2793 | m_host.AddScriptLPS(1); |
2406 | // This function has been deprecated | 2794 | Deprecated("llSound", "Use llPlaySound instead"); |
2407 | // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound | ||
2408 | Deprecated("llSound"); | ||
2409 | } | 2795 | } |
2410 | 2796 | ||
2411 | // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound | 2797 | // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound |
@@ -2417,9 +2803,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2417 | // send the sound, once, to all clients in range | 2803 | // send the sound, once, to all clients in range |
2418 | if (m_SoundModule != null) | 2804 | if (m_SoundModule != null) |
2419 | { | 2805 | { |
2420 | m_SoundModule.SendSound(m_host.UUID, | 2806 | m_SoundModule.SendSound( |
2421 | KeyOrName(sound, AssetType.Sound), volume, false, 0, | 2807 | m_host.UUID, |
2422 | 0, false, false); | 2808 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), |
2809 | volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None, | ||
2810 | 0, false, false); | ||
2423 | } | 2811 | } |
2424 | } | 2812 | } |
2425 | 2813 | ||
@@ -2428,7 +2816,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2428 | m_host.AddScriptLPS(1); | 2816 | m_host.AddScriptLPS(1); |
2429 | if (m_SoundModule != null) | 2817 | if (m_SoundModule != null) |
2430 | { | 2818 | { |
2431 | m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), | 2819 | m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), |
2432 | volume, 20, false); | 2820 | volume, 20, false); |
2433 | } | 2821 | } |
2434 | } | 2822 | } |
@@ -2438,7 +2826,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2438 | m_host.AddScriptLPS(1); | 2826 | m_host.AddScriptLPS(1); |
2439 | if (m_SoundModule != null) | 2827 | if (m_SoundModule != null) |
2440 | { | 2828 | { |
2441 | m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), | 2829 | m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), |
2442 | volume, 20, true); | 2830 | volume, 20, true); |
2443 | } | 2831 | } |
2444 | } | 2832 | } |
@@ -2460,7 +2848,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2460 | if (m_SoundModule != null) | 2848 | if (m_SoundModule != null) |
2461 | { | 2849 | { |
2462 | m_SoundModule.SendSound(m_host.UUID, | 2850 | m_SoundModule.SendSound(m_host.UUID, |
2463 | KeyOrName(sound, AssetType.Sound), volume, false, 0, | 2851 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, |
2464 | 0, true, false); | 2852 | 0, true, false); |
2465 | } | 2853 | } |
2466 | } | 2854 | } |
@@ -2472,7 +2860,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2472 | if (m_SoundModule != null) | 2860 | if (m_SoundModule != null) |
2473 | { | 2861 | { |
2474 | m_SoundModule.SendSound(m_host.UUID, | 2862 | m_SoundModule.SendSound(m_host.UUID, |
2475 | KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, | 2863 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0, |
2476 | false, false); | 2864 | false, false); |
2477 | } | 2865 | } |
2478 | } | 2866 | } |
@@ -2489,8 +2877,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2489 | { | 2877 | { |
2490 | m_host.AddScriptLPS(1); | 2878 | m_host.AddScriptLPS(1); |
2491 | if (m_SoundModule != null) | 2879 | if (m_SoundModule != null) |
2492 | m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); | 2880 | m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0); |
2493 | ScriptSleep(1000); | 2881 | ScriptSleep(m_sleepMsOnPreloadSound); |
2494 | } | 2882 | } |
2495 | 2883 | ||
2496 | /// <summary> | 2884 | /// <summary> |
@@ -2723,70 +3111,68 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2723 | return src.ToLower(); | 3111 | return src.ToLower(); |
2724 | } | 3112 | } |
2725 | 3113 | ||
2726 | public LSL_Integer llGiveMoney(string destination, int amount) | 3114 | public void llGiveMoney(string destination, int amount) |
2727 | { | 3115 | { |
2728 | m_host.AddScriptLPS(1); | 3116 | Util.FireAndForget(x => |
2729 | |||
2730 | if (m_item.PermsGranter == UUID.Zero) | ||
2731 | return 0; | ||
2732 | |||
2733 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) | ||
2734 | { | 3117 | { |
2735 | LSLError("No permissions to give money"); | 3118 | m_host.AddScriptLPS(1); |
2736 | return 0; | ||
2737 | } | ||
2738 | 3119 | ||
2739 | UUID toID = new UUID(); | 3120 | if (m_item.PermsGranter == UUID.Zero) |
3121 | return; | ||
2740 | 3122 | ||
2741 | if (!UUID.TryParse(destination, out toID)) | 3123 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) |
2742 | { | 3124 | { |
2743 | LSLError("Bad key in llGiveMoney"); | 3125 | Error("llGiveMoney", "No permissions to give money"); |
2744 | return 0; | 3126 | return; |
2745 | } | 3127 | } |
2746 | 3128 | ||
2747 | IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); | 3129 | UUID toID = new UUID(); |
2748 | 3130 | ||
2749 | if (money == null) | 3131 | if (!UUID.TryParse(destination, out toID)) |
2750 | { | 3132 | { |
2751 | NotImplemented("llGiveMoney"); | 3133 | Error("llGiveMoney", "Bad key in llGiveMoney"); |
2752 | return 0; | 3134 | return; |
2753 | } | 3135 | } |
2754 | 3136 | ||
2755 | bool result = money.ObjectGiveMoney( | 3137 | IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); |
2756 | m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); | ||
2757 | 3138 | ||
2758 | if (result) | 3139 | if (money == null) |
2759 | return 1; | 3140 | { |
3141 | NotImplemented("llGiveMoney"); | ||
3142 | return; | ||
3143 | } | ||
2760 | 3144 | ||
2761 | return 0; | 3145 | money.ObjectGiveMoney( |
3146 | m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); | ||
3147 | }, null, "LSL_Api.llGiveMoney"); | ||
2762 | } | 3148 | } |
2763 | 3149 | ||
2764 | public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) | 3150 | public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) |
2765 | { | 3151 | { |
2766 | m_host.AddScriptLPS(1); | 3152 | m_host.AddScriptLPS(1); |
2767 | Deprecated("llMakeExplosion"); | 3153 | Deprecated("llMakeExplosion", "Use llParticleSystem instead"); |
2768 | ScriptSleep(100); | 3154 | ScriptSleep(m_sleepMsOnMakeExplosion); |
2769 | } | 3155 | } |
2770 | 3156 | ||
2771 | public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset) | 3157 | public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset) |
2772 | { | 3158 | { |
2773 | m_host.AddScriptLPS(1); | 3159 | m_host.AddScriptLPS(1); |
2774 | Deprecated("llMakeFountain"); | 3160 | Deprecated("llMakeFountain", "Use llParticleSystem instead"); |
2775 | ScriptSleep(100); | 3161 | ScriptSleep(m_sleepMsOnMakeFountain); |
2776 | } | 3162 | } |
2777 | 3163 | ||
2778 | public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) | 3164 | public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) |
2779 | { | 3165 | { |
2780 | m_host.AddScriptLPS(1); | 3166 | m_host.AddScriptLPS(1); |
2781 | Deprecated("llMakeSmoke"); | 3167 | Deprecated("llMakeSmoke", "Use llParticleSystem instead"); |
2782 | ScriptSleep(100); | 3168 | ScriptSleep(m_sleepMsOnMakeSmoke); |
2783 | } | 3169 | } |
2784 | 3170 | ||
2785 | public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) | 3171 | public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) |
2786 | { | 3172 | { |
2787 | m_host.AddScriptLPS(1); | 3173 | m_host.AddScriptLPS(1); |
2788 | Deprecated("llMakeFire"); | 3174 | Deprecated("llMakeFire", "Use llParticleSystem instead"); |
2789 | ScriptSleep(100); | 3175 | ScriptSleep(m_sleepMsOnMakeFire); |
2790 | } | 3176 | } |
2791 | 3177 | ||
2792 | public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | 3178 | public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) |
@@ -2807,54 +3193,57 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2807 | 3193 | ||
2808 | if (item == null) | 3194 | if (item == null) |
2809 | { | 3195 | { |
2810 | llSay(0, "Could not find object " + inventory); | 3196 | Error("llRezAtRoot", "Can't find object '" + inventory + "'"); |
2811 | return; | 3197 | return; |
2812 | } | 3198 | } |
2813 | 3199 | ||
2814 | if (item.InvType != (int)InventoryType.Object) | 3200 | if (item.InvType != (int)InventoryType.Object) |
2815 | { | 3201 | { |
2816 | llSay(0, "Unable to create requested object. Object is missing from database."); | 3202 | Error("llRezAtRoot", "Can't create requested object; object is missing from database"); |
2817 | return; | 3203 | return; |
2818 | } | 3204 | } |
2819 | 3205 | ||
2820 | // need the magnitude later | 3206 | // need the magnitude later |
2821 | // float velmag = (float)Util.GetMagnitude(llvel); | 3207 | // float velmag = (float)Util.GetMagnitude(llvel); |
2822 | 3208 | ||
2823 | SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); | 3209 | List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param); |
2824 | 3210 | ||
2825 | // If either of these are null, then there was an unknown error. | 3211 | // If either of these are null, then there was an unknown error. |
2826 | if (new_group == null) | 3212 | if (new_groups == null) |
2827 | return; | 3213 | return; |
2828 | 3214 | ||
2829 | // objects rezzed with this method are die_at_edge by default. | 3215 | foreach (SceneObjectGroup group in new_groups) |
2830 | new_group.RootPart.SetDieAtEdge(true); | 3216 | { |
3217 | // objects rezzed with this method are die_at_edge by default. | ||
3218 | group.RootPart.SetDieAtEdge(true); | ||
2831 | 3219 | ||
2832 | new_group.ResumeScripts(); | 3220 | group.ResumeScripts(); |
2833 | 3221 | ||
2834 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( | 3222 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( |
2835 | "object_rez", new Object[] { | 3223 | "object_rez", new Object[] { |
2836 | new LSL_String( | 3224 | new LSL_String( |
2837 | new_group.RootPart.UUID.ToString()) }, | 3225 | group.RootPart.UUID.ToString()) }, |
2838 | new DetectParams[0])); | 3226 | new DetectParams[0])); |
2839 | 3227 | ||
2840 | float groupmass = new_group.GetMass(); | 3228 | float groupmass = group.GetMass(); |
2841 | 3229 | ||
2842 | PhysicsActor pa = new_group.RootPart.PhysActor; | 3230 | PhysicsActor pa = group.RootPart.PhysActor; |
2843 | 3231 | ||
2844 | //Recoil. | 3232 | //Recoil. |
2845 | if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) | 3233 | if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) |
2846 | { | ||
2847 | Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; | ||
2848 | if (recoil != Vector3.Zero) | ||
2849 | { | 3234 | { |
2850 | llApplyImpulse(recoil, 0); | 3235 | Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; |
3236 | if (recoil != Vector3.Zero) | ||
3237 | { | ||
3238 | llApplyImpulse(recoil, 0); | ||
3239 | } | ||
2851 | } | 3240 | } |
3241 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) | ||
2852 | } | 3242 | } |
2853 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) | 3243 | }, null, "LSL_Api.llRezAtRoot"); |
2854 | }); | ||
2855 | 3244 | ||
2856 | //ScriptSleep((int)((groupmass * velmag) / 10)); | 3245 | //ScriptSleep((int)((groupmass * velmag) / 10)); |
2857 | ScriptSleep(100); | 3246 | ScriptSleep(m_sleepMsOnRezAtRoot); |
2858 | } | 3247 | } |
2859 | 3248 | ||
2860 | public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | 3249 | public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) |
@@ -2868,26 +3257,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2868 | // Determine where we are looking from | 3257 | // Determine where we are looking from |
2869 | LSL_Vector from = llGetPos(); | 3258 | LSL_Vector from = llGetPos(); |
2870 | 3259 | ||
2871 | // Work out the normalised vector from the source to the target | 3260 | // normalized direction to target |
2872 | LSL_Vector delta = llVecNorm(target - from); | 3261 | LSL_Vector dir = llVecNorm(target - from); |
2873 | LSL_Vector angle = new LSL_Vector(0,0,0); | 3262 | // use vertical to help compute left axis |
3263 | LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0); | ||
3264 | // find normalized left axis parallel to horizon | ||
3265 | LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir)); | ||
3266 | // make up orthogonal to left and dir | ||
3267 | up = LSL_Vector.Cross(dir, left); | ||
2874 | 3268 | ||
2875 | // Calculate the yaw | 3269 | // compute rotation based on orthogonal axes |
2876 | // subtracting PI_BY_TWO is required to compensate for the odd SL co-ordinate system | 3270 | LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up); |
2877 | angle.x = llAtan2(delta.z, delta.y) - ScriptBaseClass.PI_BY_TWO; | ||
2878 | 3271 | ||
2879 | // Calculate pitch | ||
2880 | angle.y = llAtan2(delta.x, llSqrt((delta.y * delta.y) + (delta.z * delta.z))); | ||
2881 | |||
2882 | // we need to convert from a vector describing | ||
2883 | // the angles of rotation in radians into rotation value | ||
2884 | LSL_Rotation rot = llEuler2Rot(angle); | ||
2885 | |||
2886 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply | 3272 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply |
2887 | // set the rotation of the object, copy that behavior | 3273 | // set the rotation of the object, copy that behavior |
2888 | PhysicsActor pa = m_host.PhysActor; | 3274 | PhysicsActor pa = m_host.PhysActor; |
2889 | 3275 | ||
2890 | if (strength == 0 || pa == null || !pa.IsPhysical) | 3276 | if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical) |
2891 | { | 3277 | { |
2892 | llSetRot(rot); | 3278 | llSetRot(rot); |
2893 | } | 3279 | } |
@@ -2900,7 +3286,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2900 | public void llStopLookAt() | 3286 | public void llStopLookAt() |
2901 | { | 3287 | { |
2902 | m_host.AddScriptLPS(1); | 3288 | m_host.AddScriptLPS(1); |
2903 | // NotImplemented("llStopLookAt"); | ||
2904 | m_host.StopLookAt(); | 3289 | m_host.StopLookAt(); |
2905 | } | 3290 | } |
2906 | 3291 | ||
@@ -2917,7 +3302,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2917 | { | 3302 | { |
2918 | // m_log.Info("llSleep snoozing " + sec + "s."); | 3303 | // m_log.Info("llSleep snoozing " + sec + "s."); |
2919 | m_host.AddScriptLPS(1); | 3304 | m_host.AddScriptLPS(1); |
2920 | Thread.Sleep((int)(sec * 1000)); | 3305 | |
3306 | Sleep((int)(sec * 1000)); | ||
2921 | } | 3307 | } |
2922 | 3308 | ||
2923 | public LSL_Float llGetMass() | 3309 | public LSL_Float llGetMass() |
@@ -2950,6 +3336,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2950 | } | 3336 | } |
2951 | } | 3337 | } |
2952 | 3338 | ||
3339 | public LSL_Float llGetMassMKS() | ||
3340 | { | ||
3341 | // this is what the wiki says it does! | ||
3342 | // http://wiki.secondlife.com/wiki/LlGetMassMKS | ||
3343 | return llGetMass() * 100.0; | ||
3344 | } | ||
3345 | |||
2953 | public void llCollisionFilter(string name, string id, int accept) | 3346 | public void llCollisionFilter(string name, string id, int accept) |
2954 | { | 3347 | { |
2955 | m_host.AddScriptLPS(1); | 3348 | m_host.AddScriptLPS(1); |
@@ -2958,7 +3351,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
2958 | 3351 | ||
2959 | if (!UUID.TryParse(id, out objectID)) | 3352 | if (!UUID.TryParse(id, out objectID)) |
2960 | objectID = UUID.Zero; | 3353 | objectID = UUID.Zero; |
2961 | 3354 | ||
2962 | if (objectID == UUID.Zero && name == "") | 3355 | if (objectID == UUID.Zero && name == "") |
2963 | return; | 3356 | return; |
2964 | 3357 | ||
@@ -3026,7 +3419,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3026 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; | 3419 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; |
3027 | 3420 | ||
3028 | if (attachmentsModule != null) | 3421 | if (attachmentsModule != null) |
3029 | return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, false); | 3422 | return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true); |
3030 | else | 3423 | else |
3031 | return false; | 3424 | return false; |
3032 | } | 3425 | } |
@@ -3039,7 +3432,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3039 | /// </remarks> | 3432 | /// </remarks> |
3040 | public void DetachFromAvatar() | 3433 | public void DetachFromAvatar() |
3041 | { | 3434 | { |
3042 | Util.FireAndForget(DetachWrapper, m_host); | 3435 | Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar"); |
3043 | } | 3436 | } |
3044 | 3437 | ||
3045 | private void DetachWrapper(object o) | 3438 | private void DetachWrapper(object o) |
@@ -3083,13 +3476,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3083 | public void llTakeCamera(string avatar) | 3476 | public void llTakeCamera(string avatar) |
3084 | { | 3477 | { |
3085 | m_host.AddScriptLPS(1); | 3478 | m_host.AddScriptLPS(1); |
3086 | Deprecated("llTakeCamera"); | 3479 | Deprecated("llTakeCamera", "Use llSetCameraParams instead"); |
3087 | } | 3480 | } |
3088 | 3481 | ||
3089 | public void llReleaseCamera(string avatar) | 3482 | public void llReleaseCamera(string avatar) |
3090 | { | 3483 | { |
3091 | m_host.AddScriptLPS(1); | 3484 | m_host.AddScriptLPS(1); |
3092 | Deprecated("llReleaseCamera"); | 3485 | Deprecated("llReleaseCamera", "Use llClearCameraParams instead"); |
3093 | } | 3486 | } |
3094 | 3487 | ||
3095 | public LSL_String llGetOwner() | 3488 | public LSL_String llGetOwner() |
@@ -3112,14 +3505,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3112 | 3505 | ||
3113 | // TODO: figure out values for client, fromSession, and imSessionID | 3506 | // TODO: figure out values for client, fromSession, and imSessionID |
3114 | // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); | 3507 | // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); |
3115 | UUID friendTransactionID = UUID.Random(); | ||
3116 | |||
3117 | //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); | ||
3118 | 3508 | ||
3119 | GridInstantMessage msg = new GridInstantMessage(); | 3509 | GridInstantMessage msg = new GridInstantMessage(); |
3120 | msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; | 3510 | msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid; |
3121 | msg.toAgentID = new Guid(user); // toAgentID.Guid; | 3511 | msg.toAgentID = new Guid(user); // toAgentID.Guid; |
3122 | msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here | 3512 | msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here |
3123 | // m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); | 3513 | // m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); |
3124 | // m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); | 3514 | // m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); |
3125 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; | 3515 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; |
@@ -3142,20 +3532,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3142 | msg.ParentEstateID = 0; //ParentEstateID; | 3532 | msg.ParentEstateID = 0; //ParentEstateID; |
3143 | msg.Position = new Vector3(m_host.AbsolutePosition); | 3533 | msg.Position = new Vector3(m_host.AbsolutePosition); |
3144 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; | 3534 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; |
3145 | msg.binaryBucket | 3535 | |
3536 | Vector3 pos = m_host.AbsolutePosition; | ||
3537 | msg.binaryBucket | ||
3146 | = Util.StringToBytes256( | 3538 | = Util.StringToBytes256( |
3147 | "{0}/{1}/{2}/{3}", | 3539 | "{0}/{1}/{2}/{3}", |
3148 | World.RegionInfo.RegionName, | 3540 | World.RegionInfo.RegionName, |
3149 | (int)Math.Floor(m_host.AbsolutePosition.X), | 3541 | (int)Math.Floor(pos.X), |
3150 | (int)Math.Floor(m_host.AbsolutePosition.Y), | 3542 | (int)Math.Floor(pos.Y), |
3151 | (int)Math.Floor(m_host.AbsolutePosition.Z)); | 3543 | (int)Math.Floor(pos.Z)); |
3152 | 3544 | ||
3153 | if (m_TransferModule != null) | 3545 | if (m_TransferModule != null) |
3154 | { | 3546 | { |
3155 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 3547 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
3156 | } | 3548 | } |
3157 | 3549 | ||
3158 | ScriptSleep(2000); | 3550 | ScriptSleep(m_sleepMsOnInstantMessage); |
3159 | } | 3551 | } |
3160 | 3552 | ||
3161 | public void llEmail(string address, string subject, string message) | 3553 | public void llEmail(string address, string subject, string message) |
@@ -3164,12 +3556,36 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3164 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | 3556 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); |
3165 | if (emailModule == null) | 3557 | if (emailModule == null) |
3166 | { | 3558 | { |
3167 | ShoutError("llEmail: email module not configured"); | 3559 | Error("llEmail", "Email module not configured"); |
3168 | return; | 3560 | return; |
3169 | } | 3561 | } |
3170 | 3562 | ||
3563 | //Restrict email destination to the avatars registered email address? | ||
3564 | //The restriction only applies if the destination address is not local. | ||
3565 | if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false) | ||
3566 | { | ||
3567 | UserAccount account = | ||
3568 | World.UserAccountService.GetUserAccount( | ||
3569 | World.RegionInfo.ScopeID, | ||
3570 | m_host.OwnerID); | ||
3571 | |||
3572 | if (account == null) | ||
3573 | { | ||
3574 | Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'"); | ||
3575 | return; | ||
3576 | } | ||
3577 | |||
3578 | if (String.IsNullOrEmpty(account.Email)) | ||
3579 | { | ||
3580 | Error("llEmail", "User account has not registered an email address."); | ||
3581 | return; | ||
3582 | } | ||
3583 | |||
3584 | address = account.Email; | ||
3585 | } | ||
3586 | |||
3171 | emailModule.SendEmail(m_host.UUID, address, subject, message); | 3587 | emailModule.SendEmail(m_host.UUID, address, subject, message); |
3172 | llSleep(EMAIL_PAUSE_TIME); | 3588 | ScriptSleep(m_sleepMsOnEmail); |
3173 | } | 3589 | } |
3174 | 3590 | ||
3175 | public void llGetNextEmail(string address, string subject) | 3591 | public void llGetNextEmail(string address, string subject) |
@@ -3178,7 +3594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3178 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | 3594 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); |
3179 | if (emailModule == null) | 3595 | if (emailModule == null) |
3180 | { | 3596 | { |
3181 | ShoutError("llGetNextEmail: email module not configured"); | 3597 | Error("llGetNextEmail", "Email module not configured"); |
3182 | return; | 3598 | return; |
3183 | } | 3599 | } |
3184 | Email email; | 3600 | Email email; |
@@ -3263,23 +3679,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3263 | catch (NotImplementedException) | 3679 | catch (NotImplementedException) |
3264 | { | 3680 | { |
3265 | // Currently not implemented in DotNetEngine only XEngine | 3681 | // Currently not implemented in DotNetEngine only XEngine |
3266 | NotImplemented("llMinEventDelay in DotNetEngine"); | 3682 | NotImplemented("llMinEventDelay", "In DotNetEngine"); |
3267 | } | 3683 | } |
3268 | } | 3684 | } |
3269 | 3685 | ||
3270 | /// <summary> | ||
3271 | /// llSoundPreload is deprecated. In SL this appears to do absolutely nothing | ||
3272 | /// and is documented to have no delay. | ||
3273 | /// </summary> | ||
3274 | public void llSoundPreload(string sound) | 3686 | public void llSoundPreload(string sound) |
3275 | { | 3687 | { |
3276 | m_host.AddScriptLPS(1); | 3688 | m_host.AddScriptLPS(1); |
3689 | Deprecated("llSoundPreload", "Use llPreloadSound instead"); | ||
3277 | } | 3690 | } |
3278 | 3691 | ||
3279 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) | 3692 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) |
3280 | { | 3693 | { |
3281 | m_host.AddScriptLPS(1); | 3694 | m_host.AddScriptLPS(1); |
3282 | 3695 | ||
3283 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply | 3696 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply |
3284 | // set the rotation of the object, copy that behavior | 3697 | // set the rotation of the object, copy that behavior |
3285 | PhysicsActor pa = m_host.PhysActor; | 3698 | PhysicsActor pa = m_host.PhysActor; |
@@ -3321,7 +3734,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3321 | if (presence != null) | 3734 | if (presence != null) |
3322 | { | 3735 | { |
3323 | // Do NOT try to parse UUID, animations cannot be triggered by ID | 3736 | // Do NOT try to parse UUID, animations cannot be triggered by ID |
3324 | UUID animID = InventoryKey(anim, (int)AssetType.Animation); | 3737 | UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation); |
3325 | if (animID == UUID.Zero) | 3738 | if (animID == UUID.Zero) |
3326 | presence.Animator.AddAnimation(anim, m_host.UUID); | 3739 | presence.Animator.AddAnimation(anim, m_host.UUID); |
3327 | else | 3740 | else |
@@ -3343,7 +3756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3343 | 3756 | ||
3344 | if (presence != null) | 3757 | if (presence != null) |
3345 | { | 3758 | { |
3346 | UUID animID = KeyOrName(anim); | 3759 | UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim); |
3347 | 3760 | ||
3348 | if (animID == UUID.Zero) | 3761 | if (animID == UUID.Zero) |
3349 | presence.Animator.RemoveAnimation(anim); | 3762 | presence.Animator.RemoveAnimation(anim); |
@@ -3371,6 +3784,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3371 | 3784 | ||
3372 | protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) | 3785 | protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) |
3373 | { | 3786 | { |
3787 | PhysicsActor pa = part.PhysActor; | ||
3788 | if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d ) | ||
3789 | spinrate = 0.0d; | ||
3374 | part.UpdateAngularVelocity(axis * spinrate); | 3790 | part.UpdateAngularVelocity(axis * spinrate); |
3375 | } | 3791 | } |
3376 | 3792 | ||
@@ -3415,11 +3831,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3415 | implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | | 3831 | implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | |
3416 | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | 3832 | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | |
3417 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | | 3833 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | |
3834 | ScriptBaseClass.PERMISSION_TRACK_CAMERA | | ||
3418 | ScriptBaseClass.PERMISSION_ATTACH; | 3835 | ScriptBaseClass.PERMISSION_ATTACH; |
3419 | } | 3836 | } |
3420 | else | 3837 | else |
3421 | { | 3838 | { |
3422 | if (m_host.ParentGroup.GetSittingAvatars().Contains(agentID)) | 3839 | if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null) |
3423 | { | 3840 | { |
3424 | // When agent is sitting, certain permissions are implicit if requested from sitting agent | 3841 | // When agent is sitting, certain permissions are implicit if requested from sitting agent |
3425 | implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | 3842 | implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | |
@@ -3451,10 +3868,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3451 | } | 3868 | } |
3452 | 3869 | ||
3453 | ScenePresence presence = World.GetScenePresence(agentID); | 3870 | ScenePresence presence = World.GetScenePresence(agentID); |
3871 | |||
3454 | if (presence != null) | 3872 | if (presence != null) |
3455 | { | 3873 | { |
3456 | // If permissions are being requested from an NPC and were not implicitly granted above then | 3874 | // If permissions are being requested from an NPC and were not implicitly granted above then |
3457 | // auto grant all reuqested permissions if the script is owned by the NPC or the NPCs owner | 3875 | // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner |
3458 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); | 3876 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
3459 | if (npcModule != null && npcModule.IsNPC(agentID, World)) | 3877 | if (npcModule != null && npcModule.IsNPC(agentID, World)) |
3460 | { | 3878 | { |
@@ -3570,22 +3988,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3570 | public void llCreateLink(string target, int parent) | 3988 | public void llCreateLink(string target, int parent) |
3571 | { | 3989 | { |
3572 | m_host.AddScriptLPS(1); | 3990 | m_host.AddScriptLPS(1); |
3573 | UUID targetID; | ||
3574 | |||
3575 | if (!UUID.TryParse(target, out targetID)) | ||
3576 | return; | ||
3577 | 3991 | ||
3578 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 | 3992 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 |
3579 | && !m_automaticLinkPermission) | 3993 | && !m_automaticLinkPermission) |
3580 | { | 3994 | { |
3581 | ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); | 3995 | Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set"); |
3582 | return; | 3996 | return; |
3583 | } | 3997 | } |
3584 | 3998 | ||
3585 | IClientAPI client = null; | 3999 | CreateLink(target, parent); |
3586 | ScenePresence sp = World.GetScenePresence(m_item.PermsGranter); | 4000 | } |
3587 | if (sp != null) | 4001 | |
3588 | client = sp.ControllingClient; | 4002 | public void CreateLink(string target, int parent) |
4003 | { | ||
4004 | UUID targetID; | ||
4005 | |||
4006 | if (!UUID.TryParse(target, out targetID)) | ||
4007 | return; | ||
3589 | 4008 | ||
3590 | SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); | 4009 | SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); |
3591 | 4010 | ||
@@ -3620,10 +4039,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3620 | parentPrim.HasGroupChanged = true; | 4039 | parentPrim.HasGroupChanged = true; |
3621 | parentPrim.ScheduleGroupForFullUpdate(); | 4040 | parentPrim.ScheduleGroupForFullUpdate(); |
3622 | 4041 | ||
4042 | IClientAPI client = null; | ||
4043 | ScenePresence sp = World.GetScenePresence(m_host.OwnerID); | ||
4044 | if (sp != null) | ||
4045 | client = sp.ControllingClient; | ||
4046 | |||
3623 | if (client != null) | 4047 | if (client != null) |
3624 | parentPrim.SendPropertiesToClient(client); | 4048 | parentPrim.SendPropertiesToClient(client); |
3625 | 4049 | ||
3626 | ScriptSleep(1000); | 4050 | ScriptSleep(m_sleepMsOnCreateLink); |
3627 | } | 4051 | } |
3628 | 4052 | ||
3629 | public void llBreakLink(int linknum) | 4053 | public void llBreakLink(int linknum) |
@@ -3633,10 +4057,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3633 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 | 4057 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 |
3634 | && !m_automaticLinkPermission) | 4058 | && !m_automaticLinkPermission) |
3635 | { | 4059 | { |
3636 | ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); | 4060 | Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set"); |
3637 | return; | 4061 | return; |
3638 | } | 4062 | } |
3639 | 4063 | ||
4064 | BreakLink(linknum); | ||
4065 | } | ||
4066 | |||
4067 | public void BreakLink(int linknum) | ||
4068 | { | ||
3640 | if (linknum < ScriptBaseClass.LINK_THIS) | 4069 | if (linknum < ScriptBaseClass.LINK_THIS) |
3641 | return; | 4070 | return; |
3642 | 4071 | ||
@@ -3712,6 +4141,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3712 | public void llBreakAllLinks() | 4141 | public void llBreakAllLinks() |
3713 | { | 4142 | { |
3714 | m_host.AddScriptLPS(1); | 4143 | m_host.AddScriptLPS(1); |
4144 | |||
4145 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 | ||
4146 | && !m_automaticLinkPermission) | ||
4147 | { | ||
4148 | Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set"); | ||
4149 | return; | ||
4150 | } | ||
4151 | |||
4152 | BreakAllLinks(); | ||
4153 | } | ||
4154 | |||
4155 | public void BreakAllLinks() | ||
4156 | { | ||
3715 | SceneObjectGroup parentPrim = m_host.ParentGroup; | 4157 | SceneObjectGroup parentPrim = m_host.ParentGroup; |
3716 | if (parentPrim.AttachmentPoint != 0) | 4158 | if (parentPrim.AttachmentPoint != 0) |
3717 | return; // Fail silently if attached | 4159 | return; // Fail silently if attached |
@@ -3732,47 +4174,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3732 | { | 4174 | { |
3733 | m_host.AddScriptLPS(1); | 4175 | m_host.AddScriptLPS(1); |
3734 | 4176 | ||
3735 | if (linknum < 0) | 4177 | ISceneEntity entity = GetLinkEntity(m_host, linknum); |
3736 | { | ||
3737 | if (linknum == ScriptBaseClass.LINK_THIS) | ||
3738 | return m_host.UUID.ToString(); | ||
3739 | else | ||
3740 | return ScriptBaseClass.NULL_KEY; | ||
3741 | } | ||
3742 | |||
3743 | int actualPrimCount = m_host.ParentGroup.PrimCount; | ||
3744 | List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); | ||
3745 | int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; | ||
3746 | |||
3747 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single | ||
3748 | // prim that has any avatars sat upon it (in which case the root prim is link 1). | ||
3749 | if (linknum == 0) | ||
3750 | { | ||
3751 | if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) | ||
3752 | return m_host.UUID.ToString(); | ||
3753 | 4178 | ||
3754 | return ScriptBaseClass.NULL_KEY; | 4179 | if (entity != null) |
3755 | } | 4180 | return entity.UUID.ToString(); |
3756 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but | ||
3757 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). | ||
3758 | else if (linknum == 1 && actualPrimCount == 1) | ||
3759 | { | ||
3760 | if (sittingAvatarIds.Count > 0) | ||
3761 | return m_host.ParentGroup.RootPart.UUID.ToString(); | ||
3762 | else | ||
3763 | return ScriptBaseClass.NULL_KEY; | ||
3764 | } | ||
3765 | else if (linknum <= adjustedPrimCount) | ||
3766 | { | ||
3767 | if (linknum <= actualPrimCount) | ||
3768 | return m_host.ParentGroup.GetLinkNumPart(linknum).UUID.ToString(); | ||
3769 | else | ||
3770 | return sittingAvatarIds[linknum - actualPrimCount - 1].ToString(); | ||
3771 | } | ||
3772 | else | 4181 | else |
3773 | { | ||
3774 | return ScriptBaseClass.NULL_KEY; | 4182 | return ScriptBaseClass.NULL_KEY; |
3775 | } | ||
3776 | } | 4183 | } |
3777 | 4184 | ||
3778 | /// <summary> | 4185 | /// <summary> |
@@ -3818,55 +4225,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3818 | { | 4225 | { |
3819 | m_host.AddScriptLPS(1); | 4226 | m_host.AddScriptLPS(1); |
3820 | 4227 | ||
3821 | if (linknum < 0) | 4228 | ISceneEntity entity = GetLinkEntity(m_host, linknum); |
3822 | { | ||
3823 | if (linknum == ScriptBaseClass.LINK_THIS) | ||
3824 | return m_host.Name; | ||
3825 | else | ||
3826 | return ScriptBaseClass.NULL_KEY; | ||
3827 | } | ||
3828 | 4229 | ||
3829 | int actualPrimCount = m_host.ParentGroup.PrimCount; | 4230 | if (entity != null) |
3830 | List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars(); | 4231 | return entity.Name; |
3831 | int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count; | ||
3832 | |||
3833 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single | ||
3834 | // prim that has any avatars sat upon it (in which case the root prim is link 1). | ||
3835 | if (linknum == 0) | ||
3836 | { | ||
3837 | if (actualPrimCount == 1 && sittingAvatarIds.Count == 0) | ||
3838 | return m_host.Name; | ||
3839 | |||
3840 | return ScriptBaseClass.NULL_KEY; | ||
3841 | } | ||
3842 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but | ||
3843 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). | ||
3844 | else if (linknum == 1 && actualPrimCount == 1) | ||
3845 | { | ||
3846 | if (sittingAvatarIds.Count > 0) | ||
3847 | return m_host.ParentGroup.RootPart.Name; | ||
3848 | else | ||
3849 | return ScriptBaseClass.NULL_KEY; | ||
3850 | } | ||
3851 | else if (linknum <= adjustedPrimCount) | ||
3852 | { | ||
3853 | if (linknum <= actualPrimCount) | ||
3854 | { | ||
3855 | return m_host.ParentGroup.GetLinkNumPart(linknum).Name; | ||
3856 | } | ||
3857 | else | ||
3858 | { | ||
3859 | ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]); | ||
3860 | if (sp != null) | ||
3861 | return sp.Name; | ||
3862 | else | ||
3863 | return ScriptBaseClass.NULL_KEY; | ||
3864 | } | ||
3865 | } | ||
3866 | else | 4232 | else |
3867 | { | ||
3868 | return ScriptBaseClass.NULL_KEY; | 4233 | return ScriptBaseClass.NULL_KEY; |
3869 | } | ||
3870 | } | 4234 | } |
3871 | 4235 | ||
3872 | public LSL_Integer llGetInventoryNumber(int type) | 4236 | public LSL_Integer llGetInventoryNumber(int type) |
@@ -3931,7 +4295,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3931 | 4295 | ||
3932 | if (!UUID.TryParse(destination, out destId)) | 4296 | if (!UUID.TryParse(destination, out destId)) |
3933 | { | 4297 | { |
3934 | llSay(0, "Could not parse key " + destination); | 4298 | Error("llGiveInventory", "Can't parse destination key '" + destination + "'"); |
3935 | return; | 4299 | return; |
3936 | } | 4300 | } |
3937 | 4301 | ||
@@ -3939,8 +4303,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3939 | 4303 | ||
3940 | if (item == null) | 4304 | if (item == null) |
3941 | { | 4305 | { |
3942 | llSay(0, String.Format("Could not find object '{0}'", inventory)); | 4306 | Error("llGiveInventory", "Can't find inventory object '" + inventory + "'"); |
3943 | throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); | 4307 | return; |
3944 | } | 4308 | } |
3945 | 4309 | ||
3946 | UUID objId = item.ItemID; | 4310 | UUID objId = item.ItemID; |
@@ -3964,15 +4328,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3964 | 4328 | ||
3965 | if (account == null) | 4329 | if (account == null) |
3966 | { | 4330 | { |
3967 | llSay(0, "Can't find destination "+destId.ToString()); | 4331 | GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString()); |
3968 | return; | 4332 | if(info == null || info.Online == false) |
4333 | { | ||
4334 | Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'"); | ||
4335 | return; | ||
4336 | } | ||
3969 | } | 4337 | } |
3970 | } | 4338 | } |
3971 | // destination is an avatar | 4339 | // destination is an avatar |
3972 | InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); | 4340 | string message; |
4341 | InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message); | ||
3973 | 4342 | ||
3974 | if (agentItem == null) | 4343 | if (agentItem == null) |
4344 | { | ||
4345 | llSay(0, message); | ||
3975 | return; | 4346 | return; |
4347 | } | ||
3976 | 4348 | ||
3977 | if (m_TransferModule != null) | 4349 | if (m_TransferModule != null) |
3978 | { | 4350 | { |
@@ -3991,7 +4363,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
3991 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 4363 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
3992 | } | 4364 | } |
3993 | 4365 | ||
3994 | ScriptSleep(3000); | 4366 | ScriptSleep(m_sleepMsOnGiveInventory); |
3995 | } | 4367 | } |
3996 | } | 4368 | } |
3997 | 4369 | ||
@@ -4054,87 +4426,98 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4054 | UserAccount account; | 4426 | UserAccount account; |
4055 | 4427 | ||
4056 | UserInfoCacheEntry ce; | 4428 | UserInfoCacheEntry ce; |
4057 | if (!m_userInfoCache.TryGetValue(uuid, out ce)) | 4429 | |
4430 | lock (m_userInfoCache) | ||
4058 | { | 4431 | { |
4059 | account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); | 4432 | if (!m_userInfoCache.TryGetValue(uuid, out ce)) |
4060 | if (account == null) | ||
4061 | { | 4433 | { |
4062 | m_userInfoCache[uuid] = null; // Cache negative | 4434 | account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); |
4063 | return UUID.Zero.ToString(); | 4435 | if (account == null) |
4064 | } | 4436 | { |
4065 | 4437 | m_userInfoCache[uuid] = null; // Cache negative | |
4438 | return UUID.Zero.ToString(); | ||
4439 | } | ||
4066 | 4440 | ||
4067 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); | 4441 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); |
4068 | if (pinfos != null && pinfos.Length > 0) | 4442 | if (pinfos != null && pinfos.Length > 0) |
4069 | { | ||
4070 | foreach (PresenceInfo p in pinfos) | ||
4071 | { | 4443 | { |
4072 | if (p.RegionID != UUID.Zero) | 4444 | foreach (PresenceInfo p in pinfos) |
4073 | { | 4445 | { |
4074 | pinfo = p; | 4446 | if (p.RegionID != UUID.Zero) |
4447 | { | ||
4448 | pinfo = p; | ||
4449 | } | ||
4075 | } | 4450 | } |
4076 | } | 4451 | } |
4077 | } | ||
4078 | 4452 | ||
4079 | ce = new UserInfoCacheEntry(); | 4453 | ce = new UserInfoCacheEntry(); |
4080 | ce.time = Util.EnvironmentTickCount(); | 4454 | ce.time = Util.EnvironmentTickCount(); |
4081 | ce.account = account; | 4455 | ce.account = account; |
4082 | ce.pinfo = pinfo; | 4456 | ce.pinfo = pinfo; |
4083 | } | ||
4084 | else | ||
4085 | { | ||
4086 | if (ce == null) | ||
4087 | return UUID.Zero.ToString(); | ||
4088 | |||
4089 | account = ce.account; | ||
4090 | pinfo = ce.pinfo; | ||
4091 | } | ||
4092 | 4457 | ||
4093 | if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) >= 20000) | 4458 | m_userInfoCache[uuid] = ce; |
4094 | { | 4459 | } |
4095 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); | 4460 | else |
4096 | if (pinfos != null && pinfos.Length > 0) | ||
4097 | { | 4461 | { |
4098 | foreach (PresenceInfo p in pinfos) | 4462 | if (ce == null) |
4463 | return UUID.Zero.ToString(); | ||
4464 | |||
4465 | account = ce.account; | ||
4466 | |||
4467 | if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) | ||
4468 | >= LlRequestAgentDataCacheTimeoutMs) | ||
4099 | { | 4469 | { |
4100 | if (p.RegionID != UUID.Zero) | 4470 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); |
4471 | if (pinfos != null && pinfos.Length > 0) | ||
4101 | { | 4472 | { |
4102 | pinfo = p; | 4473 | foreach (PresenceInfo p in pinfos) |
4474 | { | ||
4475 | if (p.RegionID != UUID.Zero) | ||
4476 | { | ||
4477 | pinfo = p; | ||
4478 | } | ||
4479 | } | ||
4103 | } | 4480 | } |
4481 | else | ||
4482 | { | ||
4483 | pinfo = null; | ||
4484 | } | ||
4485 | |||
4486 | ce.time = Util.EnvironmentTickCount(); | ||
4487 | ce.pinfo = pinfo; | ||
4488 | } | ||
4489 | else | ||
4490 | { | ||
4491 | pinfo = ce.pinfo; | ||
4104 | } | 4492 | } |
4105 | } | 4493 | } |
4106 | else | ||
4107 | pinfo = null; | ||
4108 | |||
4109 | ce.time = Util.EnvironmentTickCount(); | ||
4110 | ce.pinfo = pinfo; | ||
4111 | } | 4494 | } |
4112 | 4495 | ||
4113 | string reply = String.Empty; | 4496 | string reply = String.Empty; |
4114 | 4497 | ||
4115 | switch (data) | 4498 | switch (data) |
4116 | { | 4499 | { |
4117 | case 1: // DATA_ONLINE (0|1) | 4500 | case ScriptBaseClass.DATA_ONLINE: |
4118 | if (pinfo != null && pinfo.RegionID != UUID.Zero) | 4501 | if (pinfo != null && pinfo.RegionID != UUID.Zero) |
4119 | reply = "1"; | 4502 | reply = "1"; |
4120 | else | 4503 | else |
4121 | reply = "0"; | 4504 | reply = "0"; |
4122 | break; | 4505 | break; |
4123 | case 2: // DATA_NAME (First Last) | 4506 | case ScriptBaseClass.DATA_NAME: // (First Last) |
4124 | reply = account.FirstName + " " + account.LastName; | 4507 | reply = account.FirstName + " " + account.LastName; |
4125 | break; | 4508 | break; |
4126 | case 3: // DATA_BORN (YYYY-MM-DD) | 4509 | case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD) |
4127 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); | 4510 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); |
4128 | born = born.AddSeconds(account.Created); | 4511 | born = born.AddSeconds(account.Created); |
4129 | reply = born.ToString("yyyy-MM-dd"); | 4512 | reply = born.ToString("yyyy-MM-dd"); |
4130 | break; | 4513 | break; |
4131 | case 4: // DATA_RATING (0,0,0,0,0,0) | 4514 | case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0) |
4132 | reply = "0,0,0,0,0,0"; | 4515 | reply = "0,0,0,0,0,0"; |
4133 | break; | 4516 | break; |
4134 | case 7: // DATA_USERLEVEL (integer) | 4517 | case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant. |
4135 | reply = account.UserLevel.ToString(); | 4518 | reply = account.UserLevel.ToString(); |
4136 | break; | 4519 | break; |
4137 | case 8: // DATA_PAYINFO (0|1|2|3) | 4520 | case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3) |
4138 | reply = "0"; | 4521 | reply = "0"; |
4139 | break; | 4522 | break; |
4140 | default: | 4523 | default: |
@@ -4150,7 +4533,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4150 | AsyncCommands. | 4533 | AsyncCommands. |
4151 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | 4534 | DataserverPlugin.DataserverReply(rq.ToString(), reply); |
4152 | 4535 | ||
4153 | ScriptSleep(100); | 4536 | ScriptSleep(m_sleepMsOnRequestAgentData); |
4154 | return tid.ToString(); | 4537 | return tid.ToString(); |
4155 | } | 4538 | } |
4156 | 4539 | ||
@@ -4166,10 +4549,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4166 | DataserverPlugin.RegisterRequest(m_host.LocalId, | 4549 | DataserverPlugin.RegisterRequest(m_host.LocalId, |
4167 | m_item.ItemID, item.AssetID.ToString()); | 4550 | m_item.ItemID, item.AssetID.ToString()); |
4168 | 4551 | ||
4169 | Vector3 region = new Vector3( | 4552 | Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); |
4170 | World.RegionInfo.RegionLocX * Constants.RegionSize, | ||
4171 | World.RegionInfo.RegionLocY * Constants.RegionSize, | ||
4172 | 0); | ||
4173 | 4553 | ||
4174 | World.AssetService.Get(item.AssetID.ToString(), this, | 4554 | World.AssetService.Get(item.AssetID.ToString(), this, |
4175 | delegate(string i, object sender, AssetBase a) | 4555 | delegate(string i, object sender, AssetBase a) |
@@ -4186,12 +4566,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4186 | reply); | 4566 | reply); |
4187 | }); | 4567 | }); |
4188 | 4568 | ||
4189 | ScriptSleep(1000); | 4569 | ScriptSleep(m_sleepMsOnRequestInventoryData); |
4190 | return tid.ToString(); | 4570 | return tid.ToString(); |
4191 | } | 4571 | } |
4192 | } | 4572 | } |
4193 | 4573 | ||
4194 | ScriptSleep(1000); | 4574 | ScriptSleep(m_sleepMsOnRequestInventoryData); |
4195 | return String.Empty; | 4575 | return String.Empty; |
4196 | } | 4576 | } |
4197 | 4577 | ||
@@ -4211,14 +4591,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4211 | if (presence != null) | 4591 | if (presence != null) |
4212 | { | 4592 | { |
4213 | // agent must be over the owners land | 4593 | // agent must be over the owners land |
4214 | if (m_host.OwnerID == World.LandChannel.GetLandObject( | 4594 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4215 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
4216 | { | 4595 | { |
4217 | World.TeleportClientHome(agentId, presence.ControllingClient); | 4596 | World.TeleportClientHome(agentId, presence.ControllingClient); |
4218 | } | 4597 | } |
4219 | } | 4598 | } |
4220 | } | 4599 | } |
4221 | ScriptSleep(5000); | 4600 | |
4601 | ScriptSleep(m_sleepMsOnSetDamage); | ||
4222 | } | 4602 | } |
4223 | 4603 | ||
4224 | public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) | 4604 | public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) |
@@ -4238,8 +4618,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4238 | destination = World.RegionInfo.RegionName; | 4618 | destination = World.RegionInfo.RegionName; |
4239 | 4619 | ||
4240 | // agent must be over the owners land | 4620 | // agent must be over the owners land |
4241 | if (m_host.OwnerID == World.LandChannel.GetLandObject( | 4621 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4242 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
4243 | { | 4622 | { |
4244 | DoLLTeleport(presence, destination, targetPos, targetLookAt); | 4623 | DoLLTeleport(presence, destination, targetPos, targetLookAt); |
4245 | } | 4624 | } |
@@ -4259,7 +4638,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4259 | m_host.AddScriptLPS(1); | 4638 | m_host.AddScriptLPS(1); |
4260 | UUID agentId = new UUID(); | 4639 | UUID agentId = new UUID(); |
4261 | 4640 | ||
4262 | ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); | 4641 | ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y); |
4263 | 4642 | ||
4264 | if (UUID.TryParse(agent, out agentId)) | 4643 | if (UUID.TryParse(agent, out agentId)) |
4265 | { | 4644 | { |
@@ -4270,8 +4649,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4270 | if (presence.GodLevel >= 200) return; | 4649 | if (presence.GodLevel >= 200) return; |
4271 | 4650 | ||
4272 | // agent must be over the owners land | 4651 | // agent must be over the owners land |
4273 | if (m_host.OwnerID == World.LandChannel.GetLandObject( | 4652 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4274 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
4275 | { | 4653 | { |
4276 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); | 4654 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); |
4277 | } | 4655 | } |
@@ -4288,7 +4666,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4288 | 4666 | ||
4289 | private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) | 4667 | private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) |
4290 | { | 4668 | { |
4291 | UUID assetID = KeyOrName(destination); | 4669 | UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination); |
4292 | 4670 | ||
4293 | // The destinaion is not an asset ID and also doesn't name a landmark. | 4671 | // The destinaion is not an asset ID and also doesn't name a landmark. |
4294 | // Use it as a sim name | 4672 | // Use it as a sim name |
@@ -4321,22 +4699,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4321 | UUID av = new UUID(); | 4699 | UUID av = new UUID(); |
4322 | if (!UUID.TryParse(agent,out av)) | 4700 | if (!UUID.TryParse(agent,out av)) |
4323 | { | 4701 | { |
4324 | LSLError("First parameter to llDialog needs to be a key"); | 4702 | Error("llTextBox", "First parameter must be a key"); |
4325 | return; | 4703 | return; |
4326 | } | 4704 | } |
4327 | 4705 | ||
4328 | if (message == string.Empty) | 4706 | if (message == string.Empty) |
4329 | { | 4707 | { |
4330 | ShoutError("Trying to use llTextBox with empty message."); | 4708 | Error("llTextBox", "Empty message"); |
4331 | } | 4709 | } |
4332 | else if (message.Length > 512) | 4710 | else if (message.Length > 512) |
4333 | { | 4711 | { |
4334 | ShoutError("Trying to use llTextBox with message over 512 characters."); | 4712 | Error("llTextBox", "Message more than 512 characters"); |
4335 | } | 4713 | } |
4336 | else | 4714 | else |
4337 | { | 4715 | { |
4338 | dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID); | 4716 | dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID); |
4339 | ScriptSleep(1000); | 4717 | ScriptSleep(m_sleepMsOnTextBox); |
4340 | } | 4718 | } |
4341 | } | 4719 | } |
4342 | 4720 | ||
@@ -4353,9 +4731,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4353 | public void llCollisionSound(string impact_sound, double impact_volume) | 4731 | public void llCollisionSound(string impact_sound, double impact_volume) |
4354 | { | 4732 | { |
4355 | m_host.AddScriptLPS(1); | 4733 | m_host.AddScriptLPS(1); |
4356 | 4734 | ||
4357 | // TODO: Parameter check logic required. | 4735 | // TODO: Parameter check logic required. |
4358 | m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); | 4736 | m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); |
4359 | m_host.CollisionSoundVolume = (float)impact_volume; | 4737 | m_host.CollisionSoundVolume = (float)impact_volume; |
4360 | } | 4738 | } |
4361 | 4739 | ||
@@ -4475,7 +4853,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4475 | { | 4853 | { |
4476 | if (pushrestricted) | 4854 | if (pushrestricted) |
4477 | { | 4855 | { |
4478 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y); | 4856 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); |
4479 | 4857 | ||
4480 | // We didn't find the parcel but region is push restricted so assume it is NOT ok | 4858 | // We didn't find the parcel but region is push restricted so assume it is NOT ok |
4481 | if (targetlandObj == null) | 4859 | if (targetlandObj == null) |
@@ -4490,7 +4868,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4490 | } | 4868 | } |
4491 | else | 4869 | else |
4492 | { | 4870 | { |
4493 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos.X, PusheePos.Y); | 4871 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); |
4494 | if (targetlandObj == null) | 4872 | if (targetlandObj == null) |
4495 | { | 4873 | { |
4496 | // We didn't find the parcel but region isn't push restricted so assume it's ok | 4874 | // We didn't find the parcel but region isn't push restricted so assume it's ok |
@@ -4520,6 +4898,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4520 | } | 4898 | } |
4521 | } | 4899 | } |
4522 | } | 4900 | } |
4901 | |||
4523 | if (pushAllowed) | 4902 | if (pushAllowed) |
4524 | { | 4903 | { |
4525 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); | 4904 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); |
@@ -4548,17 +4927,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4548 | applied_linear_impulse *= scaling_factor; | 4927 | applied_linear_impulse *= scaling_factor; |
4549 | 4928 | ||
4550 | } | 4929 | } |
4930 | |||
4551 | if (pusheeIsAvatar) | 4931 | if (pusheeIsAvatar) |
4552 | { | 4932 | { |
4553 | if (pusheeav != null) | 4933 | if (pusheeav != null) |
4554 | { | 4934 | { |
4555 | if (pusheeav.PhysicsActor != null) | 4935 | PhysicsActor pa = pusheeav.PhysicsActor; |
4936 | |||
4937 | if (pa != null) | ||
4556 | { | 4938 | { |
4557 | if (local != 0) | 4939 | if (local != 0) |
4558 | { | 4940 | { |
4559 | applied_linear_impulse *= m_host.GetWorldRotation(); | 4941 | applied_linear_impulse *= m_host.GetWorldRotation(); |
4560 | } | 4942 | } |
4561 | pusheeav.PhysicsActor.AddForce(applied_linear_impulse, true); | 4943 | |
4944 | pa.AddForce(applied_linear_impulse, true); | ||
4562 | } | 4945 | } |
4563 | } | 4946 | } |
4564 | } | 4947 | } |
@@ -4666,6 +5049,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4666 | 5049 | ||
4667 | s = Math.Cos(angle * 0.5); | 5050 | s = Math.Cos(angle * 0.5); |
4668 | t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs | 5051 | t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs |
5052 | axis = LSL_Vector.Norm(axis); | ||
4669 | x = axis.x * t; | 5053 | x = axis.x * t; |
4670 | y = axis.y * t; | 5054 | y = axis.y * t; |
4671 | z = axis.z * t; | 5055 | z = axis.z * t; |
@@ -4673,41 +5057,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4673 | return new LSL_Rotation(x,y,z,s); | 5057 | return new LSL_Rotation(x,y,z,s); |
4674 | } | 5058 | } |
4675 | 5059 | ||
4676 | 5060 | /// <summary> | |
4677 | // Xantor 29/apr/2008 | 5061 | /// Returns the axis of rotation for a quaternion |
4678 | // converts a Quaternion to X,Y,Z axis rotations | 5062 | /// </summary> |
5063 | /// <returns></returns> | ||
5064 | /// <param name='rot'></param> | ||
4679 | public LSL_Vector llRot2Axis(LSL_Rotation rot) | 5065 | public LSL_Vector llRot2Axis(LSL_Rotation rot) |
4680 | { | 5066 | { |
4681 | m_host.AddScriptLPS(1); | 5067 | m_host.AddScriptLPS(1); |
4682 | double x,y,z; | ||
4683 | |||
4684 | if (rot.s > 1) // normalization needed | ||
4685 | { | ||
4686 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
4687 | rot.z * rot.z + rot.s * rot.s); | ||
4688 | 5068 | ||
4689 | rot.x /= length; | 5069 | if (Math.Abs(rot.s) > 1) // normalization needed |
4690 | rot.y /= length; | 5070 | rot.Normalize(); |
4691 | rot.z /= length; | ||
4692 | rot.s /= length; | ||
4693 | 5071 | ||
4694 | } | ||
4695 | |||
4696 | // double angle = 2 * Math.Acos(rot.s); | ||
4697 | double s = Math.Sqrt(1 - rot.s * rot.s); | 5072 | double s = Math.Sqrt(1 - rot.s * rot.s); |
4698 | if (s < 0.001) | 5073 | if (s < 0.001) |
4699 | { | 5074 | { |
4700 | x = 1; | 5075 | return new LSL_Vector(1, 0, 0); |
4701 | y = z = 0; | ||
4702 | } | 5076 | } |
4703 | else | 5077 | else |
4704 | { | 5078 | { |
4705 | x = rot.x / s; // normalise axis | 5079 | double invS = 1.0 / s; |
4706 | y = rot.y / s; | 5080 | if (rot.s < 0) invS = -invS; |
4707 | z = rot.z / s; | 5081 | return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS); |
4708 | } | 5082 | } |
4709 | |||
4710 | return new LSL_Vector(x,y,z); | ||
4711 | } | 5083 | } |
4712 | 5084 | ||
4713 | 5085 | ||
@@ -4716,18 +5088,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4716 | { | 5088 | { |
4717 | m_host.AddScriptLPS(1); | 5089 | m_host.AddScriptLPS(1); |
4718 | 5090 | ||
4719 | if (rot.s > 1) // normalization needed | 5091 | if (Math.Abs(rot.s) > 1) // normalization needed |
4720 | { | 5092 | rot.Normalize(); |
4721 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
4722 | rot.z * rot.z + rot.s * rot.s); | ||
4723 | |||
4724 | rot.x /= length; | ||
4725 | rot.y /= length; | ||
4726 | rot.z /= length; | ||
4727 | rot.s /= length; | ||
4728 | } | ||
4729 | 5093 | ||
4730 | double angle = 2 * Math.Acos(rot.s); | 5094 | double angle = 2 * Math.Acos(rot.s); |
5095 | if (angle > Math.PI) | ||
5096 | angle = 2 * Math.PI - angle; | ||
4731 | 5097 | ||
4732 | return angle; | 5098 | return angle; |
4733 | } | 5099 | } |
@@ -4907,8 +5273,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
4907 | public LSL_Vector llGetCenterOfMass() | 5273 | public LSL_Vector llGetCenterOfMass() |
4908 | { | 5274 | { |
4909 | m_host.AddScriptLPS(1); | 5275 | m_host.AddScriptLPS(1); |
4910 | Vector3 center = m_host.GetGeometricCenter(); | 5276 | |
4911 | return new LSL_Vector(center.X,center.Y,center.Z); | 5277 | return new LSL_Vector(m_host.GetCenterOfMass()); |
4912 | } | 5278 | } |
4913 | 5279 | ||
4914 | public LSL_List llListSort(LSL_List src, int stride, int ascending) | 5280 | public LSL_List llListSort(LSL_List src, int stride, int ascending) |
@@ -5043,10 +5409,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5043 | // SL spits out an empty string for types other than key & string | 5409 | // SL spits out an empty string for types other than key & string |
5044 | // At the time of patching, LSL_Key is currently LSL_String, | 5410 | // At the time of patching, LSL_Key is currently LSL_String, |
5045 | // so the OR check may be a little redundant, but it's being done | 5411 | // so the OR check may be a little redundant, but it's being done |
5046 | // for completion and should LSL_Key ever be implemented | 5412 | // for completion and should LSL_Key ever be implemented |
5047 | // as it's own struct | 5413 | // as it's own struct |
5414 | // NOTE: 3rd case is needed because a NULL_KEY comes through as | ||
5415 | // type 'obj' and wrongly returns "" | ||
5048 | else if (!(src.Data[index] is LSL_String || | 5416 | else if (!(src.Data[index] is LSL_String || |
5049 | src.Data[index] is LSL_Key)) | 5417 | src.Data[index] is LSL_Key || |
5418 | src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000")) | ||
5050 | { | 5419 | { |
5051 | return ""; | 5420 | return ""; |
5052 | } | 5421 | } |
@@ -5179,8 +5548,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5179 | { | 5548 | { |
5180 | m_host.AddScriptLPS(1); | 5549 | m_host.AddScriptLPS(1); |
5181 | 5550 | ||
5182 | return string.Join(", ", | 5551 | return string.Join(", ", |
5183 | (new List<object>(src.Data)).ConvertAll<string>(o => | 5552 | (new List<object>(src.Data)).ConvertAll<string>(o => |
5184 | { | 5553 | { |
5185 | return o.ToString(); | 5554 | return o.ToString(); |
5186 | }).ToArray()); | 5555 | }).ToArray()); |
@@ -5254,7 +5623,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5254 | public LSL_List llListRandomize(LSL_List src, int stride) | 5623 | public LSL_List llListRandomize(LSL_List src, int stride) |
5255 | { | 5624 | { |
5256 | LSL_List result; | 5625 | LSL_List result; |
5257 | Random rand = new Random(); | 5626 | BetterRandom rand = new BetterRandom(); |
5258 | 5627 | ||
5259 | int chunkk; | 5628 | int chunkk; |
5260 | int[] chunks; | 5629 | int[] chunks; |
@@ -5270,24 +5639,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5270 | // If not, then return the src list. This also | 5639 | // If not, then return the src list. This also |
5271 | // traps those cases where stride > length. | 5640 | // traps those cases where stride > length. |
5272 | 5641 | ||
5273 | if (src.Length != stride && src.Length%stride == 0) | 5642 | if (src.Length != stride && src.Length % stride == 0) |
5274 | { | 5643 | { |
5275 | chunkk = src.Length/stride; | 5644 | chunkk = src.Length/stride; |
5276 | 5645 | ||
5277 | chunks = new int[chunkk]; | 5646 | chunks = new int[chunkk]; |
5278 | 5647 | ||
5279 | for (int i = 0; i < chunkk; i++) | 5648 | for (int i = 0; i < chunkk; i++) |
5649 | { | ||
5280 | chunks[i] = i; | 5650 | chunks[i] = i; |
5651 | } | ||
5281 | 5652 | ||
5282 | // Knuth shuffle the chunkk index | 5653 | // Knuth shuffle the chunkk index |
5283 | for (int i = chunkk - 1; i >= 1; i--) | 5654 | for (int i = chunkk - 1; i > 0; i--) |
5284 | { | 5655 | { |
5285 | // Elect an unrandomized chunk to swap | 5656 | // Elect an unrandomized chunk to swap |
5286 | int index = rand.Next(i + 1); | 5657 | int index = rand.Next(i + 1); |
5287 | int tmp; | ||
5288 | 5658 | ||
5289 | // and swap position with first unrandomized chunk | 5659 | // and swap position with first unrandomized chunk |
5290 | tmp = chunks[i]; | 5660 | int tmp = chunks[i]; |
5291 | chunks[i] = chunks[index]; | 5661 | chunks[i] = chunks[index]; |
5292 | chunks[index] = tmp; | 5662 | chunks[index] = tmp; |
5293 | } | 5663 | } |
@@ -5300,7 +5670,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5300 | { | 5670 | { |
5301 | for (int j = 0; j < stride; j++) | 5671 | for (int j = 0; j < stride; j++) |
5302 | { | 5672 | { |
5303 | result.Add(src.Data[chunks[i]*stride+j]); | 5673 | result.Add(src.Data[chunks[i] * stride + j]); |
5304 | } | 5674 | } |
5305 | } | 5675 | } |
5306 | } | 5676 | } |
@@ -5417,7 +5787,72 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5417 | public LSL_Vector llGetRegionCorner() | 5787 | public LSL_Vector llGetRegionCorner() |
5418 | { | 5788 | { |
5419 | m_host.AddScriptLPS(1); | 5789 | m_host.AddScriptLPS(1); |
5420 | return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); | 5790 | return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); |
5791 | } | ||
5792 | |||
5793 | public LSL_String llGetEnv(LSL_String name) | ||
5794 | { | ||
5795 | m_host.AddScriptLPS(1); | ||
5796 | if (name == "agent_limit") | ||
5797 | { | ||
5798 | return World.RegionInfo.RegionSettings.AgentLimit.ToString(); | ||
5799 | } | ||
5800 | else if (name == "dynamic_pathfinding") | ||
5801 | { | ||
5802 | return "0"; | ||
5803 | } | ||
5804 | else if (name == "estate_id") | ||
5805 | { | ||
5806 | return World.RegionInfo.EstateSettings.EstateID.ToString(); | ||
5807 | } | ||
5808 | else if (name == "estate_name") | ||
5809 | { | ||
5810 | return World.RegionInfo.EstateSettings.EstateName; | ||
5811 | } | ||
5812 | else if (name == "frame_number") | ||
5813 | { | ||
5814 | return World.Frame.ToString(); | ||
5815 | } | ||
5816 | else if (name == "region_cpu_ratio") | ||
5817 | { | ||
5818 | return "1"; | ||
5819 | } | ||
5820 | else if (name == "region_idle") | ||
5821 | { | ||
5822 | return "0"; | ||
5823 | } | ||
5824 | else if (name == "region_product_name") | ||
5825 | { | ||
5826 | if (World.RegionInfo.RegionType != String.Empty) | ||
5827 | return World.RegionInfo.RegionType; | ||
5828 | else | ||
5829 | return ""; | ||
5830 | } | ||
5831 | else if (name == "region_product_sku") | ||
5832 | { | ||
5833 | return "OpenSim"; | ||
5834 | } | ||
5835 | else if (name == "region_start_time") | ||
5836 | { | ||
5837 | return World.UnixStartTime.ToString(); | ||
5838 | } | ||
5839 | else if (name == "sim_channel") | ||
5840 | { | ||
5841 | return "OpenSim"; | ||
5842 | } | ||
5843 | else if (name == "sim_version") | ||
5844 | { | ||
5845 | return World.GetSimulatorVersion(); | ||
5846 | } | ||
5847 | else if (name == "simulator_hostname") | ||
5848 | { | ||
5849 | IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); | ||
5850 | return UrlModule.ExternalHostNameForLSL; | ||
5851 | } | ||
5852 | else | ||
5853 | { | ||
5854 | return ""; | ||
5855 | } | ||
5421 | } | 5856 | } |
5422 | 5857 | ||
5423 | /// <summary> | 5858 | /// <summary> |
@@ -5429,8 +5864,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5429 | public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) | 5864 | public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) |
5430 | { | 5865 | { |
5431 | 5866 | ||
5432 | LSL_List pref = null; | 5867 | LSL_List pref; |
5433 | LSL_List suff = null; | 5868 | LSL_List suff; |
5434 | 5869 | ||
5435 | m_host.AddScriptLPS(1); | 5870 | m_host.AddScriptLPS(1); |
5436 | 5871 | ||
@@ -5564,7 +5999,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5564 | LSL_Float mag; | 5999 | LSL_Float mag; |
5565 | if (dir.x > 0) | 6000 | if (dir.x > 0) |
5566 | { | 6001 | { |
5567 | mag = (Constants.RegionSize - pos.x) / dir.x; | 6002 | mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x; |
5568 | } | 6003 | } |
5569 | else | 6004 | else |
5570 | { | 6005 | { |
@@ -5575,7 +6010,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5575 | 6010 | ||
5576 | edge.y = pos.y + (dir.y * mag); | 6011 | edge.y = pos.y + (dir.y * mag); |
5577 | 6012 | ||
5578 | if (edge.y > Constants.RegionSize || edge.y < 0) | 6013 | if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0) |
5579 | { | 6014 | { |
5580 | // Y goes out of bounds first | 6015 | // Y goes out of bounds first |
5581 | edge.y = dir.y / Math.Abs(dir.y); | 6016 | edge.y = dir.y / Math.Abs(dir.y); |
@@ -5704,12 +6139,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5704 | 6139 | ||
5705 | public LSL_String llGetAgentLanguage(string id) | 6140 | public LSL_String llGetAgentLanguage(string id) |
5706 | { | 6141 | { |
5707 | // This should only return a value if the avatar is in the same region | 6142 | // This should only return a value if the avatar is in the same region, but eh. idc. |
5708 | //ckrinke 1-30-09 : This needs to parse the XMLRPC language field supplied | ||
5709 | //by the client at login. Currently returning only en-us until our I18N | ||
5710 | //effort gains momentum | ||
5711 | m_host.AddScriptLPS(1); | 6143 | m_host.AddScriptLPS(1); |
5712 | return "en-us"; | 6144 | if (World.AgentPreferencesService == null) |
6145 | { | ||
6146 | Error("llGetAgentLanguage", "No AgentPreferencesService present"); | ||
6147 | } | ||
6148 | else | ||
6149 | { | ||
6150 | UUID key = new UUID(); | ||
6151 | if (UUID.TryParse(id, out key)) | ||
6152 | { | ||
6153 | return new LSL_String(World.AgentPreferencesService.GetLang(key)); | ||
6154 | } | ||
6155 | } | ||
6156 | return new LSL_String("en-us"); | ||
5713 | } | 6157 | } |
5714 | /// <summary> | 6158 | /// <summary> |
5715 | /// http://wiki.secondlife.com/wiki/LlGetAgentList | 6159 | /// http://wiki.secondlife.com/wiki/LlGetAgentList |
@@ -5739,12 +6183,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5739 | } | 6183 | } |
5740 | 6184 | ||
5741 | ILandObject land; | 6185 | ILandObject land; |
5742 | Vector3 pos; | ||
5743 | UUID id = UUID.Zero; | 6186 | UUID id = UUID.Zero; |
6187 | |||
5744 | if (parcel || parcelOwned) | 6188 | if (parcel || parcelOwned) |
5745 | { | 6189 | { |
5746 | pos = m_host.ParentGroup.RootPart.GetWorldPosition(); | 6190 | land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition()); |
5747 | land = World.LandChannel.GetLandObject(pos.X, pos.Y); | ||
5748 | if (land == null) | 6191 | if (land == null) |
5749 | { | 6192 | { |
5750 | id = UUID.Zero; | 6193 | id = UUID.Zero; |
@@ -5770,8 +6213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5770 | { | 6213 | { |
5771 | if (!regionWide) | 6214 | if (!regionWide) |
5772 | { | 6215 | { |
5773 | pos = ssp.AbsolutePosition; | 6216 | land = World.LandChannel.GetLandObject(ssp.AbsolutePosition); |
5774 | land = World.LandChannel.GetLandObject(pos.X, pos.Y); | ||
5775 | if (land != null) | 6217 | if (land != null) |
5776 | { | 6218 | { |
5777 | if (parcelOwned && land.LandData.OwnerID == id || | 6219 | if (parcelOwned && land.LandData.OwnerID == id || |
@@ -5800,7 +6242,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5800 | { | 6242 | { |
5801 | m_host.AddScriptLPS(1); | 6243 | m_host.AddScriptLPS(1); |
5802 | m_host.AdjustSoundGain(volume); | 6244 | m_host.AdjustSoundGain(volume); |
5803 | ScriptSleep(100); | 6245 | ScriptSleep(m_sleepMsOnAdjustSoundVolume); |
5804 | } | 6246 | } |
5805 | 6247 | ||
5806 | public void llSetSoundRadius(double radius) | 6248 | public void llSetSoundRadius(double radius) |
@@ -5881,7 +6323,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5881 | if (m_SoundModule != null) | 6323 | if (m_SoundModule != null) |
5882 | { | 6324 | { |
5883 | m_SoundModule.TriggerSoundLimited(m_host.UUID, | 6325 | m_SoundModule.TriggerSoundLimited(m_host.UUID, |
5884 | KeyOrName(sound, AssetType.Sound), volume, | 6326 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, |
5885 | bottom_south_west, top_north_east); | 6327 | bottom_south_west, top_north_east); |
5886 | } | 6328 | } |
5887 | } | 6329 | } |
@@ -5896,7 +6338,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5896 | if (presence != null) | 6338 | if (presence != null) |
5897 | { | 6339 | { |
5898 | // agent must be over the owners land | 6340 | // agent must be over the owners land |
5899 | ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition.X, presence.AbsolutePosition.Y); | 6341 | ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition); |
5900 | if (land == null) | 6342 | if (land == null) |
5901 | return; | 6343 | return; |
5902 | 6344 | ||
@@ -5906,7 +6348,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5906 | } | 6348 | } |
5907 | } | 6349 | } |
5908 | } | 6350 | } |
5909 | ScriptSleep(5000); | 6351 | ScriptSleep(m_sleepMsOnEjectFromLand); |
5910 | } | 6352 | } |
5911 | 6353 | ||
5912 | public LSL_Integer llOverMyLand(string id) | 6354 | public LSL_Integer llOverMyLand(string id) |
@@ -5918,19 +6360,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5918 | ScenePresence presence = World.GetScenePresence(key); | 6360 | ScenePresence presence = World.GetScenePresence(key); |
5919 | if (presence != null) // object is an avatar | 6361 | if (presence != null) // object is an avatar |
5920 | { | 6362 | { |
5921 | if (m_host.OwnerID | 6363 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
5922 | == World.LandChannel.GetLandObject( | ||
5923 | presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) | ||
5924 | return 1; | 6364 | return 1; |
5925 | } | 6365 | } |
5926 | else // object is not an avatar | 6366 | else // object is not an avatar |
5927 | { | 6367 | { |
5928 | SceneObjectPart obj = World.GetSceneObjectPart(key); | 6368 | SceneObjectPart obj = World.GetSceneObjectPart(key); |
6369 | |||
5929 | if (obj != null) | 6370 | if (obj != null) |
5930 | if (m_host.OwnerID | 6371 | { |
5931 | == World.LandChannel.GetLandObject( | 6372 | if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID) |
5932 | obj.AbsolutePosition.X, obj.AbsolutePosition.Y).LandData.OwnerID) | ||
5933 | return 1; | 6373 | return 1; |
6374 | } | ||
5934 | } | 6375 | } |
5935 | } | 6376 | } |
5936 | 6377 | ||
@@ -5962,8 +6403,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5962 | } | 6403 | } |
5963 | else | 6404 | else |
5964 | { | 6405 | { |
5965 | agentSize = new LSL_Vector(0.45, 0.6, avatar.Appearance.AvatarHeight); | 6406 | agentSize = GetAgentSize(avatar); |
5966 | } | 6407 | } |
6408 | |||
5967 | return agentSize; | 6409 | return agentSize; |
5968 | } | 6410 | } |
5969 | 6411 | ||
@@ -5991,10 +6433,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
5991 | if (UUID.TryParse(id, out key)) | 6433 | if (UUID.TryParse(id, out key)) |
5992 | { | 6434 | { |
5993 | ScenePresence av = World.GetScenePresence(key); | 6435 | ScenePresence av = World.GetScenePresence(key); |
6436 | List<ScenePresence> sittingAvatars = m_host.ParentGroup.GetSittingAvatars(); | ||
5994 | 6437 | ||
5995 | if (av != null) | 6438 | if (av != null) |
5996 | { | 6439 | { |
5997 | if (llAvatarOnSitTarget() == id) | 6440 | if (sittingAvatars.Contains(av)) |
5998 | { | 6441 | { |
5999 | // if the avatar is sitting on this object, then | 6442 | // if the avatar is sitting on this object, then |
6000 | // we can unsit them. We don't want random scripts unsitting random people | 6443 | // we can unsit them. We don't want random scripts unsitting random people |
@@ -6008,8 +6451,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6008 | // if the land is group owned and the object is group owned by the same group | 6451 | // if the land is group owned and the object is group owned by the same group |
6009 | // or | 6452 | // or |
6010 | // if the object is owned by a person with estate access. | 6453 | // if the object is owned by a person with estate access. |
6011 | 6454 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition); | |
6012 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y); | ||
6013 | if (parcel != null) | 6455 | if (parcel != null) |
6014 | { | 6456 | { |
6015 | if (m_host.OwnerID == parcel.LandData.OwnerID || | 6457 | if (m_host.OwnerID == parcel.LandData.OwnerID || |
@@ -6021,14 +6463,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6021 | } | 6463 | } |
6022 | } | 6464 | } |
6023 | } | 6465 | } |
6024 | |||
6025 | } | 6466 | } |
6026 | |||
6027 | } | 6467 | } |
6028 | 6468 | ||
6029 | public LSL_Vector llGroundSlope(LSL_Vector offset) | 6469 | public LSL_Vector llGroundSlope(LSL_Vector offset) |
6030 | { | 6470 | { |
6031 | m_host.AddScriptLPS(1); | 6471 | m_host.AddScriptLPS(1); |
6472 | |||
6032 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. | 6473 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. |
6033 | LSL_Vector vsn = llGroundNormal(offset); | 6474 | LSL_Vector vsn = llGroundNormal(offset); |
6034 | 6475 | ||
@@ -6039,7 +6480,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6039 | vsl.Normalize(); | 6480 | vsl.Normalize(); |
6040 | //Normalization might be overkill here | 6481 | //Normalization might be overkill here |
6041 | 6482 | ||
6042 | return new LSL_Vector(vsl.X, vsl.Y, vsl.Z); | 6483 | vsn.x = vsl.X; |
6484 | vsn.y = vsl.Y; | ||
6485 | vsn.z = vsl.Z; | ||
6486 | |||
6487 | return vsn; | ||
6043 | } | 6488 | } |
6044 | 6489 | ||
6045 | public LSL_Vector llGroundNormal(LSL_Vector offset) | 6490 | public LSL_Vector llGroundNormal(LSL_Vector offset) |
@@ -6089,7 +6534,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6089 | //I believe the crossproduct of two normalized vectors is a normalized vector so | 6534 | //I believe the crossproduct of two normalized vectors is a normalized vector so |
6090 | //this normalization may be overkill | 6535 | //this normalization may be overkill |
6091 | 6536 | ||
6092 | return new LSL_Vector(vsn.X, vsn.Y, vsn.Z); | 6537 | return new LSL_Vector(vsn); |
6093 | } | 6538 | } |
6094 | 6539 | ||
6095 | public LSL_Vector llGroundContour(LSL_Vector offset) | 6540 | public LSL_Vector llGroundContour(LSL_Vector offset) |
@@ -6105,11 +6550,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6105 | return m_host.ParentGroup.AttachmentPoint; | 6550 | return m_host.ParentGroup.AttachmentPoint; |
6106 | } | 6551 | } |
6107 | 6552 | ||
6108 | public LSL_Integer llGetFreeMemory() | 6553 | public virtual LSL_Integer llGetFreeMemory() |
6109 | { | 6554 | { |
6110 | m_host.AddScriptLPS(1); | 6555 | m_host.AddScriptLPS(1); |
6111 | // Make scripts designed for LSO happy | 6556 | // Make scripts designed for Mono happy |
6112 | return 16384; | 6557 | return 65536; |
6113 | } | 6558 | } |
6114 | 6559 | ||
6115 | public LSL_Integer llGetFreeURLs() | 6560 | public LSL_Integer llGetFreeURLs() |
@@ -6176,7 +6621,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6176 | PSYS_SRC_TARGET_KEY = 20, | 6621 | PSYS_SRC_TARGET_KEY = 20, |
6177 | PSYS_SRC_OMEGA = 21, | 6622 | PSYS_SRC_OMEGA = 21, |
6178 | PSYS_SRC_ANGLE_BEGIN = 22, | 6623 | PSYS_SRC_ANGLE_BEGIN = 22, |
6179 | PSYS_SRC_ANGLE_END = 23 | 6624 | PSYS_SRC_ANGLE_END = 23, |
6625 | PSYS_PART_BLEND_FUNC_SOURCE = 24, | ||
6626 | PSYS_PART_BLEND_FUNC_DEST = 25, | ||
6627 | PSYS_PART_START_GLOW = 26, | ||
6628 | PSYS_PART_END_GLOW = 27 | ||
6180 | } | 6629 | } |
6181 | 6630 | ||
6182 | internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) | 6631 | internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) |
@@ -6202,6 +6651,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6202 | ps.BurstRate = 0.1f; | 6651 | ps.BurstRate = 0.1f; |
6203 | ps.PartMaxAge = 10.0f; | 6652 | ps.PartMaxAge = 10.0f; |
6204 | ps.BurstPartCount = 1; | 6653 | ps.BurstPartCount = 1; |
6654 | ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA; | ||
6655 | ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA; | ||
6656 | ps.PartStartGlow = 0.0f; | ||
6657 | ps.PartEndGlow = 0.0f; | ||
6658 | |||
6205 | return ps; | 6659 | return ps; |
6206 | } | 6660 | } |
6207 | 6661 | ||
@@ -6213,17 +6667,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6213 | 6667 | ||
6214 | foreach (SceneObjectPart part in parts) | 6668 | foreach (SceneObjectPart part in parts) |
6215 | { | 6669 | { |
6216 | SetParticleSystem(part, rules); | 6670 | SetParticleSystem(part, rules, "llLinkParticleSystem"); |
6217 | } | 6671 | } |
6218 | } | 6672 | } |
6219 | 6673 | ||
6220 | public void llParticleSystem(LSL_List rules) | 6674 | public void llParticleSystem(LSL_List rules) |
6221 | { | 6675 | { |
6222 | m_host.AddScriptLPS(1); | 6676 | m_host.AddScriptLPS(1); |
6223 | SetParticleSystem(m_host, rules); | 6677 | SetParticleSystem(m_host, rules, "llParticleSystem"); |
6224 | } | 6678 | } |
6225 | 6679 | ||
6226 | private void SetParticleSystem(SceneObjectPart part, LSL_List rules) | 6680 | private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc) |
6227 | { | 6681 | { |
6228 | if (rules.Length == 0) | 6682 | if (rules.Length == 0) |
6229 | { | 6683 | { |
@@ -6236,65 +6690,156 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6236 | LSL_Vector tempv = new LSL_Vector(); | 6690 | LSL_Vector tempv = new LSL_Vector(); |
6237 | 6691 | ||
6238 | float tempf = 0; | 6692 | float tempf = 0; |
6693 | int tmpi = 0; | ||
6239 | 6694 | ||
6240 | for (int i = 0; i < rules.Length; i += 2) | 6695 | for (int i = 0; i < rules.Length; i += 2) |
6241 | { | 6696 | { |
6242 | switch (rules.GetLSLIntegerItem(i)) | 6697 | int psystype; |
6698 | try | ||
6699 | { | ||
6700 | psystype = rules.GetLSLIntegerItem(i); | ||
6701 | } | ||
6702 | catch (InvalidCastException) | ||
6703 | { | ||
6704 | Error(originFunc, string.Format("Error running particle system params index #{0}: particle system parameter type must be integer", i)); | ||
6705 | return; | ||
6706 | } | ||
6707 | switch (psystype) | ||
6243 | { | 6708 | { |
6244 | case (int)ScriptBaseClass.PSYS_PART_FLAGS: | 6709 | case (int)ScriptBaseClass.PSYS_PART_FLAGS: |
6245 | prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); | 6710 | try |
6711 | { | ||
6712 | prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); | ||
6713 | } | ||
6714 | catch(InvalidCastException) | ||
6715 | { | ||
6716 | Error(originFunc, string.Format("Error running rule PSYS_PART_FLAGS: arg #{0} - parameter 1 must be integer", i + 1)); | ||
6717 | return; | ||
6718 | } | ||
6246 | break; | 6719 | break; |
6247 | 6720 | ||
6248 | case (int)ScriptBaseClass.PSYS_PART_START_COLOR: | 6721 | case (int)ScriptBaseClass.PSYS_PART_START_COLOR: |
6249 | tempv = rules.GetVector3Item(i + 1); | 6722 | try |
6723 | { | ||
6724 | tempv = rules.GetVector3Item(i + 1); | ||
6725 | } | ||
6726 | catch(InvalidCastException) | ||
6727 | { | ||
6728 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); | ||
6729 | return; | ||
6730 | } | ||
6250 | prules.PartStartColor.R = (float)tempv.x; | 6731 | prules.PartStartColor.R = (float)tempv.x; |
6251 | prules.PartStartColor.G = (float)tempv.y; | 6732 | prules.PartStartColor.G = (float)tempv.y; |
6252 | prules.PartStartColor.B = (float)tempv.z; | 6733 | prules.PartStartColor.B = (float)tempv.z; |
6253 | break; | 6734 | break; |
6254 | 6735 | ||
6255 | case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: | 6736 | case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: |
6256 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6737 | try |
6738 | { | ||
6739 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6740 | } | ||
6741 | catch(InvalidCastException) | ||
6742 | { | ||
6743 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); | ||
6744 | return; | ||
6745 | } | ||
6257 | prules.PartStartColor.A = tempf; | 6746 | prules.PartStartColor.A = tempf; |
6258 | break; | 6747 | break; |
6259 | 6748 | ||
6260 | case (int)ScriptBaseClass.PSYS_PART_END_COLOR: | 6749 | case (int)ScriptBaseClass.PSYS_PART_END_COLOR: |
6261 | tempv = rules.GetVector3Item(i + 1); | 6750 | try |
6751 | { | ||
6752 | tempv = rules.GetVector3Item(i + 1); | ||
6753 | } | ||
6754 | catch(InvalidCastException) | ||
6755 | { | ||
6756 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); | ||
6757 | return; | ||
6758 | } | ||
6262 | prules.PartEndColor.R = (float)tempv.x; | 6759 | prules.PartEndColor.R = (float)tempv.x; |
6263 | prules.PartEndColor.G = (float)tempv.y; | 6760 | prules.PartEndColor.G = (float)tempv.y; |
6264 | prules.PartEndColor.B = (float)tempv.z; | 6761 | prules.PartEndColor.B = (float)tempv.z; |
6265 | break; | 6762 | break; |
6266 | 6763 | ||
6267 | case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: | 6764 | case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: |
6268 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6765 | try |
6766 | { | ||
6767 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6768 | } | ||
6769 | catch(InvalidCastException) | ||
6770 | { | ||
6771 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); | ||
6772 | return; | ||
6773 | } | ||
6269 | prules.PartEndColor.A = tempf; | 6774 | prules.PartEndColor.A = tempf; |
6270 | break; | 6775 | break; |
6271 | 6776 | ||
6272 | case (int)ScriptBaseClass.PSYS_PART_START_SCALE: | 6777 | case (int)ScriptBaseClass.PSYS_PART_START_SCALE: |
6273 | tempv = rules.GetVector3Item(i + 1); | 6778 | try |
6274 | prules.PartStartScaleX = (float)tempv.x; | 6779 | { |
6275 | prules.PartStartScaleY = (float)tempv.y; | 6780 | tempv = rules.GetVector3Item(i + 1); |
6781 | } | ||
6782 | catch(InvalidCastException) | ||
6783 | { | ||
6784 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); | ||
6785 | return; | ||
6786 | } | ||
6787 | prules.PartStartScaleX = validParticleScale((float)tempv.x); | ||
6788 | prules.PartStartScaleY = validParticleScale((float)tempv.y); | ||
6276 | break; | 6789 | break; |
6277 | 6790 | ||
6278 | case (int)ScriptBaseClass.PSYS_PART_END_SCALE: | 6791 | case (int)ScriptBaseClass.PSYS_PART_END_SCALE: |
6279 | tempv = rules.GetVector3Item(i + 1); | 6792 | try |
6280 | prules.PartEndScaleX = (float)tempv.x; | 6793 | { |
6281 | prules.PartEndScaleY = (float)tempv.y; | 6794 | tempv = rules.GetVector3Item(i + 1); |
6795 | } | ||
6796 | catch(InvalidCastException) | ||
6797 | { | ||
6798 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); | ||
6799 | return; | ||
6800 | } | ||
6801 | prules.PartEndScaleX = validParticleScale((float)tempv.x); | ||
6802 | prules.PartEndScaleY = validParticleScale((float)tempv.y); | ||
6282 | break; | 6803 | break; |
6283 | 6804 | ||
6284 | case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: | 6805 | case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: |
6285 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6806 | try |
6807 | { | ||
6808 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6809 | } | ||
6810 | catch(InvalidCastException) | ||
6811 | { | ||
6812 | Error(originFunc, string.Format("Error running rule PSYS_PART_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); | ||
6813 | return; | ||
6814 | } | ||
6286 | prules.PartMaxAge = tempf; | 6815 | prules.PartMaxAge = tempf; |
6287 | break; | 6816 | break; |
6288 | 6817 | ||
6289 | case (int)ScriptBaseClass.PSYS_SRC_ACCEL: | 6818 | case (int)ScriptBaseClass.PSYS_SRC_ACCEL: |
6290 | tempv = rules.GetVector3Item(i + 1); | 6819 | try |
6820 | { | ||
6821 | tempv = rules.GetVector3Item(i + 1); | ||
6822 | } | ||
6823 | catch(InvalidCastException) | ||
6824 | { | ||
6825 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ACCEL: arg #{0} - parameter 1 must be vector", i + 1)); | ||
6826 | return; | ||
6827 | } | ||
6291 | prules.PartAcceleration.X = (float)tempv.x; | 6828 | prules.PartAcceleration.X = (float)tempv.x; |
6292 | prules.PartAcceleration.Y = (float)tempv.y; | 6829 | prules.PartAcceleration.Y = (float)tempv.y; |
6293 | prules.PartAcceleration.Z = (float)tempv.z; | 6830 | prules.PartAcceleration.Z = (float)tempv.z; |
6294 | break; | 6831 | break; |
6295 | 6832 | ||
6296 | case (int)ScriptBaseClass.PSYS_SRC_PATTERN: | 6833 | case (int)ScriptBaseClass.PSYS_SRC_PATTERN: |
6297 | int tmpi = (int)rules.GetLSLIntegerItem(i + 1); | 6834 | try |
6835 | { | ||
6836 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); | ||
6837 | } | ||
6838 | catch(InvalidCastException) | ||
6839 | { | ||
6840 | Error(originFunc, string.Format("Error running rule PSYS_SRC_PATTERN: arg #{0} - parameter 1 must be integer", i + 1)); | ||
6841 | return; | ||
6842 | } | ||
6298 | prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; | 6843 | prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; |
6299 | break; | 6844 | break; |
6300 | 6845 | ||
@@ -6303,47 +6848,171 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6303 | // client tells the difference between the two by looking at the 0x02 bit in | 6848 | // client tells the difference between the two by looking at the 0x02 bit in |
6304 | // the PartFlags variable. | 6849 | // the PartFlags variable. |
6305 | case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: | 6850 | case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: |
6306 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6851 | try |
6852 | { | ||
6853 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6854 | } | ||
6855 | catch(InvalidCastException) | ||
6856 | { | ||
6857 | Error(originFunc, string.Format("Error running rule PSYS_SRC_INNERANGLE: arg #{0} - parameter 1 must be float", i + 1)); | ||
6858 | return; | ||
6859 | } | ||
6307 | prules.InnerAngle = (float)tempf; | 6860 | prules.InnerAngle = (float)tempf; |
6308 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. | 6861 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. |
6309 | break; | 6862 | break; |
6310 | 6863 | ||
6311 | case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: | 6864 | case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: |
6312 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6865 | try |
6866 | { | ||
6867 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6868 | } | ||
6869 | catch(InvalidCastException) | ||
6870 | { | ||
6871 | Error(originFunc, string.Format("Error running rule PSYS_SRC_OUTERANGLE: arg #{0} - parameter 1 must be float", i + 1)); | ||
6872 | return; | ||
6873 | } | ||
6313 | prules.OuterAngle = (float)tempf; | 6874 | prules.OuterAngle = (float)tempf; |
6314 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. | 6875 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. |
6315 | break; | 6876 | break; |
6316 | 6877 | ||
6878 | case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE: | ||
6879 | try | ||
6880 | { | ||
6881 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); | ||
6882 | } | ||
6883 | catch(InvalidCastException) | ||
6884 | { | ||
6885 | Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_SOURCE: arg #{0} - parameter 1 must be integer", i + 1)); | ||
6886 | return; | ||
6887 | } | ||
6888 | prules.BlendFuncSource = (byte)tmpi; | ||
6889 | break; | ||
6890 | |||
6891 | case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST: | ||
6892 | try | ||
6893 | { | ||
6894 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); | ||
6895 | } | ||
6896 | catch(InvalidCastException) | ||
6897 | { | ||
6898 | Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_DEST: arg #{0} - parameter 1 must be integer", i + 1)); | ||
6899 | return; | ||
6900 | } | ||
6901 | prules.BlendFuncDest = (byte)tmpi; | ||
6902 | break; | ||
6903 | |||
6904 | case (int)ScriptBaseClass.PSYS_PART_START_GLOW: | ||
6905 | try | ||
6906 | { | ||
6907 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6908 | } | ||
6909 | catch(InvalidCastException) | ||
6910 | { | ||
6911 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_GLOW: arg #{0} - parameter 1 must be float", i + 1)); | ||
6912 | return; | ||
6913 | } | ||
6914 | prules.PartStartGlow = (float)tempf; | ||
6915 | break; | ||
6916 | |||
6917 | case (int)ScriptBaseClass.PSYS_PART_END_GLOW: | ||
6918 | try | ||
6919 | { | ||
6920 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6921 | } | ||
6922 | catch(InvalidCastException) | ||
6923 | { | ||
6924 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_GLOW: arg #{0} - parameter 1 must be float", i + 1)); | ||
6925 | return; | ||
6926 | } | ||
6927 | prules.PartEndGlow = (float)tempf; | ||
6928 | break; | ||
6929 | |||
6317 | case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: | 6930 | case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: |
6318 | prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1)); | 6931 | try |
6932 | { | ||
6933 | prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1)); | ||
6934 | } | ||
6935 | catch(InvalidCastException) | ||
6936 | { | ||
6937 | Error(originFunc, string.Format("Error running rule PSYS_SRC_TEXTURE: arg #{0} - parameter 1 must be string or key", i + 1)); | ||
6938 | return; | ||
6939 | } | ||
6319 | break; | 6940 | break; |
6320 | 6941 | ||
6321 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: | 6942 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: |
6322 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6943 | try |
6944 | { | ||
6945 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6946 | } | ||
6947 | catch(InvalidCastException) | ||
6948 | { | ||
6949 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RATE: arg #{0} - parameter 1 must be float", i + 1)); | ||
6950 | return; | ||
6951 | } | ||
6323 | prules.BurstRate = (float)tempf; | 6952 | prules.BurstRate = (float)tempf; |
6324 | break; | 6953 | break; |
6325 | 6954 | ||
6326 | case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: | 6955 | case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: |
6327 | prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); | 6956 | try |
6957 | { | ||
6958 | prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); | ||
6959 | } | ||
6960 | catch(InvalidCastException) | ||
6961 | { | ||
6962 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_PART_COUNT: arg #{0} - parameter 1 must be integer", i + 1)); | ||
6963 | return; | ||
6964 | } | ||
6328 | break; | 6965 | break; |
6329 | 6966 | ||
6330 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: | 6967 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: |
6331 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6968 | try |
6969 | { | ||
6970 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6971 | } | ||
6972 | catch(InvalidCastException) | ||
6973 | { | ||
6974 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RADIUS: arg #{0} - parameter 1 must be float", i + 1)); | ||
6975 | return; | ||
6976 | } | ||
6332 | prules.BurstRadius = (float)tempf; | 6977 | prules.BurstRadius = (float)tempf; |
6333 | break; | 6978 | break; |
6334 | 6979 | ||
6335 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: | 6980 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: |
6336 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6981 | try |
6982 | { | ||
6983 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6984 | } | ||
6985 | catch(InvalidCastException) | ||
6986 | { | ||
6987 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MIN: arg #{0} - parameter 1 must be float", i + 1)); | ||
6988 | return; | ||
6989 | } | ||
6337 | prules.BurstSpeedMin = (float)tempf; | 6990 | prules.BurstSpeedMin = (float)tempf; |
6338 | break; | 6991 | break; |
6339 | 6992 | ||
6340 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: | 6993 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: |
6341 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6994 | try |
6995 | { | ||
6996 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
6997 | } | ||
6998 | catch(InvalidCastException) | ||
6999 | { | ||
7000 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MAX: arg #{0} - parameter 1 must be float", i + 1)); | ||
7001 | return; | ||
7002 | } | ||
6342 | prules.BurstSpeedMax = (float)tempf; | 7003 | prules.BurstSpeedMax = (float)tempf; |
6343 | break; | 7004 | break; |
6344 | 7005 | ||
6345 | case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: | 7006 | case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: |
6346 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7007 | try |
7008 | { | ||
7009 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
7010 | } | ||
7011 | catch(InvalidCastException) | ||
7012 | { | ||
7013 | Error(originFunc, string.Format("Error running rule PSYS_SRC_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); | ||
7014 | return; | ||
7015 | } | ||
6347 | prules.MaxAge = (float)tempf; | 7016 | prules.MaxAge = (float)tempf; |
6348 | break; | 7017 | break; |
6349 | 7018 | ||
@@ -6361,20 +7030,44 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6361 | 7030 | ||
6362 | case (int)ScriptBaseClass.PSYS_SRC_OMEGA: | 7031 | case (int)ScriptBaseClass.PSYS_SRC_OMEGA: |
6363 | // AL: This is an assumption, since it is the only thing that would match. | 7032 | // AL: This is an assumption, since it is the only thing that would match. |
6364 | tempv = rules.GetVector3Item(i + 1); | 7033 | try |
7034 | { | ||
7035 | tempv = rules.GetVector3Item(i + 1); | ||
7036 | } | ||
7037 | catch(InvalidCastException) | ||
7038 | { | ||
7039 | Error(originFunc, string.Format("Error running rule PSYS_SRC_OMEGA: arg #{0} - parameter 1 must be vector", i + 1)); | ||
7040 | return; | ||
7041 | } | ||
6365 | prules.AngularVelocity.X = (float)tempv.x; | 7042 | prules.AngularVelocity.X = (float)tempv.x; |
6366 | prules.AngularVelocity.Y = (float)tempv.y; | 7043 | prules.AngularVelocity.Y = (float)tempv.y; |
6367 | prules.AngularVelocity.Z = (float)tempv.z; | 7044 | prules.AngularVelocity.Z = (float)tempv.z; |
6368 | break; | 7045 | break; |
6369 | 7046 | ||
6370 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: | 7047 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: |
6371 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7048 | try |
7049 | { | ||
7050 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
7051 | } | ||
7052 | catch(InvalidCastException) | ||
7053 | { | ||
7054 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_BEGIN: arg #{0} - parameter 1 must be float", i + 1)); | ||
7055 | return; | ||
7056 | } | ||
6372 | prules.InnerAngle = (float)tempf; | 7057 | prules.InnerAngle = (float)tempf; |
6373 | prules.PartFlags |= 0x02; // Set new angle format. | 7058 | prules.PartFlags |= 0x02; // Set new angle format. |
6374 | break; | 7059 | break; |
6375 | 7060 | ||
6376 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: | 7061 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: |
6377 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7062 | try |
7063 | { | ||
7064 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
7065 | } | ||
7066 | catch (InvalidCastException) | ||
7067 | { | ||
7068 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_END: arg #{0} - parameter 1 must be float", i + 1)); | ||
7069 | return; | ||
7070 | } | ||
6378 | prules.OuterAngle = (float)tempf; | 7071 | prules.OuterAngle = (float)tempf; |
6379 | prules.PartFlags |= 0x02; // Set new angle format. | 7072 | prules.PartFlags |= 0x02; // Set new angle format. |
6380 | break; | 7073 | break; |
@@ -6389,6 +7082,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6389 | part.SendFullUpdateToAllClients(); | 7082 | part.SendFullUpdateToAllClients(); |
6390 | } | 7083 | } |
6391 | 7084 | ||
7085 | private float validParticleScale(float value) | ||
7086 | { | ||
7087 | if (value > 4.0f) return 4.0f; | ||
7088 | return value; | ||
7089 | } | ||
7090 | |||
6392 | public void llGroundRepel(double height, int water, double tau) | 7091 | public void llGroundRepel(double height, int water, double tau) |
6393 | { | 7092 | { |
6394 | m_host.AddScriptLPS(1); | 7093 | m_host.AddScriptLPS(1); |
@@ -6460,7 +7159,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6460 | m_host.OwnerID, m_host.Name, destID, | 7159 | m_host.OwnerID, m_host.Name, destID, |
6461 | (byte)InstantMessageDialog.TaskInventoryOffered, | 7160 | (byte)InstantMessageDialog.TaskInventoryOffered, |
6462 | false, string.Format("'{0}'", category), | 7161 | false, string.Format("'{0}'", category), |
6463 | // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 | 7162 | // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 |
6464 | // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), | 7163 | // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), |
6465 | folderID, false, pos, | 7164 | folderID, false, pos, |
6466 | bucket, false); | 7165 | bucket, false); |
@@ -6575,12 +7274,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6575 | public LSL_String llAvatarOnLinkSitTarget(int linknum) | 7274 | public LSL_String llAvatarOnLinkSitTarget(int linknum) |
6576 | { | 7275 | { |
6577 | m_host.AddScriptLPS(1); | 7276 | m_host.AddScriptLPS(1); |
6578 | if(linknum == ScriptBaseClass.LINK_SET || | 7277 | if(linknum == ScriptBaseClass.LINK_SET || |
6579 | linknum == ScriptBaseClass.LINK_ALL_CHILDREN || | 7278 | linknum == ScriptBaseClass.LINK_ALL_CHILDREN || |
6580 | linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); | 7279 | linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); |
6581 | 7280 | ||
6582 | List<SceneObjectPart> parts = GetLinkParts(linknum); | 7281 | List<SceneObjectPart> parts = GetLinkParts(linknum); |
6583 | if (parts.Count == 0) return UUID.Zero.ToString(); | 7282 | if (parts.Count == 0) return UUID.Zero.ToString(); |
6584 | return parts[0].SitTargetAvatar.ToString(); | 7283 | return parts[0].SitTargetAvatar.ToString(); |
6585 | } | 7284 | } |
6586 | 7285 | ||
@@ -6589,7 +7288,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6589 | { | 7288 | { |
6590 | m_host.AddScriptLPS(1); | 7289 | m_host.AddScriptLPS(1); |
6591 | UUID key; | 7290 | UUID key; |
6592 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 7291 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
7292 | |||
6593 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 7293 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
6594 | { | 7294 | { |
6595 | int expires = 0; | 7295 | int expires = 0; |
@@ -6623,7 +7323,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6623 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | 7323 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); |
6624 | } | 7324 | } |
6625 | } | 7325 | } |
6626 | ScriptSleep(100); | 7326 | ScriptSleep(m_sleepMsOnAddToLandPassList); |
6627 | } | 7327 | } |
6628 | 7328 | ||
6629 | public void llSetTouchText(string text) | 7329 | public void llSetTouchText(string text) |
@@ -6642,12 +7342,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6642 | { | 7342 | { |
6643 | m_host.AddScriptLPS(1); | 7343 | m_host.AddScriptLPS(1); |
6644 | m_host.SetCameraEyeOffset(offset); | 7344 | m_host.SetCameraEyeOffset(offset); |
7345 | |||
7346 | if (m_host.ParentGroup.RootPart.GetCameraEyeOffset() == Vector3.Zero) | ||
7347 | m_host.ParentGroup.RootPart.SetCameraEyeOffset(offset); | ||
6645 | } | 7348 | } |
6646 | 7349 | ||
6647 | public void llSetCameraAtOffset(LSL_Vector offset) | 7350 | public void llSetCameraAtOffset(LSL_Vector offset) |
6648 | { | 7351 | { |
6649 | m_host.AddScriptLPS(1); | 7352 | m_host.AddScriptLPS(1); |
6650 | m_host.SetCameraAtOffset(offset); | 7353 | m_host.SetCameraAtOffset(offset); |
7354 | |||
7355 | if (m_host.ParentGroup.RootPart.GetCameraAtOffset() == Vector3.Zero) | ||
7356 | m_host.ParentGroup.RootPart.SetCameraAtOffset(offset); | ||
6651 | } | 7357 | } |
6652 | 7358 | ||
6653 | public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at) | 7359 | public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at) |
@@ -6722,17 +7428,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6722 | UUID av = new UUID(); | 7428 | UUID av = new UUID(); |
6723 | if (!UUID.TryParse(avatar,out av)) | 7429 | if (!UUID.TryParse(avatar,out av)) |
6724 | { | 7430 | { |
6725 | LSLError("First parameter to llDialog needs to be a key"); | 7431 | Error("llDialog", "First parameter must be a key"); |
6726 | return; | 7432 | return; |
6727 | } | 7433 | } |
6728 | if (buttons.Length < 1) | 7434 | if (buttons.Length < 1) |
6729 | { | 7435 | { |
6730 | LSLError("No less than 1 button can be shown"); | 7436 | Error("llDialog", "At least 1 button must be shown"); |
6731 | return; | 7437 | return; |
6732 | } | 7438 | } |
6733 | if (buttons.Length > 12) | 7439 | if (buttons.Length > 12) |
6734 | { | 7440 | { |
6735 | LSLError("No more than 12 buttons can be shown"); | 7441 | Error("llDialog", "No more than 12 buttons can be shown"); |
6736 | return; | 7442 | return; |
6737 | } | 7443 | } |
6738 | string[] buts = new string[buttons.Length]; | 7444 | string[] buts = new string[buttons.Length]; |
@@ -6740,12 +7446,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6740 | { | 7446 | { |
6741 | if (buttons.Data[i].ToString() == String.Empty) | 7447 | if (buttons.Data[i].ToString() == String.Empty) |
6742 | { | 7448 | { |
6743 | LSLError("button label cannot be blank"); | 7449 | Error("llDialog", "Button label cannot be blank"); |
6744 | return; | 7450 | return; |
6745 | } | 7451 | } |
6746 | if (buttons.Data[i].ToString().Length > 24) | 7452 | if (buttons.Data[i].ToString().Length > 24) |
6747 | { | 7453 | { |
6748 | LSLError("button label cannot be longer than 24 characters"); | 7454 | Error("llDialog", "Button label cannot be longer than 24 characters"); |
6749 | return; | 7455 | return; |
6750 | } | 7456 | } |
6751 | buts[i] = buttons.Data[i].ToString(); | 7457 | buts[i] = buttons.Data[i].ToString(); |
@@ -6755,7 +7461,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6755 | av, m_host.Name, m_host.UUID, m_host.OwnerID, | 7461 | av, m_host.Name, m_host.UUID, m_host.OwnerID, |
6756 | message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); | 7462 | message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); |
6757 | 7463 | ||
6758 | ScriptSleep(1000); | 7464 | ScriptSleep(m_sleepMsOnDialog); |
6759 | } | 7465 | } |
6760 | 7466 | ||
6761 | public void llVolumeDetect(int detect) | 7467 | public void llVolumeDetect(int detect) |
@@ -6766,16 +7472,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6766 | m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0); | 7472 | m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0); |
6767 | } | 7473 | } |
6768 | 7474 | ||
6769 | /// <summary> | ||
6770 | /// This is a depecated function so this just replicates the result of | ||
6771 | /// invoking it in SL | ||
6772 | /// </summary> | ||
6773 | public void llRemoteLoadScript(string target, string name, int running, int start_param) | 7475 | public void llRemoteLoadScript(string target, string name, int running, int start_param) |
6774 | { | 7476 | { |
6775 | m_host.AddScriptLPS(1); | 7477 | m_host.AddScriptLPS(1); |
6776 | // Report an error as it does in SL | 7478 | Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead"); |
6777 | ShoutError("Deprecated. Please use llRemoteLoadScriptPin instead."); | 7479 | ScriptSleep(m_sleepMsOnRemoteLoadScript); |
6778 | ScriptSleep(3000); | ||
6779 | } | 7480 | } |
6780 | 7481 | ||
6781 | public void llSetRemoteScriptAccessPin(int pin) | 7482 | public void llSetRemoteScriptAccessPin(int pin) |
@@ -6792,7 +7493,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6792 | 7493 | ||
6793 | if (!UUID.TryParse(target, out destId)) | 7494 | if (!UUID.TryParse(target, out destId)) |
6794 | { | 7495 | { |
6795 | llSay(0, "Could not parse key " + target); | 7496 | Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'"); |
6796 | return; | 7497 | return; |
6797 | } | 7498 | } |
6798 | 7499 | ||
@@ -6808,7 +7509,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6808 | // make sure the object is a script | 7509 | // make sure the object is a script |
6809 | if (item == null || item.Type != 10) | 7510 | if (item == null || item.Type != 10) |
6810 | { | 7511 | { |
6811 | llSay(0, "Could not find script " + name); | 7512 | Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'"); |
6812 | return; | 7513 | return; |
6813 | } | 7514 | } |
6814 | 7515 | ||
@@ -6816,14 +7517,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6816 | World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); | 7517 | World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); |
6817 | 7518 | ||
6818 | // this will cause the delay even if the script pin or permissions were wrong - seems ok | 7519 | // this will cause the delay even if the script pin or permissions were wrong - seems ok |
6819 | ScriptSleep(3000); | 7520 | ScriptSleep(m_sleepMsOnRemoteLoadScriptPin); |
6820 | } | 7521 | } |
6821 | 7522 | ||
6822 | public void llOpenRemoteDataChannel() | 7523 | public void llOpenRemoteDataChannel() |
6823 | { | 7524 | { |
6824 | m_host.AddScriptLPS(1); | 7525 | m_host.AddScriptLPS(1); |
6825 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7526 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
6826 | if (xmlrpcMod.IsEnabled()) | 7527 | if (xmlrpcMod != null && xmlrpcMod.IsEnabled()) |
6827 | { | 7528 | { |
6828 | UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); | 7529 | UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); |
6829 | IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); | 7530 | IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); |
@@ -6847,14 +7548,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6847 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj, | 7548 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj, |
6848 | new DetectParams[0])); | 7549 | new DetectParams[0])); |
6849 | } | 7550 | } |
6850 | ScriptSleep(1000); | 7551 | ScriptSleep(m_sleepMsOnOpenRemoteDataChannel); |
6851 | } | 7552 | } |
6852 | 7553 | ||
6853 | public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) | 7554 | public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) |
6854 | { | 7555 | { |
6855 | m_host.AddScriptLPS(1); | 7556 | m_host.AddScriptLPS(1); |
6856 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7557 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
6857 | ScriptSleep(3000); | 7558 | ScriptSleep(m_sleepMsOnSendRemoteData); |
7559 | if (xmlrpcMod == null) | ||
7560 | return ""; | ||
6858 | return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); | 7561 | return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); |
6859 | } | 7562 | } |
6860 | 7563 | ||
@@ -6862,8 +7565,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6862 | { | 7565 | { |
6863 | m_host.AddScriptLPS(1); | 7566 | m_host.AddScriptLPS(1); |
6864 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7567 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
6865 | xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); | 7568 | if (xmlrpcMod != null) |
6866 | ScriptSleep(3000); | 7569 | xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); |
7570 | ScriptSleep(m_sleepMsOnRemoteDataReply); | ||
6867 | } | 7571 | } |
6868 | 7572 | ||
6869 | public void llCloseRemoteDataChannel(string channel) | 7573 | public void llCloseRemoteDataChannel(string channel) |
@@ -6877,8 +7581,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6877 | } | 7581 | } |
6878 | 7582 | ||
6879 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7583 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
6880 | xmlrpcMod.CloseXMLRPCChannel((UUID)channel); | 7584 | if (xmlrpcMod != null) |
6881 | ScriptSleep(1000); | 7585 | xmlrpcMod.CloseXMLRPCChannel((UUID)channel); |
7586 | ScriptSleep(m_sleepMsOnCloseRemoteDataChannel); | ||
6882 | } | 7587 | } |
6883 | 7588 | ||
6884 | public LSL_String llMD5String(string src, int nonce) | 7589 | public LSL_String llMD5String(string src, int nonce) |
@@ -6924,13 +7629,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6924 | { | 7629 | { |
6925 | cut.y = 1f; | 7630 | cut.y = 1f; |
6926 | } | 7631 | } |
6927 | if (cut.y - cut.x < 0.05f) | 7632 | if (cut.y - cut.x < 0.02f) |
6928 | { | 7633 | { |
6929 | cut.x = cut.y - 0.05f; | 7634 | cut.x = cut.y - 0.02f; |
6930 | if (cut.x < 0.0f) | 7635 | if (cut.x < 0.0f) |
6931 | { | 7636 | { |
6932 | cut.x = 0.0f; | 7637 | cut.x = 0.0f; |
6933 | cut.y = 0.05f; | 7638 | cut.y = 0.02f; |
6934 | } | 7639 | } |
6935 | } | 7640 | } |
6936 | shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); | 7641 | shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); |
@@ -6952,12 +7657,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
6952 | hollow = 0.70f; | 7657 | hollow = 0.70f; |
6953 | } | 7658 | } |
6954 | } | 7659 | } |
6955 | // Otherwise, hollow is limited to 95%. | 7660 | // Otherwise, hollow is limited to 99%. |
6956 | else | 7661 | else |
6957 | { | 7662 | { |
6958 | if (hollow > 0.95f) | 7663 | if (hollow > 0.99f) |
6959 | { | 7664 | { |
6960 | hollow = 0.95f; | 7665 | hollow = 0.99f; |
6961 | } | 7666 | } |
6962 | } | 7667 | } |
6963 | shapeBlock.ProfileHollow = (ushort)(50000 * hollow); | 7668 | shapeBlock.ProfileHollow = (ushort)(50000 * hollow); |
@@ -7081,9 +7786,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7081 | { | 7786 | { |
7082 | dimple.y = 1f; | 7787 | dimple.y = 1f; |
7083 | } | 7788 | } |
7084 | if (dimple.y - cut.x < 0.05f) | 7789 | if (dimple.y - dimple.x < 0.02f) |
7085 | { | 7790 | { |
7086 | dimple.x = cut.y - 0.05f; | 7791 | dimple.x = dimple.y - 0.02f; |
7792 | if (dimple.x < 0.0f) | ||
7793 | { | ||
7794 | dimple.x = 0.0f; | ||
7795 | dimple.y = 0.02f; | ||
7796 | } | ||
7087 | } | 7797 | } |
7088 | shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); | 7798 | shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); |
7089 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); | 7799 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); |
@@ -7104,17 +7814,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7104 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; | 7814 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; |
7105 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; | 7815 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; |
7106 | 7816 | ||
7107 | if (holesize.x < 0.05f) | 7817 | if (holesize.x < 0.01f) |
7108 | { | 7818 | { |
7109 | holesize.x = 0.05f; | 7819 | holesize.x = 0.01f; |
7110 | } | 7820 | } |
7111 | if (holesize.x > 1f) | 7821 | if (holesize.x > 1f) |
7112 | { | 7822 | { |
7113 | holesize.x = 1f; | 7823 | holesize.x = 1f; |
7114 | } | 7824 | } |
7115 | if (holesize.y < 0.05f) | 7825 | if (holesize.y < 0.01f) |
7116 | { | 7826 | { |
7117 | holesize.y = 0.05f; | 7827 | holesize.y = 0.01f; |
7118 | } | 7828 | } |
7119 | if (holesize.y > 0.5f) | 7829 | if (holesize.y > 0.5f) |
7120 | { | 7830 | { |
@@ -7160,13 +7870,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7160 | { | 7870 | { |
7161 | profilecut.y = 1f; | 7871 | profilecut.y = 1f; |
7162 | } | 7872 | } |
7163 | if (profilecut.y - profilecut.x < 0.05f) | 7873 | if (profilecut.y - profilecut.x < 0.02f) |
7164 | { | 7874 | { |
7165 | profilecut.x = profilecut.y - 0.05f; | 7875 | profilecut.x = profilecut.y - 0.02f; |
7166 | if (profilecut.x < 0.0f) | 7876 | if (profilecut.x < 0.0f) |
7167 | { | 7877 | { |
7168 | profilecut.x = 0.0f; | 7878 | profilecut.x = 0.0f; |
7169 | profilecut.y = 0.05f; | 7879 | profilecut.y = 0.02f; |
7170 | } | 7880 | } |
7171 | } | 7881 | } |
7172 | shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); | 7882 | shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); |
@@ -7234,9 +7944,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7234 | UUID sculptId; | 7944 | UUID sculptId; |
7235 | 7945 | ||
7236 | if (!UUID.TryParse(map, out sculptId)) | 7946 | if (!UUID.TryParse(map, out sculptId)) |
7237 | { | 7947 | sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture); |
7238 | sculptId = InventoryKey(map, (int)AssetType.Texture); | ||
7239 | } | ||
7240 | 7948 | ||
7241 | if (sculptId == UUID.Zero) | 7949 | if (sculptId == UUID.Zero) |
7242 | return; | 7950 | return; |
@@ -7266,45 +7974,205 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7266 | { | 7974 | { |
7267 | m_host.AddScriptLPS(1); | 7975 | m_host.AddScriptLPS(1); |
7268 | 7976 | ||
7269 | setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); | 7977 | SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); |
7270 | 7978 | ||
7271 | ScriptSleep(200); | 7979 | ScriptSleep(m_sleepMsOnSetPrimitiveParams); |
7272 | } | 7980 | } |
7273 | 7981 | ||
7274 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) | 7982 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) |
7275 | { | 7983 | { |
7276 | m_host.AddScriptLPS(1); | 7984 | m_host.AddScriptLPS(1); |
7277 | 7985 | ||
7278 | setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); | 7986 | SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); |
7279 | 7987 | ||
7280 | ScriptSleep(200); | 7988 | ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams); |
7281 | } | 7989 | } |
7282 | 7990 | ||
7283 | public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) | 7991 | public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) |
7284 | { | 7992 | { |
7285 | m_host.AddScriptLPS(1); | 7993 | m_host.AddScriptLPS(1); |
7286 | 7994 | ||
7287 | setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); | 7995 | SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); |
7288 | } | 7996 | } |
7289 | 7997 | ||
7290 | protected void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) | 7998 | protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc) |
7291 | { | 7999 | { |
7292 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 8000 | SetEntityParams(GetLinkEntities(linknumber), rules, originFunc); |
8001 | } | ||
7293 | 8002 | ||
7294 | LSL_List remaining = null; | 8003 | protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc) |
8004 | { | ||
8005 | LSL_List remaining = new LSL_List(); | ||
7295 | uint rulesParsed = 0; | 8006 | uint rulesParsed = 0; |
7296 | 8007 | ||
7297 | foreach (SceneObjectPart part in parts) | 8008 | foreach (ISceneEntity entity in entities) |
7298 | remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); | 8009 | { |
8010 | if (entity is SceneObjectPart) | ||
8011 | remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); | ||
8012 | else | ||
8013 | remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); | ||
8014 | } | ||
7299 | 8015 | ||
7300 | while (remaining != null && remaining.Length > 2) | 8016 | while (remaining.Length > 2) |
7301 | { | 8017 | { |
7302 | linknumber = remaining.GetLSLIntegerItem(0); | 8018 | int linknumber; |
8019 | try | ||
8020 | { | ||
8021 | linknumber = remaining.GetLSLIntegerItem(0); | ||
8022 | } | ||
8023 | catch(InvalidCastException) | ||
8024 | { | ||
8025 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_LINK_TARGET: parameter 2 must be integer", rulesParsed)); | ||
8026 | return; | ||
8027 | } | ||
8028 | |||
7303 | rules = remaining.GetSublist(1, -1); | 8029 | rules = remaining.GetSublist(1, -1); |
7304 | parts = GetLinkParts(linknumber); | 8030 | entities = GetLinkEntities(linknumber); |
7305 | 8031 | ||
7306 | foreach (SceneObjectPart part in parts) | 8032 | foreach (ISceneEntity entity in entities) |
7307 | remaining = SetPrimParams(part, rules, originFunc, ref rulesParsed); | 8033 | { |
8034 | if (entity is SceneObjectPart) | ||
8035 | remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); | ||
8036 | else | ||
8037 | remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); | ||
8038 | } | ||
8039 | } | ||
8040 | } | ||
8041 | |||
8042 | public void llSetKeyframedMotion(LSL_List frames, LSL_List options) | ||
8043 | { | ||
8044 | SceneObjectGroup group = m_host.ParentGroup; | ||
8045 | |||
8046 | if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical) | ||
8047 | return; | ||
8048 | if (group.IsAttachment) | ||
8049 | return; | ||
8050 | |||
8051 | if (frames.Data.Length > 0) // We are getting a new motion | ||
8052 | { | ||
8053 | if (group.RootPart.KeyframeMotion != null) | ||
8054 | group.RootPart.KeyframeMotion.Delete(); | ||
8055 | group.RootPart.KeyframeMotion = null; | ||
8056 | |||
8057 | int idx = 0; | ||
8058 | |||
8059 | KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward; | ||
8060 | KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation; | ||
8061 | |||
8062 | while (idx < options.Data.Length) | ||
8063 | { | ||
8064 | int option = (int)options.GetLSLIntegerItem(idx++); | ||
8065 | int remain = options.Data.Length - idx; | ||
8066 | |||
8067 | switch (option) | ||
8068 | { | ||
8069 | case ScriptBaseClass.KFM_MODE: | ||
8070 | if (remain < 1) | ||
8071 | break; | ||
8072 | int modeval = (int)options.GetLSLIntegerItem(idx++); | ||
8073 | switch(modeval) | ||
8074 | { | ||
8075 | case ScriptBaseClass.KFM_FORWARD: | ||
8076 | mode = KeyframeMotion.PlayMode.Forward; | ||
8077 | break; | ||
8078 | case ScriptBaseClass.KFM_REVERSE: | ||
8079 | mode = KeyframeMotion.PlayMode.Reverse; | ||
8080 | break; | ||
8081 | case ScriptBaseClass.KFM_LOOP: | ||
8082 | mode = KeyframeMotion.PlayMode.Loop; | ||
8083 | break; | ||
8084 | case ScriptBaseClass.KFM_PING_PONG: | ||
8085 | mode = KeyframeMotion.PlayMode.PingPong; | ||
8086 | break; | ||
8087 | } | ||
8088 | break; | ||
8089 | case ScriptBaseClass.KFM_DATA: | ||
8090 | if (remain < 1) | ||
8091 | break; | ||
8092 | int dataval = (int)options.GetLSLIntegerItem(idx++); | ||
8093 | data = (KeyframeMotion.DataFormat)dataval; | ||
8094 | break; | ||
8095 | } | ||
8096 | } | ||
8097 | |||
8098 | group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data); | ||
8099 | |||
8100 | idx = 0; | ||
8101 | |||
8102 | int elemLength = 2; | ||
8103 | if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation)) | ||
8104 | elemLength = 3; | ||
8105 | |||
8106 | List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>(); | ||
8107 | while (idx < frames.Data.Length) | ||
8108 | { | ||
8109 | int remain = frames.Data.Length - idx; | ||
8110 | |||
8111 | if (remain < elemLength) | ||
8112 | break; | ||
8113 | |||
8114 | KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe(); | ||
8115 | frame.Position = null; | ||
8116 | frame.Rotation = null; | ||
8117 | |||
8118 | if ((data & KeyframeMotion.DataFormat.Translation) != 0) | ||
8119 | { | ||
8120 | LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++); | ||
8121 | frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z); | ||
8122 | } | ||
8123 | if ((data & KeyframeMotion.DataFormat.Rotation) != 0) | ||
8124 | { | ||
8125 | LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++); | ||
8126 | Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s); | ||
8127 | q.Normalize(); | ||
8128 | frame.Rotation = q; | ||
8129 | } | ||
8130 | |||
8131 | float tempf = (float)frames.GetLSLFloatItem(idx++); | ||
8132 | frame.TimeMS = (int)(tempf * 1000.0f); | ||
8133 | |||
8134 | keyframes.Add(frame); | ||
8135 | } | ||
8136 | |||
8137 | group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray()); | ||
8138 | group.RootPart.KeyframeMotion.Start(); | ||
8139 | } | ||
8140 | else | ||
8141 | { | ||
8142 | if (group.RootPart.KeyframeMotion == null) | ||
8143 | return; | ||
8144 | |||
8145 | if (options.Data.Length == 0) | ||
8146 | { | ||
8147 | group.RootPart.KeyframeMotion.Stop(); | ||
8148 | return; | ||
8149 | } | ||
8150 | |||
8151 | int idx = 0; | ||
8152 | |||
8153 | while (idx < options.Data.Length) | ||
8154 | { | ||
8155 | int option = (int)options.GetLSLIntegerItem(idx++); | ||
8156 | |||
8157 | switch (option) | ||
8158 | { | ||
8159 | case ScriptBaseClass.KFM_COMMAND: | ||
8160 | int cmd = (int)options.GetLSLIntegerItem(idx++); | ||
8161 | switch (cmd) | ||
8162 | { | ||
8163 | case ScriptBaseClass.KFM_CMD_PLAY: | ||
8164 | group.RootPart.KeyframeMotion.Start(); | ||
8165 | break; | ||
8166 | case ScriptBaseClass.KFM_CMD_STOP: | ||
8167 | group.RootPart.KeyframeMotion.Stop(); | ||
8168 | break; | ||
8169 | case ScriptBaseClass.KFM_CMD_PAUSE: | ||
8170 | group.RootPart.KeyframeMotion.Pause(); | ||
8171 | break; | ||
8172 | } | ||
8173 | break; | ||
8174 | } | ||
8175 | } | ||
7308 | } | 8176 | } |
7309 | } | 8177 | } |
7310 | 8178 | ||
@@ -7331,29 +8199,48 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7331 | 8199 | ||
7332 | switch (code) | 8200 | switch (code) |
7333 | { | 8201 | { |
7334 | case (int)ScriptBaseClass.PRIM_POSITION: | 8202 | case ScriptBaseClass.PRIM_POSITION: |
7335 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | 8203 | case ScriptBaseClass.PRIM_POS_LOCAL: |
7336 | if (remain < 1) | 8204 | if (remain < 1) |
7337 | return null; | 8205 | return new LSL_List(); |
7338 | 8206 | ||
7339 | v=rules.GetVector3Item(idx++); | 8207 | try |
8208 | { | ||
8209 | v = rules.GetVector3Item(idx++); | ||
8210 | } | ||
8211 | catch(InvalidCastException) | ||
8212 | { | ||
8213 | if(code == ScriptBaseClass.PRIM_POSITION) | ||
8214 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8215 | else | ||
8216 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8217 | return new LSL_List(); | ||
8218 | } | ||
7340 | positionChanged = true; | 8219 | positionChanged = true; |
7341 | currentPosition = GetSetPosTarget(part, v, currentPosition); | 8220 | currentPosition = GetSetPosTarget(part, v, currentPosition); |
7342 | 8221 | ||
7343 | break; | 8222 | break; |
7344 | case (int)ScriptBaseClass.PRIM_SIZE: | 8223 | case ScriptBaseClass.PRIM_SIZE: |
7345 | if (remain < 1) | 8224 | if (remain < 1) |
7346 | return null; | 8225 | return new LSL_List(); |
7347 | 8226 | ||
7348 | v=rules.GetVector3Item(idx++); | 8227 | v=rules.GetVector3Item(idx++); |
7349 | SetScale(part, v); | 8228 | SetScale(part, v); |
7350 | 8229 | ||
7351 | break; | 8230 | break; |
7352 | case (int)ScriptBaseClass.PRIM_ROTATION: | 8231 | case ScriptBaseClass.PRIM_ROTATION: |
7353 | if (remain < 1) | 8232 | if (remain < 1) |
7354 | return null; | 8233 | return new LSL_List(); |
7355 | 8234 | LSL_Rotation q; | |
7356 | LSL_Rotation q = rules.GetQuaternionItem(idx++); | 8235 | try |
8236 | { | ||
8237 | q = rules.GetQuaternionItem(idx++); | ||
8238 | } | ||
8239 | catch(InvalidCastException) | ||
8240 | { | ||
8241 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 1 must be rotation", rulesParsed, idx - idxStart - 1)); | ||
8242 | return new LSL_List(); | ||
8243 | } | ||
7357 | // try to let this work as in SL... | 8244 | // try to let this work as in SL... |
7358 | if (part.ParentID == 0) | 8245 | if (part.ParentID == 0) |
7359 | { | 8246 | { |
@@ -7369,11 +8256,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7369 | 8256 | ||
7370 | break; | 8257 | break; |
7371 | 8258 | ||
7372 | case (int)ScriptBaseClass.PRIM_TYPE: | 8259 | case ScriptBaseClass.PRIM_TYPE: |
7373 | if (remain < 3) | 8260 | if (remain < 3) |
7374 | return null; | 8261 | return new LSL_List(); |
7375 | 8262 | ||
7376 | code = (int)rules.GetLSLIntegerItem(idx++); | 8263 | try |
8264 | { | ||
8265 | code = (int)rules.GetLSLIntegerItem(idx++); | ||
8266 | } | ||
8267 | catch(InvalidCastException) | ||
8268 | { | ||
8269 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8270 | return new LSL_List(); | ||
8271 | } | ||
7377 | 8272 | ||
7378 | remain = rules.Length - idx; | 8273 | remain = rules.Length - idx; |
7379 | float hollow; | 8274 | float hollow; |
@@ -7388,140 +8283,625 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7388 | 8283 | ||
7389 | switch (code) | 8284 | switch (code) |
7390 | { | 8285 | { |
7391 | case (int)ScriptBaseClass.PRIM_TYPE_BOX: | 8286 | case ScriptBaseClass.PRIM_TYPE_BOX: |
7392 | if (remain < 6) | 8287 | if (remain < 6) |
7393 | return null; | 8288 | return new LSL_List(); |
7394 | 8289 | ||
7395 | face = (int)rules.GetLSLIntegerItem(idx++); | 8290 | try |
7396 | v = rules.GetVector3Item(idx++); // cut | 8291 | { |
7397 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8292 | face = (int)rules.GetLSLIntegerItem(idx++); |
7398 | twist = rules.GetVector3Item(idx++); | 8293 | } |
7399 | taper_b = rules.GetVector3Item(idx++); | 8294 | catch(InvalidCastException) |
7400 | topshear = rules.GetVector3Item(idx++); | 8295 | { |
8296 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8297 | return new LSL_List(); | ||
8298 | } | ||
8299 | try | ||
8300 | { | ||
8301 | v = rules.GetVector3Item(idx++); // cut | ||
8302 | } | ||
8303 | catch(InvalidCastException) | ||
8304 | { | ||
8305 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8306 | return new LSL_List(); | ||
8307 | } | ||
8308 | try | ||
8309 | { | ||
8310 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
8311 | } | ||
8312 | catch(InvalidCastException) | ||
8313 | { | ||
8314 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | ||
8315 | return new LSL_List(); | ||
8316 | } | ||
8317 | try | ||
8318 | { | ||
8319 | twist = rules.GetVector3Item(idx++); | ||
8320 | } | ||
8321 | catch(InvalidCastException) | ||
8322 | { | ||
8323 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 5 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8324 | return new LSL_List(); | ||
8325 | } | ||
8326 | try | ||
8327 | { | ||
8328 | taper_b = rules.GetVector3Item(idx++); | ||
8329 | } | ||
8330 | catch(InvalidCastException) | ||
8331 | { | ||
8332 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8333 | return new LSL_List(); | ||
8334 | } | ||
8335 | try | ||
8336 | { | ||
8337 | topshear = rules.GetVector3Item(idx++); | ||
8338 | } | ||
8339 | catch(InvalidCastException) | ||
8340 | { | ||
8341 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8342 | return new LSL_List(); | ||
8343 | } | ||
7401 | 8344 | ||
7402 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, | 8345 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, |
7403 | (byte)ProfileShape.Square, (byte)Extrusion.Straight); | 8346 | (byte)ProfileShape.Square, (byte)Extrusion.Straight); |
7404 | break; | 8347 | break; |
7405 | 8348 | ||
7406 | case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: | 8349 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: |
7407 | if (remain < 6) | 8350 | if (remain < 6) |
7408 | return null; | 8351 | return new LSL_List(); |
7409 | 8352 | ||
7410 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8353 | try |
7411 | v = rules.GetVector3Item(idx++); // cut | 8354 | { |
7412 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8355 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
7413 | twist = rules.GetVector3Item(idx++); | 8356 | } |
7414 | taper_b = rules.GetVector3Item(idx++); | 8357 | catch(InvalidCastException) |
7415 | topshear = rules.GetVector3Item(idx++); | 8358 | { |
8359 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8360 | return new LSL_List(); | ||
8361 | } | ||
8362 | try | ||
8363 | { | ||
8364 | v = rules.GetVector3Item(idx++); // cut | ||
8365 | } | ||
8366 | catch(InvalidCastException) | ||
8367 | { | ||
8368 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8369 | return new LSL_List(); | ||
8370 | } | ||
8371 | try | ||
8372 | { | ||
8373 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
8374 | } | ||
8375 | catch(InvalidCastException) | ||
8376 | { | ||
8377 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8378 | return new LSL_List(); | ||
8379 | } | ||
8380 | try | ||
8381 | { | ||
8382 | twist = rules.GetVector3Item(idx++); | ||
8383 | } | ||
8384 | catch(InvalidCastException) | ||
8385 | { | ||
8386 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8387 | return new LSL_List(); | ||
8388 | } | ||
8389 | try | ||
8390 | { | ||
8391 | taper_b = rules.GetVector3Item(idx++); | ||
8392 | } | ||
8393 | catch(InvalidCastException) | ||
8394 | { | ||
8395 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8396 | return new LSL_List(); | ||
8397 | } | ||
8398 | try | ||
8399 | { | ||
8400 | topshear = rules.GetVector3Item(idx++); | ||
8401 | } | ||
8402 | catch(InvalidCastException) | ||
8403 | { | ||
8404 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8405 | return new LSL_List(); | ||
8406 | } | ||
7416 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, | 8407 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, |
7417 | (byte)ProfileShape.Circle, (byte)Extrusion.Straight); | 8408 | (byte)ProfileShape.Circle, (byte)Extrusion.Straight); |
7418 | break; | 8409 | break; |
7419 | 8410 | ||
7420 | case (int)ScriptBaseClass.PRIM_TYPE_PRISM: | 8411 | case ScriptBaseClass.PRIM_TYPE_PRISM: |
7421 | if (remain < 6) | 8412 | if (remain < 6) |
7422 | return null; | 8413 | return new LSL_List(); |
7423 | 8414 | ||
7424 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8415 | try |
7425 | v = rules.GetVector3Item(idx++); //cut | 8416 | { |
7426 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8417 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
7427 | twist = rules.GetVector3Item(idx++); | 8418 | } |
7428 | taper_b = rules.GetVector3Item(idx++); | 8419 | catch(InvalidCastException) |
7429 | topshear = rules.GetVector3Item(idx++); | 8420 | { |
8421 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8422 | return new LSL_List(); | ||
8423 | } | ||
8424 | try | ||
8425 | { | ||
8426 | v = rules.GetVector3Item(idx++); //cut | ||
8427 | } | ||
8428 | catch(InvalidCastException) | ||
8429 | { | ||
8430 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8431 | return new LSL_List(); | ||
8432 | } | ||
8433 | try | ||
8434 | { | ||
8435 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
8436 | } | ||
8437 | catch(InvalidCastException) | ||
8438 | { | ||
8439 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8440 | return new LSL_List(); | ||
8441 | } | ||
8442 | try | ||
8443 | { | ||
8444 | twist = rules.GetVector3Item(idx++); | ||
8445 | } | ||
8446 | catch(InvalidCastException) | ||
8447 | { | ||
8448 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8449 | return new LSL_List(); | ||
8450 | } | ||
8451 | try | ||
8452 | { | ||
8453 | taper_b = rules.GetVector3Item(idx++); | ||
8454 | } | ||
8455 | catch(InvalidCastException) | ||
8456 | { | ||
8457 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8458 | return new LSL_List(); | ||
8459 | } | ||
8460 | try | ||
8461 | { | ||
8462 | topshear = rules.GetVector3Item(idx++); | ||
8463 | } | ||
8464 | catch(InvalidCastException) | ||
8465 | { | ||
8466 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8467 | return new LSL_List(); | ||
8468 | } | ||
7430 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, | 8469 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, |
7431 | (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight); | 8470 | (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight); |
7432 | break; | 8471 | break; |
7433 | 8472 | ||
7434 | case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: | 8473 | case ScriptBaseClass.PRIM_TYPE_SPHERE: |
7435 | if (remain < 5) | 8474 | if (remain < 5) |
7436 | return null; | 8475 | return new LSL_List(); |
7437 | 8476 | ||
7438 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8477 | try |
7439 | v = rules.GetVector3Item(idx++); // cut | 8478 | { |
7440 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8479 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
7441 | twist = rules.GetVector3Item(idx++); | 8480 | } |
7442 | taper_b = rules.GetVector3Item(idx++); // dimple | 8481 | catch(InvalidCastException) |
8482 | { | ||
8483 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8484 | return new LSL_List(); | ||
8485 | } | ||
8486 | try | ||
8487 | { | ||
8488 | v = rules.GetVector3Item(idx++); // cut | ||
8489 | } | ||
8490 | catch(InvalidCastException) | ||
8491 | { | ||
8492 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8493 | return new LSL_List(); | ||
8494 | } | ||
8495 | try | ||
8496 | { | ||
8497 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
8498 | } | ||
8499 | catch(InvalidCastException) | ||
8500 | { | ||
8501 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8502 | return new LSL_List(); | ||
8503 | } | ||
8504 | try | ||
8505 | { | ||
8506 | twist = rules.GetVector3Item(idx++); | ||
8507 | } | ||
8508 | catch(InvalidCastException) | ||
8509 | { | ||
8510 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8511 | return new LSL_List(); | ||
8512 | } | ||
8513 | try | ||
8514 | { | ||
8515 | taper_b = rules.GetVector3Item(idx++); // dimple | ||
8516 | } | ||
8517 | catch(InvalidCastException) | ||
8518 | { | ||
8519 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8520 | return new LSL_List(); | ||
8521 | } | ||
7443 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, | 8522 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, |
7444 | (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1); | 8523 | (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1); |
7445 | break; | 8524 | break; |
7446 | 8525 | ||
7447 | case (int)ScriptBaseClass.PRIM_TYPE_TORUS: | 8526 | case ScriptBaseClass.PRIM_TYPE_TORUS: |
7448 | if (remain < 11) | 8527 | if (remain < 11) |
7449 | return null; | 8528 | return new LSL_List(); |
7450 | 8529 | ||
7451 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8530 | try |
7452 | v = rules.GetVector3Item(idx++); //cut | 8531 | { |
7453 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8532 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
7454 | twist = rules.GetVector3Item(idx++); | 8533 | } |
7455 | holesize = rules.GetVector3Item(idx++); | 8534 | catch(InvalidCastException) |
7456 | topshear = rules.GetVector3Item(idx++); | 8535 | { |
7457 | profilecut = rules.GetVector3Item(idx++); | 8536 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
7458 | taper_b = rules.GetVector3Item(idx++); // taper_a | 8537 | return new LSL_List(); |
7459 | revolutions = (float)rules.GetLSLFloatItem(idx++); | 8538 | } |
7460 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | 8539 | try |
7461 | skew = (float)rules.GetLSLFloatItem(idx++); | 8540 | { |
8541 | v = rules.GetVector3Item(idx++); //cut | ||
8542 | } | ||
8543 | catch(InvalidCastException) | ||
8544 | { | ||
8545 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8546 | return new LSL_List(); | ||
8547 | } | ||
8548 | try | ||
8549 | { | ||
8550 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
8551 | } | ||
8552 | catch(InvalidCastException) | ||
8553 | { | ||
8554 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8555 | return new LSL_List(); | ||
8556 | } | ||
8557 | try | ||
8558 | { | ||
8559 | twist = rules.GetVector3Item(idx++); | ||
8560 | } | ||
8561 | catch(InvalidCastException) | ||
8562 | { | ||
8563 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8564 | return new LSL_List(); | ||
8565 | } | ||
8566 | try | ||
8567 | { | ||
8568 | holesize = rules.GetVector3Item(idx++); | ||
8569 | } | ||
8570 | catch(InvalidCastException) | ||
8571 | { | ||
8572 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8573 | return new LSL_List(); | ||
8574 | } | ||
8575 | try | ||
8576 | { | ||
8577 | topshear = rules.GetVector3Item(idx++); | ||
8578 | } | ||
8579 | catch(InvalidCastException) | ||
8580 | { | ||
8581 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8582 | return new LSL_List(); | ||
8583 | } | ||
8584 | try | ||
8585 | { | ||
8586 | profilecut = rules.GetVector3Item(idx++); | ||
8587 | } | ||
8588 | catch(InvalidCastException) | ||
8589 | { | ||
8590 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8591 | return new LSL_List(); | ||
8592 | } | ||
8593 | try | ||
8594 | { | ||
8595 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
8596 | } | ||
8597 | catch(InvalidCastException) | ||
8598 | { | ||
8599 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8600 | return new LSL_List(); | ||
8601 | } | ||
8602 | try | ||
8603 | { | ||
8604 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
8605 | } | ||
8606 | catch(InvalidCastException) | ||
8607 | { | ||
8608 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); | ||
8609 | return new LSL_List(); | ||
8610 | } | ||
8611 | try | ||
8612 | { | ||
8613 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
8614 | } | ||
8615 | catch(InvalidCastException) | ||
8616 | { | ||
8617 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); | ||
8618 | return new LSL_List(); | ||
8619 | } | ||
8620 | try | ||
8621 | { | ||
8622 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
8623 | } | ||
8624 | catch(InvalidCastException) | ||
8625 | { | ||
8626 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 13 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8627 | return new LSL_List(); | ||
8628 | } | ||
7462 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, | 8629 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, |
7463 | revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1); | 8630 | revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1); |
7464 | break; | 8631 | break; |
7465 | 8632 | ||
7466 | case (int)ScriptBaseClass.PRIM_TYPE_TUBE: | 8633 | case ScriptBaseClass.PRIM_TYPE_TUBE: |
7467 | if (remain < 11) | 8634 | if (remain < 11) |
7468 | return null; | 8635 | return new LSL_List(); |
7469 | 8636 | ||
7470 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8637 | try |
7471 | v = rules.GetVector3Item(idx++); //cut | 8638 | { |
7472 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8639 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
7473 | twist = rules.GetVector3Item(idx++); | 8640 | } |
7474 | holesize = rules.GetVector3Item(idx++); | 8641 | catch(InvalidCastException) |
7475 | topshear = rules.GetVector3Item(idx++); | 8642 | { |
7476 | profilecut = rules.GetVector3Item(idx++); | 8643 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
7477 | taper_b = rules.GetVector3Item(idx++); // taper_a | 8644 | return new LSL_List(); |
7478 | revolutions = (float)rules.GetLSLFloatItem(idx++); | 8645 | } |
7479 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | 8646 | try |
7480 | skew = (float)rules.GetLSLFloatItem(idx++); | 8647 | { |
8648 | v = rules.GetVector3Item(idx++); //cut | ||
8649 | } | ||
8650 | catch(InvalidCastException) | ||
8651 | { | ||
8652 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8653 | return new LSL_List(); | ||
8654 | } | ||
8655 | try | ||
8656 | { | ||
8657 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
8658 | } | ||
8659 | catch(InvalidCastException) | ||
8660 | { | ||
8661 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8662 | return new LSL_List(); | ||
8663 | } | ||
8664 | try | ||
8665 | { | ||
8666 | twist = rules.GetVector3Item(idx++); | ||
8667 | } | ||
8668 | catch(InvalidCastException) | ||
8669 | { | ||
8670 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8671 | return new LSL_List(); | ||
8672 | } | ||
8673 | try | ||
8674 | { | ||
8675 | holesize = rules.GetVector3Item(idx++); | ||
8676 | } | ||
8677 | catch(InvalidCastException) | ||
8678 | { | ||
8679 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8680 | return new LSL_List(); | ||
8681 | } | ||
8682 | try | ||
8683 | { | ||
8684 | topshear = rules.GetVector3Item(idx++); | ||
8685 | } | ||
8686 | catch(InvalidCastException) | ||
8687 | { | ||
8688 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8689 | return new LSL_List(); | ||
8690 | } | ||
8691 | try | ||
8692 | { | ||
8693 | profilecut = rules.GetVector3Item(idx++); | ||
8694 | } | ||
8695 | catch(InvalidCastException) | ||
8696 | { | ||
8697 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8698 | return new LSL_List(); | ||
8699 | } | ||
8700 | try | ||
8701 | { | ||
8702 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
8703 | } | ||
8704 | catch(InvalidCastException) | ||
8705 | { | ||
8706 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8707 | return new LSL_List(); | ||
8708 | } | ||
8709 | try | ||
8710 | { | ||
8711 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
8712 | } | ||
8713 | catch(InvalidCastException) | ||
8714 | { | ||
8715 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); | ||
8716 | return new LSL_List(); | ||
8717 | } | ||
8718 | try | ||
8719 | { | ||
8720 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
8721 | } | ||
8722 | catch(InvalidCastException) | ||
8723 | { | ||
8724 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); | ||
8725 | return new LSL_List(); | ||
8726 | } | ||
8727 | try | ||
8728 | { | ||
8729 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
8730 | } | ||
8731 | catch(InvalidCastException) | ||
8732 | { | ||
8733 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); | ||
8734 | return new LSL_List(); | ||
8735 | } | ||
7481 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, | 8736 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, |
7482 | revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1); | 8737 | revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1); |
7483 | break; | 8738 | break; |
7484 | 8739 | ||
7485 | case (int)ScriptBaseClass.PRIM_TYPE_RING: | 8740 | case ScriptBaseClass.PRIM_TYPE_RING: |
7486 | if (remain < 11) | 8741 | if (remain < 11) |
7487 | return null; | 8742 | return new LSL_List(); |
7488 | 8743 | ||
7489 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8744 | try |
7490 | v = rules.GetVector3Item(idx++); //cut | 8745 | { |
7491 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8746 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
7492 | twist = rules.GetVector3Item(idx++); | 8747 | } |
7493 | holesize = rules.GetVector3Item(idx++); | 8748 | catch(InvalidCastException) |
7494 | topshear = rules.GetVector3Item(idx++); | 8749 | { |
7495 | profilecut = rules.GetVector3Item(idx++); | 8750 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
7496 | taper_b = rules.GetVector3Item(idx++); // taper_a | 8751 | return new LSL_List(); |
7497 | revolutions = (float)rules.GetLSLFloatItem(idx++); | 8752 | } |
7498 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | 8753 | try |
7499 | skew = (float)rules.GetLSLFloatItem(idx++); | 8754 | { |
8755 | v = rules.GetVector3Item(idx++); //cut | ||
8756 | } | ||
8757 | catch(InvalidCastException) | ||
8758 | { | ||
8759 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8760 | return new LSL_List(); | ||
8761 | } | ||
8762 | try | ||
8763 | { | ||
8764 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
8765 | } | ||
8766 | catch(InvalidCastException) | ||
8767 | { | ||
8768 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8769 | return new LSL_List(); | ||
8770 | } | ||
8771 | try | ||
8772 | { | ||
8773 | twist = rules.GetVector3Item(idx++); | ||
8774 | } | ||
8775 | catch(InvalidCastException) | ||
8776 | { | ||
8777 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8778 | return new LSL_List(); | ||
8779 | } | ||
8780 | try | ||
8781 | { | ||
8782 | holesize = rules.GetVector3Item(idx++); | ||
8783 | } | ||
8784 | catch(InvalidCastException) | ||
8785 | { | ||
8786 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8787 | return new LSL_List(); | ||
8788 | } | ||
8789 | try | ||
8790 | { | ||
8791 | topshear = rules.GetVector3Item(idx++); | ||
8792 | } | ||
8793 | catch(InvalidCastException) | ||
8794 | { | ||
8795 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8796 | return new LSL_List(); | ||
8797 | } | ||
8798 | try | ||
8799 | { | ||
8800 | profilecut = rules.GetVector3Item(idx++); | ||
8801 | } | ||
8802 | catch(InvalidCastException) | ||
8803 | { | ||
8804 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8805 | return new LSL_List(); | ||
8806 | } | ||
8807 | try | ||
8808 | { | ||
8809 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
8810 | } | ||
8811 | catch(InvalidCastException) | ||
8812 | { | ||
8813 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8814 | return new LSL_List(); | ||
8815 | } | ||
8816 | try | ||
8817 | { | ||
8818 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
8819 | } | ||
8820 | catch(InvalidCastException) | ||
8821 | { | ||
8822 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); | ||
8823 | return new LSL_List(); | ||
8824 | } | ||
8825 | try | ||
8826 | { | ||
8827 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
8828 | } | ||
8829 | catch(InvalidCastException) | ||
8830 | { | ||
8831 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); | ||
8832 | return new LSL_List(); | ||
8833 | } | ||
8834 | try | ||
8835 | { | ||
8836 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
8837 | } | ||
8838 | catch(InvalidCastException) | ||
8839 | { | ||
8840 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); | ||
8841 | return new LSL_List(); | ||
8842 | } | ||
7500 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, | 8843 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, |
7501 | revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1); | 8844 | revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1); |
7502 | break; | 8845 | break; |
7503 | 8846 | ||
7504 | case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: | 8847 | case ScriptBaseClass.PRIM_TYPE_SCULPT: |
7505 | if (remain < 2) | 8848 | if (remain < 2) |
7506 | return null; | 8849 | return new LSL_List(); |
7507 | 8850 | ||
7508 | string map = rules.Data[idx++].ToString(); | 8851 | string map = rules.Data[idx++].ToString(); |
7509 | face = (int)rules.GetLSLIntegerItem(idx++); // type | 8852 | try |
8853 | { | ||
8854 | face = (int)rules.GetLSLIntegerItem(idx++); // type | ||
8855 | } | ||
8856 | catch(InvalidCastException) | ||
8857 | { | ||
8858 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SCULPT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8859 | return new LSL_List(); | ||
8860 | } | ||
7510 | SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1); | 8861 | SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1); |
7511 | break; | 8862 | break; |
7512 | } | 8863 | } |
7513 | 8864 | ||
7514 | break; | 8865 | break; |
7515 | 8866 | ||
7516 | case (int)ScriptBaseClass.PRIM_TEXTURE: | 8867 | case ScriptBaseClass.PRIM_TEXTURE: |
7517 | if (remain < 5) | 8868 | if (remain < 5) |
7518 | return null; | 8869 | return new LSL_List(); |
7519 | 8870 | ||
7520 | face=(int)rules.GetLSLIntegerItem(idx++); | 8871 | face=(int)rules.GetLSLIntegerItem(idx++); |
7521 | string tex=rules.Data[idx++].ToString(); | 8872 | string tex; |
7522 | LSL_Vector repeats=rules.GetVector3Item(idx++); | 8873 | LSL_Vector repeats; |
7523 | LSL_Vector offsets=rules.GetVector3Item(idx++); | 8874 | LSL_Vector offsets; |
7524 | double rotation=(double)rules.GetLSLFloatItem(idx++); | 8875 | double rotation; |
8876 | |||
8877 | tex = rules.Data[idx++].ToString(); | ||
8878 | try | ||
8879 | { | ||
8880 | repeats = rules.GetVector3Item(idx++); | ||
8881 | } | ||
8882 | catch(InvalidCastException) | ||
8883 | { | ||
8884 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8885 | return new LSL_List(); | ||
8886 | } | ||
8887 | try | ||
8888 | { | ||
8889 | offsets = rules.GetVector3Item(idx++); | ||
8890 | } | ||
8891 | catch(InvalidCastException) | ||
8892 | { | ||
8893 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8894 | return new LSL_List(); | ||
8895 | } | ||
8896 | try | ||
8897 | { | ||
8898 | rotation = (double)rules.GetLSLFloatItem(idx++); | ||
8899 | } | ||
8900 | catch(InvalidCastException) | ||
8901 | { | ||
8902 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8903 | return new LSL_List(); | ||
8904 | } | ||
7525 | 8905 | ||
7526 | SetTexture(part, tex, face); | 8906 | SetTexture(part, tex, face); |
7527 | ScaleTexture(part, repeats.x, repeats.y, face); | 8907 | ScaleTexture(part, repeats.x, repeats.y, face); |
@@ -7530,180 +8910,525 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7530 | 8910 | ||
7531 | break; | 8911 | break; |
7532 | 8912 | ||
7533 | case (int)ScriptBaseClass.PRIM_COLOR: | 8913 | case ScriptBaseClass.PRIM_COLOR: |
7534 | if (remain < 3) | 8914 | if (remain < 3) |
7535 | return null; | 8915 | return new LSL_List(); |
7536 | 8916 | ||
7537 | face=(int)rules.GetLSLIntegerItem(idx++); | 8917 | LSL_Vector color; |
7538 | LSL_Vector color=rules.GetVector3Item(idx++); | 8918 | double alpha; |
7539 | double alpha=(double)rules.GetLSLFloatItem(idx++); | 8919 | |
8920 | try | ||
8921 | { | ||
8922 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
8923 | } | ||
8924 | catch(InvalidCastException) | ||
8925 | { | ||
8926 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8927 | return new LSL_List(); | ||
8928 | } | ||
8929 | try | ||
8930 | { | ||
8931 | color = rules.GetVector3Item(idx++); | ||
8932 | } | ||
8933 | catch(InvalidCastException) | ||
8934 | { | ||
8935 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | ||
8936 | return new LSL_List(); | ||
8937 | } | ||
8938 | try | ||
8939 | { | ||
8940 | alpha = (double)rules.GetLSLFloatItem(idx++); | ||
8941 | } | ||
8942 | catch(InvalidCastException) | ||
8943 | { | ||
8944 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | ||
8945 | return new LSL_List(); | ||
8946 | } | ||
7540 | 8947 | ||
7541 | part.SetFaceColorAlpha(face, color, alpha); | 8948 | part.SetFaceColorAlpha(face, color, alpha); |
7542 | 8949 | ||
7543 | break; | 8950 | break; |
7544 | 8951 | ||
7545 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | 8952 | case ScriptBaseClass.PRIM_FLEXIBLE: |
7546 | if (remain < 7) | 8953 | if (remain < 7) |
7547 | return null; | 8954 | return new LSL_List(); |
7548 | 8955 | bool flexi; | |
7549 | bool flexi = rules.GetLSLIntegerItem(idx++); | 8956 | int softness; |
7550 | int softness = rules.GetLSLIntegerItem(idx++); | 8957 | float gravity; |
7551 | float gravity = (float)rules.GetLSLFloatItem(idx++); | 8958 | float friction; |
7552 | float friction = (float)rules.GetLSLFloatItem(idx++); | 8959 | float wind; |
7553 | float wind = (float)rules.GetLSLFloatItem(idx++); | 8960 | float tension; |
7554 | float tension = (float)rules.GetLSLFloatItem(idx++); | 8961 | LSL_Vector force; |
7555 | LSL_Vector force = rules.GetVector3Item(idx++); | 8962 | |
8963 | try | ||
8964 | { | ||
8965 | flexi = rules.GetLSLIntegerItem(idx++); | ||
8966 | } | ||
8967 | catch(InvalidCastException) | ||
8968 | { | ||
8969 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8970 | return new LSL_List(); | ||
8971 | } | ||
8972 | try | ||
8973 | { | ||
8974 | softness = rules.GetLSLIntegerItem(idx++); | ||
8975 | } | ||
8976 | catch(InvalidCastException) | ||
8977 | { | ||
8978 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | ||
8979 | return new LSL_List(); | ||
8980 | } | ||
8981 | try | ||
8982 | { | ||
8983 | gravity = (float)rules.GetLSLFloatItem(idx++); | ||
8984 | } | ||
8985 | catch(InvalidCastException) | ||
8986 | { | ||
8987 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | ||
8988 | return new LSL_List(); | ||
8989 | } | ||
8990 | try | ||
8991 | { | ||
8992 | friction = (float)rules.GetLSLFloatItem(idx++); | ||
8993 | } | ||
8994 | catch(InvalidCastException) | ||
8995 | { | ||
8996 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
8997 | return new LSL_List(); | ||
8998 | } | ||
8999 | try | ||
9000 | { | ||
9001 | wind = (float)rules.GetLSLFloatItem(idx++); | ||
9002 | } | ||
9003 | catch(InvalidCastException) | ||
9004 | { | ||
9005 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); | ||
9006 | return new LSL_List(); | ||
9007 | } | ||
9008 | try | ||
9009 | { | ||
9010 | tension = (float)rules.GetLSLFloatItem(idx++); | ||
9011 | } | ||
9012 | catch(InvalidCastException) | ||
9013 | { | ||
9014 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 7 must be float", rulesParsed, idx - idxStart - 1)); | ||
9015 | return new LSL_List(); | ||
9016 | } | ||
9017 | try | ||
9018 | { | ||
9019 | force = rules.GetVector3Item(idx++); | ||
9020 | } | ||
9021 | catch(InvalidCastException) | ||
9022 | { | ||
9023 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | ||
9024 | return new LSL_List(); | ||
9025 | } | ||
7556 | 9026 | ||
7557 | SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); | 9027 | SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); |
7558 | 9028 | ||
7559 | break; | 9029 | break; |
7560 | 9030 | ||
7561 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | 9031 | case ScriptBaseClass.PRIM_POINT_LIGHT: |
7562 | if (remain < 5) | 9032 | if (remain < 5) |
7563 | return null; | 9033 | return new LSL_List(); |
7564 | bool light = rules.GetLSLIntegerItem(idx++); | 9034 | bool light; |
7565 | LSL_Vector lightcolor = rules.GetVector3Item(idx++); | 9035 | LSL_Vector lightcolor; |
7566 | float intensity = (float)rules.GetLSLFloatItem(idx++); | 9036 | float intensity; |
7567 | float radius = (float)rules.GetLSLFloatItem(idx++); | 9037 | float radius; |
7568 | float falloff = (float)rules.GetLSLFloatItem(idx++); | 9038 | float falloff; |
9039 | |||
9040 | try | ||
9041 | { | ||
9042 | light = rules.GetLSLIntegerItem(idx++); | ||
9043 | } | ||
9044 | catch(InvalidCastException) | ||
9045 | { | ||
9046 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9047 | return new LSL_List(); | ||
9048 | } | ||
9049 | try | ||
9050 | { | ||
9051 | lightcolor = rules.GetVector3Item(idx++); | ||
9052 | } | ||
9053 | catch(InvalidCastException) | ||
9054 | { | ||
9055 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | ||
9056 | return new LSL_List(); | ||
9057 | } | ||
9058 | try | ||
9059 | { | ||
9060 | intensity = (float)rules.GetLSLFloatItem(idx++); | ||
9061 | } | ||
9062 | catch(InvalidCastException) | ||
9063 | { | ||
9064 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | ||
9065 | return new LSL_List(); | ||
9066 | } | ||
9067 | try | ||
9068 | { | ||
9069 | radius = (float)rules.GetLSLFloatItem(idx++); | ||
9070 | } | ||
9071 | catch(InvalidCastException) | ||
9072 | { | ||
9073 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | ||
9074 | return new LSL_List(); | ||
9075 | } | ||
9076 | try | ||
9077 | { | ||
9078 | falloff = (float)rules.GetLSLFloatItem(idx++); | ||
9079 | } | ||
9080 | catch(InvalidCastException) | ||
9081 | { | ||
9082 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); | ||
9083 | return new LSL_List(); | ||
9084 | } | ||
7569 | 9085 | ||
7570 | SetPointLight(part, light, lightcolor, intensity, radius, falloff); | 9086 | SetPointLight(part, light, lightcolor, intensity, radius, falloff); |
7571 | 9087 | ||
7572 | break; | 9088 | break; |
7573 | 9089 | ||
7574 | case (int)ScriptBaseClass.PRIM_GLOW: | 9090 | case ScriptBaseClass.PRIM_GLOW: |
7575 | if (remain < 2) | 9091 | if (remain < 2) |
7576 | return null; | 9092 | return new LSL_List(); |
7577 | face = rules.GetLSLIntegerItem(idx++); | 9093 | |
7578 | float glow = (float)rules.GetLSLFloatItem(idx++); | 9094 | float glow; |
9095 | |||
9096 | try | ||
9097 | { | ||
9098 | face = rules.GetLSLIntegerItem(idx++); | ||
9099 | } | ||
9100 | catch(InvalidCastException) | ||
9101 | { | ||
9102 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9103 | return new LSL_List(); | ||
9104 | } | ||
9105 | try | ||
9106 | { | ||
9107 | glow = (float)rules.GetLSLFloatItem(idx++); | ||
9108 | } | ||
9109 | catch(InvalidCastException) | ||
9110 | { | ||
9111 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); | ||
9112 | return new LSL_List(); | ||
9113 | } | ||
7579 | 9114 | ||
7580 | SetGlow(part, face, glow); | 9115 | SetGlow(part, face, glow); |
7581 | 9116 | ||
7582 | break; | 9117 | break; |
7583 | 9118 | ||
7584 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | 9119 | case ScriptBaseClass.PRIM_BUMP_SHINY: |
7585 | if (remain < 3) | 9120 | if (remain < 3) |
7586 | return null; | 9121 | return new LSL_List(); |
7587 | face = (int)rules.GetLSLIntegerItem(idx++); | 9122 | |
7588 | int shiny = (int)rules.GetLSLIntegerItem(idx++); | 9123 | int shiny; |
7589 | Bumpiness bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); | 9124 | Bumpiness bump; |
9125 | |||
9126 | try | ||
9127 | { | ||
9128 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
9129 | } | ||
9130 | catch(InvalidCastException) | ||
9131 | { | ||
9132 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9133 | return new LSL_List(); | ||
9134 | } | ||
9135 | try | ||
9136 | { | ||
9137 | shiny = (int)rules.GetLSLIntegerItem(idx++); | ||
9138 | } | ||
9139 | catch(InvalidCastException) | ||
9140 | { | ||
9141 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9142 | return new LSL_List(); | ||
9143 | } | ||
9144 | try | ||
9145 | { | ||
9146 | bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); | ||
9147 | } | ||
9148 | catch(InvalidCastException) | ||
9149 | { | ||
9150 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9151 | return new LSL_List(); | ||
9152 | } | ||
7590 | 9153 | ||
7591 | SetShiny(part, face, shiny, bump); | 9154 | SetShiny(part, face, shiny, bump); |
7592 | 9155 | ||
7593 | break; | 9156 | break; |
7594 | 9157 | ||
7595 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | 9158 | case ScriptBaseClass.PRIM_FULLBRIGHT: |
7596 | if (remain < 2) | 9159 | if (remain < 2) |
7597 | return null; | 9160 | return new LSL_List(); |
7598 | face = rules.GetLSLIntegerItem(idx++); | 9161 | bool st; |
7599 | bool st = rules.GetLSLIntegerItem(idx++); | 9162 | |
7600 | SetFullBright(part, face , st); | 9163 | try |
7601 | break; | 9164 | { |
9165 | face = rules.GetLSLIntegerItem(idx++); | ||
9166 | } | ||
9167 | catch(InvalidCastException) | ||
9168 | { | ||
9169 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9170 | return new LSL_List(); | ||
9171 | } | ||
9172 | try | ||
9173 | { | ||
9174 | st = rules.GetLSLIntegerItem(idx++); | ||
9175 | } | ||
9176 | catch(InvalidCastException) | ||
9177 | { | ||
9178 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9179 | return new LSL_List(); | ||
9180 | } | ||
9181 | SetFullBright(part, face , st); | ||
9182 | break; | ||
9183 | |||
9184 | case ScriptBaseClass.PRIM_MATERIAL: | ||
9185 | if (remain < 1) | ||
9186 | return new LSL_List(); | ||
9187 | int mat; | ||
9188 | |||
9189 | try | ||
9190 | { | ||
9191 | mat = rules.GetLSLIntegerItem(idx++); | ||
9192 | } | ||
9193 | catch(InvalidCastException) | ||
9194 | { | ||
9195 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_MATERIAL: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9196 | return new LSL_List(); | ||
9197 | } | ||
9198 | if (mat < 0 || mat > 7) | ||
9199 | return new LSL_List(); | ||
7602 | 9200 | ||
7603 | case (int)ScriptBaseClass.PRIM_MATERIAL: | 9201 | part.Material = Convert.ToByte(mat); |
7604 | if (remain < 1) | 9202 | break; |
7605 | return null; | ||
7606 | int mat = rules.GetLSLIntegerItem(idx++); | ||
7607 | if (mat < 0 || mat > 7) | ||
7608 | return null; | ||
7609 | 9203 | ||
7610 | part.Material = Convert.ToByte(mat); | 9204 | case ScriptBaseClass.PRIM_PHANTOM: |
7611 | break; | 9205 | if (remain < 1) |
9206 | return new LSL_List(); | ||
7612 | 9207 | ||
7613 | case (int)ScriptBaseClass.PRIM_PHANTOM: | 9208 | string ph = rules.Data[idx++].ToString(); |
7614 | if (remain < 1) | 9209 | part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); |
7615 | return null; | ||
7616 | 9210 | ||
7617 | string ph = rules.Data[idx++].ToString(); | 9211 | break; |
7618 | m_host.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); | ||
7619 | 9212 | ||
7620 | break; | 9213 | case ScriptBaseClass.PRIM_PHYSICS: |
9214 | if (remain < 1) | ||
9215 | return new LSL_List(); | ||
9216 | string phy = rules.Data[idx++].ToString(); | ||
9217 | part.ScriptSetPhysicsStatus(phy.Equals("1")); | ||
9218 | break; | ||
7621 | 9219 | ||
7622 | case (int)ScriptBaseClass.PRIM_PHYSICS: | 9220 | case ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: |
7623 | if (remain < 1) | 9221 | if (remain < 1) |
7624 | return null; | 9222 | return new LSL_List(); |
7625 | string phy = rules.Data[idx++].ToString(); | ||
7626 | bool physics; | ||
7627 | 9223 | ||
7628 | if (phy.Equals("1")) | 9224 | int shape_type; |
7629 | physics = true; | ||
7630 | else | ||
7631 | physics = false; | ||
7632 | 9225 | ||
7633 | part.ScriptSetPhysicsStatus(physics); | 9226 | try |
7634 | break; | 9227 | { |
9228 | shape_type = rules.GetLSLIntegerItem(idx++); | ||
9229 | } | ||
9230 | catch(InvalidCastException) | ||
9231 | { | ||
9232 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_PHYSICS_SHAPE_TYPE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9233 | return new LSL_List(); | ||
9234 | } | ||
9235 | |||
9236 | ExtraPhysicsData physdata = new ExtraPhysicsData(); | ||
9237 | physdata.Density = part.Density; | ||
9238 | physdata.Bounce = part.Restitution; | ||
9239 | physdata.GravitationModifier = part.GravityModifier; | ||
9240 | physdata.PhysShapeType = (PhysShapeType)shape_type; | ||
9241 | |||
9242 | part.UpdateExtraPhysics(physdata); | ||
7635 | 9243 | ||
7636 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | 9244 | break; |
9245 | |||
9246 | case ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
7637 | if (remain < 1) | 9247 | if (remain < 1) |
7638 | return null; | 9248 | return new LSL_List(); |
7639 | string temp = rules.Data[idx++].ToString(); | 9249 | string temp = rules.Data[idx++].ToString(); |
7640 | 9250 | ||
7641 | m_host.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); | 9251 | part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); |
7642 | 9252 | ||
7643 | break; | 9253 | break; |
7644 | 9254 | ||
7645 | case (int)ScriptBaseClass.PRIM_TEXGEN: | 9255 | case ScriptBaseClass.PRIM_TEXGEN: |
7646 | if (remain < 2) | 9256 | if (remain < 2) |
7647 | return null; | 9257 | return new LSL_List(); |
7648 | //face,type | 9258 | //face,type |
7649 | face = rules.GetLSLIntegerItem(idx++); | 9259 | int style; |
7650 | int style = rules.GetLSLIntegerItem(idx++); | 9260 | |
9261 | try | ||
9262 | { | ||
9263 | face = rules.GetLSLIntegerItem(idx++); | ||
9264 | } | ||
9265 | catch(InvalidCastException) | ||
9266 | { | ||
9267 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9268 | return new LSL_List(); | ||
9269 | } | ||
9270 | try | ||
9271 | { | ||
9272 | style = rules.GetLSLIntegerItem(idx++); | ||
9273 | } | ||
9274 | catch(InvalidCastException) | ||
9275 | { | ||
9276 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | ||
9277 | return new LSL_List(); | ||
9278 | } | ||
7651 | SetTexGen(part, face, style); | 9279 | SetTexGen(part, face, style); |
7652 | break; | 9280 | break; |
7653 | case (int)ScriptBaseClass.PRIM_TEXT: | 9281 | case ScriptBaseClass.PRIM_TEXT: |
7654 | if (remain < 3) | 9282 | if (remain < 3) |
7655 | return null; | 9283 | return new LSL_List(); |
7656 | string primText = rules.GetLSLStringItem(idx++); | 9284 | string primText; |
7657 | LSL_Vector primTextColor = rules.GetVector3Item(idx++); | 9285 | LSL_Vector primTextColor; |
7658 | LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); | 9286 | LSL_Float primTextAlpha; |
9287 | |||
9288 | try | ||
9289 | { | ||
9290 | primText = rules.GetLSLStringItem(idx++); | ||
9291 | } | ||
9292 | catch(InvalidCastException) | ||
9293 | { | ||
9294 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); | ||
9295 | return new LSL_List(); | ||
9296 | } | ||
9297 | try | ||
9298 | { | ||
9299 | primTextColor = rules.GetVector3Item(idx++); | ||
9300 | } | ||
9301 | catch(InvalidCastException) | ||
9302 | { | ||
9303 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | ||
9304 | return new LSL_List(); | ||
9305 | } | ||
9306 | try | ||
9307 | { | ||
9308 | primTextAlpha = rules.GetLSLFloatItem(idx++); | ||
9309 | } | ||
9310 | catch(InvalidCastException) | ||
9311 | { | ||
9312 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | ||
9313 | return new LSL_List(); | ||
9314 | } | ||
7659 | Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); | 9315 | Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); |
7660 | part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); | 9316 | part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); |
7661 | 9317 | ||
7662 | break; | 9318 | break; |
7663 | case (int)ScriptBaseClass.PRIM_NAME: | 9319 | |
9320 | case ScriptBaseClass.PRIM_NAME: | ||
7664 | if (remain < 1) | 9321 | if (remain < 1) |
7665 | return null; | 9322 | return new LSL_List(); |
7666 | string primName = rules.GetLSLStringItem(idx++); | 9323 | try |
7667 | part.Name = primName; | 9324 | { |
9325 | string primName = rules.GetLSLStringItem(idx++); | ||
9326 | part.Name = primName; | ||
9327 | } | ||
9328 | catch(InvalidCastException) | ||
9329 | { | ||
9330 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NAME: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); | ||
9331 | return new LSL_List(); | ||
9332 | } | ||
7668 | break; | 9333 | break; |
7669 | case (int)ScriptBaseClass.PRIM_DESC: | 9334 | case ScriptBaseClass.PRIM_DESC: |
7670 | if (remain < 1) | 9335 | if (remain < 1) |
7671 | return null; | 9336 | return new LSL_List(); |
7672 | string primDesc = rules.GetLSLStringItem(idx++); | 9337 | try |
7673 | part.Description = primDesc; | 9338 | { |
9339 | string primDesc = rules.GetLSLStringItem(idx++); | ||
9340 | part.Description = primDesc; | ||
9341 | } | ||
9342 | catch(InvalidCastException) | ||
9343 | { | ||
9344 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_DESC: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); | ||
9345 | return new LSL_List(); | ||
9346 | } | ||
7674 | break; | 9347 | break; |
7675 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | 9348 | case ScriptBaseClass.PRIM_ROT_LOCAL: |
7676 | if (remain < 1) | 9349 | if (remain < 1) |
7677 | return null; | 9350 | return new LSL_List(); |
7678 | SetRot(part, rules.GetQuaternionItem(idx++)); | 9351 | LSL_Rotation rot; |
9352 | try | ||
9353 | { | ||
9354 | rot = rules.GetQuaternionItem(idx++); | ||
9355 | } | ||
9356 | catch(InvalidCastException) | ||
9357 | { | ||
9358 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); | ||
9359 | return new LSL_List(); | ||
9360 | } | ||
9361 | SetRot(part, rot); | ||
7679 | break; | 9362 | break; |
7680 | case (int)ScriptBaseClass.PRIM_OMEGA: | 9363 | |
9364 | case ScriptBaseClass.PRIM_OMEGA: | ||
7681 | if (remain < 3) | 9365 | if (remain < 3) |
7682 | return null; | 9366 | return new LSL_List(); |
7683 | LSL_Vector axis = rules.GetVector3Item(idx++); | 9367 | LSL_Vector axis; |
7684 | LSL_Float spinrate = rules.GetLSLFloatItem(idx++); | 9368 | LSL_Float spinrate; |
7685 | LSL_Float gain = rules.GetLSLFloatItem(idx++); | 9369 | LSL_Float gain; |
9370 | |||
9371 | try | ||
9372 | { | ||
9373 | axis = rules.GetVector3Item(idx++); | ||
9374 | } | ||
9375 | catch(InvalidCastException) | ||
9376 | { | ||
9377 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | ||
9378 | return new LSL_List(); | ||
9379 | } | ||
9380 | try | ||
9381 | { | ||
9382 | spinrate = rules.GetLSLFloatItem(idx++); | ||
9383 | } | ||
9384 | catch(InvalidCastException) | ||
9385 | { | ||
9386 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); | ||
9387 | return new LSL_List(); | ||
9388 | } | ||
9389 | try | ||
9390 | { | ||
9391 | gain = rules.GetLSLFloatItem(idx++); | ||
9392 | } | ||
9393 | catch(InvalidCastException) | ||
9394 | { | ||
9395 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | ||
9396 | return new LSL_List(); | ||
9397 | } | ||
7686 | TargetOmega(part, axis, (double)spinrate, (double)gain); | 9398 | TargetOmega(part, axis, (double)spinrate, (double)gain); |
7687 | break; | 9399 | break; |
7688 | case (int)ScriptBaseClass.PRIM_SLICE: | 9400 | |
9401 | case ScriptBaseClass.PRIM_SLICE: | ||
7689 | if (remain < 1) | 9402 | if (remain < 1) |
7690 | return null; | 9403 | return new LSL_List(); |
7691 | LSL_Vector slice = rules.GetVector3Item(idx++); | 9404 | LSL_Vector slice; |
9405 | try | ||
9406 | { | ||
9407 | slice = rules.GetVector3Item(idx++); | ||
9408 | } | ||
9409 | catch(InvalidCastException) | ||
9410 | { | ||
9411 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SLICE: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | ||
9412 | return new LSL_List(); | ||
9413 | } | ||
7692 | part.UpdateSlice((float)slice.x, (float)slice.y); | 9414 | part.UpdateSlice((float)slice.x, (float)slice.y); |
7693 | break; | 9415 | break; |
7694 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | 9416 | |
9417 | case ScriptBaseClass.PRIM_LINK_TARGET: | ||
7695 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | 9418 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. |
7696 | return null; | 9419 | return new LSL_List(); |
7697 | 9420 | ||
7698 | return rules.GetSublist(idx, -1); | 9421 | return rules.GetSublist(idx, -1); |
9422 | |||
9423 | default: | ||
9424 | Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - unsupported parameter", rulesParsed, idx - idxStart)); | ||
9425 | return new LSL_List(); | ||
7699 | } | 9426 | } |
7700 | } | 9427 | } |
7701 | } | 9428 | } |
7702 | catch (InvalidCastException e) | 9429 | catch (InvalidCastException e) |
7703 | { | 9430 | { |
7704 | ShoutError(string.Format( | 9431 | Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); |
7705 | "{0} error running rule #{1}: arg #{2} ", | ||
7706 | originFunc, rulesParsed, idx - idxStart) + e.Message); | ||
7707 | } | 9432 | } |
7708 | finally | 9433 | finally |
7709 | { | 9434 | { |
@@ -7723,7 +9448,118 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7723 | } | 9448 | } |
7724 | } | 9449 | } |
7725 | } | 9450 | } |
7726 | return null; | 9451 | |
9452 | return new LSL_List(); | ||
9453 | } | ||
9454 | |||
9455 | protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed) | ||
9456 | { | ||
9457 | int idx = 0; | ||
9458 | int idxStart = 0; | ||
9459 | |||
9460 | try | ||
9461 | { | ||
9462 | while (idx < rules.Length) | ||
9463 | { | ||
9464 | ++rulesParsed; | ||
9465 | int code = rules.GetLSLIntegerItem(idx++); | ||
9466 | |||
9467 | int remain = rules.Length - idx; | ||
9468 | idxStart = idx; | ||
9469 | |||
9470 | switch (code) | ||
9471 | { | ||
9472 | case ScriptBaseClass.PRIM_POSITION: | ||
9473 | case ScriptBaseClass.PRIM_POS_LOCAL: | ||
9474 | if (remain < 1) | ||
9475 | return new LSL_List(); | ||
9476 | |||
9477 | try | ||
9478 | { | ||
9479 | sp.OffsetPosition = rules.GetVector3Item(idx++); | ||
9480 | } | ||
9481 | catch(InvalidCastException) | ||
9482 | { | ||
9483 | if (code == ScriptBaseClass.PRIM_POSITION) | ||
9484 | { | ||
9485 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | ||
9486 | } | ||
9487 | else | ||
9488 | { | ||
9489 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | ||
9490 | } | ||
9491 | return new LSL_List(); | ||
9492 | } | ||
9493 | break; | ||
9494 | |||
9495 | case ScriptBaseClass.PRIM_ROTATION: | ||
9496 | if (remain < 1) | ||
9497 | return new LSL_List(); | ||
9498 | |||
9499 | Quaternion inRot; | ||
9500 | |||
9501 | try | ||
9502 | { | ||
9503 | inRot = rules.GetQuaternionItem(idx++); | ||
9504 | } | ||
9505 | catch(InvalidCastException) | ||
9506 | { | ||
9507 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); | ||
9508 | return new LSL_List(); | ||
9509 | } | ||
9510 | |||
9511 | SceneObjectPart parentPart = sp.ParentPart; | ||
9512 | |||
9513 | if (parentPart != null) | ||
9514 | sp.Rotation = m_host.GetWorldRotation() * inRot; | ||
9515 | |||
9516 | break; | ||
9517 | |||
9518 | case ScriptBaseClass.PRIM_ROT_LOCAL: | ||
9519 | if (remain < 1) | ||
9520 | return new LSL_List(); | ||
9521 | |||
9522 | try | ||
9523 | { | ||
9524 | sp.Rotation = rules.GetQuaternionItem(idx++); | ||
9525 | } | ||
9526 | catch(InvalidCastException) | ||
9527 | { | ||
9528 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); | ||
9529 | return new LSL_List(); | ||
9530 | } | ||
9531 | |||
9532 | break; | ||
9533 | |||
9534 | case ScriptBaseClass.PRIM_TYPE: | ||
9535 | Error(originFunc, "PRIM_TYPE disallowed on agent"); | ||
9536 | return new LSL_List(); | ||
9537 | |||
9538 | case ScriptBaseClass.PRIM_OMEGA: | ||
9539 | Error(originFunc, "PRIM_OMEGA disallowed on agent"); | ||
9540 | return new LSL_List(); | ||
9541 | |||
9542 | case ScriptBaseClass.PRIM_LINK_TARGET: | ||
9543 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | ||
9544 | return new LSL_List(); | ||
9545 | |||
9546 | return rules.GetSublist(idx, -1); | ||
9547 | |||
9548 | default: | ||
9549 | Error(originFunc, | ||
9550 | string.Format("Error running rule #{0} on agent: arg #{1} - disallowed on agent", rulesParsed, idx - idxStart)); | ||
9551 | return new LSL_List(); | ||
9552 | } | ||
9553 | } | ||
9554 | } | ||
9555 | catch (InvalidCastException e) | ||
9556 | { | ||
9557 | Error( | ||
9558 | originFunc, | ||
9559 | string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); | ||
9560 | } | ||
9561 | |||
9562 | return new LSL_List(); | ||
7727 | } | 9563 | } |
7728 | 9564 | ||
7729 | public LSL_String llStringToBase64(string str) | 9565 | public LSL_String llStringToBase64(string str) |
@@ -7731,14 +9567,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7731 | m_host.AddScriptLPS(1); | 9567 | m_host.AddScriptLPS(1); |
7732 | try | 9568 | try |
7733 | { | 9569 | { |
7734 | byte[] encData_byte = new byte[str.Length]; | 9570 | byte[] encData_byte; |
7735 | encData_byte = Util.UTF8.GetBytes(str); | 9571 | encData_byte = Util.UTF8.GetBytes(str); |
7736 | string encodedData = Convert.ToBase64String(encData_byte); | 9572 | string encodedData = Convert.ToBase64String(encData_byte); |
7737 | return encodedData; | 9573 | return encodedData; |
7738 | } | 9574 | } |
7739 | catch (Exception e) | 9575 | catch |
7740 | { | 9576 | { |
7741 | throw new Exception("Error in base64Encode" + e.Message); | 9577 | Error("llBase64ToString", "Error encoding string"); |
9578 | return String.Empty; | ||
7742 | } | 9579 | } |
7743 | } | 9580 | } |
7744 | 9581 | ||
@@ -7747,26 +9584,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7747 | m_host.AddScriptLPS(1); | 9584 | m_host.AddScriptLPS(1); |
7748 | try | 9585 | try |
7749 | { | 9586 | { |
7750 | return Util.Base64ToString(str); | 9587 | byte[] b = Convert.FromBase64String(str); |
9588 | return Encoding.UTF8.GetString(b); | ||
7751 | } | 9589 | } |
7752 | catch (Exception e) | 9590 | catch |
7753 | { | 9591 | { |
7754 | throw new Exception("Error in base64Decode" + e.Message); | 9592 | Error("llBase64ToString", "Error decoding string"); |
9593 | return String.Empty; | ||
7755 | } | 9594 | } |
7756 | } | 9595 | } |
7757 | 9596 | ||
7758 | public LSL_String llXorBase64Strings(string str1, string str2) | 9597 | public LSL_String llXorBase64Strings(string str1, string str2) |
7759 | { | 9598 | { |
7760 | m_host.AddScriptLPS(1); | 9599 | m_host.AddScriptLPS(1); |
7761 | Deprecated("llXorBase64Strings"); | 9600 | Deprecated("llXorBase64Strings", "Use llXorBase64 instead"); |
7762 | ScriptSleep(300); | 9601 | ScriptSleep(m_sleepMsOnXorBase64Strings); |
7763 | return String.Empty; | 9602 | return String.Empty; |
7764 | } | 9603 | } |
7765 | 9604 | ||
7766 | public void llRemoteDataSetRegion() | 9605 | public void llRemoteDataSetRegion() |
7767 | { | 9606 | { |
7768 | m_host.AddScriptLPS(1); | 9607 | m_host.AddScriptLPS(1); |
7769 | Deprecated("llRemoteDataSetRegion"); | 9608 | Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead"); |
7770 | } | 9609 | } |
7771 | 9610 | ||
7772 | public LSL_Float llLog10(double val) | 9611 | public LSL_Float llLog10(double val) |
@@ -7800,21 +9639,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7800 | { | 9639 | { |
7801 | m_host.AddScriptLPS(1); | 9640 | m_host.AddScriptLPS(1); |
7802 | 9641 | ||
7803 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 9642 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
7804 | 9643 | ||
7805 | if (land.LandData.OwnerID != m_host.OwnerID) | 9644 | if (land.LandData.OwnerID != m_host.OwnerID) |
7806 | return; | 9645 | return; |
7807 | 9646 | ||
7808 | land.SetMusicUrl(url); | 9647 | land.SetMusicUrl(url); |
7809 | 9648 | ||
7810 | ScriptSleep(2000); | 9649 | ScriptSleep(m_sleepMsOnSetParcelMusicURL); |
7811 | } | 9650 | } |
7812 | 9651 | ||
7813 | public LSL_String llGetParcelMusicURL() | 9652 | public LSL_String llGetParcelMusicURL() |
7814 | { | 9653 | { |
7815 | m_host.AddScriptLPS(1); | 9654 | m_host.AddScriptLPS(1); |
7816 | 9655 | ||
7817 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 9656 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
7818 | 9657 | ||
7819 | if (land.LandData.OwnerID != m_host.OwnerID) | 9658 | if (land.LandData.OwnerID != m_host.OwnerID) |
7820 | return String.Empty; | 9659 | return String.Empty; |
@@ -7825,8 +9664,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7825 | public LSL_Vector llGetRootPosition() | 9664 | public LSL_Vector llGetRootPosition() |
7826 | { | 9665 | { |
7827 | m_host.AddScriptLPS(1); | 9666 | m_host.AddScriptLPS(1); |
7828 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, | 9667 | |
7829 | m_host.ParentGroup.AbsolutePosition.Z); | 9668 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition); |
7830 | } | 9669 | } |
7831 | 9670 | ||
7832 | /// <summary> | 9671 | /// <summary> |
@@ -7849,13 +9688,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7849 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) | 9688 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) |
7850 | q = avatar.CameraRotation; // Mouselook | 9689 | q = avatar.CameraRotation; // Mouselook |
7851 | else | 9690 | else |
7852 | q = avatar.Rotation; // Currently infrequently updated so may be inaccurate | 9691 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate |
7853 | else | 9692 | else |
7854 | q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case | 9693 | q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case |
7855 | } | 9694 | } |
7856 | else | 9695 | else |
7857 | q = m_host.ParentGroup.GroupRotation; // just the group rotation | 9696 | q = m_host.ParentGroup.GroupRotation; // just the group rotation |
7858 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 9697 | |
9698 | return new LSL_Rotation(q); | ||
7859 | } | 9699 | } |
7860 | 9700 | ||
7861 | public LSL_String llGetObjectDesc() | 9701 | public LSL_String llGetObjectDesc() |
@@ -7889,137 +9729,668 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
7889 | } | 9729 | } |
7890 | 9730 | ||
7891 | /// <summary> | 9731 | /// <summary> |
7892 | /// A partial implementation. | 9732 | /// Full implementation of llGetBoundingBox according to SL 2015-04-15. |
9733 | /// http://wiki.secondlife.com/wiki/LlGetBoundingBox | ||
7893 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox | 9734 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox |
7894 | /// So far only valid for standing/flying/ground sitting avatars and single prim objects. | 9735 | /// Returns local bounding box of avatar without attachments |
7895 | /// If the object has multiple prims and/or a sitting avatar then the bounding | 9736 | /// if target is non-seated avatar or prim/mesh in avatar attachment. |
7896 | /// box is for the root prim only. | 9737 | /// Returns local bounding box of object including seated avatars |
9738 | /// if target is seated avatar or prim/mesh in object. | ||
9739 | /// Uses meshing of prims for high accuracy | ||
9740 | /// or less accurate box models for speed. | ||
7897 | /// </summary> | 9741 | /// </summary> |
7898 | public LSL_List llGetBoundingBox(string obj) | 9742 | public LSL_List llGetBoundingBox(string obj) |
7899 | { | 9743 | { |
7900 | m_host.AddScriptLPS(1); | 9744 | m_host.AddScriptLPS(1); |
9745 | |||
9746 | // Get target avatar if non-seated avatar or attachment, or prim and object | ||
7901 | UUID objID = UUID.Zero; | 9747 | UUID objID = UUID.Zero; |
9748 | UUID.TryParse(obj, out objID); | ||
9749 | ScenePresence agent = World.GetScenePresence(objID); | ||
9750 | if (agent != null) | ||
9751 | { | ||
9752 | if (agent.ParentPart != null) | ||
9753 | { | ||
9754 | objID = agent.ParentPart.UUID; | ||
9755 | agent = null; | ||
9756 | } | ||
9757 | } | ||
9758 | SceneObjectGroup group = null; | ||
9759 | SceneObjectPart target = World.GetSceneObjectPart(objID); | ||
9760 | if (target != null) | ||
9761 | { | ||
9762 | group = target.ParentGroup; | ||
9763 | if (group.IsAttachment) { | ||
9764 | objID = group.AttachedAvatar; | ||
9765 | agent = World.GetScenePresence(objID); | ||
9766 | group = null; | ||
9767 | target = null; | ||
9768 | } | ||
9769 | } | ||
9770 | |||
9771 | // Initialize but break if no target | ||
7902 | LSL_List result = new LSL_List(); | 9772 | LSL_List result = new LSL_List(); |
7903 | if (!UUID.TryParse(obj, out objID)) | 9773 | int groupCount = 0; |
9774 | int partCount = 0; | ||
9775 | int vertexCount = 0; | ||
9776 | if (target == null && agent == null) | ||
7904 | { | 9777 | { |
7905 | result.Add(new LSL_Vector()); | 9778 | result.Add(new LSL_Vector()); |
7906 | result.Add(new LSL_Vector()); | 9779 | result.Add(new LSL_Vector()); |
9780 | if (m_addStatsInGetBoundingBox) | ||
9781 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | ||
7907 | return result; | 9782 | return result; |
7908 | } | 9783 | } |
7909 | ScenePresence presence = World.GetScenePresence(objID); | 9784 | Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); |
7910 | if (presence != null) | 9785 | Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue); |
9786 | |||
9787 | // Try to get a mesher | ||
9788 | IRendering primMesher = null; | ||
9789 | List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); | ||
9790 | if (renderers.Count > 0) | ||
9791 | primMesher = RenderingLoader.LoadRenderer(renderers[0]); | ||
9792 | |||
9793 | // Get bounding box of just avatar, seated or not | ||
9794 | if (agent != null) | ||
9795 | { | ||
9796 | bool hasParent = false; | ||
9797 | Vector3 lower; | ||
9798 | Vector3 upper; | ||
9799 | BoundingBoxOfScenePresence(agent, out lower, out upper); | ||
9800 | Vector3 offset = Vector3.Zero; | ||
9801 | |||
9802 | // Since local bounding box unrotated and untilted, keep it simple | ||
9803 | AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9804 | partCount++; | ||
9805 | groupCount++; | ||
9806 | |||
9807 | // Return lower and upper bounding box corners | ||
9808 | result.Add(new LSL_Vector(minPosition)); | ||
9809 | result.Add(new LSL_Vector(maxPosition)); | ||
9810 | if (m_addStatsInGetBoundingBox) | ||
9811 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | ||
9812 | return result; | ||
9813 | } | ||
9814 | // Get bounding box of object including seated avatars | ||
9815 | else if (group != null) | ||
7911 | { | 9816 | { |
7912 | if (presence.ParentID == 0) // not sat on an object | 9817 | // Merge bounding boxes of all parts (prims and mesh) |
9818 | foreach (SceneObjectPart part in group.Parts) | ||
7913 | { | 9819 | { |
7914 | LSL_Vector lower; | 9820 | bool hasParent = (!part.IsRoot); |
7915 | LSL_Vector upper; | 9821 | // When requested or if no mesher, keep it simple |
7916 | if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID | 9822 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) |
7917 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | ||
7918 | { | 9823 | { |
7919 | // This is for ground sitting avatars | 9824 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
7920 | float height = presence.Appearance.AvatarHeight / 2.66666667f; | ||
7921 | lower = new LSL_Vector(-0.3375f, -0.45f, height * -1.0f); | ||
7922 | upper = new LSL_Vector(0.3375f, 0.45f, 0.0f); | ||
7923 | } | 9825 | } |
9826 | // Do the full mounty | ||
7924 | else | 9827 | else |
7925 | { | 9828 | { |
7926 | // This is for standing/flying avatars | 9829 | Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset); |
7927 | float height = presence.Appearance.AvatarHeight / 2.0f; | 9830 | byte[] sculptAsset = null; |
7928 | lower = new LSL_Vector(-0.225f, -0.3f, height * -1.0f); | 9831 | if (omvPrim.Sculpt != null) |
7929 | upper = new LSL_Vector(0.225f, 0.3f, height + 0.05f); | 9832 | sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); |
9833 | |||
9834 | // When part is mesh | ||
9835 | // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler. | ||
9836 | if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) | ||
9837 | { | ||
9838 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); | ||
9839 | FacetedMesh mesh = null; | ||
9840 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); | ||
9841 | meshAsset = null; | ||
9842 | if (mesh != null) | ||
9843 | { | ||
9844 | AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9845 | mesh = null; | ||
9846 | } | ||
9847 | } | ||
9848 | |||
9849 | // When part is sculpt | ||
9850 | // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. | ||
9851 | else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) | ||
9852 | { | ||
9853 | IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); | ||
9854 | if (imgDecoder != null) | ||
9855 | { | ||
9856 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); | ||
9857 | if (sculpt != null) | ||
9858 | { | ||
9859 | SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); | ||
9860 | sculpt.Dispose(); | ||
9861 | if (mesh != null) | ||
9862 | { | ||
9863 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9864 | mesh = null; | ||
9865 | } | ||
9866 | } | ||
9867 | } | ||
9868 | } | ||
9869 | |||
9870 | // When part is prim | ||
9871 | else if (omvPrim.Sculpt == null) | ||
9872 | { | ||
9873 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); | ||
9874 | if (mesh != null) | ||
9875 | { | ||
9876 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9877 | mesh = null; | ||
9878 | } | ||
9879 | } | ||
9880 | |||
9881 | // When all else fails, try fallback to simple box | ||
9882 | else | ||
9883 | { | ||
9884 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9885 | } | ||
7930 | } | 9886 | } |
7931 | result.Add(lower); | 9887 | partCount++; |
7932 | result.Add(upper); | ||
7933 | return result; | ||
7934 | } | 9888 | } |
9889 | } | ||
9890 | |||
9891 | // Merge bounding boxes of seated avatars | ||
9892 | foreach (ScenePresence sp in group.GetSittingAvatars()) | ||
9893 | { | ||
9894 | Vector3 lower; | ||
9895 | Vector3 upper; | ||
9896 | BoundingBoxOfScenePresence(sp, out lower, out upper); | ||
9897 | Vector3 offset = sp.OffsetPosition; | ||
9898 | |||
9899 | bool hasParent = true; | ||
9900 | // When requested or if no mesher, keep it simple | ||
9901 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) | ||
9902 | { | ||
9903 | AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | ||
9904 | } | ||
9905 | // Do the full mounty | ||
7935 | else | 9906 | else |
7936 | { | 9907 | { |
7937 | // sitting on an object so we need the bounding box of that | 9908 | // Prim shapes don't do center offsets, so add it here. |
7938 | // which should include the avatar so set the UUID to the | 9909 | offset = offset + (lower + upper) * 0.5f * sp.Rotation; |
7939 | // UUID of the object the avatar is sat on and allow it to fall through | 9910 | Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); |
7940 | // to processing an object | 9911 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); |
7941 | SceneObjectPart p = World.GetSceneObjectPart(presence.ParentID); | 9912 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
7942 | objID = p.UUID; | 9913 | mesh = null; |
7943 | } | 9914 | } |
9915 | partCount++; | ||
7944 | } | 9916 | } |
7945 | SceneObjectPart part = World.GetSceneObjectPart(objID); | 9917 | |
7946 | // Currently only works for single prims without a sitting avatar | 9918 | groupCount++; |
7947 | if (part != null) | 9919 | |
9920 | // Return lower and upper bounding box corners | ||
9921 | result.Add(new LSL_Vector(minPosition)); | ||
9922 | result.Add(new LSL_Vector(maxPosition)); | ||
9923 | if (m_addStatsInGetBoundingBox) | ||
9924 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | ||
9925 | |||
9926 | primMesher = null; | ||
9927 | return result; | ||
9928 | } | ||
9929 | |||
9930 | /// <summary> | ||
9931 | /// Helper to calculate bounding box of an avatar. | ||
9932 | /// </summary> | ||
9933 | private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) | ||
9934 | { | ||
9935 | // Adjust from OS model | ||
9936 | // avatar height = visual height - 0.2, bounding box height = visual height | ||
9937 | // to SL model | ||
9938 | // avatar height = visual height, bounding box height = visual height + 0.2 | ||
9939 | float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; | ||
9940 | |||
9941 | // According to avatar bounding box in SL 2015-04-18: | ||
9942 | // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> | ||
9943 | // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> | ||
9944 | // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> | ||
9945 | |||
9946 | // When avatar is sitting | ||
9947 | if (sp.ParentPart != null) | ||
7948 | { | 9948 | { |
7949 | Vector3 halfSize = part.Scale / 2.0f; | 9949 | lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); |
7950 | LSL_Vector lower = (new LSL_Vector(halfSize)) * -1.0f; | 9950 | upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); |
7951 | LSL_Vector upper = new LSL_Vector(halfSize); | 9951 | } |
7952 | result.Add(lower); | 9952 | // When avatar is groundsitting |
7953 | result.Add(upper); | 9953 | else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) |
7954 | return result; | 9954 | { |
9955 | lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); | ||
9956 | upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); | ||
9957 | } | ||
9958 | // When avatar is standing or flying | ||
9959 | else | ||
9960 | { | ||
9961 | lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); | ||
9962 | upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); | ||
7955 | } | 9963 | } |
9964 | } | ||
7956 | 9965 | ||
7957 | // Not found so return empty values | 9966 | /// <summary> |
7958 | result.Add(new LSL_Vector()); | 9967 | /// Helper to approximate a part with a simple box. |
7959 | result.Add(new LSL_Vector()); | 9968 | /// </summary> |
7960 | return result; | 9969 | private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) |
9970 | { | ||
9971 | // Parse the 8 box corners | ||
9972 | for (int i = 0; i < 8; i++) | ||
9973 | { | ||
9974 | // Calculate each box corner | ||
9975 | Vector3 position = corner1; | ||
9976 | if ((i & 1) != 0) | ||
9977 | position.X = corner2.X; | ||
9978 | if ((i & 2) != 0) | ||
9979 | position.Y = corner2.Y; | ||
9980 | if ((i & 4) != 0) | ||
9981 | position.Z = corner2.Z; | ||
9982 | // Rotate part unless part is root | ||
9983 | if (hasParent) | ||
9984 | position = position * rotation; | ||
9985 | position = position + offset; | ||
9986 | // Adjust lower and upper bounding box corners if needed | ||
9987 | lower = Vector3.Min(lower, position); | ||
9988 | upper = Vector3.Max(upper, position); | ||
9989 | count++; | ||
9990 | } | ||
7961 | } | 9991 | } |
7962 | 9992 | ||
7963 | public LSL_Vector llGetGeometricCenter() | 9993 | /// <summary> |
9994 | /// Helper to parse a meshed prim and needed especially | ||
9995 | /// for accuracy with tortured prims and sculpts. | ||
9996 | /// </summary> | ||
9997 | private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | ||
7964 | { | 9998 | { |
7965 | return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); | 9999 | // Quirk: A meshed box contains 10 instead of the 8 necessary vertices. |
10000 | if (mesh != null) | ||
10001 | { | ||
10002 | // Parse each vertex in mesh | ||
10003 | foreach (Vertex vertex in mesh.Vertices) | ||
10004 | { | ||
10005 | Vector3 position = vertex.Position; | ||
10006 | position = position * prim.Scale; | ||
10007 | // Rotate part unless part is root | ||
10008 | if (hasParent) | ||
10009 | position = position * prim.Rotation; | ||
10010 | position = position + prim.Position; | ||
10011 | // Adjust lower and upper bounding box corners if needed | ||
10012 | lower = Vector3.Min(lower, position); | ||
10013 | upper = Vector3.Max(upper, position); | ||
10014 | count++; | ||
10015 | } | ||
10016 | } | ||
7966 | } | 10017 | } |
7967 | 10018 | ||
7968 | public LSL_List llGetPrimitiveParams(LSL_List rules) | 10019 | /// <summary> |
10020 | /// Helper to parse mesh because no method exists | ||
10021 | /// to parse mesh assets to SimpleMesh. | ||
10022 | /// </summary> | ||
10023 | private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | ||
7969 | { | 10024 | { |
7970 | m_host.AddScriptLPS(1); | 10025 | if (mesh != null) |
10026 | { | ||
10027 | // Parse each face in mesh | ||
10028 | // since vertex array isn't populated. | ||
10029 | // This parses each unique vertex 3-6 times. | ||
10030 | foreach (Face face in mesh.Faces) | ||
10031 | { | ||
10032 | // Parse each vertex in face | ||
10033 | foreach (Vertex vertex in face.Vertices) | ||
10034 | { | ||
10035 | Vector3 position = vertex.Position; | ||
10036 | position = position * prim.Scale; | ||
10037 | // Rotate part unless part is root | ||
10038 | if (hasParent) | ||
10039 | position = position * prim.Rotation; | ||
10040 | position = position + prim.Position; | ||
10041 | // Adjust lower and upper bounding box corners if needed | ||
10042 | lower = Vector3.Min(lower, position); | ||
10043 | upper = Vector3.Max(upper, position); | ||
10044 | count++; | ||
10045 | } | ||
10046 | } | ||
10047 | } | ||
10048 | } | ||
7971 | 10049 | ||
7972 | LSL_List result = new LSL_List(); | 10050 | /// <summary> |
10051 | /// Helper to make up an OpenMetaverse prim | ||
10052 | /// needed to create mesh from parts. | ||
10053 | /// </summary> | ||
10054 | private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType) | ||
10055 | { | ||
10056 | // Initialize and set common parameters | ||
10057 | Primitive prim = new OpenMetaverse.Primitive(); | ||
10058 | prim.Scale = scale; | ||
10059 | prim.Position = position; | ||
10060 | prim.Rotation = rotation; | ||
10061 | prim.PrimData.PathShearX = 0.0f; | ||
10062 | prim.PrimData.PathShearY = 0.0f; | ||
10063 | prim.PrimData.PathBegin = 0.0f; | ||
10064 | prim.PrimData.PathEnd = 1.0f; | ||
10065 | prim.PrimData.PathScaleX = 1.0f; | ||
10066 | prim.PrimData.PathScaleY = 1.0f; | ||
10067 | prim.PrimData.PathTaperX = 0.0f; | ||
10068 | prim.PrimData.PathTaperY = 0.0f; | ||
10069 | prim.PrimData.PathTwistBegin = 0.0f; | ||
10070 | prim.PrimData.PathTwist = 0.0f; | ||
10071 | prim.PrimData.ProfileBegin = 0.0f; | ||
10072 | prim.PrimData.ProfileEnd = 1.0f; | ||
10073 | prim.PrimData.ProfileHollow = 0.0f; | ||
10074 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
10075 | prim.PrimData.ProfileHole = (HoleType)0; | ||
10076 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10077 | prim.PrimData.PathRadiusOffset = 0.0f; | ||
10078 | prim.PrimData.PathRevolutions = 1.0f; | ||
10079 | prim.PrimData.PathSkew = 0.0f; | ||
10080 | prim.PrimData.PCode = OpenMetaverse.PCode.Prim; | ||
10081 | prim.PrimData.State = (byte)0; | ||
10082 | |||
10083 | // Set type specific parameters | ||
10084 | switch (primType) | ||
10085 | { | ||
10086 | // Set specific parameters for box | ||
10087 | case ScriptBaseClass.PRIM_TYPE_BOX: | ||
10088 | prim.PrimData.PathScaleY = 1.0f; | ||
10089 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
10090 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10091 | break; | ||
10092 | // Set specific parameters for cylinder | ||
10093 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
10094 | prim.PrimData.PathScaleY = 1.0f; | ||
10095 | prim.PrimData.ProfileCurve = (ProfileCurve)0; | ||
10096 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10097 | break; | ||
10098 | // Set specific parameters for prism | ||
10099 | case ScriptBaseClass.PRIM_TYPE_PRISM: | ||
10100 | prim.PrimData.PathScaleY = 1.0f; | ||
10101 | prim.PrimData.ProfileCurve = (ProfileCurve)3; | ||
10102 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10103 | break; | ||
10104 | // Set specific parameters for sphere | ||
10105 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
10106 | prim.PrimData.PathScaleY = 1.0f; | ||
10107 | prim.PrimData.ProfileCurve = (ProfileCurve)5; | ||
10108 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10109 | break; | ||
10110 | // Set specific parameters for torus | ||
10111 | case ScriptBaseClass.PRIM_TYPE_TORUS: | ||
10112 | prim.PrimData.PathScaleY = 0.5f; | ||
10113 | prim.PrimData.ProfileCurve = (ProfileCurve)0; | ||
10114 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10115 | break; | ||
10116 | // Set specific parameters for tube | ||
10117 | case ScriptBaseClass.PRIM_TYPE_TUBE: | ||
10118 | prim.PrimData.PathScaleY = 0.5f; | ||
10119 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
10120 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10121 | break; | ||
10122 | // Set specific parameters for ring | ||
10123 | case ScriptBaseClass.PRIM_TYPE_RING: | ||
10124 | prim.PrimData.PathScaleY = 0.5f; | ||
10125 | prim.PrimData.ProfileCurve = (ProfileCurve)3; | ||
10126 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10127 | break; | ||
10128 | // Set specific parameters for sculpt | ||
10129 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
10130 | prim.PrimData.PathScaleY = 1.0f; | ||
10131 | prim.PrimData.ProfileCurve = (ProfileCurve)5; | ||
10132 | prim.PrimData.PathCurve = (PathCurve)32; | ||
10133 | break; | ||
10134 | // Default to specific parameters for box | ||
10135 | default: | ||
10136 | prim.PrimData.PathScaleY = 1.0f; | ||
10137 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | ||
10138 | prim.PrimData.PathCurve = (PathCurve)16; | ||
10139 | break; | ||
10140 | } | ||
7973 | 10141 | ||
7974 | LSL_List remaining = GetPrimParams(m_host, rules, ref result); | 10142 | return prim; |
10143 | } | ||
10144 | |||
10145 | /// <summary> | ||
10146 | /// Implementation of llGetGeometricCenter according to SL 2015-04-30. | ||
10147 | /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter | ||
10148 | /// Returns the average position offset of all linked parts, | ||
10149 | /// including the root prim and seated avatars, | ||
10150 | /// relative to the root prim in local coordinates. | ||
10151 | /// </summary> | ||
10152 | public LSL_Vector llGetGeometricCenter() | ||
10153 | { | ||
10154 | // Subtract whatever position the root prim has to make it zero | ||
10155 | Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f; | ||
10156 | |||
10157 | // Add all prim/part position offsets | ||
10158 | foreach (SceneObjectPart part in m_host.ParentGroup.Parts) | ||
10159 | offset = offset + part.OffsetPosition; | ||
10160 | // Add all avatar/scene presence position offsets | ||
10161 | foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars()) | ||
10162 | offset = offset + sp.OffsetPosition; | ||
7975 | 10163 | ||
7976 | while (remaining != null && remaining.Length > 2) | 10164 | // Calculate and return the average offset |
10165 | offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount()); | ||
10166 | return new LSL_Vector(offset); | ||
10167 | } | ||
10168 | |||
10169 | public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) | ||
10170 | { | ||
10171 | LSL_List result = new LSL_List(); | ||
10172 | LSL_List remaining; | ||
10173 | |||
10174 | while (true) | ||
7977 | { | 10175 | { |
10176 | // m_log.DebugFormat( | ||
10177 | // "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}", | ||
10178 | // rules.Length, entity != null ? entity.Name : "NULL"); | ||
10179 | |||
10180 | if (entity == null) | ||
10181 | return result; | ||
10182 | |||
10183 | if (entity is SceneObjectPart) | ||
10184 | remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result); | ||
10185 | else | ||
10186 | remaining = GetAgentParams((ScenePresence)entity, rules, ref result); | ||
10187 | |||
10188 | if (remaining == null || remaining.Length < 2) | ||
10189 | return result; | ||
10190 | |||
7978 | int linknumber = remaining.GetLSLIntegerItem(0); | 10191 | int linknumber = remaining.GetLSLIntegerItem(0); |
7979 | rules = remaining.GetSublist(1, -1); | 10192 | rules = remaining.GetSublist(1, -1); |
7980 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 10193 | entity = GetLinkEntity(m_host, linknumber); |
7981 | |||
7982 | foreach (SceneObjectPart part in parts) | ||
7983 | remaining = GetPrimParams(part, rules, ref result); | ||
7984 | } | 10194 | } |
10195 | } | ||
7985 | 10196 | ||
7986 | return result; | 10197 | public LSL_List llGetPrimitiveParams(LSL_List rules) |
10198 | { | ||
10199 | m_host.AddScriptLPS(1); | ||
10200 | |||
10201 | return GetEntityParams(m_host, rules); | ||
7987 | } | 10202 | } |
7988 | 10203 | ||
7989 | public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) | 10204 | public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) |
7990 | { | 10205 | { |
7991 | m_host.AddScriptLPS(1); | 10206 | m_host.AddScriptLPS(1); |
7992 | 10207 | ||
7993 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 10208 | return GetEntityParams(GetLinkEntity(m_host, linknumber), rules); |
10209 | } | ||
7994 | 10210 | ||
7995 | LSL_List res = new LSL_List(); | 10211 | public LSL_Vector GetAgentSize(ScenePresence sp) |
7996 | LSL_List remaining = null; | 10212 | { |
10213 | return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight); | ||
10214 | } | ||
7997 | 10215 | ||
7998 | foreach (SceneObjectPart part in parts) | 10216 | /// <summary> |
10217 | /// Gets params for a seated avatar in a linkset. | ||
10218 | /// </summary> | ||
10219 | /// <returns></returns> | ||
10220 | /// <param name='sp'></param> | ||
10221 | /// <param name='rules'></param> | ||
10222 | /// <param name='res'></param> | ||
10223 | public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res) | ||
10224 | { | ||
10225 | int idx = 0; | ||
10226 | while (idx < rules.Length) | ||
7999 | { | 10227 | { |
8000 | remaining = GetPrimParams(part, rules, ref res); | 10228 | int code = (int)rules.GetLSLIntegerItem(idx++); |
8001 | } | 10229 | int remain = rules.Length-idx; |
8002 | 10230 | ||
8003 | while (remaining != null && remaining.Length > 2) | 10231 | switch (code) |
8004 | { | 10232 | { |
8005 | linknumber = remaining.GetLSLIntegerItem(0); | 10233 | case (int)ScriptBaseClass.PRIM_MATERIAL: |
8006 | rules = remaining.GetSublist(1, -1); | 10234 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH)); |
8007 | parts = GetLinkParts(linknumber); | 10235 | break; |
8008 | 10236 | ||
8009 | foreach (SceneObjectPart part in parts) | 10237 | case (int)ScriptBaseClass.PRIM_PHYSICS: |
8010 | remaining = GetPrimParams(part, rules, ref res); | 10238 | res.Add(ScriptBaseClass.FALSE); |
10239 | break; | ||
10240 | |||
10241 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
10242 | res.Add(ScriptBaseClass.FALSE); | ||
10243 | break; | ||
10244 | |||
10245 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
10246 | res.Add(ScriptBaseClass.FALSE); | ||
10247 | break; | ||
10248 | |||
10249 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
10250 | res.Add(new LSL_Vector(sp.AbsolutePosition)); | ||
10251 | break; | ||
10252 | |||
10253 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
10254 | res.Add(GetAgentSize(sp)); | ||
10255 | break; | ||
10256 | |||
10257 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
10258 | res.Add(sp.GetWorldRotation()); | ||
10259 | break; | ||
10260 | |||
10261 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
10262 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); | ||
10263 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); | ||
10264 | res.Add(new LSL_Vector(0, 1, 0)); | ||
10265 | res.Add(new LSL_Float(0)); | ||
10266 | res.Add(new LSL_Vector(0, 0, 0)); | ||
10267 | res.Add(new LSL_Vector(1, 1, 0)); | ||
10268 | res.Add(new LSL_Vector(0, 0, 0)); | ||
10269 | break; | ||
10270 | |||
10271 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
10272 | if (remain < 1) | ||
10273 | return new LSL_List(); | ||
10274 | |||
10275 | int face = (int)rules.GetLSLIntegerItem(idx++); | ||
10276 | if (face > 21) | ||
10277 | break; | ||
10278 | |||
10279 | res.Add(new LSL_String("")); | ||
10280 | res.Add(ScriptBaseClass.ZERO_VECTOR); | ||
10281 | res.Add(ScriptBaseClass.ZERO_VECTOR); | ||
10282 | res.Add(new LSL_Float(0)); | ||
10283 | break; | ||
10284 | |||
10285 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
10286 | if (remain < 1) | ||
10287 | return new LSL_List(); | ||
10288 | |||
10289 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
10290 | if (face > 21) | ||
10291 | break; | ||
10292 | |||
10293 | res.Add(ScriptBaseClass.ZERO_VECTOR); | ||
10294 | res.Add(new LSL_Float(0)); | ||
10295 | break; | ||
10296 | |||
10297 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
10298 | if (remain < 1) | ||
10299 | return new LSL_List(); | ||
10300 | |||
10301 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
10302 | if (face > 21) | ||
10303 | break; | ||
10304 | |||
10305 | res.Add(ScriptBaseClass.PRIM_SHINY_NONE); | ||
10306 | res.Add(ScriptBaseClass.PRIM_BUMP_NONE); | ||
10307 | break; | ||
10308 | |||
10309 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
10310 | if (remain < 1) | ||
10311 | return new LSL_List(); | ||
10312 | |||
10313 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
10314 | if (face > 21) | ||
10315 | break; | ||
10316 | |||
10317 | res.Add(ScriptBaseClass.FALSE); | ||
10318 | break; | ||
10319 | |||
10320 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
10321 | res.Add(ScriptBaseClass.FALSE); | ||
10322 | res.Add(new LSL_Integer(0)); | ||
10323 | res.Add(new LSL_Float(0)); | ||
10324 | res.Add(new LSL_Float(0)); | ||
10325 | res.Add(new LSL_Float(0)); | ||
10326 | res.Add(new LSL_Float(0)); | ||
10327 | res.Add(ScriptBaseClass.ZERO_VECTOR); | ||
10328 | break; | ||
10329 | |||
10330 | case (int)ScriptBaseClass.PRIM_TEXGEN: | ||
10331 | if (remain < 1) | ||
10332 | return new LSL_List(); | ||
10333 | |||
10334 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
10335 | if (face > 21) | ||
10336 | break; | ||
10337 | |||
10338 | res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT); | ||
10339 | break; | ||
10340 | |||
10341 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
10342 | res.Add(ScriptBaseClass.FALSE); | ||
10343 | res.Add(ScriptBaseClass.ZERO_VECTOR); | ||
10344 | res.Add(ScriptBaseClass.ZERO_VECTOR); | ||
10345 | break; | ||
10346 | |||
10347 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
10348 | if (remain < 1) | ||
10349 | return new LSL_List(); | ||
10350 | |||
10351 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
10352 | if (face > 21) | ||
10353 | break; | ||
10354 | |||
10355 | res.Add(new LSL_Float(0)); | ||
10356 | break; | ||
10357 | |||
10358 | case (int)ScriptBaseClass.PRIM_TEXT: | ||
10359 | res.Add(new LSL_String("")); | ||
10360 | res.Add(ScriptBaseClass.ZERO_VECTOR); | ||
10361 | res.Add(new LSL_Float(1)); | ||
10362 | break; | ||
10363 | |||
10364 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | ||
10365 | res.Add(new LSL_Rotation(sp.Rotation)); | ||
10366 | break; | ||
10367 | |||
10368 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | ||
10369 | res.Add(new LSL_Vector(sp.OffsetPosition)); | ||
10370 | break; | ||
10371 | |||
10372 | case (int)ScriptBaseClass.PRIM_SLICE: | ||
10373 | res.Add(new LSL_Vector(0, 1, 0)); | ||
10374 | break; | ||
10375 | |||
10376 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | ||
10377 | if(remain < 3) | ||
10378 | return new LSL_List(); | ||
10379 | |||
10380 | return rules.GetSublist(idx, -1); | ||
10381 | } | ||
8011 | } | 10382 | } |
8012 | 10383 | ||
8013 | return res; | 10384 | return new LSL_List(); |
8014 | } | 10385 | } |
8015 | 10386 | ||
8016 | public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) | 10387 | public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) |
8017 | { | 10388 | { |
8018 | int idx=0; | 10389 | int idx = 0; |
8019 | while (idx < rules.Length) | 10390 | while (idx < rules.Length) |
8020 | { | 10391 | { |
8021 | int code=(int)rules.GetLSLIntegerItem(idx++); | 10392 | int code = (int)rules.GetLSLIntegerItem(idx++); |
8022 | int remain=rules.Length-idx; | 10393 | int remain = rules.Length - idx; |
8023 | 10394 | ||
8024 | switch (code) | 10395 | switch (code) |
8025 | { | 10396 | { |
@@ -8049,29 +10420,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8049 | break; | 10420 | break; |
8050 | 10421 | ||
8051 | case (int)ScriptBaseClass.PRIM_POSITION: | 10422 | case (int)ScriptBaseClass.PRIM_POSITION: |
8052 | LSL_Vector v = new LSL_Vector(part.AbsolutePosition.X, | 10423 | LSL_Vector v = new LSL_Vector(part.AbsolutePosition); |
8053 | part.AbsolutePosition.Y, | 10424 | |
8054 | part.AbsolutePosition.Z); | ||
8055 | // For some reason, the part.AbsolutePosition.* values do not change if the | 10425 | // For some reason, the part.AbsolutePosition.* values do not change if the |
8056 | // linkset is rotated; they always reflect the child prim's world position | 10426 | // linkset is rotated; they always reflect the child prim's world position |
8057 | // as though the linkset is unrotated. This is incompatible behavior with SL's | 10427 | // as though the linkset is unrotated. This is incompatible behavior with SL's |
8058 | // implementation, so will break scripts imported from there (not to mention it | 10428 | // implementation, so will break scripts imported from there (not to mention it |
8059 | // makes it more difficult to determine a child prim's actual inworld position). | 10429 | // makes it more difficult to determine a child prim's actual inworld position). |
8060 | if (part.ParentID != 0) | 10430 | if (!part.IsRoot) |
8061 | v = ((v - llGetRootPosition()) * llGetRootRotation()) + llGetRootPosition(); | 10431 | { |
10432 | LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition); | ||
10433 | v = ((v - rootPos) * llGetRootRotation()) + rootPos; | ||
10434 | } | ||
10435 | |||
8062 | res.Add(v); | 10436 | res.Add(v); |
8063 | break; | 10437 | break; |
8064 | 10438 | ||
8065 | case (int)ScriptBaseClass.PRIM_SIZE: | 10439 | case (int)ScriptBaseClass.PRIM_SIZE: |
8066 | res.Add(new LSL_Vector(part.Scale.X, | 10440 | res.Add(new LSL_Vector(part.Scale)); |
8067 | part.Scale.Y, | ||
8068 | part.Scale.Z)); | ||
8069 | break; | 10441 | break; |
8070 | 10442 | ||
8071 | case (int)ScriptBaseClass.PRIM_ROTATION: | 10443 | case (int)ScriptBaseClass.PRIM_ROTATION: |
8072 | res.Add(GetPartRot(part)); | 10444 | res.Add(GetPartRot(part)); |
8073 | break; | 10445 | break; |
8074 | 10446 | ||
10447 | case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: | ||
10448 | res.Add(new LSL_Integer((int)part.PhysicsShapeType)); | ||
10449 | break; | ||
10450 | |||
8075 | case (int)ScriptBaseClass.PRIM_TYPE: | 10451 | case (int)ScriptBaseClass.PRIM_TYPE: |
8076 | // implementing box | 10452 | // implementing box |
8077 | PrimitiveBaseShape Shape = part.Shape; | 10453 | PrimitiveBaseShape Shape = part.Shape; |
@@ -8101,7 +10477,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8101 | break; | 10477 | break; |
8102 | 10478 | ||
8103 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | 10479 | case ScriptBaseClass.PRIM_TYPE_SCULPT: |
8104 | res.Add(Shape.SculptTexture.ToString()); | 10480 | res.Add(new LSL_String(Shape.SculptTexture.ToString())); |
8105 | res.Add(new LSL_Integer(Shape.SculptType)); | 10481 | res.Add(new LSL_Integer(Shape.SculptType)); |
8106 | break; | 10482 | break; |
8107 | 10483 | ||
@@ -8133,16 +10509,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8133 | res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); | 10509 | res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); |
8134 | 10510 | ||
8135 | // float revolutions | 10511 | // float revolutions |
8136 | res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); | 10512 | res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); |
8137 | // Slightly inaccurate, because an unsigned byte is being used to represent | 10513 | // Slightly inaccurate, because an unsigned byte is being used to represent |
8138 | // the entire range of floating-point values from 1.0 through 4.0 (which is how | 10514 | // the entire range of floating-point values from 1.0 through 4.0 (which is how |
8139 | // SL does it). | 10515 | // SL does it). |
8140 | // | 10516 | // |
8141 | // Using these formulas to store and retrieve PathRevolutions, it is not | 10517 | // Using these formulas to store and retrieve PathRevolutions, it is not |
8142 | // possible to use all values between 1.00 and 4.00. For instance, you can't | 10518 | // possible to use all values between 1.00 and 4.00. For instance, you can't |
8143 | // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you | 10519 | // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you |
8144 | // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them | 10520 | // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them |
8145 | // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar | 10521 | // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar |
8146 | // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. | 10522 | // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. |
8147 | // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value | 10523 | // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value |
8148 | // such as 1.10. So, SL must store and retreive the actual user input rather | 10524 | // such as 1.10. So, SL must store and retreive the actual user input rather |
@@ -8159,7 +10535,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8159 | 10535 | ||
8160 | case (int)ScriptBaseClass.PRIM_TEXTURE: | 10536 | case (int)ScriptBaseClass.PRIM_TEXTURE: |
8161 | if (remain < 1) | 10537 | if (remain < 1) |
8162 | return null; | 10538 | return new LSL_List(); |
8163 | 10539 | ||
8164 | int face = (int)rules.GetLSLIntegerItem(idx++); | 10540 | int face = (int)rules.GetLSLIntegerItem(idx++); |
8165 | Primitive.TextureEntry tex = part.Shape.Textures; | 10541 | Primitive.TextureEntry tex = part.Shape.Textures; |
@@ -8199,7 +10575,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8199 | 10575 | ||
8200 | case (int)ScriptBaseClass.PRIM_COLOR: | 10576 | case (int)ScriptBaseClass.PRIM_COLOR: |
8201 | if (remain < 1) | 10577 | if (remain < 1) |
8202 | return null; | 10578 | return new LSL_List(); |
8203 | 10579 | ||
8204 | face=(int)rules.GetLSLIntegerItem(idx++); | 10580 | face=(int)rules.GetLSLIntegerItem(idx++); |
8205 | 10581 | ||
@@ -8228,7 +10604,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8228 | 10604 | ||
8229 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | 10605 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: |
8230 | if (remain < 1) | 10606 | if (remain < 1) |
8231 | return null; | 10607 | return new LSL_List(); |
8232 | 10608 | ||
8233 | face=(int)rules.GetLSLIntegerItem(idx++); | 10609 | face=(int)rules.GetLSLIntegerItem(idx++); |
8234 | 10610 | ||
@@ -8259,9 +10635,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8259 | 10635 | ||
8260 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | 10636 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: |
8261 | if (remain < 1) | 10637 | if (remain < 1) |
8262 | return null; | 10638 | return new LSL_List(); |
8263 | 10639 | ||
8264 | face=(int)rules.GetLSLIntegerItem(idx++); | 10640 | face = (int)rules.GetLSLIntegerItem(idx++); |
8265 | 10641 | ||
8266 | tex = part.Shape.Textures; | 10642 | tex = part.Shape.Textures; |
8267 | if (face == ScriptBaseClass.ALL_SIDES) | 10643 | if (face == ScriptBaseClass.ALL_SIDES) |
@@ -8301,7 +10677,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8301 | 10677 | ||
8302 | case (int)ScriptBaseClass.PRIM_TEXGEN: | 10678 | case (int)ScriptBaseClass.PRIM_TEXGEN: |
8303 | if (remain < 1) | 10679 | if (remain < 1) |
8304 | return null; | 10680 | return new LSL_List(); |
8305 | 10681 | ||
8306 | face=(int)rules.GetLSLIntegerItem(idx++); | 10682 | face=(int)rules.GetLSLIntegerItem(idx++); |
8307 | 10683 | ||
@@ -8342,7 +10718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8342 | 10718 | ||
8343 | case (int)ScriptBaseClass.PRIM_GLOW: | 10719 | case (int)ScriptBaseClass.PRIM_GLOW: |
8344 | if (remain < 1) | 10720 | if (remain < 1) |
8345 | return null; | 10721 | return new LSL_List(); |
8346 | 10722 | ||
8347 | face=(int)rules.GetLSLIntegerItem(idx++); | 10723 | face=(int)rules.GetLSLIntegerItem(idx++); |
8348 | 10724 | ||
@@ -8371,7 +10747,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8371 | res.Add(new LSL_Vector(textColor.R, | 10747 | res.Add(new LSL_Vector(textColor.R, |
8372 | textColor.G, | 10748 | textColor.G, |
8373 | textColor.B)); | 10749 | textColor.B)); |
8374 | res.Add(new LSL_Float(textColor.A)); | 10750 | res.Add(new LSL_Float(1.0 - textColor.A)); |
8375 | break; | 10751 | break; |
8376 | case (int)ScriptBaseClass.PRIM_NAME: | 10752 | case (int)ScriptBaseClass.PRIM_NAME: |
8377 | res.Add(new LSL_String(part.Name)); | 10753 | res.Add(new LSL_String(part.Name)); |
@@ -8380,7 +10756,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8380 | res.Add(new LSL_String(part.Description)); | 10756 | res.Add(new LSL_String(part.Description)); |
8381 | break; | 10757 | break; |
8382 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | 10758 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: |
8383 | res.Add(new LSL_Rotation(part.RotationOffset.X, part.RotationOffset.Y, part.RotationOffset.Z, part.RotationOffset.W)); | 10759 | res.Add(new LSL_Rotation(part.RotationOffset)); |
8384 | break; | 10760 | break; |
8385 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | 10761 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: |
8386 | res.Add(new LSL_Vector(GetPartLocalPos(part))); | 10762 | res.Add(new LSL_Vector(GetPartLocalPos(part))); |
@@ -8395,27 +10771,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8395 | )); | 10771 | )); |
8396 | break; | 10772 | break; |
8397 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | 10773 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: |
8398 | if(remain < 3) | 10774 | |
8399 | return null; | 10775 | // TODO: Should be issuing a runtime script warning in this case. |
10776 | if (remain < 2) | ||
10777 | return new LSL_List(); | ||
8400 | 10778 | ||
8401 | return rules.GetSublist(idx, -1); | 10779 | return rules.GetSublist(idx, -1); |
8402 | } | 10780 | } |
8403 | } | 10781 | } |
8404 | 10782 | ||
8405 | return null; | 10783 | return new LSL_List(); |
8406 | } | 10784 | } |
8407 | 10785 | ||
8408 | public LSL_List llGetPrimMediaParams(int face, LSL_List rules) | 10786 | public LSL_List llGetPrimMediaParams(int face, LSL_List rules) |
8409 | { | 10787 | { |
8410 | m_host.AddScriptLPS(1); | 10788 | m_host.AddScriptLPS(1); |
8411 | ScriptSleep(1000); | 10789 | ScriptSleep(m_sleepMsOnGetPrimMediaParams); |
8412 | return GetPrimMediaParams(m_host, face, rules); | 10790 | return GetPrimMediaParams(m_host, face, rules); |
8413 | } | 10791 | } |
8414 | 10792 | ||
8415 | public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) | 10793 | public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) |
8416 | { | 10794 | { |
8417 | m_host.AddScriptLPS(1); | 10795 | m_host.AddScriptLPS(1); |
8418 | ScriptSleep(1000); | 10796 | ScriptSleep(m_sleepMsOnGetLinkMedia); |
8419 | if (link == ScriptBaseClass.LINK_ROOT) | 10797 | if (link == ScriptBaseClass.LINK_ROOT) |
8420 | return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); | 10798 | return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); |
8421 | else if (link == ScriptBaseClass.LINK_THIS) | 10799 | else if (link == ScriptBaseClass.LINK_THIS) |
@@ -8535,14 +10913,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8535 | public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules) | 10913 | public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules) |
8536 | { | 10914 | { |
8537 | m_host.AddScriptLPS(1); | 10915 | m_host.AddScriptLPS(1); |
8538 | ScriptSleep(1000); | 10916 | ScriptSleep(m_sleepMsOnSetPrimMediaParams); |
8539 | return SetPrimMediaParams(m_host, face, rules); | 10917 | return SetPrimMediaParams(m_host, face, rules); |
8540 | } | 10918 | } |
8541 | 10919 | ||
8542 | public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) | 10920 | public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) |
8543 | { | 10921 | { |
8544 | m_host.AddScriptLPS(1); | 10922 | m_host.AddScriptLPS(1); |
8545 | ScriptSleep(1000); | 10923 | ScriptSleep(m_sleepMsOnSetLinkMedia); |
8546 | if (link == ScriptBaseClass.LINK_ROOT) | 10924 | if (link == ScriptBaseClass.LINK_ROOT) |
8547 | return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); | 10925 | return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); |
8548 | else if (link == ScriptBaseClass.LINK_THIS) | 10926 | else if (link == ScriptBaseClass.LINK_THIS) |
@@ -8661,14 +11039,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
8661 | public LSL_Integer llClearPrimMedia(LSL_Integer face) | 11039 | public LSL_Integer llClearPrimMedia(LSL_Integer face) |
8662 | { | 11040 | { |
8663 | m_host.AddScriptLPS(1); | 11041 | m_host.AddScriptLPS(1); |
8664 | ScriptSleep(1000); | 11042 | ScriptSleep(m_sleepMsOnClearPrimMedia); |
8665 | return ClearPrimMedia(m_host, face); | 11043 | return ClearPrimMedia(m_host, face); |
8666 | } | 11044 | } |
8667 | 11045 | ||
8668 | public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face) | 11046 | public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face) |
8669 | { | 11047 | { |
8670 | m_host.AddScriptLPS(1); | 11048 | m_host.AddScriptLPS(1); |
8671 | ScriptSleep(1000); | 11049 | ScriptSleep(m_sleepMsOnClearLinkMedia); |
8672 | if (link == ScriptBaseClass.LINK_ROOT) | 11050 | if (link == ScriptBaseClass.LINK_ROOT) |
8673 | return ClearPrimMedia(m_host.ParentGroup.RootPart, face); | 11051 | return ClearPrimMedia(m_host.ParentGroup.RootPart, face); |
8674 | else if (link == ScriptBaseClass.LINK_THIS) | 11052 | else if (link == ScriptBaseClass.LINK_THIS) |
@@ -9307,7 +11685,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9307 | 11685 | ||
9308 | if (item == null) | 11686 | if (item == null) |
9309 | { | 11687 | { |
9310 | llSay(0, "No item name '" + item + "'"); | 11688 | Error("llGetInventoryCreator", "Can't find item '" + item + "'"); |
9311 | 11689 | ||
9312 | return String.Empty; | 11690 | return String.Empty; |
9313 | } | 11691 | } |
@@ -9355,7 +11733,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9355 | case ScriptBaseClass.DATA_SIM_POS: | 11733 | case ScriptBaseClass.DATA_SIM_POS: |
9356 | if (info == null) | 11734 | if (info == null) |
9357 | { | 11735 | { |
9358 | ScriptSleep(1000); | 11736 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
9359 | return UUID.Zero.ToString(); | 11737 | return UUID.Zero.ToString(); |
9360 | } | 11738 | } |
9361 | 11739 | ||
@@ -9402,7 +11780,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9402 | case ScriptBaseClass.DATA_SIM_RATING: | 11780 | case ScriptBaseClass.DATA_SIM_RATING: |
9403 | if (info == null) | 11781 | if (info == null) |
9404 | { | 11782 | { |
9405 | ScriptSleep(1000); | 11783 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
9406 | return UUID.Zero.ToString(); | 11784 | return UUID.Zero.ToString(); |
9407 | } | 11785 | } |
9408 | int access = info.Maturity; | 11786 | int access = info.Maturity; |
@@ -9421,7 +11799,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9421 | reply = "OpenSim"; | 11799 | reply = "OpenSim"; |
9422 | break; | 11800 | break; |
9423 | default: | 11801 | default: |
9424 | ScriptSleep(1000); | 11802 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
9425 | return UUID.Zero.ToString(); // Raise no event | 11803 | return UUID.Zero.ToString(); // Raise no event |
9426 | } | 11804 | } |
9427 | UUID rq = UUID.Random(); | 11805 | UUID rq = UUID.Random(); |
@@ -9432,7 +11810,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9432 | AsyncCommands. | 11810 | AsyncCommands. |
9433 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | 11811 | DataserverPlugin.DataserverReply(rq.ToString(), reply); |
9434 | 11812 | ||
9435 | ScriptSleep(1000); | 11813 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
9436 | return tid.ToString(); | 11814 | return tid.ToString(); |
9437 | } | 11815 | } |
9438 | catch(Exception) | 11816 | catch(Exception) |
@@ -9441,6 +11819,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9441 | return UUID.Zero.ToString(); | 11819 | return UUID.Zero.ToString(); |
9442 | } | 11820 | } |
9443 | } | 11821 | } |
11822 | |||
9444 | public LSL_String llRequestURL() | 11823 | public LSL_String llRequestURL() |
9445 | { | 11824 | { |
9446 | m_host.AddScriptLPS(1); | 11825 | m_host.AddScriptLPS(1); |
@@ -9499,7 +11878,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9499 | 11878 | ||
9500 | public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) | 11879 | public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) |
9501 | { | 11880 | { |
9502 | LSL_List pref = null; | 11881 | LSL_List pref; |
9503 | 11882 | ||
9504 | m_host.AddScriptLPS(1); | 11883 | m_host.AddScriptLPS(1); |
9505 | 11884 | ||
@@ -9576,7 +11955,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9576 | dm.SendUrlToUser( | 11955 | dm.SendUrlToUser( |
9577 | new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url); | 11956 | new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url); |
9578 | 11957 | ||
9579 | ScriptSleep(10000); | 11958 | ScriptSleep(m_sleepMsOnLoadURL); |
9580 | } | 11959 | } |
9581 | 11960 | ||
9582 | public void llParcelMediaCommandList(LSL_List commandList) | 11961 | public void llParcelMediaCommandList(LSL_List commandList) |
@@ -9588,7 +11967,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9588 | 11967 | ||
9589 | // according to the docs, this command only works if script owner and land owner are the same | 11968 | // according to the docs, this command only works if script owner and land owner are the same |
9590 | // lets add estate owners and gods, too, and use the generic permission check. | 11969 | // lets add estate owners and gods, too, and use the generic permission check. |
9591 | ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 11970 | ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
9592 | if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; | 11971 | if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; |
9593 | 11972 | ||
9594 | bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? | 11973 | bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? |
@@ -9625,7 +12004,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9625 | presence = World.GetScenePresence(agentID); | 12004 | presence = World.GetScenePresence(agentID); |
9626 | } | 12005 | } |
9627 | } | 12006 | } |
9628 | else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); | 12007 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); |
9629 | ++i; | 12008 | ++i; |
9630 | } | 12009 | } |
9631 | break; | 12010 | break; |
@@ -9656,7 +12035,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9656 | url = (LSL_String)commandList.Data[i + 1]; | 12035 | url = (LSL_String)commandList.Data[i + 1]; |
9657 | update = true; | 12036 | update = true; |
9658 | } | 12037 | } |
9659 | else ShoutError("The argument of PARCEL_MEDIA_COMMAND_URL must be a string."); | 12038 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string"); |
9660 | ++i; | 12039 | ++i; |
9661 | } | 12040 | } |
9662 | break; | 12041 | break; |
@@ -9669,7 +12048,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9669 | texture = (LSL_String)commandList.Data[i + 1]; | 12048 | texture = (LSL_String)commandList.Data[i + 1]; |
9670 | update = true; | 12049 | update = true; |
9671 | } | 12050 | } |
9672 | else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or key."); | 12051 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key"); |
9673 | ++i; | 12052 | ++i; |
9674 | } | 12053 | } |
9675 | break; | 12054 | break; |
@@ -9681,7 +12060,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9681 | { | 12060 | { |
9682 | time = (float)(LSL_Float)commandList.Data[i + 1]; | 12061 | time = (float)(LSL_Float)commandList.Data[i + 1]; |
9683 | } | 12062 | } |
9684 | else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TIME must be a float."); | 12063 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float"); |
9685 | ++i; | 12064 | ++i; |
9686 | } | 12065 | } |
9687 | break; | 12066 | break; |
@@ -9695,7 +12074,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9695 | update = true; | 12074 | update = true; |
9696 | } | 12075 | } |
9697 | 12076 | ||
9698 | else ShoutError("The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer."); | 12077 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer"); |
9699 | ++i; | 12078 | ++i; |
9700 | } | 12079 | } |
9701 | break; | 12080 | break; |
@@ -9708,7 +12087,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9708 | mediaType = (LSL_String)commandList.Data[i + 1]; | 12087 | mediaType = (LSL_String)commandList.Data[i + 1]; |
9709 | update = true; | 12088 | update = true; |
9710 | } | 12089 | } |
9711 | else ShoutError("The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string."); | 12090 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string"); |
9712 | ++i; | 12091 | ++i; |
9713 | } | 12092 | } |
9714 | break; | 12093 | break; |
@@ -9721,7 +12100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9721 | description = (LSL_String)commandList.Data[i + 1]; | 12100 | description = (LSL_String)commandList.Data[i + 1]; |
9722 | update = true; | 12101 | update = true; |
9723 | } | 12102 | } |
9724 | else ShoutError("The argument of PARCEL_MEDIA_COMMAND_DESC must be a string."); | 12103 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string"); |
9725 | ++i; | 12104 | ++i; |
9726 | } | 12105 | } |
9727 | break; | 12106 | break; |
@@ -9737,15 +12116,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9737 | height = (LSL_Integer)commandList.Data[i + 2]; | 12116 | height = (LSL_Integer)commandList.Data[i + 2]; |
9738 | update = true; | 12117 | update = true; |
9739 | } | 12118 | } |
9740 | else ShoutError("The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); | 12119 | else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); |
9741 | } | 12120 | } |
9742 | else ShoutError("The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer."); | 12121 | else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); |
9743 | i += 2; | 12122 | i += 2; |
9744 | } | 12123 | } |
9745 | break; | 12124 | break; |
9746 | 12125 | ||
9747 | default: | 12126 | default: |
9748 | NotImplemented("llParcelMediaCommandList parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString()); | 12127 | NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString()); |
9749 | break; | 12128 | break; |
9750 | }//end switch | 12129 | }//end switch |
9751 | }//end for | 12130 | }//end for |
@@ -9819,7 +12198,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9819 | time); | 12198 | time); |
9820 | } | 12199 | } |
9821 | } | 12200 | } |
9822 | ScriptSleep(2000); | 12201 | ScriptSleep(m_sleepMsOnParcelMediaCommandList); |
9823 | } | 12202 | } |
9824 | 12203 | ||
9825 | public LSL_List llParcelMediaQuery(LSL_List aList) | 12204 | public LSL_List llParcelMediaQuery(LSL_List aList) |
@@ -9853,13 +12232,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9853 | break; | 12232 | break; |
9854 | default: | 12233 | default: |
9855 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; | 12234 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; |
9856 | NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); | 12235 | NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); |
9857 | break; | 12236 | break; |
9858 | } | 12237 | } |
9859 | 12238 | ||
9860 | } | 12239 | } |
9861 | } | 12240 | } |
9862 | ScriptSleep(2000); | 12241 | ScriptSleep(m_sleepMsOnParcelMediaQuery); |
9863 | return list; | 12242 | return list; |
9864 | } | 12243 | } |
9865 | 12244 | ||
@@ -9868,7 +12247,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9868 | m_host.AddScriptLPS(1); | 12247 | m_host.AddScriptLPS(1); |
9869 | Int64 tmp = 0; | 12248 | Int64 tmp = 0; |
9870 | Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); | 12249 | Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); |
9871 | ScriptSleep(1000); | 12250 | ScriptSleep(m_sleepMsOnModPow); |
9872 | return Convert.ToInt32(tmp); | 12251 | return Convert.ToInt32(tmp); |
9873 | } | 12252 | } |
9874 | 12253 | ||
@@ -9890,7 +12269,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9890 | 12269 | ||
9891 | if (quick_pay_buttons.Data.Length < 4) | 12270 | if (quick_pay_buttons.Data.Length < 4) |
9892 | { | 12271 | { |
9893 | LSLError("List must have at least 4 elements"); | 12272 | Error("llSetPayPrice", "List must have at least 4 elements"); |
9894 | return; | 12273 | return; |
9895 | } | 12274 | } |
9896 | m_host.ParentGroup.RootPart.PayPrice[0]=price; | 12275 | m_host.ParentGroup.RootPart.PayPrice[0]=price; |
@@ -9907,21 +12286,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9907 | m_host.AddScriptLPS(1); | 12286 | m_host.AddScriptLPS(1); |
9908 | 12287 | ||
9909 | if (m_item.PermsGranter == UUID.Zero) | 12288 | if (m_item.PermsGranter == UUID.Zero) |
9910 | return new LSL_Vector(); | 12289 | return Vector3.Zero; |
9911 | 12290 | ||
9912 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | 12291 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) |
9913 | { | 12292 | { |
9914 | ShoutError("No permissions to track the camera"); | 12293 | Error("llGetCameraPos", "No permissions to track the camera"); |
9915 | return new LSL_Vector(); | 12294 | return Vector3.Zero; |
9916 | } | 12295 | } |
9917 | 12296 | ||
9918 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | 12297 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); |
9919 | if (presence != null) | 12298 | if (presence != null) |
9920 | { | 12299 | { |
9921 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); | 12300 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition); |
9922 | return pos; | 12301 | return pos; |
9923 | } | 12302 | } |
9924 | return new LSL_Vector(); | 12303 | |
12304 | return Vector3.Zero; | ||
9925 | } | 12305 | } |
9926 | 12306 | ||
9927 | public LSL_Rotation llGetCameraRot() | 12307 | public LSL_Rotation llGetCameraRot() |
@@ -9929,42 +12309,35 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
9929 | m_host.AddScriptLPS(1); | 12309 | m_host.AddScriptLPS(1); |
9930 | 12310 | ||
9931 | if (m_item.PermsGranter == UUID.Zero) | 12311 | if (m_item.PermsGranter == UUID.Zero) |
9932 | return new LSL_Rotation(); | 12312 | return Quaternion.Identity; |
9933 | 12313 | ||
9934 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | 12314 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) |
9935 | { | 12315 | { |
9936 | ShoutError("No permissions to track the camera"); | 12316 | Error("llGetCameraRot", "No permissions to track the camera"); |
9937 | return new LSL_Rotation(); | 12317 | return Quaternion.Identity; |
9938 | } | 12318 | } |
9939 | 12319 | ||
9940 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | 12320 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); |
9941 | if (presence != null) | 12321 | if (presence != null) |
9942 | { | 12322 | { |
9943 | return new LSL_Rotation(presence.CameraRotation.X, presence.CameraRotation.Y, presence.CameraRotation.Z, presence.CameraRotation.W); | 12323 | return new LSL_Rotation(presence.CameraRotation); |
9944 | } | 12324 | } |
9945 | 12325 | ||
9946 | return new LSL_Rotation(); | 12326 | return Quaternion.Identity; |
9947 | } | 12327 | } |
9948 | 12328 | ||
9949 | /// <summary> | ||
9950 | /// The SL implementation does nothing, it is deprecated | ||
9951 | /// This duplicates SL | ||
9952 | /// </summary> | ||
9953 | public void llSetPrimURL(string url) | 12329 | public void llSetPrimURL(string url) |
9954 | { | 12330 | { |
9955 | m_host.AddScriptLPS(1); | 12331 | m_host.AddScriptLPS(1); |
9956 | ScriptSleep(2000); | 12332 | Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead"); |
12333 | ScriptSleep(m_sleepMsOnSetPrimURL); | ||
9957 | } | 12334 | } |
9958 | 12335 | ||
9959 | /// <summary> | ||
9960 | /// The SL implementation shouts an error, it is deprecated | ||
9961 | /// This duplicates SL | ||
9962 | /// </summary> | ||
9963 | public void llRefreshPrimURL() | 12336 | public void llRefreshPrimURL() |
9964 | { | 12337 | { |
9965 | m_host.AddScriptLPS(1); | 12338 | m_host.AddScriptLPS(1); |
9966 | ShoutError("llRefreshPrimURL - not yet supported"); | 12339 | Deprecated("llRefreshPrimURL"); |
9967 | ScriptSleep(20000); | 12340 | ScriptSleep(m_sleepMsOnRefreshPrimURL); |
9968 | } | 12341 | } |
9969 | 12342 | ||
9970 | public LSL_String llEscapeURL(string url) | 12343 | public LSL_String llEscapeURL(string url) |
@@ -10005,14 +12378,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10005 | avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, | 12378 | avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, |
10006 | simname, pos, lookAt); | 12379 | simname, pos, lookAt); |
10007 | } | 12380 | } |
10008 | ScriptSleep(1000); | 12381 | ScriptSleep(m_sleepMsOnMapDestination); |
10009 | } | 12382 | } |
10010 | 12383 | ||
10011 | public void llAddToLandBanList(string avatar, double hours) | 12384 | public void llAddToLandBanList(string avatar, double hours) |
10012 | { | 12385 | { |
10013 | m_host.AddScriptLPS(1); | 12386 | m_host.AddScriptLPS(1); |
10014 | UUID key; | 12387 | UUID key; |
10015 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 12388 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
10016 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 12389 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
10017 | { | 12390 | { |
10018 | int expires = 0; | 12391 | int expires = 0; |
@@ -10046,14 +12419,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10046 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | 12419 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); |
10047 | } | 12420 | } |
10048 | } | 12421 | } |
10049 | ScriptSleep(100); | 12422 | ScriptSleep(m_sleepMsOnAddToLandBanList); |
10050 | } | 12423 | } |
10051 | 12424 | ||
10052 | public void llRemoveFromLandPassList(string avatar) | 12425 | public void llRemoveFromLandPassList(string avatar) |
10053 | { | 12426 | { |
10054 | m_host.AddScriptLPS(1); | 12427 | m_host.AddScriptLPS(1); |
10055 | UUID key; | 12428 | UUID key; |
10056 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 12429 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
10057 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) | 12430 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) |
10058 | { | 12431 | { |
10059 | if (UUID.TryParse(avatar, out key)) | 12432 | if (UUID.TryParse(avatar, out key)) |
@@ -10073,14 +12446,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10073 | } | 12446 | } |
10074 | } | 12447 | } |
10075 | } | 12448 | } |
10076 | ScriptSleep(100); | 12449 | ScriptSleep(m_sleepMsOnRemoveFromLandPassList); |
10077 | } | 12450 | } |
10078 | 12451 | ||
10079 | public void llRemoveFromLandBanList(string avatar) | 12452 | public void llRemoveFromLandBanList(string avatar) |
10080 | { | 12453 | { |
10081 | m_host.AddScriptLPS(1); | 12454 | m_host.AddScriptLPS(1); |
10082 | UUID key; | 12455 | UUID key; |
10083 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | 12456 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
10084 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 12457 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
10085 | { | 12458 | { |
10086 | if (UUID.TryParse(avatar, out key)) | 12459 | if (UUID.TryParse(avatar, out key)) |
@@ -10100,7 +12473,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10100 | } | 12473 | } |
10101 | } | 12474 | } |
10102 | } | 12475 | } |
10103 | ScriptSleep(100); | 12476 | ScriptSleep(m_sleepMsOnRemoveFromLandBanList); |
10104 | } | 12477 | } |
10105 | 12478 | ||
10106 | public void llSetCameraParams(LSL_List rules) | 12479 | public void llSetCameraParams(LSL_List rules) |
@@ -10128,19 +12501,84 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10128 | 12501 | ||
10129 | SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); | 12502 | SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); |
10130 | object[] data = rules.Data; | 12503 | object[] data = rules.Data; |
10131 | for (int i = 0; i < data.Length; ++i) { | 12504 | for (int i = 0; i < data.Length; ++i) |
10132 | int type = Convert.ToInt32(data[i++].ToString()); | 12505 | { |
12506 | int type; | ||
12507 | try | ||
12508 | { | ||
12509 | type = Convert.ToInt32(data[i++].ToString()); | ||
12510 | } | ||
12511 | catch | ||
12512 | { | ||
12513 | Error("llSetCameraParams", string.Format("Invalid camera param type {0}", data[i - 1])); | ||
12514 | return; | ||
12515 | } | ||
10133 | if (i >= data.Length) break; // odd number of entries => ignore the last | 12516 | if (i >= data.Length) break; // odd number of entries => ignore the last |
10134 | 12517 | ||
10135 | // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) | 12518 | // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) |
10136 | switch (type) { | 12519 | switch (type) |
12520 | { | ||
10137 | case ScriptBaseClass.CAMERA_FOCUS: | 12521 | case ScriptBaseClass.CAMERA_FOCUS: |
10138 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | 12522 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: |
10139 | case ScriptBaseClass.CAMERA_POSITION: | 12523 | case ScriptBaseClass.CAMERA_POSITION: |
10140 | LSL_Vector v = (LSL_Vector)data[i]; | 12524 | LSL_Vector v = (LSL_Vector)data[i]; |
10141 | parameters.Add(type + 1, (float)v.x); | 12525 | try |
10142 | parameters.Add(type + 2, (float)v.y); | 12526 | { |
10143 | parameters.Add(type + 3, (float)v.z); | 12527 | parameters.Add(type + 1, (float)v.x); |
12528 | } | ||
12529 | catch | ||
12530 | { | ||
12531 | switch(type) | ||
12532 | { | ||
12533 | case ScriptBaseClass.CAMERA_FOCUS: | ||
12534 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter x is invalid"); | ||
12535 | return; | ||
12536 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | ||
12537 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter x is invalid"); | ||
12538 | return; | ||
12539 | case ScriptBaseClass.CAMERA_POSITION: | ||
12540 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter x is invalid"); | ||
12541 | return; | ||
12542 | } | ||
12543 | } | ||
12544 | try | ||
12545 | { | ||
12546 | parameters.Add(type + 2, (float)v.y); | ||
12547 | } | ||
12548 | catch | ||
12549 | { | ||
12550 | switch(type) | ||
12551 | { | ||
12552 | case ScriptBaseClass.CAMERA_FOCUS: | ||
12553 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter y is invalid"); | ||
12554 | return; | ||
12555 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | ||
12556 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter y is invalid"); | ||
12557 | return; | ||
12558 | case ScriptBaseClass.CAMERA_POSITION: | ||
12559 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter y is invalid"); | ||
12560 | return; | ||
12561 | } | ||
12562 | } | ||
12563 | try | ||
12564 | { | ||
12565 | parameters.Add(type + 3, (float)v.z); | ||
12566 | } | ||
12567 | catch | ||
12568 | { | ||
12569 | switch(type) | ||
12570 | { | ||
12571 | case ScriptBaseClass.CAMERA_FOCUS: | ||
12572 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter z is invalid"); | ||
12573 | return; | ||
12574 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | ||
12575 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter z is invalid"); | ||
12576 | return; | ||
12577 | case ScriptBaseClass.CAMERA_POSITION: | ||
12578 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter z is invalid"); | ||
12579 | return; | ||
12580 | } | ||
12581 | } | ||
10144 | break; | 12582 | break; |
10145 | default: | 12583 | default: |
10146 | // TODO: clean that up as soon as the implicit casts are in | 12584 | // TODO: clean that up as soon as the implicit casts are in |
@@ -10148,7 +12586,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10148 | parameters.Add(type, (float)((LSL_Float)data[i]).value); | 12586 | parameters.Add(type, (float)((LSL_Float)data[i]).value); |
10149 | else if (data[i] is LSL_Integer) | 12587 | else if (data[i] is LSL_Integer) |
10150 | parameters.Add(type, (float)((LSL_Integer)data[i]).value); | 12588 | parameters.Add(type, (float)((LSL_Integer)data[i]).value); |
10151 | else parameters.Add(type, Convert.ToSingle(data[i])); | 12589 | else |
12590 | { | ||
12591 | try | ||
12592 | { | ||
12593 | parameters.Add(type, Convert.ToSingle(data[i])); | ||
12594 | } | ||
12595 | catch | ||
12596 | { | ||
12597 | Error("llSetCameraParams", string.Format("{0}: Parameter is invalid", type)); | ||
12598 | } | ||
12599 | } | ||
10152 | break; | 12600 | break; |
10153 | } | 12601 | } |
10154 | } | 12602 | } |
@@ -10264,9 +12712,60 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10264 | IHttpRequestModule httpScriptMod = | 12712 | IHttpRequestModule httpScriptMod = |
10265 | m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); | 12713 | m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); |
10266 | List<string> param = new List<string>(); | 12714 | List<string> param = new List<string>(); |
10267 | foreach (object o in parameters.Data) | 12715 | bool ok; |
12716 | Int32 flag; | ||
12717 | |||
12718 | for (int i = 0; i < parameters.Data.Length; i += 2) | ||
10268 | { | 12719 | { |
10269 | param.Add(o.ToString()); | 12720 | ok = Int32.TryParse(parameters.Data[i].ToString(), out flag); |
12721 | if (!ok || flag < 0 || | ||
12722 | flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE) | ||
12723 | { | ||
12724 | Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag"); | ||
12725 | } | ||
12726 | |||
12727 | param.Add(parameters.Data[i].ToString()); //Add parameter flag | ||
12728 | |||
12729 | if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER) | ||
12730 | { | ||
12731 | param.Add(parameters.Data[i+1].ToString()); //Add parameter value | ||
12732 | } | ||
12733 | else | ||
12734 | { | ||
12735 | //Parameters are in pairs and custom header takes | ||
12736 | //arguments in pairs so adjust for header marker. | ||
12737 | ++i; | ||
12738 | |||
12739 | //Maximum of 8 headers are allowed based on the | ||
12740 | //Second Life documentation for llHTTPRequest. | ||
12741 | for (int count = 1; count <= 8; ++count) | ||
12742 | { | ||
12743 | //Enough parameters remaining for (another) header? | ||
12744 | if (parameters.Data.Length - i < 2) | ||
12745 | { | ||
12746 | //There must be at least one name/value pair for custom header | ||
12747 | if (count == 1) | ||
12748 | Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString()); | ||
12749 | break; | ||
12750 | } | ||
12751 | |||
12752 | if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase)) | ||
12753 | Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString()); | ||
12754 | |||
12755 | param.Add(parameters.Data[i].ToString()); | ||
12756 | param.Add(parameters.Data[i+1].ToString()); | ||
12757 | |||
12758 | //Have we reached the end of the list of headers? | ||
12759 | //End is marked by a string with a single digit. | ||
12760 | if (i+2 >= parameters.Data.Length || | ||
12761 | Char.IsDigit(parameters.Data[i].ToString()[0])) | ||
12762 | { | ||
12763 | break; | ||
12764 | } | ||
12765 | |||
12766 | i += 2; | ||
12767 | } | ||
12768 | } | ||
10270 | } | 12769 | } |
10271 | 12770 | ||
10272 | Vector3 position = m_host.AbsolutePosition; | 12771 | Vector3 position = m_host.AbsolutePosition; |
@@ -10318,8 +12817,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10318 | } | 12817 | } |
10319 | } | 12818 | } |
10320 | 12819 | ||
12820 | HttpInitialRequestStatus status; | ||
10321 | UUID reqID | 12821 | UUID reqID |
10322 | = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body); | 12822 | = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status); |
12823 | |||
12824 | if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER) | ||
12825 | Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url)); | ||
10323 | 12826 | ||
10324 | if (reqID != UUID.Zero) | 12827 | if (reqID != UUID.Zero) |
10325 | return reqID.ToString(); | 12828 | return reqID.ToString(); |
@@ -10342,7 +12845,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10342 | public void llResetLandBanList() | 12845 | public void llResetLandBanList() |
10343 | { | 12846 | { |
10344 | m_host.AddScriptLPS(1); | 12847 | m_host.AddScriptLPS(1); |
10345 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; | 12848 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
10346 | if (land.OwnerID == m_host.OwnerID) | 12849 | if (land.OwnerID == m_host.OwnerID) |
10347 | { | 12850 | { |
10348 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 12851 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
@@ -10353,13 +12856,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10353 | } | 12856 | } |
10354 | } | 12857 | } |
10355 | } | 12858 | } |
10356 | ScriptSleep(100); | 12859 | ScriptSleep(m_sleepMsOnResetLandBanList); |
10357 | } | 12860 | } |
10358 | 12861 | ||
10359 | public void llResetLandPassList() | 12862 | public void llResetLandPassList() |
10360 | { | 12863 | { |
10361 | m_host.AddScriptLPS(1); | 12864 | m_host.AddScriptLPS(1); |
10362 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).LandData; | 12865 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
10363 | if (land.OwnerID == m_host.OwnerID) | 12866 | if (land.OwnerID == m_host.OwnerID) |
10364 | { | 12867 | { |
10365 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 12868 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
@@ -10370,18 +12873,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10370 | } | 12873 | } |
10371 | } | 12874 | } |
10372 | } | 12875 | } |
10373 | ScriptSleep(100); | 12876 | ScriptSleep(m_sleepMsOnResetLandPassList); |
10374 | } | 12877 | } |
10375 | 12878 | ||
10376 | public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) | 12879 | public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) |
10377 | { | 12880 | { |
10378 | m_host.AddScriptLPS(1); | 12881 | m_host.AddScriptLPS(1); |
10379 | 12882 | ||
10380 | ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); | 12883 | ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); |
10381 | 12884 | ||
10382 | if (lo == null) | 12885 | if (lo == null) |
10383 | return 0; | 12886 | return 0; |
10384 | 12887 | ||
10385 | IPrimCounts pc = lo.PrimCounts; | 12888 | IPrimCounts pc = lo.PrimCounts; |
10386 | 12889 | ||
10387 | if (sim_wide != ScriptBaseClass.FALSE) | 12890 | if (sim_wide != ScriptBaseClass.FALSE) |
@@ -10411,7 +12914,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10411 | else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP) | 12914 | else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP) |
10412 | return 0; // counts not implemented yet | 12915 | return 0; // counts not implemented yet |
10413 | } | 12916 | } |
10414 | 12917 | ||
10415 | return 0; | 12918 | return 0; |
10416 | } | 12919 | } |
10417 | 12920 | ||
@@ -10428,7 +12931,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10428 | ret.Add(new LSL_Integer(detectedParams.Value)); | 12931 | ret.Add(new LSL_Integer(detectedParams.Value)); |
10429 | } | 12932 | } |
10430 | } | 12933 | } |
10431 | ScriptSleep(2000); | 12934 | ScriptSleep(m_sleepMsOnGetParcelPrimOwners); |
10432 | return ret; | 12935 | return ret; |
10433 | } | 12936 | } |
10434 | 12937 | ||
@@ -10535,10 +13038,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10535 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); | 13038 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); |
10536 | break; | 13039 | break; |
10537 | case ScriptBaseClass.OBJECT_ROT: | 13040 | case ScriptBaseClass.OBJECT_ROT: |
10538 | ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); | 13041 | ret.Add(new LSL_Rotation(av.GetWorldRotation())); |
10539 | break; | 13042 | break; |
10540 | case ScriptBaseClass.OBJECT_VELOCITY: | 13043 | case ScriptBaseClass.OBJECT_VELOCITY: |
10541 | ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); | 13044 | ret.Add(new LSL_Vector(av.GetWorldVelocity())); |
10542 | break; | 13045 | break; |
10543 | case ScriptBaseClass.OBJECT_OWNER: | 13046 | case ScriptBaseClass.OBJECT_OWNER: |
10544 | ret.Add(new LSL_String(id)); | 13047 | ret.Add(new LSL_String(id)); |
@@ -10603,6 +13106,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10603 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: | 13106 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: |
10604 | ret.Add(new LSL_Integer(0)); | 13107 | ret.Add(new LSL_Integer(0)); |
10605 | break; | 13108 | break; |
13109 | case ScriptBaseClass.OBJECT_RENDER_WEIGHT: | ||
13110 | ret.Add(new LSL_Integer(-1)); | ||
13111 | break; | ||
13112 | case ScriptBaseClass.OBJECT_HOVER_HEIGHT: | ||
13113 | ret.Add(new LSL_Float(0)); | ||
13114 | break; | ||
13115 | case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: | ||
13116 | LSL_Float shapeType; | ||
13117 | if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0) | ||
13118 | shapeType = new LSL_Float(1); | ||
13119 | else | ||
13120 | shapeType = new LSL_Float(0); | ||
13121 | ret.Add(shapeType); | ||
13122 | break; | ||
13123 | case ScriptBaseClass.OBJECT_LAST_OWNER_ID: | ||
13124 | ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY)); | ||
13125 | break; | ||
10606 | default: | 13126 | default: |
10607 | // Invalid or unhandled constant. | 13127 | // Invalid or unhandled constant. |
10608 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); | 13128 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); |
@@ -10630,20 +13150,43 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10630 | ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); | 13150 | ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); |
10631 | break; | 13151 | break; |
10632 | case ScriptBaseClass.OBJECT_ROT: | 13152 | case ScriptBaseClass.OBJECT_ROT: |
13153 | Quaternion rot = Quaternion.Identity; | ||
13154 | |||
13155 | if (obj.ParentGroup.IsAttachment) | ||
10633 | { | 13156 | { |
10634 | Quaternion rot = Quaternion.Identity; | 13157 | ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); |
10635 | 13158 | ||
13159 | if (sp != null) | ||
13160 | rot = sp.GetWorldRotation(); | ||
13161 | } | ||
13162 | else | ||
13163 | { | ||
10636 | if (obj.ParentGroup.RootPart == obj) | 13164 | if (obj.ParentGroup.RootPart == obj) |
10637 | rot = obj.ParentGroup.GroupRotation; | 13165 | rot = obj.ParentGroup.GroupRotation; |
10638 | else | 13166 | else |
10639 | rot = obj.GetWorldRotation(); | 13167 | rot = obj.GetWorldRotation(); |
10640 | |||
10641 | LSL_Rotation objrot = new LSL_Rotation(rot); | ||
10642 | ret.Add(objrot); | ||
10643 | } | 13168 | } |
13169 | |||
13170 | LSL_Rotation objrot = new LSL_Rotation(rot); | ||
13171 | ret.Add(objrot); | ||
13172 | |||
10644 | break; | 13173 | break; |
10645 | case ScriptBaseClass.OBJECT_VELOCITY: | 13174 | case ScriptBaseClass.OBJECT_VELOCITY: |
10646 | ret.Add(new LSL_Vector(obj.Velocity)); | 13175 | Vector3 vel = Vector3.Zero; |
13176 | |||
13177 | if (obj.ParentGroup.IsAttachment) | ||
13178 | { | ||
13179 | ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); | ||
13180 | |||
13181 | if (sp != null) | ||
13182 | vel = sp.GetWorldVelocity(); | ||
13183 | } | ||
13184 | else | ||
13185 | { | ||
13186 | vel = obj.Velocity; | ||
13187 | } | ||
13188 | |||
13189 | ret.Add(vel); | ||
10647 | break; | 13190 | break; |
10648 | case ScriptBaseClass.OBJECT_OWNER: | 13191 | case ScriptBaseClass.OBJECT_OWNER: |
10649 | ret.Add(new LSL_String(obj.OwnerID.ToString())); | 13192 | ret.Add(new LSL_String(obj.OwnerID.ToString())); |
@@ -10744,6 +13287,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10744 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: | 13287 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: |
10745 | ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); | 13288 | ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); |
10746 | break; | 13289 | break; |
13290 | case ScriptBaseClass.OBJECT_RENDER_WEIGHT: | ||
13291 | ret.Add(new LSL_Integer(0)); | ||
13292 | break; | ||
13293 | case ScriptBaseClass.OBJECT_HOVER_HEIGHT: | ||
13294 | ret.Add(new LSL_Float(0)); | ||
13295 | break; | ||
13296 | case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: | ||
13297 | ret.Add(new LSL_Float(-1)); | ||
13298 | break; | ||
13299 | case ScriptBaseClass.OBJECT_LAST_OWNER_ID: | ||
13300 | ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString())); | ||
13301 | break; | ||
10747 | default: | 13302 | default: |
10748 | // Invalid or unhandled constant. | 13303 | // Invalid or unhandled constant. |
10749 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); | 13304 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); |
@@ -10754,7 +13309,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10754 | return ret; | 13309 | return ret; |
10755 | } | 13310 | } |
10756 | } | 13311 | } |
10757 | 13312 | ||
10758 | return new LSL_List(); | 13313 | return new LSL_List(); |
10759 | } | 13314 | } |
10760 | 13315 | ||
@@ -10768,25 +13323,71 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10768 | return item.ItemID; | 13323 | return item.ItemID; |
10769 | } | 13324 | } |
10770 | 13325 | ||
10771 | internal void ShoutError(string msg) | 13326 | /// <summary> |
13327 | /// Reports the script error in the viewer's Script Warning/Error dialog and shouts it on the debug channel. | ||
13328 | /// </summary> | ||
13329 | /// <param name="command">The name of the command that generated the error.</param> | ||
13330 | /// <param name="message">The error message to report to the user.</param> | ||
13331 | internal void Error(string command, string message) | ||
10772 | { | 13332 | { |
10773 | llShout(ScriptBaseClass.DEBUG_CHANNEL, msg); | 13333 | string text = command + ": " + message; |
13334 | if (text.Length > 1023) | ||
13335 | { | ||
13336 | text = text.Substring(0, 1023); | ||
13337 | } | ||
13338 | |||
13339 | World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL, | ||
13340 | m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
13341 | |||
13342 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
13343 | if (wComm != null) | ||
13344 | { | ||
13345 | wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text); | ||
13346 | } | ||
10774 | } | 13347 | } |
10775 | 13348 | ||
10776 | internal void NotImplemented(string command) | 13349 | /// <summary> |
13350 | /// Reports that the command is not implemented as a script error. | ||
13351 | /// </summary> | ||
13352 | /// <param name="command">The name of the command that is not implemented.</param> | ||
13353 | /// <param name="message">Additional information to report to the user. (Optional)</param> | ||
13354 | internal void NotImplemented(string command, string message = "") | ||
10777 | { | 13355 | { |
10778 | if (throwErrorOnNotImplemented) | 13356 | if (throwErrorOnNotImplemented) |
10779 | throw new NotImplementedException("Command not implemented: " + command); | 13357 | { |
10780 | } | 13358 | if (message != "") |
13359 | { | ||
13360 | message = " - " + message; | ||
13361 | } | ||
10781 | 13362 | ||
10782 | internal void Deprecated(string command) | 13363 | throw new NotImplementedException("Command not implemented: " + command + message); |
10783 | { | 13364 | } |
10784 | throw new ScriptException("Command deprecated: " + command); | 13365 | else |
13366 | { | ||
13367 | string text = "Command not implemented"; | ||
13368 | if (message != "") | ||
13369 | { | ||
13370 | text = text + " - " + message; | ||
13371 | } | ||
13372 | |||
13373 | Error(command, text); | ||
13374 | } | ||
10785 | } | 13375 | } |
10786 | 13376 | ||
10787 | internal void LSLError(string msg) | 13377 | /// <summary> |
13378 | /// Reports that the command is deprecated as a script error. | ||
13379 | /// </summary> | ||
13380 | /// <param name="command">The name of the command that is deprecated.</param> | ||
13381 | /// <param name="message">Additional information to report to the user. (Optional)</param> | ||
13382 | internal void Deprecated(string command, string message = "") | ||
10788 | { | 13383 | { |
10789 | throw new ScriptException("LSL Runtime Error: " + msg); | 13384 | string text = "Command deprecated"; |
13385 | if (message != "") | ||
13386 | { | ||
13387 | text = text + " - " + message; | ||
13388 | } | ||
13389 | |||
13390 | Error(command, text); | ||
10790 | } | 13391 | } |
10791 | 13392 | ||
10792 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); | 13393 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); |
@@ -10818,20 +13419,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10818 | if (assetID == UUID.Zero) | 13419 | if (assetID == UUID.Zero) |
10819 | { | 13420 | { |
10820 | // => complain loudly, as specified by the LSL docs | 13421 | // => complain loudly, as specified by the LSL docs |
10821 | ShoutError("Notecard '" + name + "' could not be found."); | 13422 | Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); |
10822 | 13423 | ||
10823 | return UUID.Zero.ToString(); | 13424 | return UUID.Zero.ToString(); |
10824 | } | 13425 | } |
10825 | 13426 | ||
13427 | string reqIdentifier = UUID.Random().ToString(); | ||
13428 | |||
10826 | // was: UUID tid = tid = AsyncCommands. | 13429 | // was: UUID tid = tid = AsyncCommands. |
10827 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString()); | 13430 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); |
10828 | 13431 | ||
10829 | if (NotecardCache.IsCached(assetID)) | 13432 | if (NotecardCache.IsCached(assetID)) |
10830 | { | 13433 | { |
10831 | AsyncCommands. | 13434 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString()); |
10832 | DataserverPlugin.DataserverReply(assetID.ToString(), | 13435 | |
10833 | NotecardCache.GetLines(assetID).ToString()); | 13436 | ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); |
10834 | ScriptSleep(100); | ||
10835 | return tid.ToString(); | 13437 | return tid.ToString(); |
10836 | } | 13438 | } |
10837 | 13439 | ||
@@ -10839,19 +13441,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10839 | { | 13441 | { |
10840 | if (a == null || a.Type != 7) | 13442 | if (a == null || a.Type != 7) |
10841 | { | 13443 | { |
10842 | ShoutError("Notecard '" + name + "' could not be found."); | 13444 | Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); |
10843 | return; | 13445 | return; |
10844 | } | 13446 | } |
10845 | 13447 | ||
10846 | string data = Encoding.UTF8.GetString(a.Data); | 13448 | NotecardCache.Cache(id, a.Data); |
10847 | //m_log.Debug(data); | 13449 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString()); |
10848 | NotecardCache.Cache(id, data); | ||
10849 | AsyncCommands. | ||
10850 | DataserverPlugin.DataserverReply(id.ToString(), | ||
10851 | NotecardCache.GetLines(id).ToString()); | ||
10852 | }); | 13450 | }); |
10853 | 13451 | ||
10854 | ScriptSleep(100); | 13452 | ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); |
10855 | return tid.ToString(); | 13453 | return tid.ToString(); |
10856 | } | 13454 | } |
10857 | 13455 | ||
@@ -10872,19 +13470,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10872 | if (assetID == UUID.Zero) | 13470 | if (assetID == UUID.Zero) |
10873 | { | 13471 | { |
10874 | // => complain loudly, as specified by the LSL docs | 13472 | // => complain loudly, as specified by the LSL docs |
10875 | ShoutError("Notecard '" + name + "' could not be found."); | 13473 | Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); |
10876 | 13474 | ||
10877 | return UUID.Zero.ToString(); | 13475 | return UUID.Zero.ToString(); |
10878 | } | 13476 | } |
10879 | 13477 | ||
13478 | string reqIdentifier = UUID.Random().ToString(); | ||
13479 | |||
10880 | // was: UUID tid = tid = AsyncCommands. | 13480 | // was: UUID tid = tid = AsyncCommands. |
10881 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, assetID.ToString()); | 13481 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); |
10882 | 13482 | ||
10883 | if (NotecardCache.IsCached(assetID)) | 13483 | if (NotecardCache.IsCached(assetID)) |
10884 | { | 13484 | { |
10885 | AsyncCommands.DataserverPlugin.DataserverReply(assetID.ToString(), | 13485 | AsyncCommands.DataserverPlugin.DataserverReply( |
10886 | NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); | 13486 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); |
10887 | ScriptSleep(100); | 13487 | |
13488 | ScriptSleep(m_sleepMsOnGetNotecardLine); | ||
10888 | return tid.ToString(); | 13489 | return tid.ToString(); |
10889 | } | 13490 | } |
10890 | 13491 | ||
@@ -10892,18 +13493,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10892 | { | 13493 | { |
10893 | if (a == null || a.Type != 7) | 13494 | if (a == null || a.Type != 7) |
10894 | { | 13495 | { |
10895 | ShoutError("Notecard '" + name + "' could not be found."); | 13496 | Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); |
10896 | return; | 13497 | return; |
10897 | } | 13498 | } |
10898 | 13499 | ||
10899 | string data = Encoding.UTF8.GetString(a.Data); | 13500 | string data = Encoding.UTF8.GetString(a.Data); |
10900 | //m_log.Debug(data); | 13501 | //m_log.Debug(data); |
10901 | NotecardCache.Cache(id, data); | 13502 | NotecardCache.Cache(id, a.Data); |
10902 | AsyncCommands.DataserverPlugin.DataserverReply(id.ToString(), | 13503 | AsyncCommands.DataserverPlugin.DataserverReply( |
10903 | NotecardCache.GetLine(id, line, m_notecardLineReadCharsMax)); | 13504 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); |
10904 | }); | 13505 | }); |
10905 | 13506 | ||
10906 | ScriptSleep(100); | 13507 | ScriptSleep(m_sleepMsOnGetNotecardLine); |
10907 | return tid.ToString(); | 13508 | return tid.ToString(); |
10908 | } | 13509 | } |
10909 | 13510 | ||
@@ -10916,41 +13517,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
10916 | if (obj.OwnerID != m_host.OwnerID) | 13517 | if (obj.OwnerID != m_host.OwnerID) |
10917 | return; | 13518 | return; |
10918 | 13519 | ||
10919 | uint rulesParsed = 0; | 13520 | SetEntityParams(new List<ISceneEntity>() { obj }, rules, originFunc); |
10920 | LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed); | ||
10921 | |||
10922 | while ((object)remaining != null && remaining.Length > 2) | ||
10923 | { | ||
10924 | LSL_Integer newLink = remaining.GetLSLIntegerItem(0); | ||
10925 | LSL_List newrules = remaining.GetSublist(1, -1); | ||
10926 | foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ | ||
10927 | remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed); | ||
10928 | } | ||
10929 | } | ||
10930 | } | 13521 | } |
10931 | 13522 | ||
10932 | public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) | 13523 | public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) |
10933 | { | 13524 | { |
10934 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); | 13525 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); |
10935 | 13526 | ||
10936 | LSL_List result = new LSL_List(); | 13527 | if (obj != null && obj.OwnerID == m_host.OwnerID) |
10937 | 13528 | return GetEntityParams(obj, rules); | |
10938 | if (obj != null && obj.OwnerID != m_host.OwnerID) | ||
10939 | { | ||
10940 | LSL_List remaining = GetPrimParams(obj, rules, ref result); | ||
10941 | |||
10942 | while (remaining != null && remaining.Length > 2) | ||
10943 | { | ||
10944 | int linknumber = remaining.GetLSLIntegerItem(0); | ||
10945 | rules = remaining.GetSublist(1, -1); | ||
10946 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | ||
10947 | 13529 | ||
10948 | foreach (SceneObjectPart part in parts) | 13530 | return new LSL_List(); |
10949 | remaining = GetPrimParams(part, rules, ref result); | ||
10950 | } | ||
10951 | } | ||
10952 | |||
10953 | return result; | ||
10954 | } | 13531 | } |
10955 | 13532 | ||
10956 | public void print(string str) | 13533 | public void print(string str) |
@@ -11036,7 +13613,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11036 | World.ForEachScenePresence(delegate(ScenePresence sp) | 13613 | World.ForEachScenePresence(delegate(ScenePresence sp) |
11037 | { | 13614 | { |
11038 | Vector3 ac = sp.AbsolutePosition - rayStart; | 13615 | Vector3 ac = sp.AbsolutePosition - rayStart; |
11039 | Vector3 bc = sp.AbsolutePosition - rayEnd; | 13616 | // Vector3 bc = sp.AbsolutePosition - rayEnd; |
11040 | 13617 | ||
11041 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | 13618 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); |
11042 | 13619 | ||
@@ -11124,9 +13701,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11124 | radius = Math.Abs(maxY); | 13701 | radius = Math.Abs(maxY); |
11125 | if (Math.Abs(maxZ) > radius) | 13702 | if (Math.Abs(maxZ) > radius) |
11126 | radius = Math.Abs(maxZ); | 13703 | radius = Math.Abs(maxZ); |
11127 | 13704 | radius = radius*1.413f; | |
11128 | Vector3 ac = group.AbsolutePosition - rayStart; | 13705 | Vector3 ac = group.AbsolutePosition - rayStart; |
11129 | Vector3 bc = group.AbsolutePosition - rayEnd; | 13706 | // Vector3 bc = group.AbsolutePosition - rayEnd; |
11130 | 13707 | ||
11131 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | 13708 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); |
11132 | 13709 | ||
@@ -11139,11 +13716,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11139 | if (d2 > 0) | 13716 | if (d2 > 0) |
11140 | return; | 13717 | return; |
11141 | 13718 | ||
13719 | ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); | ||
11142 | EntityIntersection intersection = group.TestIntersection(ray, true, false); | 13720 | EntityIntersection intersection = group.TestIntersection(ray, true, false); |
11143 | // Miss. | 13721 | // Miss. |
11144 | if (!intersection.HitTF) | 13722 | if (!intersection.HitTF) |
11145 | return; | 13723 | return; |
11146 | 13724 | ||
13725 | Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ); | ||
13726 | Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ); | ||
13727 | //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); | ||
13728 | if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X && | ||
13729 | intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y && | ||
13730 | intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z)) | ||
13731 | return; | ||
13732 | |||
11147 | ContactResult result = new ContactResult (); | 13733 | ContactResult result = new ContactResult (); |
11148 | result.ConsumerID = group.LocalId; | 13734 | result.ConsumerID = group.LocalId; |
11149 | result.Depth = intersection.distance; | 13735 | result.Depth = intersection.distance; |
@@ -11284,6 +13870,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11284 | 13870 | ||
11285 | public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) | 13871 | public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) |
11286 | { | 13872 | { |
13873 | // Use llCastRay V3 if configured | ||
13874 | if (m_useCastRayV3) | ||
13875 | return llCastRayV3(start, end, options); | ||
13876 | |||
11287 | LSL_List list = new LSL_List(); | 13877 | LSL_List list = new LSL_List(); |
11288 | 13878 | ||
11289 | m_host.AddScriptLPS(1); | 13879 | m_host.AddScriptLPS(1); |
@@ -11322,25 +13912,93 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11322 | bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); | 13912 | bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); |
11323 | 13913 | ||
11324 | 13914 | ||
11325 | if (checkTerrain) | 13915 | if (World.SupportsRayCastFiltered()) |
11326 | { | 13916 | { |
11327 | ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); | 13917 | if (dist == 0) |
11328 | if (groundContact != null) | 13918 | return list; |
11329 | results.Add((ContactResult)groundContact); | 13919 | |
11330 | } | 13920 | RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull; |
13921 | if (checkTerrain) | ||
13922 | rayfilter |= RayFilterFlags.land; | ||
13923 | // if (checkAgents) | ||
13924 | // rayfilter |= RayFilterFlags.agent; | ||
13925 | if (checkPhysical) | ||
13926 | rayfilter |= RayFilterFlags.physical; | ||
13927 | if (checkNonPhysical) | ||
13928 | rayfilter |= RayFilterFlags.nonphysical; | ||
13929 | if (detectPhantom) | ||
13930 | rayfilter |= RayFilterFlags.LSLPhantom; | ||
11331 | 13931 | ||
11332 | if (checkAgents) | 13932 | Vector3 direction = dir * ( 1/dist); |
13933 | |||
13934 | if(rayfilter == 0) | ||
13935 | { | ||
13936 | list.Add(new LSL_Integer(0)); | ||
13937 | return list; | ||
13938 | } | ||
13939 | |||
13940 | // get some more contacts to sort ??? | ||
13941 | int physcount = 4 * count; | ||
13942 | if (physcount > 20) | ||
13943 | physcount = 20; | ||
13944 | |||
13945 | object physresults; | ||
13946 | physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter); | ||
13947 | |||
13948 | if (physresults == null) | ||
13949 | { | ||
13950 | list.Add(new LSL_Integer(-3)); // timeout error | ||
13951 | return list; | ||
13952 | } | ||
13953 | |||
13954 | results = (List<ContactResult>)physresults; | ||
13955 | |||
13956 | // for now physics doesn't detect sitted avatars so do it outside physics | ||
13957 | if (checkAgents) | ||
13958 | { | ||
13959 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); | ||
13960 | foreach (ContactResult r in agentHits) | ||
13961 | results.Add(r); | ||
13962 | } | ||
13963 | |||
13964 | // TODO: Replace this with a better solution. ObjectIntersection can only | ||
13965 | // detect nonphysical phantoms. They are detected by virtue of being | ||
13966 | // nonphysical (e.g. no PhysActor) so will not conflict with detecting | ||
13967 | // physicsl phantoms as done by the physics scene | ||
13968 | // We don't want anything else but phantoms here. | ||
13969 | if (detectPhantom) | ||
13970 | { | ||
13971 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true); | ||
13972 | foreach (ContactResult r in objectHits) | ||
13973 | results.Add(r); | ||
13974 | } | ||
13975 | } | ||
13976 | else | ||
11333 | { | 13977 | { |
11334 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); | 13978 | if (checkAgents) |
11335 | foreach (ContactResult r in agentHits) | 13979 | { |
11336 | results.Add(r); | 13980 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); |
13981 | foreach (ContactResult r in agentHits) | ||
13982 | results.Add(r); | ||
13983 | } | ||
13984 | |||
13985 | if (checkPhysical || checkNonPhysical || detectPhantom) | ||
13986 | { | ||
13987 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); | ||
13988 | for (int iter = 0; iter < objectHits.Length; iter++) | ||
13989 | { | ||
13990 | // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler. | ||
13991 | objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart); | ||
13992 | results.Add(objectHits[iter]); | ||
13993 | } | ||
13994 | } | ||
11337 | } | 13995 | } |
11338 | 13996 | ||
11339 | if (checkPhysical || checkNonPhysical || detectPhantom) | 13997 | if (checkTerrain) |
11340 | { | 13998 | { |
11341 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); | 13999 | ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); |
11342 | foreach (ContactResult r in objectHits) | 14000 | if (groundContact != null) |
11343 | results.Add(r); | 14001 | results.Add((ContactResult)groundContact); |
11344 | } | 14002 | } |
11345 | 14003 | ||
11346 | results.Sort(delegate(ContactResult a, ContactResult b) | 14004 | results.Sort(delegate(ContactResult a, ContactResult b) |
@@ -11381,7 +14039,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11381 | else | 14039 | else |
11382 | { | 14040 | { |
11383 | ScenePresence sp = World.GetScenePresence(result.ConsumerID); | 14041 | ScenePresence sp = World.GetScenePresence(result.ConsumerID); |
11384 | /// It it a boy? a girl? | 14042 | /// It it a boy? a girl? |
11385 | if (sp != null) | 14043 | if (sp != null) |
11386 | itemID = sp.UUID; | 14044 | itemID = sp.UUID; |
11387 | } | 14045 | } |
@@ -11393,7 +14051,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11393 | list.Add(new LSL_Integer(linkNum)); | 14051 | list.Add(new LSL_Integer(linkNum)); |
11394 | 14052 | ||
11395 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) | 14053 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) |
11396 | list.Add(new LSL_Vector(result.Normal.X, result.Normal.Y, result.Normal.Z)); | 14054 | list.Add(new LSL_Vector(result.Normal)); |
11397 | 14055 | ||
11398 | values++; | 14056 | values++; |
11399 | if (values >= count) | 14057 | if (values >= count) |
@@ -11405,6 +14063,872 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11405 | return list; | 14063 | return list; |
11406 | } | 14064 | } |
11407 | 14065 | ||
14066 | /// <summary> | ||
14067 | /// Implementation of llCastRay similar to SL 2015-04-21. | ||
14068 | /// http://wiki.secondlife.com/wiki/LlCastRay | ||
14069 | /// Uses pure geometry, bounding shapes, meshing and no physics | ||
14070 | /// for prims, sculpts, meshes, avatars and terrain. | ||
14071 | /// Implements all flags, reject types and data flags. | ||
14072 | /// Can handle both objects/groups and prims/parts, by config. | ||
14073 | /// May sometimes be inaccurate owing to calculation precision, | ||
14074 | /// meshing detail level and a bug in libopenmetaverse PrimMesher. | ||
14075 | /// </summary> | ||
14076 | public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options) | ||
14077 | { | ||
14078 | m_host.AddScriptLPS(1); | ||
14079 | LSL_List result = new LSL_List(); | ||
14080 | |||
14081 | // Prepare throttle data | ||
14082 | int calledMs = Environment.TickCount; | ||
14083 | Stopwatch stopWatch = new Stopwatch(); | ||
14084 | stopWatch.Start(); | ||
14085 | UUID regionId = World.RegionInfo.RegionID; | ||
14086 | UUID userId = UUID.Zero; | ||
14087 | int msAvailable = 0; | ||
14088 | // Throttle per owner when attachment or "vehicle" (sat upon) | ||
14089 | if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0) | ||
14090 | { | ||
14091 | userId = m_host.OwnerID; | ||
14092 | msAvailable = m_msPerAvatarInCastRay; | ||
14093 | } | ||
14094 | // Throttle per parcel when not attachment or vehicle | ||
14095 | else | ||
14096 | { | ||
14097 | LandData land = World.GetLandData(m_host.GetWorldPosition()); | ||
14098 | if (land != null) | ||
14099 | msAvailable = m_msPerRegionInCastRay * land.Area / 65536; | ||
14100 | } | ||
14101 | // Clamp for "oversized" parcels on varregions | ||
14102 | if (msAvailable > m_msMaxInCastRay) | ||
14103 | msAvailable = m_msMaxInCastRay; | ||
14104 | |||
14105 | // Check throttle data | ||
14106 | int fromCalledMs = calledMs - m_msThrottleInCastRay; | ||
14107 | lock (m_castRayCalls) | ||
14108 | { | ||
14109 | for (int i = m_castRayCalls.Count - 1; i >= 0; i--) | ||
14110 | { | ||
14111 | // Delete old calls from throttle data | ||
14112 | if (m_castRayCalls[i].CalledMs < fromCalledMs) | ||
14113 | m_castRayCalls.RemoveAt(i); | ||
14114 | // Use current region (in multi-region sims) | ||
14115 | else if (m_castRayCalls[i].RegionId == regionId) | ||
14116 | { | ||
14117 | // Reduce available time with recent calls | ||
14118 | if (m_castRayCalls[i].UserId == userId) | ||
14119 | msAvailable -= m_castRayCalls[i].UsedMs; | ||
14120 | } | ||
14121 | } | ||
14122 | } | ||
14123 | |||
14124 | // Return failure if not enough available time | ||
14125 | if (msAvailable < m_msMinInCastRay) | ||
14126 | { | ||
14127 | result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED)); | ||
14128 | return result; | ||
14129 | } | ||
14130 | |||
14131 | // Initialize | ||
14132 | List<RayHit> rayHits = new List<RayHit>(); | ||
14133 | float tol = m_floatToleranceInCastRay; | ||
14134 | Vector3 pos1Ray = start; | ||
14135 | Vector3 pos2Ray = end; | ||
14136 | |||
14137 | // Get input options | ||
14138 | int rejectTypes = 0; | ||
14139 | int dataFlags = 0; | ||
14140 | int maxHits = 1; | ||
14141 | bool detectPhantom = false; | ||
14142 | for (int i = 0; i < options.Length; i += 2) | ||
14143 | { | ||
14144 | if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) | ||
14145 | rejectTypes = options.GetLSLIntegerItem(i + 1); | ||
14146 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) | ||
14147 | dataFlags = options.GetLSLIntegerItem(i + 1); | ||
14148 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) | ||
14149 | maxHits = options.GetLSLIntegerItem(i + 1); | ||
14150 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) | ||
14151 | detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0); | ||
14152 | } | ||
14153 | if (maxHits > m_maxHitsInCastRay) | ||
14154 | maxHits = m_maxHitsInCastRay; | ||
14155 | bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0); | ||
14156 | bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0); | ||
14157 | bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0); | ||
14158 | bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0); | ||
14159 | bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0); | ||
14160 | bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0); | ||
14161 | bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); | ||
14162 | |||
14163 | // Calculate some basic parameters | ||
14164 | Vector3 vecRay = pos2Ray - pos1Ray; | ||
14165 | float rayLength = vecRay.Length(); | ||
14166 | |||
14167 | // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits | ||
14168 | IRendering primMesher = null; | ||
14169 | List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); | ||
14170 | if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) | ||
14171 | { | ||
14172 | result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); | ||
14173 | return result; | ||
14174 | } | ||
14175 | primMesher = RenderingLoader.LoadRenderer(renderers[0]); | ||
14176 | |||
14177 | // Iterate over all objects/groups and prims/parts in region | ||
14178 | World.ForEachSOG( | ||
14179 | delegate(SceneObjectGroup group) | ||
14180 | { | ||
14181 | // Check group filters unless part filters are configured | ||
14182 | bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical); | ||
14183 | bool isNonphysical = !isPhysical; | ||
14184 | bool isPhantom = group.IsPhantom || group.IsVolumeDetect; | ||
14185 | bool isAttachment = group.IsAttachment; | ||
14186 | bool doGroup = true; | ||
14187 | if (isPhysical && rejectPhysical) | ||
14188 | doGroup = false; | ||
14189 | if (isNonphysical && rejectNonphysical) | ||
14190 | doGroup = false; | ||
14191 | if (isPhantom && detectPhantom) | ||
14192 | doGroup = true; | ||
14193 | if (m_filterPartsInCastRay) | ||
14194 | doGroup = true; | ||
14195 | if (isAttachment && !m_doAttachmentsInCastRay) | ||
14196 | doGroup = false; | ||
14197 | // Parse object/group if passed filters | ||
14198 | if (doGroup) | ||
14199 | { | ||
14200 | // Iterate over all prims/parts in object/group | ||
14201 | foreach(SceneObjectPart part in group.Parts) | ||
14202 | { | ||
14203 | // Check part filters if configured | ||
14204 | if (m_filterPartsInCastRay) | ||
14205 | { | ||
14206 | isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical); | ||
14207 | isNonphysical = !isPhysical; | ||
14208 | isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive); | ||
14209 | bool doPart = true; | ||
14210 | if (isPhysical && rejectPhysical) | ||
14211 | doPart = false; | ||
14212 | if (isNonphysical && rejectNonphysical) | ||
14213 | doPart = false; | ||
14214 | if (isPhantom && detectPhantom) | ||
14215 | doPart = true; | ||
14216 | if (!doPart) | ||
14217 | continue; | ||
14218 | } | ||
14219 | |||
14220 | // Parse prim/part and project ray if passed filters | ||
14221 | Vector3 scalePart = part.Scale; | ||
14222 | Vector3 posPart = part.GetWorldPosition(); | ||
14223 | Quaternion rotPart = part.GetWorldRotation(); | ||
14224 | Quaternion rotPartInv = Quaternion.Inverse(rotPart); | ||
14225 | Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; | ||
14226 | Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; | ||
14227 | |||
14228 | // Filter parts by shape bounding boxes | ||
14229 | Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f); | ||
14230 | if (!part.Shape.SculptEntry) | ||
14231 | shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); | ||
14232 | shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol)); | ||
14233 | if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) | ||
14234 | { | ||
14235 | // Prepare data needed to check for ray hits | ||
14236 | RayTrans rayTrans = new RayTrans(); | ||
14237 | rayTrans.PartId = part.UUID; | ||
14238 | rayTrans.GroupId = part.ParentGroup.UUID; | ||
14239 | rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; | ||
14240 | rayTrans.ScalePart = scalePart; | ||
14241 | rayTrans.PositionPart = posPart; | ||
14242 | rayTrans.RotationPart = rotPart; | ||
14243 | rayTrans.ShapeNeedsEnds = true; | ||
14244 | rayTrans.Position1Ray = pos1Ray; | ||
14245 | rayTrans.Position1RayProj = pos1RayProj; | ||
14246 | rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; | ||
14247 | |||
14248 | // Get detail level depending on type | ||
14249 | int lod = 0; | ||
14250 | // Mesh detail level | ||
14251 | if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) | ||
14252 | lod = (int)m_meshLodInCastRay; | ||
14253 | // Sculpt detail level | ||
14254 | else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) | ||
14255 | lod = (int)m_sculptLodInCastRay; | ||
14256 | // Shape detail level | ||
14257 | else if (!part.Shape.SculptEntry) | ||
14258 | lod = (int)m_primLodInCastRay; | ||
14259 | |||
14260 | // Try to get cached mesh if configured | ||
14261 | ulong meshKey = 0; | ||
14262 | FacetedMesh mesh = null; | ||
14263 | if (m_useMeshCacheInCastRay) | ||
14264 | { | ||
14265 | meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); | ||
14266 | lock (m_cachedMeshes) | ||
14267 | { | ||
14268 | m_cachedMeshes.TryGetValue(meshKey, out mesh); | ||
14269 | } | ||
14270 | } | ||
14271 | |||
14272 | // Create mesh if no cached mesh | ||
14273 | if (mesh == null) | ||
14274 | { | ||
14275 | // Make an OMV prim to be able to mesh part | ||
14276 | Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); | ||
14277 | byte[] sculptAsset = null; | ||
14278 | if (omvPrim.Sculpt != null) | ||
14279 | sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); | ||
14280 | |||
14281 | // When part is mesh, get mesh | ||
14282 | if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) | ||
14283 | { | ||
14284 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); | ||
14285 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); | ||
14286 | meshAsset = null; | ||
14287 | } | ||
14288 | |||
14289 | // When part is sculpt, create mesh | ||
14290 | // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. | ||
14291 | else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) | ||
14292 | { | ||
14293 | IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); | ||
14294 | if (imgDecoder != null) | ||
14295 | { | ||
14296 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); | ||
14297 | if (sculpt != null) | ||
14298 | { | ||
14299 | mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); | ||
14300 | sculpt.Dispose(); | ||
14301 | } | ||
14302 | } | ||
14303 | } | ||
14304 | |||
14305 | // When part is shape, create mesh | ||
14306 | else if (omvPrim.Sculpt == null) | ||
14307 | { | ||
14308 | if ( | ||
14309 | omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && | ||
14310 | omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && | ||
14311 | omvPrim.PrimData.PathSkew == 0.0 && | ||
14312 | omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 | ||
14313 | ) | ||
14314 | rayTrans.ShapeNeedsEnds = false; | ||
14315 | mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); | ||
14316 | } | ||
14317 | |||
14318 | // Cache mesh if configured | ||
14319 | if (m_useMeshCacheInCastRay && mesh != null) | ||
14320 | { | ||
14321 | lock(m_cachedMeshes) | ||
14322 | { | ||
14323 | if (!m_cachedMeshes.ContainsKey(meshKey)) | ||
14324 | m_cachedMeshes.Add(meshKey, mesh); | ||
14325 | } | ||
14326 | } | ||
14327 | } | ||
14328 | // Check mesh for ray hits | ||
14329 | AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); | ||
14330 | mesh = null; | ||
14331 | } | ||
14332 | } | ||
14333 | } | ||
14334 | } | ||
14335 | ); | ||
14336 | |||
14337 | // Check avatar filter | ||
14338 | if (!rejectAgents) | ||
14339 | { | ||
14340 | // Iterate over all avatars in region | ||
14341 | World.ForEachRootScenePresence( | ||
14342 | delegate (ScenePresence sp) | ||
14343 | { | ||
14344 | // Get bounding box | ||
14345 | Vector3 lower; | ||
14346 | Vector3 upper; | ||
14347 | BoundingBoxOfScenePresence(sp, out lower, out upper); | ||
14348 | // Parse avatar | ||
14349 | Vector3 scalePart = upper - lower; | ||
14350 | Vector3 posPart = sp.AbsolutePosition; | ||
14351 | Quaternion rotPart = sp.GetWorldRotation(); | ||
14352 | Quaternion rotPartInv = Quaternion.Inverse(rotPart); | ||
14353 | posPart = posPart + (lower + upper) * 0.5f * rotPart; | ||
14354 | // Project ray | ||
14355 | Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; | ||
14356 | Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; | ||
14357 | |||
14358 | // Filter avatars by shape bounding boxes | ||
14359 | Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol); | ||
14360 | if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) | ||
14361 | { | ||
14362 | // Prepare data needed to check for ray hits | ||
14363 | RayTrans rayTrans = new RayTrans(); | ||
14364 | rayTrans.PartId = sp.UUID; | ||
14365 | rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; | ||
14366 | rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; | ||
14367 | rayTrans.ScalePart = scalePart; | ||
14368 | rayTrans.PositionPart = posPart; | ||
14369 | rayTrans.RotationPart = rotPart; | ||
14370 | rayTrans.ShapeNeedsEnds = false; | ||
14371 | rayTrans.Position1Ray = pos1Ray; | ||
14372 | rayTrans.Position1RayProj = pos1RayProj; | ||
14373 | rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; | ||
14374 | |||
14375 | // Try to get cached mesh if configured | ||
14376 | PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); | ||
14377 | int lod = (int)m_avatarLodInCastRay; | ||
14378 | ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod)); | ||
14379 | FacetedMesh mesh = null; | ||
14380 | if (m_useMeshCacheInCastRay) | ||
14381 | { | ||
14382 | lock (m_cachedMeshes) | ||
14383 | { | ||
14384 | m_cachedMeshes.TryGetValue(meshKey, out mesh); | ||
14385 | } | ||
14386 | } | ||
14387 | |||
14388 | // Create mesh if no cached mesh | ||
14389 | if (mesh == null) | ||
14390 | { | ||
14391 | // Make OMV prim and create mesh | ||
14392 | prim.Scale = scalePart; | ||
14393 | Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); | ||
14394 | mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay); | ||
14395 | |||
14396 | // Cache mesh if configured | ||
14397 | if (m_useMeshCacheInCastRay && mesh != null) | ||
14398 | { | ||
14399 | lock(m_cachedMeshes) | ||
14400 | { | ||
14401 | if (!m_cachedMeshes.ContainsKey(meshKey)) | ||
14402 | m_cachedMeshes.Add(meshKey, mesh); | ||
14403 | } | ||
14404 | } | ||
14405 | } | ||
14406 | |||
14407 | // Check mesh for ray hits | ||
14408 | AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); | ||
14409 | mesh = null; | ||
14410 | } | ||
14411 | } | ||
14412 | ); | ||
14413 | } | ||
14414 | |||
14415 | // Check terrain filter | ||
14416 | if (!rejectLand) | ||
14417 | { | ||
14418 | // Parse terrain | ||
14419 | |||
14420 | // Mesh terrain and check bounding box | ||
14421 | Vector3 lower; | ||
14422 | Vector3 upper; | ||
14423 | List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper); | ||
14424 | lower.Z -= tol; | ||
14425 | upper.Z += tol; | ||
14426 | if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z)) | ||
14427 | { | ||
14428 | // Prepare data needed to check for ray hits | ||
14429 | RayTrans rayTrans = new RayTrans(); | ||
14430 | rayTrans.PartId = UUID.Zero; | ||
14431 | rayTrans.GroupId = UUID.Zero; | ||
14432 | rayTrans.Link = 0; | ||
14433 | rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f); | ||
14434 | rayTrans.PositionPart = Vector3.Zero; | ||
14435 | rayTrans.RotationPart = Quaternion.Identity; | ||
14436 | rayTrans.ShapeNeedsEnds = true; | ||
14437 | rayTrans.Position1Ray = pos1Ray; | ||
14438 | rayTrans.Position1RayProj = pos1Ray; | ||
14439 | rayTrans.VectorRayProj = vecRay; | ||
14440 | |||
14441 | // Check mesh | ||
14442 | AddRayInTris(triangles, rayTrans, ref rayHits); | ||
14443 | triangles = null; | ||
14444 | } | ||
14445 | } | ||
14446 | |||
14447 | // Sort hits by ascending distance | ||
14448 | rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance)); | ||
14449 | |||
14450 | // Check excess hits per part and group | ||
14451 | for (int t = 0; t < 2; t++) | ||
14452 | { | ||
14453 | int maxHitsPerType = 0; | ||
14454 | UUID id = UUID.Zero; | ||
14455 | if (t == 0) | ||
14456 | maxHitsPerType = m_maxHitsPerPrimInCastRay; | ||
14457 | else | ||
14458 | maxHitsPerType = m_maxHitsPerObjectInCastRay; | ||
14459 | |||
14460 | // Handle excess hits only when needed | ||
14461 | if (maxHitsPerType < m_maxHitsInCastRay) | ||
14462 | { | ||
14463 | // Find excess hits | ||
14464 | Hashtable hits = new Hashtable(); | ||
14465 | for (int i = rayHits.Count - 1; i >= 0; i--) | ||
14466 | { | ||
14467 | if (t == 0) | ||
14468 | id = rayHits[i].PartId; | ||
14469 | else | ||
14470 | id = rayHits[i].GroupId; | ||
14471 | if (hits.ContainsKey(id)) | ||
14472 | hits[id] = (int)hits[id] + 1; | ||
14473 | else | ||
14474 | hits[id] = 1; | ||
14475 | } | ||
14476 | |||
14477 | // Remove excess hits | ||
14478 | for (int i = rayHits.Count - 1; i >= 0; i--) | ||
14479 | { | ||
14480 | if (t == 0) | ||
14481 | id = rayHits[i].PartId; | ||
14482 | else | ||
14483 | id = rayHits[i].GroupId; | ||
14484 | int hit = (int)hits[id]; | ||
14485 | if (hit > m_maxHitsPerPrimInCastRay) | ||
14486 | { | ||
14487 | rayHits.RemoveAt(i); | ||
14488 | hit--; | ||
14489 | hits[id] = hit; | ||
14490 | } | ||
14491 | } | ||
14492 | } | ||
14493 | } | ||
14494 | |||
14495 | // Parse hits into result list according to data flags | ||
14496 | int hitCount = rayHits.Count; | ||
14497 | if (hitCount > maxHits) | ||
14498 | hitCount = maxHits; | ||
14499 | for (int i = 0; i < hitCount; i++) | ||
14500 | { | ||
14501 | RayHit rayHit = rayHits[i]; | ||
14502 | if (getRootKey) | ||
14503 | result.Add(new LSL_Key(rayHit.GroupId.ToString())); | ||
14504 | else | ||
14505 | result.Add(new LSL_Key(rayHit.PartId.ToString())); | ||
14506 | result.Add(new LSL_Vector(rayHit.Position)); | ||
14507 | if (getLinkNum) | ||
14508 | result.Add(new LSL_Integer(rayHit.Link)); | ||
14509 | if (getNormal) | ||
14510 | result.Add(new LSL_Vector(rayHit.Normal)); | ||
14511 | } | ||
14512 | result.Add(new LSL_Integer(hitCount)); | ||
14513 | |||
14514 | // Add to throttle data | ||
14515 | stopWatch.Stop(); | ||
14516 | CastRayCall castRayCall = new CastRayCall(); | ||
14517 | castRayCall.RegionId = regionId; | ||
14518 | castRayCall.UserId = userId; | ||
14519 | castRayCall.CalledMs = calledMs; | ||
14520 | castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds; | ||
14521 | lock (m_castRayCalls) | ||
14522 | { | ||
14523 | m_castRayCalls.Add(castRayCall); | ||
14524 | } | ||
14525 | |||
14526 | // Return hits | ||
14527 | return result; | ||
14528 | } | ||
14529 | |||
14530 | /// <summary> | ||
14531 | /// Struct for transmitting parameters required for finding llCastRay ray hits. | ||
14532 | /// </summary> | ||
14533 | public struct RayTrans | ||
14534 | { | ||
14535 | public UUID PartId; | ||
14536 | public UUID GroupId; | ||
14537 | public int Link; | ||
14538 | public Vector3 ScalePart; | ||
14539 | public Vector3 PositionPart; | ||
14540 | public Quaternion RotationPart; | ||
14541 | public bool ShapeNeedsEnds; | ||
14542 | public Vector3 Position1Ray; | ||
14543 | public Vector3 Position1RayProj; | ||
14544 | public Vector3 VectorRayProj; | ||
14545 | } | ||
14546 | |||
14547 | /// <summary> | ||
14548 | /// Struct for llCastRay ray hits. | ||
14549 | /// </summary> | ||
14550 | public struct RayHit | ||
14551 | { | ||
14552 | public UUID PartId; | ||
14553 | public UUID GroupId; | ||
14554 | public int Link; | ||
14555 | public Vector3 Position; | ||
14556 | public Vector3 Normal; | ||
14557 | public float Distance; | ||
14558 | } | ||
14559 | |||
14560 | /// <summary> | ||
14561 | /// Struct for llCastRay throttle data. | ||
14562 | /// </summary> | ||
14563 | public struct CastRayCall | ||
14564 | { | ||
14565 | public UUID RegionId; | ||
14566 | public UUID UserId; | ||
14567 | public int CalledMs; | ||
14568 | public int UsedMs; | ||
14569 | } | ||
14570 | |||
14571 | /// <summary> | ||
14572 | /// Helper to check if a ray intersects a shape bounding box. | ||
14573 | /// </summary> | ||
14574 | private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax) | ||
14575 | { | ||
14576 | // Skip if ray can't intersect bounding box; | ||
14577 | Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj); | ||
14578 | Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj); | ||
14579 | if ( | ||
14580 | rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z || | ||
14581 | rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z | ||
14582 | ) | ||
14583 | return false; | ||
14584 | |||
14585 | // Check if ray intersect any bounding box side | ||
14586 | int sign = 0; | ||
14587 | float dist = 0.0f; | ||
14588 | Vector3 posProj = Vector3.Zero; | ||
14589 | Vector3 vecRayProj = pos2RayProj - pos1RayProj; | ||
14590 | |||
14591 | // Check both X sides unless ray is parallell to them | ||
14592 | if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay) | ||
14593 | { | ||
14594 | for (sign = -1; sign <= 1; sign += 2) | ||
14595 | { | ||
14596 | dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X; | ||
14597 | posProj = pos1RayProj + vecRayProj * dist; | ||
14598 | if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z) | ||
14599 | return true; | ||
14600 | } | ||
14601 | } | ||
14602 | |||
14603 | // Check both Y sides unless ray is parallell to them | ||
14604 | if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay) | ||
14605 | { | ||
14606 | for (sign = -1; sign <= 1; sign += 2) | ||
14607 | { | ||
14608 | dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y; | ||
14609 | posProj = pos1RayProj + vecRayProj * dist; | ||
14610 | if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z) | ||
14611 | return true; | ||
14612 | } | ||
14613 | } | ||
14614 | |||
14615 | // Check both Z sides unless ray is parallell to them | ||
14616 | if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay) | ||
14617 | { | ||
14618 | for (sign = -1; sign <= 1; sign += 2) | ||
14619 | { | ||
14620 | dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z; | ||
14621 | posProj = pos1RayProj + vecRayProj * dist; | ||
14622 | if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y) | ||
14623 | return true; | ||
14624 | } | ||
14625 | } | ||
14626 | |||
14627 | // No hits on bounding box so return false | ||
14628 | return false; | ||
14629 | } | ||
14630 | |||
14631 | /// <summary> | ||
14632 | /// Helper to parse FacetedMesh for ray hits. | ||
14633 | /// </summary> | ||
14634 | private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits) | ||
14635 | { | ||
14636 | if (mesh != null) | ||
14637 | { | ||
14638 | foreach (Face face in mesh.Faces) | ||
14639 | { | ||
14640 | for (int i = 0; i < face.Indices.Count; i += 3) | ||
14641 | { | ||
14642 | Tri triangle = new Tri(); | ||
14643 | triangle.p1 = face.Vertices[face.Indices[i]].Position; | ||
14644 | triangle.p2 = face.Vertices[face.Indices[i + 1]].Position; | ||
14645 | triangle.p3 = face.Vertices[face.Indices[i + 2]].Position; | ||
14646 | AddRayInTri(triangle, rayTrans, ref rayHits); | ||
14647 | } | ||
14648 | } | ||
14649 | } | ||
14650 | } | ||
14651 | |||
14652 | /// <summary> | ||
14653 | /// Helper to parse Tri (triangle) List for ray hits. | ||
14654 | /// </summary> | ||
14655 | private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits) | ||
14656 | { | ||
14657 | foreach (Tri triangle in triangles) | ||
14658 | { | ||
14659 | AddRayInTri(triangle, rayTrans, ref rayHits); | ||
14660 | } | ||
14661 | } | ||
14662 | |||
14663 | /// <summary> | ||
14664 | /// Helper to add ray hit in a Tri (triangle). | ||
14665 | /// </summary> | ||
14666 | private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits) | ||
14667 | { | ||
14668 | // Check for hit in triangle | ||
14669 | Vector3 posHitProj; | ||
14670 | Vector3 normalProj; | ||
14671 | if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj)) | ||
14672 | { | ||
14673 | // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center | ||
14674 | if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds) | ||
14675 | return; | ||
14676 | |||
14677 | // Transform hit and normal to region coordinate system | ||
14678 | Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart; | ||
14679 | Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart); | ||
14680 | |||
14681 | // Remove duplicate hits at triangle intersections | ||
14682 | float distance = Vector3.Distance(rayTrans.Position1Ray, posHit); | ||
14683 | for (int i = rayHits.Count - 1; i >= 0; i--) | ||
14684 | { | ||
14685 | if (rayHits[i].PartId != rayTrans.PartId) | ||
14686 | break; | ||
14687 | if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay) | ||
14688 | return; | ||
14689 | } | ||
14690 | |||
14691 | // Build result data set | ||
14692 | RayHit rayHit = new RayHit(); | ||
14693 | rayHit.PartId = rayTrans.PartId; | ||
14694 | rayHit.GroupId = rayTrans.GroupId; | ||
14695 | rayHit.Link = rayTrans.Link; | ||
14696 | rayHit.Position = posHit; | ||
14697 | rayHit.Normal = normal; | ||
14698 | rayHit.Distance = distance; | ||
14699 | rayHits.Add(rayHit); | ||
14700 | } | ||
14701 | } | ||
14702 | |||
14703 | /// <summary> | ||
14704 | /// Helper to find ray hit in triangle | ||
14705 | /// </summary> | ||
14706 | bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj) | ||
14707 | { | ||
14708 | float tol = m_floatToleranceInCastRay; | ||
14709 | posHitProj = Vector3.Zero; | ||
14710 | |||
14711 | // Calculate triangle edge vectors | ||
14712 | Vector3 vec1Proj = triProj.p2 - triProj.p1; | ||
14713 | Vector3 vec2Proj = triProj.p3 - triProj.p2; | ||
14714 | Vector3 vec3Proj = triProj.p1 - triProj.p3; | ||
14715 | |||
14716 | // Calculate triangle normal | ||
14717 | normalProj = Vector3.Cross(vec1Proj, vec2Proj); | ||
14718 | |||
14719 | // Skip if degenerate triangle or ray parallell with triangle plane | ||
14720 | float divisor = Vector3.Dot(vecRayProj, normalProj); | ||
14721 | if (Math.Abs(divisor) < tol) | ||
14722 | return false; | ||
14723 | |||
14724 | // Skip if exit and not configured to detect | ||
14725 | if (divisor > tol && !m_detectExitsInCastRay) | ||
14726 | return false; | ||
14727 | |||
14728 | // Skip if outside ray ends | ||
14729 | float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor; | ||
14730 | if (distanceProj < -tol || distanceProj > 1 + tol) | ||
14731 | return false; | ||
14732 | |||
14733 | // Calculate hit position in triangle | ||
14734 | posHitProj = pos1RayProj + vecRayProj * distanceProj; | ||
14735 | |||
14736 | // Skip if outside triangle bounding box | ||
14737 | Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3); | ||
14738 | Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3); | ||
14739 | if ( | ||
14740 | posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol || | ||
14741 | posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol | ||
14742 | ) | ||
14743 | return false; | ||
14744 | |||
14745 | // Skip if outside triangle | ||
14746 | if ( | ||
14747 | Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol || | ||
14748 | Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol || | ||
14749 | Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol | ||
14750 | ) | ||
14751 | return false; | ||
14752 | |||
14753 | // Return hit | ||
14754 | return true; | ||
14755 | } | ||
14756 | |||
14757 | /// <summary> | ||
14758 | /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box. | ||
14759 | /// </summary> | ||
14760 | private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper) | ||
14761 | { | ||
14762 | // Get bounding X-Y rectangle of terrain under ray | ||
14763 | lower = Vector3.Min(posStart, posEnd); | ||
14764 | upper = Vector3.Max(posStart, posEnd); | ||
14765 | lower.X = (float)Math.Floor(lower.X); | ||
14766 | lower.Y = (float)Math.Floor(lower.Y); | ||
14767 | float zLower = float.MaxValue; | ||
14768 | upper.X = (float)Math.Ceiling(upper.X); | ||
14769 | upper.Y = (float)Math.Ceiling(upper.Y); | ||
14770 | float zUpper = float.MinValue; | ||
14771 | |||
14772 | // Initialize Tri (triangle) List | ||
14773 | List<Tri> triangles = new List<Tri>(); | ||
14774 | |||
14775 | // Set parsing lane direction to major ray X-Y axis | ||
14776 | Vector3 vec = posEnd - posStart; | ||
14777 | float xAbs = Math.Abs(vec.X); | ||
14778 | float yAbs = Math.Abs(vec.Y); | ||
14779 | bool bigX = true; | ||
14780 | if (yAbs > xAbs) | ||
14781 | { | ||
14782 | bigX = false; | ||
14783 | vec = vec / yAbs; | ||
14784 | } | ||
14785 | else if (xAbs > yAbs || xAbs > 0.0f) | ||
14786 | vec = vec / xAbs; | ||
14787 | else | ||
14788 | vec = new Vector3(1.0f, 1.0f, 0.0f); | ||
14789 | |||
14790 | // Simplify by start parsing in lower end of lane | ||
14791 | if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f)) | ||
14792 | { | ||
14793 | Vector3 posTemp = posStart; | ||
14794 | posStart = posEnd; | ||
14795 | posEnd = posTemp; | ||
14796 | vec = vec * -1.0f; | ||
14797 | } | ||
14798 | |||
14799 | // First 1x1 rectangle under ray | ||
14800 | float xFloorOld = 0.0f; | ||
14801 | float yFloorOld = 0.0f; | ||
14802 | Vector3 pos = posStart; | ||
14803 | float xFloor = (float)Math.Floor(pos.X); | ||
14804 | float yFloor = (float)Math.Floor(pos.Y); | ||
14805 | AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); | ||
14806 | |||
14807 | // Parse every remaining 1x1 rectangle under ray | ||
14808 | while (pos != posEnd) | ||
14809 | { | ||
14810 | // Next 1x1 rectangle under ray | ||
14811 | xFloorOld = xFloor; | ||
14812 | yFloorOld = yFloor; | ||
14813 | pos = pos + vec; | ||
14814 | |||
14815 | // Clip position to 1x1 rectangle border | ||
14816 | xFloor = (float)Math.Floor(pos.X); | ||
14817 | yFloor = (float)Math.Floor(pos.Y); | ||
14818 | if (bigX && pos.X > xFloor) | ||
14819 | { | ||
14820 | pos.Y -= vec.Y * (pos.X - xFloor); | ||
14821 | pos.X = xFloor; | ||
14822 | } | ||
14823 | else if (!bigX && pos.Y > yFloor) | ||
14824 | { | ||
14825 | pos.X -= vec.X * (pos.Y - yFloor); | ||
14826 | pos.Y = yFloor; | ||
14827 | } | ||
14828 | |||
14829 | // Last 1x1 rectangle under ray | ||
14830 | if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y)) | ||
14831 | { | ||
14832 | pos = posEnd; | ||
14833 | xFloor = (float)Math.Floor(pos.X); | ||
14834 | yFloor = (float)Math.Floor(pos.Y); | ||
14835 | } | ||
14836 | |||
14837 | // Add new 1x1 rectangle in lane | ||
14838 | if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld)) | ||
14839 | AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); | ||
14840 | // Add last 1x1 rectangle in old lane at lane shift | ||
14841 | if (bigX && yFloor != yFloorOld) | ||
14842 | AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper); | ||
14843 | if (!bigX && xFloor != xFloorOld) | ||
14844 | AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper); | ||
14845 | } | ||
14846 | |||
14847 | // Finalize bounding box Z | ||
14848 | lower.Z = zLower; | ||
14849 | upper.Z = zUpper; | ||
14850 | |||
14851 | // Done and returning Tri (triangle)List | ||
14852 | return triangles; | ||
14853 | } | ||
14854 | |||
14855 | /// <summary> | ||
14856 | /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box. | ||
14857 | /// </summary> | ||
14858 | private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper) | ||
14859 | { | ||
14860 | int xInt = (int)xPos; | ||
14861 | int yInt = (int)yPos; | ||
14862 | |||
14863 | // Corner 1 of 1x1 rectangle | ||
14864 | int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); | ||
14865 | int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); | ||
14866 | Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]); | ||
14867 | // Adjust bounding box | ||
14868 | zLower = Math.Min(zLower, pos1.Z); | ||
14869 | zUpper = Math.Max(zUpper, pos1.Z); | ||
14870 | |||
14871 | // Corner 2 of 1x1 rectangle | ||
14872 | x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); | ||
14873 | y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); | ||
14874 | Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); | ||
14875 | // Adjust bounding box | ||
14876 | zLower = Math.Min(zLower, pos2.Z); | ||
14877 | zUpper = Math.Max(zUpper, pos2.Z); | ||
14878 | |||
14879 | // Corner 3 of 1x1 rectangle | ||
14880 | x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); | ||
14881 | y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); | ||
14882 | Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); | ||
14883 | // Adjust bounding box | ||
14884 | zLower = Math.Min(zLower, pos3.Z); | ||
14885 | zUpper = Math.Max(zUpper, pos3.Z); | ||
14886 | |||
14887 | // Corner 4 of 1x1 rectangle | ||
14888 | x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); | ||
14889 | y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); | ||
14890 | Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); | ||
14891 | // Adjust bounding box | ||
14892 | zLower = Math.Min(zLower, pos4.Z); | ||
14893 | zUpper = Math.Max(zUpper, pos4.Z); | ||
14894 | |||
14895 | // Add triangle 1 | ||
14896 | Tri triangle1 = new Tri(); | ||
14897 | triangle1.p1 = pos1; | ||
14898 | triangle1.p2 = pos2; | ||
14899 | triangle1.p3 = pos3; | ||
14900 | triangles.Add(triangle1); | ||
14901 | |||
14902 | // Add triangle 2 | ||
14903 | Tri triangle2 = new Tri(); | ||
14904 | triangle2.p1 = pos3; | ||
14905 | triangle2.p2 = pos4; | ||
14906 | triangle2.p3 = pos1; | ||
14907 | triangles.Add(triangle2); | ||
14908 | } | ||
14909 | |||
14910 | /// <summary> | ||
14911 | /// Helper to get link number for a UUID. | ||
14912 | /// </summary> | ||
14913 | private int UUID2LinkNumber(SceneObjectPart part, UUID id) | ||
14914 | { | ||
14915 | SceneObjectGroup group = part.ParentGroup; | ||
14916 | if (group != null) | ||
14917 | { | ||
14918 | // Parse every link for UUID | ||
14919 | int linkCount = group.PrimCount + group.GetSittingAvatarsCount(); | ||
14920 | for (int link = linkCount; link > 0; link--) | ||
14921 | { | ||
14922 | ISceneEntity entity = GetLinkEntity(part, link); | ||
14923 | // Return link number if UUID match | ||
14924 | if (entity != null && entity.UUID == id) | ||
14925 | return link; | ||
14926 | } | ||
14927 | } | ||
14928 | // Return link number 0 if no links or UUID matches | ||
14929 | return 0; | ||
14930 | } | ||
14931 | |||
11408 | public LSL_Integer llManageEstateAccess(int action, string avatar) | 14932 | public LSL_Integer llManageEstateAccess(int action, string avatar) |
11409 | { | 14933 | { |
11410 | m_host.AddScriptLPS(1); | 14934 | m_host.AddScriptLPS(1); |
@@ -11477,8 +15001,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11477 | public LSL_Integer llGetMemoryLimit() | 15001 | public LSL_Integer llGetMemoryLimit() |
11478 | { | 15002 | { |
11479 | m_host.AddScriptLPS(1); | 15003 | m_host.AddScriptLPS(1); |
11480 | // The value returned for LSO scripts in SL | 15004 | // The value returned for Mono scripts in SL |
11481 | return 16384; | 15005 | return 65536; |
11482 | } | 15006 | } |
11483 | 15007 | ||
11484 | public LSL_Integer llSetMemoryLimit(LSL_Integer limit) | 15008 | public LSL_Integer llSetMemoryLimit(LSL_Integer limit) |
@@ -11491,15 +15015,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11491 | public LSL_Integer llGetSPMaxMemory() | 15015 | public LSL_Integer llGetSPMaxMemory() |
11492 | { | 15016 | { |
11493 | m_host.AddScriptLPS(1); | 15017 | m_host.AddScriptLPS(1); |
11494 | // The value returned for LSO scripts in SL | 15018 | // The value returned for Mono scripts in SL |
11495 | return 16384; | 15019 | return 65536; |
11496 | } | 15020 | } |
11497 | 15021 | ||
11498 | public LSL_Integer llGetUsedMemory() | 15022 | public virtual LSL_Integer llGetUsedMemory() |
11499 | { | 15023 | { |
11500 | m_host.AddScriptLPS(1); | 15024 | m_host.AddScriptLPS(1); |
11501 | // The value returned for LSO scripts in SL | 15025 | // The value returned for Mono scripts in SL |
11502 | return 16384; | 15026 | return 65536; |
11503 | } | 15027 | } |
11504 | 15028 | ||
11505 | public void llScriptProfiler(LSL_Integer flags) | 15029 | public void llScriptProfiler(LSL_Integer flags) |
@@ -11514,16 +15038,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11514 | // them from this region as they are completed | 15038 | // them from this region as they are completed |
11515 | // | 15039 | // |
11516 | 15040 | ||
11517 | public void llGetEnv(LSL_String name) | ||
11518 | { | ||
11519 | m_host.AddScriptLPS(1); | ||
11520 | NotImplemented("llGetEnv"); | ||
11521 | } | ||
11522 | |||
11523 | public void llSetSoundQueueing(int queue) | 15041 | public void llSetSoundQueueing(int queue) |
11524 | { | 15042 | { |
11525 | m_host.AddScriptLPS(1); | 15043 | m_host.AddScriptLPS(1); |
11526 | NotImplemented("llSetSoundQueueing"); | 15044 | |
15045 | if (m_SoundModule != null) | ||
15046 | m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value); | ||
11527 | } | 15047 | } |
11528 | 15048 | ||
11529 | public void llCollisionSprite(string impact_sprite) | 15049 | public void llCollisionSprite(string impact_sprite) |
@@ -11538,6 +15058,79 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11538 | NotImplemented("llGodLikeRezObject"); | 15058 | NotImplemented("llGodLikeRezObject"); |
11539 | } | 15059 | } |
11540 | 15060 | ||
15061 | public LSL_String llTransferLindenDollars(string destination, int amount) | ||
15062 | { | ||
15063 | UUID txn = UUID.Random(); | ||
15064 | |||
15065 | Util.FireAndForget(delegate(object x) | ||
15066 | { | ||
15067 | int replycode = 0; | ||
15068 | string replydata = destination + "," + amount.ToString(); | ||
15069 | |||
15070 | try | ||
15071 | { | ||
15072 | TaskInventoryItem item = m_item; | ||
15073 | if (item == null) | ||
15074 | { | ||
15075 | replydata = "SERVICE_ERROR"; | ||
15076 | return; | ||
15077 | } | ||
15078 | |||
15079 | m_host.AddScriptLPS(1); | ||
15080 | |||
15081 | if (item.PermsGranter == UUID.Zero) | ||
15082 | { | ||
15083 | replydata = "MISSING_PERMISSION_DEBIT"; | ||
15084 | return; | ||
15085 | } | ||
15086 | |||
15087 | if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) | ||
15088 | { | ||
15089 | replydata = "MISSING_PERMISSION_DEBIT"; | ||
15090 | return; | ||
15091 | } | ||
15092 | |||
15093 | UUID toID = new UUID(); | ||
15094 | |||
15095 | if (!UUID.TryParse(destination, out toID)) | ||
15096 | { | ||
15097 | replydata = "INVALID_AGENT"; | ||
15098 | return; | ||
15099 | } | ||
15100 | |||
15101 | IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); | ||
15102 | |||
15103 | if (money == null) | ||
15104 | { | ||
15105 | replydata = "TRANSFERS_DISABLED"; | ||
15106 | return; | ||
15107 | } | ||
15108 | |||
15109 | bool result = money.ObjectGiveMoney( | ||
15110 | m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); | ||
15111 | |||
15112 | if (result) | ||
15113 | { | ||
15114 | replycode = 1; | ||
15115 | return; | ||
15116 | } | ||
15117 | |||
15118 | replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS"; | ||
15119 | } | ||
15120 | finally | ||
15121 | { | ||
15122 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( | ||
15123 | "transaction_result", new Object[] { | ||
15124 | new LSL_String(txn.ToString()), | ||
15125 | new LSL_Integer(replycode), | ||
15126 | new LSL_String(replydata) }, | ||
15127 | new DetectParams[0])); | ||
15128 | } | ||
15129 | }, null, "LSL_Api.llTransferLindenDollars"); | ||
15130 | |||
15131 | return txn.ToString(); | ||
15132 | } | ||
15133 | |||
11541 | #endregion | 15134 | #endregion |
11542 | } | 15135 | } |
11543 | 15136 | ||
@@ -11549,12 +15142,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11549 | public DateTime lastRef; | 15142 | public DateTime lastRef; |
11550 | } | 15143 | } |
11551 | 15144 | ||
11552 | protected static Dictionary<UUID, Notecard> m_Notecards = | 15145 | private static Dictionary<UUID, Notecard> m_Notecards = |
11553 | new Dictionary<UUID, Notecard>(); | 15146 | new Dictionary<UUID, Notecard>(); |
11554 | 15147 | ||
11555 | public static void Cache(UUID assetID, string text) | 15148 | public static void Cache(UUID assetID, byte[] text) |
11556 | { | 15149 | { |
11557 | CacheCheck(); | 15150 | CheckCache(); |
11558 | 15151 | ||
11559 | lock (m_Notecards) | 15152 | lock (m_Notecards) |
11560 | { | 15153 | { |
@@ -11563,7 +15156,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11563 | 15156 | ||
11564 | Notecard nc = new Notecard(); | 15157 | Notecard nc = new Notecard(); |
11565 | nc.lastRef = DateTime.Now; | 15158 | nc.lastRef = DateTime.Now; |
11566 | nc.text = SLUtil.ParseNotecardToList(text).ToArray(); | 15159 | try |
15160 | { | ||
15161 | nc.text = SLUtil.ParseNotecardToArray(text); | ||
15162 | } | ||
15163 | catch(SLUtil.NotANotecardFormatException) | ||
15164 | { | ||
15165 | nc.text = new string[0]; | ||
15166 | } | ||
11567 | m_Notecards[assetID] = nc; | 15167 | m_Notecards[assetID] = nc; |
11568 | } | 15168 | } |
11569 | } | 15169 | } |
@@ -11639,13 +15239,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
11639 | return line; | 15239 | return line; |
11640 | } | 15240 | } |
11641 | 15241 | ||
11642 | public static void CacheCheck() | 15242 | public static void CheckCache() |
11643 | { | 15243 | { |
11644 | foreach (UUID key in new List<UUID>(m_Notecards.Keys)) | 15244 | lock (m_Notecards) |
11645 | { | 15245 | { |
11646 | Notecard nc = m_Notecards[key]; | 15246 | foreach (UUID key in new List<UUID>(m_Notecards.Keys)) |
11647 | if (nc.lastRef.AddSeconds(30) < DateTime.Now) | 15247 | { |
11648 | m_Notecards.Remove(key); | 15248 | Notecard nc = m_Notecards[key]; |
15249 | if (nc.lastRef.AddSeconds(30) < DateTime.Now) | ||
15250 | m_Notecards.Remove(key); | ||
15251 | } | ||
11649 | } | 15252 | } |
11650 | } | 15253 | } |
11651 | } | 15254 | } |