diff options
Diffstat (limited to 'OpenSim/Region/ScriptEngine/Shared/Api')
-rw-r--r-- | OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 30556 |
1 files changed, 15278 insertions, 15278 deletions
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index afc4393..b4a8620 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -1,15278 +1,15278 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) Contributors, http://opensimulator.org/ | 2 | * Copyright (c) Contributors, http://opensimulator.org/ |
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | 3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. |
4 | * | 4 | * |
5 | * Redistribution and use in source and binary forms, with or without | 5 | * Redistribution and use in source and binary forms, with or without |
6 | * modification, are permitted provided that the following conditions are met: | 6 | * modification, are permitted provided that the following conditions are met: |
7 | * * Redistributions of source code must retain the above copyright | 7 | * * Redistributions of source code must retain the above copyright |
8 | * notice, this list of conditions and the following disclaimer. | 8 | * notice, this list of conditions and the following disclaimer. |
9 | * * Redistributions in binary form must reproduce the above copyright | 9 | * * Redistributions in binary form must reproduce the above copyright |
10 | * notice, this list of conditions and the following disclaimer in the | 10 | * notice, this list of conditions and the following disclaimer in the |
11 | * documentation and/or other materials provided with the distribution. | 11 | * documentation and/or other materials provided with the distribution. |
12 | * * Neither the name of the OpenSimulator Project nor the | 12 | * * Neither the name of the OpenSimulator Project nor the |
13 | * names of its contributors may be used to endorse or promote products | 13 | * names of its contributors may be used to endorse or promote products |
14 | * derived from this software without specific prior written permission. | 14 | * derived from this software without specific prior written permission. |
15 | * | 15 | * |
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | 16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY |
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | 19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY |
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | 20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | 21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | 22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | 27 | ||
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; | 31 | using System.Diagnostics; |
32 | using System.Drawing; | 32 | using System.Drawing; |
33 | using System.Drawing.Imaging; | 33 | using System.Drawing.Imaging; |
34 | using System.Runtime.Remoting.Lifetime; | 34 | using System.Runtime.Remoting.Lifetime; |
35 | using System.Text; | 35 | using System.Text; |
36 | using System.Threading; | 36 | using System.Threading; |
37 | using System.Text.RegularExpressions; | 37 | using System.Text.RegularExpressions; |
38 | using Nini.Config; | 38 | using Nini.Config; |
39 | using log4net; | 39 | using log4net; |
40 | using OpenMetaverse; | 40 | using OpenMetaverse; |
41 | using OpenMetaverse.Assets; | 41 | using OpenMetaverse.Assets; |
42 | using OpenMetaverse.Packets; | 42 | using OpenMetaverse.Packets; |
43 | using OpenMetaverse.Rendering; | 43 | using OpenMetaverse.Rendering; |
44 | using OpenSim; | 44 | using OpenSim; |
45 | using OpenSim.Framework; | 45 | using OpenSim.Framework; |
46 | 46 | ||
47 | using OpenSim.Region.CoreModules; | 47 | using OpenSim.Region.CoreModules; |
48 | using OpenSim.Region.CoreModules.World.Land; | 48 | using OpenSim.Region.CoreModules.World.Land; |
49 | using OpenSim.Region.CoreModules.World.Terrain; | 49 | using OpenSim.Region.CoreModules.World.Terrain; |
50 | using OpenSim.Region.Framework.Interfaces; | 50 | using OpenSim.Region.Framework.Interfaces; |
51 | using OpenSim.Region.Framework.Scenes; | 51 | using OpenSim.Region.Framework.Scenes; |
52 | using OpenSim.Region.Framework.Scenes.Animation; | 52 | using OpenSim.Region.Framework.Scenes.Animation; |
53 | using OpenSim.Region.Framework.Scenes.Scripting; | 53 | using OpenSim.Region.Framework.Scenes.Scripting; |
54 | using OpenSim.Region.Physics.Manager; | 54 | using OpenSim.Region.Physics.Manager; |
55 | using OpenSim.Region.ScriptEngine.Shared; | 55 | using OpenSim.Region.ScriptEngine.Shared; |
56 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; | 56 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; |
57 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | 57 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; |
58 | using OpenSim.Region.ScriptEngine.Interfaces; | 58 | using OpenSim.Region.ScriptEngine.Interfaces; |
59 | using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; | 59 | using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; |
60 | using OpenSim.Services.Interfaces; | 60 | using OpenSim.Services.Interfaces; |
61 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; | 61 | using GridRegion = OpenSim.Services.Interfaces.GridRegion; |
62 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; | 62 | using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; |
63 | using PrimType = OpenSim.Region.Framework.Scenes.PrimType; | 63 | using PrimType = OpenSim.Region.Framework.Scenes.PrimType; |
64 | using AssetLandmark = OpenSim.Framework.AssetLandmark; | 64 | using AssetLandmark = OpenSim.Framework.AssetLandmark; |
65 | using RegionFlags = OpenSim.Framework.RegionFlags; | 65 | using RegionFlags = OpenSim.Framework.RegionFlags; |
66 | 66 | ||
67 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | 67 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; |
68 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | 68 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; |
69 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | 69 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
70 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; | 70 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; |
71 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | 71 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; |
72 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | 72 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; |
73 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | 73 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; |
74 | using System.Reflection; | 74 | using System.Reflection; |
75 | using System.Linq; | 75 | using System.Linq; |
76 | using PermissionMask = OpenSim.Framework.PermissionMask; | 76 | using PermissionMask = OpenSim.Framework.PermissionMask; |
77 | 77 | ||
78 | namespace OpenSim.Region.ScriptEngine.Shared.Api | 78 | namespace OpenSim.Region.ScriptEngine.Shared.Api |
79 | { | 79 | { |
80 | // MUST be a ref type | 80 | // MUST be a ref type |
81 | public class UserInfoCacheEntry | 81 | public class UserInfoCacheEntry |
82 | { | 82 | { |
83 | public int time; | 83 | public int time; |
84 | public UserAccount account; | 84 | public UserAccount account; |
85 | public PresenceInfo pinfo; | 85 | public PresenceInfo pinfo; |
86 | } | 86 | } |
87 | 87 | ||
88 | /// <summary> | 88 | /// <summary> |
89 | /// Contains all LSL ll-functions. This class will be in Default AppDomain. | 89 | /// Contains all LSL ll-functions. This class will be in Default AppDomain. |
90 | /// </summary> | 90 | /// </summary> |
91 | public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi | 91 | public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi |
92 | { | 92 | { |
93 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 93 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
94 | 94 | ||
95 | public int LlRequestAgentDataCacheTimeoutMs { get; set; } | 95 | public int LlRequestAgentDataCacheTimeoutMs { get; set; } |
96 | 96 | ||
97 | protected IScriptEngine m_ScriptEngine; | 97 | protected IScriptEngine m_ScriptEngine; |
98 | protected SceneObjectPart m_host; | 98 | protected SceneObjectPart m_host; |
99 | 99 | ||
100 | /// <summary> | 100 | /// <summary> |
101 | /// Used for script sleeps when we are using co-operative script termination. | 101 | /// Used for script sleeps when we are using co-operative script termination. |
102 | /// </summary> | 102 | /// </summary> |
103 | /// <remarks>null if co-operative script termination is not active</remarks> | 103 | /// <remarks>null if co-operative script termination is not active</remarks> |
104 | WaitHandle m_coopSleepHandle; | 104 | WaitHandle m_coopSleepHandle; |
105 | 105 | ||
106 | /// <summary> | 106 | /// <summary> |
107 | /// The timer used by the ScriptInstance to measure how long the script has executed. | 107 | /// The timer used by the ScriptInstance to measure how long the script has executed. |
108 | /// </summary> | 108 | /// </summary> |
109 | private Stopwatch m_executionTimer; | 109 | private Stopwatch m_executionTimer; |
110 | 110 | ||
111 | /// <summary> | 111 | /// <summary> |
112 | /// The item that hosts this script | 112 | /// The item that hosts this script |
113 | /// </summary> | 113 | /// </summary> |
114 | protected TaskInventoryItem m_item; | 114 | protected TaskInventoryItem m_item; |
115 | 115 | ||
116 | protected bool throwErrorOnNotImplemented = false; | 116 | protected bool throwErrorOnNotImplemented = false; |
117 | protected AsyncCommandManager AsyncCommands = null; | 117 | protected AsyncCommandManager AsyncCommands = null; |
118 | protected float m_ScriptDelayFactor = 1.0f; | 118 | protected float m_ScriptDelayFactor = 1.0f; |
119 | protected float m_ScriptDistanceFactor = 1.0f; | 119 | protected float m_ScriptDistanceFactor = 1.0f; |
120 | protected float m_MinTimerInterval = 0.5f; | 120 | protected float m_MinTimerInterval = 0.5f; |
121 | protected float m_recoilScaleFactor = 0.0f; | 121 | protected float m_recoilScaleFactor = 0.0f; |
122 | 122 | ||
123 | protected DateTime m_timer = DateTime.Now; | 123 | protected DateTime m_timer = DateTime.Now; |
124 | protected bool m_waitingForScriptAnswer = false; | 124 | protected bool m_waitingForScriptAnswer = false; |
125 | protected bool m_automaticLinkPermission = false; | 125 | protected bool m_automaticLinkPermission = false; |
126 | protected IMessageTransferModule m_TransferModule = null; | 126 | protected IMessageTransferModule m_TransferModule = null; |
127 | protected int m_notecardLineReadCharsMax = 255; | 127 | protected int m_notecardLineReadCharsMax = 255; |
128 | protected int m_scriptConsoleChannel = 0; | 128 | protected int m_scriptConsoleChannel = 0; |
129 | protected bool m_scriptConsoleChannelEnabled = false; | 129 | protected bool m_scriptConsoleChannelEnabled = false; |
130 | protected IUrlModule m_UrlModule = null; | 130 | protected IUrlModule m_UrlModule = null; |
131 | protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); | 131 | protected Dictionary<UUID, UserInfoCacheEntry> m_userInfoCache = new Dictionary<UUID, UserInfoCacheEntry>(); |
132 | protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. | 132 | protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. |
133 | protected int m_sleepMsOnSetTexture = 200; | 133 | protected int m_sleepMsOnSetTexture = 200; |
134 | protected int m_sleepMsOnSetLinkTexture = 200; | 134 | protected int m_sleepMsOnSetLinkTexture = 200; |
135 | protected int m_sleepMsOnScaleTexture = 200; | 135 | protected int m_sleepMsOnScaleTexture = 200; |
136 | protected int m_sleepMsOnOffsetTexture = 200; | 136 | protected int m_sleepMsOnOffsetTexture = 200; |
137 | protected int m_sleepMsOnRotateTexture = 200; | 137 | protected int m_sleepMsOnRotateTexture = 200; |
138 | protected int m_sleepMsOnSetPos = 200; | 138 | protected int m_sleepMsOnSetPos = 200; |
139 | protected int m_sleepMsOnSetRot = 200; | 139 | protected int m_sleepMsOnSetRot = 200; |
140 | protected int m_sleepMsOnSetLocalRot = 200; | 140 | protected int m_sleepMsOnSetLocalRot = 200; |
141 | protected int m_sleepMsOnPreloadSound = 1000; | 141 | protected int m_sleepMsOnPreloadSound = 1000; |
142 | protected int m_sleepMsOnMakeExplosion = 100; | 142 | protected int m_sleepMsOnMakeExplosion = 100; |
143 | protected int m_sleepMsOnMakeFountain = 100; | 143 | protected int m_sleepMsOnMakeFountain = 100; |
144 | protected int m_sleepMsOnMakeSmoke = 100; | 144 | protected int m_sleepMsOnMakeSmoke = 100; |
145 | protected int m_sleepMsOnMakeFire = 100; | 145 | protected int m_sleepMsOnMakeFire = 100; |
146 | protected int m_sleepMsOnRezAtRoot = 100; | 146 | protected int m_sleepMsOnRezAtRoot = 100; |
147 | protected int m_sleepMsOnInstantMessage = 2000; | 147 | protected int m_sleepMsOnInstantMessage = 2000; |
148 | protected int m_sleepMsOnEmail = 20000; | 148 | protected int m_sleepMsOnEmail = 20000; |
149 | protected int m_sleepMsOnCreateLink = 1000; | 149 | protected int m_sleepMsOnCreateLink = 1000; |
150 | protected int m_sleepMsOnGiveInventory = 3000; | 150 | protected int m_sleepMsOnGiveInventory = 3000; |
151 | protected int m_sleepMsOnRequestAgentData = 100; | 151 | protected int m_sleepMsOnRequestAgentData = 100; |
152 | protected int m_sleepMsOnRequestInventoryData = 1000; | 152 | protected int m_sleepMsOnRequestInventoryData = 1000; |
153 | protected int m_sleepMsOnSetDamage = 5000; | 153 | protected int m_sleepMsOnSetDamage = 5000; |
154 | protected int m_sleepMsOnTextBox = 1000; | 154 | protected int m_sleepMsOnTextBox = 1000; |
155 | protected int m_sleepMsOnAdjustSoundVolume = 100; | 155 | protected int m_sleepMsOnAdjustSoundVolume = 100; |
156 | protected int m_sleepMsOnEjectFromLand = 5000; | 156 | protected int m_sleepMsOnEjectFromLand = 5000; |
157 | protected int m_sleepMsOnAddToLandPassList = 100; | 157 | protected int m_sleepMsOnAddToLandPassList = 100; |
158 | protected int m_sleepMsOnDialog = 1000; | 158 | protected int m_sleepMsOnDialog = 1000; |
159 | protected int m_sleepMsOnRemoteLoadScript = 3000; | 159 | protected int m_sleepMsOnRemoteLoadScript = 3000; |
160 | protected int m_sleepMsOnRemoteLoadScriptPin = 3000; | 160 | protected int m_sleepMsOnRemoteLoadScriptPin = 3000; |
161 | protected int m_sleepMsOnOpenRemoteDataChannel = 1000; | 161 | protected int m_sleepMsOnOpenRemoteDataChannel = 1000; |
162 | protected int m_sleepMsOnSendRemoteData = 3000; | 162 | protected int m_sleepMsOnSendRemoteData = 3000; |
163 | protected int m_sleepMsOnRemoteDataReply = 3000; | 163 | protected int m_sleepMsOnRemoteDataReply = 3000; |
164 | protected int m_sleepMsOnCloseRemoteDataChannel = 1000; | 164 | protected int m_sleepMsOnCloseRemoteDataChannel = 1000; |
165 | protected int m_sleepMsOnSetPrimitiveParams = 200; | 165 | protected int m_sleepMsOnSetPrimitiveParams = 200; |
166 | protected int m_sleepMsOnSetLinkPrimitiveParams = 200; | 166 | protected int m_sleepMsOnSetLinkPrimitiveParams = 200; |
167 | protected int m_sleepMsOnXorBase64Strings = 300; | 167 | protected int m_sleepMsOnXorBase64Strings = 300; |
168 | protected int m_sleepMsOnSetParcelMusicURL = 2000; | 168 | protected int m_sleepMsOnSetParcelMusicURL = 2000; |
169 | protected int m_sleepMsOnGetPrimMediaParams = 1000; | 169 | protected int m_sleepMsOnGetPrimMediaParams = 1000; |
170 | protected int m_sleepMsOnGetLinkMedia = 1000; | 170 | protected int m_sleepMsOnGetLinkMedia = 1000; |
171 | protected int m_sleepMsOnSetPrimMediaParams = 1000; | 171 | protected int m_sleepMsOnSetPrimMediaParams = 1000; |
172 | protected int m_sleepMsOnSetLinkMedia = 1000; | 172 | protected int m_sleepMsOnSetLinkMedia = 1000; |
173 | protected int m_sleepMsOnClearPrimMedia = 1000; | 173 | protected int m_sleepMsOnClearPrimMedia = 1000; |
174 | protected int m_sleepMsOnClearLinkMedia = 1000; | 174 | protected int m_sleepMsOnClearLinkMedia = 1000; |
175 | protected int m_sleepMsOnRequestSimulatorData = 1000; | 175 | protected int m_sleepMsOnRequestSimulatorData = 1000; |
176 | protected int m_sleepMsOnLoadURL = 10000; | 176 | protected int m_sleepMsOnLoadURL = 10000; |
177 | protected int m_sleepMsOnParcelMediaCommandList = 2000; | 177 | protected int m_sleepMsOnParcelMediaCommandList = 2000; |
178 | protected int m_sleepMsOnParcelMediaQuery = 2000; | 178 | protected int m_sleepMsOnParcelMediaQuery = 2000; |
179 | protected int m_sleepMsOnModPow = 1000; | 179 | protected int m_sleepMsOnModPow = 1000; |
180 | protected int m_sleepMsOnSetPrimURL = 2000; | 180 | protected int m_sleepMsOnSetPrimURL = 2000; |
181 | protected int m_sleepMsOnRefreshPrimURL = 20000; | 181 | protected int m_sleepMsOnRefreshPrimURL = 20000; |
182 | protected int m_sleepMsOnMapDestination = 1000; | 182 | protected int m_sleepMsOnMapDestination = 1000; |
183 | protected int m_sleepMsOnAddToLandBanList = 100; | 183 | protected int m_sleepMsOnAddToLandBanList = 100; |
184 | protected int m_sleepMsOnRemoveFromLandPassList = 100; | 184 | protected int m_sleepMsOnRemoveFromLandPassList = 100; |
185 | protected int m_sleepMsOnRemoveFromLandBanList = 100; | 185 | protected int m_sleepMsOnRemoveFromLandBanList = 100; |
186 | protected int m_sleepMsOnResetLandBanList = 100; | 186 | protected int m_sleepMsOnResetLandBanList = 100; |
187 | protected int m_sleepMsOnResetLandPassList = 100; | 187 | protected int m_sleepMsOnResetLandPassList = 100; |
188 | protected int m_sleepMsOnGetParcelPrimOwners = 2000; | 188 | protected int m_sleepMsOnGetParcelPrimOwners = 2000; |
189 | protected int m_sleepMsOnGetNumberOfNotecardLines = 100; | 189 | protected int m_sleepMsOnGetNumberOfNotecardLines = 100; |
190 | protected int m_sleepMsOnGetNotecardLine = 100; | 190 | protected int m_sleepMsOnGetNotecardLine = 100; |
191 | protected string m_internalObjectHost = "lsl.opensim.local"; | 191 | protected string m_internalObjectHost = "lsl.opensim.local"; |
192 | protected bool m_restrictEmail = false; | 192 | protected bool m_restrictEmail = false; |
193 | protected ISoundModule m_SoundModule = null; | 193 | protected ISoundModule m_SoundModule = null; |
194 | 194 | ||
195 | protected float m_avatarHeightCorrection = 0.2f; | 195 | protected float m_avatarHeightCorrection = 0.2f; |
196 | protected bool m_useSimpleBoxesInGetBoundingBox = false; | 196 | protected bool m_useSimpleBoxesInGetBoundingBox = false; |
197 | protected bool m_addStatsInGetBoundingBox = false; | 197 | protected bool m_addStatsInGetBoundingBox = false; |
198 | 198 | ||
199 | //LSL Avatar Bounding Box (lABB), lower (1) and upper (2), | 199 | //LSL Avatar Bounding Box (lABB), lower (1) and upper (2), |
200 | //standing (Std), Groundsitting (Grs), Sitting (Sit), | 200 | //standing (Std), Groundsitting (Grs), Sitting (Sit), |
201 | //along X, Y and Z axes, constants (0) and coefficients (1) | 201 | //along X, Y and Z axes, constants (0) and coefficients (1) |
202 | protected float m_lABB1StdX0 = -0.275f; | 202 | protected float m_lABB1StdX0 = -0.275f; |
203 | protected float m_lABB2StdX0 = 0.275f; | 203 | protected float m_lABB2StdX0 = 0.275f; |
204 | protected float m_lABB1StdY0 = -0.35f; | 204 | protected float m_lABB1StdY0 = -0.35f; |
205 | protected float m_lABB2StdY0 = 0.35f; | 205 | protected float m_lABB2StdY0 = 0.35f; |
206 | protected float m_lABB1StdZ0 = -0.1f; | 206 | protected float m_lABB1StdZ0 = -0.1f; |
207 | protected float m_lABB1StdZ1 = -0.5f; | 207 | protected float m_lABB1StdZ1 = -0.5f; |
208 | protected float m_lABB2StdZ0 = 0.1f; | 208 | protected float m_lABB2StdZ0 = 0.1f; |
209 | protected float m_lABB2StdZ1 = 0.5f; | 209 | protected float m_lABB2StdZ1 = 0.5f; |
210 | protected float m_lABB1GrsX0 = -0.3875f; | 210 | protected float m_lABB1GrsX0 = -0.3875f; |
211 | protected float m_lABB2GrsX0 = 0.3875f; | 211 | protected float m_lABB2GrsX0 = 0.3875f; |
212 | protected float m_lABB1GrsY0 = -0.5f; | 212 | protected float m_lABB1GrsY0 = -0.5f; |
213 | protected float m_lABB2GrsY0 = 0.5f; | 213 | protected float m_lABB2GrsY0 = 0.5f; |
214 | protected float m_lABB1GrsZ0 = -0.05f; | 214 | protected float m_lABB1GrsZ0 = -0.05f; |
215 | protected float m_lABB1GrsZ1 = -0.375f; | 215 | protected float m_lABB1GrsZ1 = -0.375f; |
216 | protected float m_lABB2GrsZ0 = 0.5f; | 216 | protected float m_lABB2GrsZ0 = 0.5f; |
217 | protected float m_lABB2GrsZ1 = 0.0f; | 217 | protected float m_lABB2GrsZ1 = 0.0f; |
218 | protected float m_lABB1SitX0 = -0.5875f; | 218 | protected float m_lABB1SitX0 = -0.5875f; |
219 | protected float m_lABB2SitX0 = 0.1875f; | 219 | protected float m_lABB2SitX0 = 0.1875f; |
220 | protected float m_lABB1SitY0 = -0.35f; | 220 | protected float m_lABB1SitY0 = -0.35f; |
221 | protected float m_lABB2SitY0 = 0.35f; | 221 | protected float m_lABB2SitY0 = 0.35f; |
222 | protected float m_lABB1SitZ0 = -0.35f; | 222 | protected float m_lABB1SitZ0 = -0.35f; |
223 | protected float m_lABB1SitZ1 = -0.375f; | 223 | protected float m_lABB1SitZ1 = -0.375f; |
224 | protected float m_lABB2SitZ0 = -0.25f; | 224 | protected float m_lABB2SitZ0 = -0.25f; |
225 | protected float m_lABB2SitZ1 = 0.25f; | 225 | protected float m_lABB2SitZ1 = 0.25f; |
226 | 226 | ||
227 | protected float m_primSafetyCoeffX = 2.414214f; | 227 | protected float m_primSafetyCoeffX = 2.414214f; |
228 | protected float m_primSafetyCoeffY = 2.414214f; | 228 | protected float m_primSafetyCoeffY = 2.414214f; |
229 | protected float m_primSafetyCoeffZ = 1.618034f; | 229 | protected float m_primSafetyCoeffZ = 1.618034f; |
230 | protected bool m_useCastRayV3 = false; | 230 | protected bool m_useCastRayV3 = false; |
231 | protected float m_floatToleranceInCastRay = 0.00001f; | 231 | protected float m_floatToleranceInCastRay = 0.00001f; |
232 | protected float m_floatTolerance2InCastRay = 0.001f; | 232 | protected float m_floatTolerance2InCastRay = 0.001f; |
233 | protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; | 233 | protected DetailLevel m_primLodInCastRay = DetailLevel.Medium; |
234 | protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; | 234 | protected DetailLevel m_sculptLodInCastRay = DetailLevel.Medium; |
235 | protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; | 235 | protected DetailLevel m_meshLodInCastRay = DetailLevel.Highest; |
236 | protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium; | 236 | protected DetailLevel m_avatarLodInCastRay = DetailLevel.Medium; |
237 | protected int m_maxHitsInCastRay = 16; | 237 | protected int m_maxHitsInCastRay = 16; |
238 | protected int m_maxHitsPerPrimInCastRay = 16; | 238 | protected int m_maxHitsPerPrimInCastRay = 16; |
239 | protected int m_maxHitsPerObjectInCastRay = 16; | 239 | protected int m_maxHitsPerObjectInCastRay = 16; |
240 | protected bool m_detectExitsInCastRay = false; | 240 | protected bool m_detectExitsInCastRay = false; |
241 | protected bool m_filterPartsInCastRay = false; | 241 | protected bool m_filterPartsInCastRay = false; |
242 | protected bool m_doAttachmentsInCastRay = false; | 242 | protected bool m_doAttachmentsInCastRay = false; |
243 | protected int m_msThrottleInCastRay = 200; | 243 | protected int m_msThrottleInCastRay = 200; |
244 | protected int m_msPerRegionInCastRay = 40; | 244 | protected int m_msPerRegionInCastRay = 40; |
245 | protected int m_msPerAvatarInCastRay = 10; | 245 | protected int m_msPerAvatarInCastRay = 10; |
246 | protected int m_msMinInCastRay = 2; | 246 | protected int m_msMinInCastRay = 2; |
247 | protected int m_msMaxInCastRay = 40; | 247 | protected int m_msMaxInCastRay = 40; |
248 | protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>(); | 248 | protected static List<CastRayCall> m_castRayCalls = new List<CastRayCall>(); |
249 | protected bool m_useMeshCacheInCastRay = true; | 249 | protected bool m_useMeshCacheInCastRay = true; |
250 | protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); | 250 | protected static Dictionary<ulong, FacetedMesh> m_cachedMeshes = new Dictionary<ulong, FacetedMesh>(); |
251 | 251 | ||
252 | //An array of HTTP/1.1 headers that are not allowed to be used | 252 | //An array of HTTP/1.1 headers that are not allowed to be used |
253 | //as custom headers by llHTTPRequest. | 253 | //as custom headers by llHTTPRequest. |
254 | private string[] HttpStandardHeaders = | 254 | private string[] HttpStandardHeaders = |
255 | { | 255 | { |
256 | "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", | 256 | "Accept", "Accept-Charset", "Accept-Encoding", "Accept-Language", |
257 | "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control", | 257 | "Accept-Ranges", "Age", "Allow", "Authorization", "Cache-Control", |
258 | "Connection", "Content-Encoding", "Content-Language", | 258 | "Connection", "Content-Encoding", "Content-Language", |
259 | "Content-Length", "Content-Location", "Content-MD5", | 259 | "Content-Length", "Content-Location", "Content-MD5", |
260 | "Content-Range", "Content-Type", "Date", "ETag", "Expect", | 260 | "Content-Range", "Content-Type", "Date", "ETag", "Expect", |
261 | "Expires", "From", "Host", "If-Match", "If-Modified-Since", | 261 | "Expires", "From", "Host", "If-Match", "If-Modified-Since", |
262 | "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", | 262 | "If-None-Match", "If-Range", "If-Unmodified-Since", "Last-Modified", |
263 | "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate", | 263 | "Location", "Max-Forwards", "Pragma", "Proxy-Authenticate", |
264 | "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server", | 264 | "Proxy-Authorization", "Range", "Referer", "Retry-After", "Server", |
265 | "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent", | 265 | "TE", "Trailer", "Transfer-Encoding", "Upgrade", "User-Agent", |
266 | "Vary", "Via", "Warning", "WWW-Authenticate" | 266 | "Vary", "Via", "Warning", "WWW-Authenticate" |
267 | }; | 267 | }; |
268 | 268 | ||
269 | public void Initialize( | 269 | public void Initialize( |
270 | IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle, | 270 | IScriptEngine scriptEngine, SceneObjectPart host, TaskInventoryItem item, WaitHandle coopSleepHandle, |
271 | Stopwatch executionTimer) | 271 | Stopwatch executionTimer) |
272 | { | 272 | { |
273 | m_ScriptEngine = scriptEngine; | 273 | m_ScriptEngine = scriptEngine; |
274 | m_host = host; | 274 | m_host = host; |
275 | m_item = item; | 275 | m_item = item; |
276 | m_coopSleepHandle = coopSleepHandle; | 276 | m_coopSleepHandle = coopSleepHandle; |
277 | m_executionTimer = executionTimer; | 277 | m_executionTimer = executionTimer; |
278 | 278 | ||
279 | LoadConfig(); | 279 | LoadConfig(); |
280 | 280 | ||
281 | m_TransferModule = | 281 | m_TransferModule = |
282 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); | 282 | m_ScriptEngine.World.RequestModuleInterface<IMessageTransferModule>(); |
283 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); | 283 | m_UrlModule = m_ScriptEngine.World.RequestModuleInterface<IUrlModule>(); |
284 | m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); | 284 | m_SoundModule = m_ScriptEngine.World.RequestModuleInterface<ISoundModule>(); |
285 | 285 | ||
286 | AsyncCommands = new AsyncCommandManager(m_ScriptEngine); | 286 | AsyncCommands = new AsyncCommandManager(m_ScriptEngine); |
287 | } | 287 | } |
288 | 288 | ||
289 | /// <summary> | 289 | /// <summary> |
290 | /// Load configuration items that affect script, object and run-time behavior. */ | 290 | /// Load configuration items that affect script, object and run-time behavior. */ |
291 | /// </summary> | 291 | /// </summary> |
292 | private void LoadConfig() | 292 | private void LoadConfig() |
293 | { | 293 | { |
294 | LlRequestAgentDataCacheTimeoutMs = 20000; | 294 | LlRequestAgentDataCacheTimeoutMs = 20000; |
295 | 295 | ||
296 | IConfig seConfig = m_ScriptEngine.Config; | 296 | IConfig seConfig = m_ScriptEngine.Config; |
297 | 297 | ||
298 | if (seConfig != null) | 298 | if (seConfig != null) |
299 | { | 299 | { |
300 | m_ScriptDelayFactor = | 300 | m_ScriptDelayFactor = |
301 | seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor); | 301 | seConfig.GetFloat("ScriptDelayFactor", m_ScriptDelayFactor); |
302 | m_ScriptDistanceFactor = | 302 | m_ScriptDistanceFactor = |
303 | seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor); | 303 | seConfig.GetFloat("ScriptDistanceLimitFactor", m_ScriptDistanceFactor); |
304 | m_MinTimerInterval = | 304 | m_MinTimerInterval = |
305 | seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval); | 305 | seConfig.GetFloat("MinTimerInterval", m_MinTimerInterval); |
306 | m_automaticLinkPermission = | 306 | m_automaticLinkPermission = |
307 | seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission); | 307 | seConfig.GetBoolean("AutomaticLinkPermission", m_automaticLinkPermission); |
308 | m_notecardLineReadCharsMax = | 308 | m_notecardLineReadCharsMax = |
309 | seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax); | 309 | seConfig.GetInt("NotecardLineReadCharsMax", m_notecardLineReadCharsMax); |
310 | 310 | ||
311 | // Rezzing an object with a velocity can create recoil. This feature seems to have been | 311 | // Rezzing an object with a velocity can create recoil. This feature seems to have been |
312 | // removed from recent versions of SL. The code computes recoil (vel*mass) and scales | 312 | // removed from recent versions of SL. The code computes recoil (vel*mass) and scales |
313 | // it by this factor. May be zero to turn off recoil all together. | 313 | // it by this factor. May be zero to turn off recoil all together. |
314 | m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor); | 314 | m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor); |
315 | } | 315 | } |
316 | 316 | ||
317 | if (m_notecardLineReadCharsMax > 65535) | 317 | if (m_notecardLineReadCharsMax > 65535) |
318 | m_notecardLineReadCharsMax = 65535; | 318 | m_notecardLineReadCharsMax = 65535; |
319 | 319 | ||
320 | // load limits for particular subsystems. | 320 | // load limits for particular subsystems. |
321 | IConfigSource seConfigSource = m_ScriptEngine.ConfigSource; | 321 | IConfigSource seConfigSource = m_ScriptEngine.ConfigSource; |
322 | 322 | ||
323 | if (seConfigSource != null) | 323 | if (seConfigSource != null) |
324 | { | 324 | { |
325 | IConfig lslConfig = seConfigSource.Configs["LL-Functions"]; | 325 | IConfig lslConfig = seConfigSource.Configs["LL-Functions"]; |
326 | if (lslConfig != null) | 326 | if (lslConfig != null) |
327 | { | 327 | { |
328 | m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); | 328 | m_restrictEmail = lslConfig.GetBoolean("RestrictEmail", m_restrictEmail); |
329 | m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection); | 329 | m_avatarHeightCorrection = lslConfig.GetFloat("AvatarHeightCorrection", m_avatarHeightCorrection); |
330 | m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox); | 330 | m_useSimpleBoxesInGetBoundingBox = lslConfig.GetBoolean("UseSimpleBoxesInGetBoundingBox", m_useSimpleBoxesInGetBoundingBox); |
331 | m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox); | 331 | m_addStatsInGetBoundingBox = lslConfig.GetBoolean("AddStatsInGetBoundingBox", m_addStatsInGetBoundingBox); |
332 | m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0); | 332 | m_lABB1StdX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingXconst", m_lABB1StdX0); |
333 | m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0); | 333 | m_lABB2StdX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingXconst", m_lABB2StdX0); |
334 | m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0); | 334 | m_lABB1StdY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingYconst", m_lABB1StdY0); |
335 | m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0); | 335 | m_lABB2StdY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingYconst", m_lABB2StdY0); |
336 | m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0); | 336 | m_lABB1StdZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZconst", m_lABB1StdZ0); |
337 | m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1); | 337 | m_lABB1StdZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxStandingZcoeff", m_lABB1StdZ1); |
338 | m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0); | 338 | m_lABB2StdZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZconst", m_lABB2StdZ0); |
339 | m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1); | 339 | m_lABB2StdZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxStandingZcoeff", m_lABB2StdZ1); |
340 | m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0); | 340 | m_lABB1GrsX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingXconst", m_lABB1GrsX0); |
341 | m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0); | 341 | m_lABB2GrsX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingXconst", m_lABB2GrsX0); |
342 | m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0); | 342 | m_lABB1GrsY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingYconst", m_lABB1GrsY0); |
343 | m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0); | 343 | m_lABB2GrsY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingYconst", m_lABB2GrsY0); |
344 | m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0); | 344 | m_lABB1GrsZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZconst", m_lABB1GrsZ0); |
345 | m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1); | 345 | m_lABB1GrsZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxGroundsittingZcoeff", m_lABB1GrsZ1); |
346 | m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0); | 346 | m_lABB2GrsZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZconst", m_lABB2GrsZ0); |
347 | m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1); | 347 | m_lABB2GrsZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxGroundsittingZcoeff", m_lABB2GrsZ1); |
348 | m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0); | 348 | m_lABB1SitX0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingXconst", m_lABB1SitX0); |
349 | m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0); | 349 | m_lABB2SitX0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingXconst", m_lABB2SitX0); |
350 | m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0); | 350 | m_lABB1SitY0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingYconst", m_lABB1SitY0); |
351 | m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0); | 351 | m_lABB2SitY0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingYconst", m_lABB2SitY0); |
352 | m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0); | 352 | m_lABB1SitZ0 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZconst", m_lABB1SitZ0); |
353 | m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1); | 353 | m_lABB1SitZ1 = lslConfig.GetFloat("LowerAvatarBoundingBoxSittingZcoeff", m_lABB1SitZ1); |
354 | m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0); | 354 | m_lABB2SitZ0 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZconst", m_lABB2SitZ0); |
355 | m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1); | 355 | m_lABB2SitZ1 = lslConfig.GetFloat("UpperAvatarBoundingBoxSittingZcoeff", m_lABB2SitZ1); |
356 | m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); | 356 | m_primSafetyCoeffX = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientX", m_primSafetyCoeffX); |
357 | m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); | 357 | m_primSafetyCoeffY = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientY", m_primSafetyCoeffY); |
358 | m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); | 358 | m_primSafetyCoeffZ = lslConfig.GetFloat("PrimBoundingBoxSafetyCoefficientZ", m_primSafetyCoeffZ); |
359 | m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3); | 359 | m_useCastRayV3 = lslConfig.GetBoolean("UseLlCastRayV3", m_useCastRayV3); |
360 | m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); | 360 | m_floatToleranceInCastRay = lslConfig.GetFloat("FloatToleranceInLlCastRay", m_floatToleranceInCastRay); |
361 | m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); | 361 | m_floatTolerance2InCastRay = lslConfig.GetFloat("FloatTolerance2InLlCastRay", m_floatTolerance2InCastRay); |
362 | m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay); | 362 | m_primLodInCastRay = (DetailLevel)lslConfig.GetInt("PrimDetailLevelInLlCastRay", (int)m_primLodInCastRay); |
363 | m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay); | 363 | m_sculptLodInCastRay = (DetailLevel)lslConfig.GetInt("SculptDetailLevelInLlCastRay", (int)m_sculptLodInCastRay); |
364 | m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay); | 364 | m_meshLodInCastRay = (DetailLevel)lslConfig.GetInt("MeshDetailLevelInLlCastRay", (int)m_meshLodInCastRay); |
365 | m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay); | 365 | m_avatarLodInCastRay = (DetailLevel)lslConfig.GetInt("AvatarDetailLevelInLlCastRay", (int)m_avatarLodInCastRay); |
366 | m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); | 366 | m_maxHitsInCastRay = lslConfig.GetInt("MaxHitsInLlCastRay", m_maxHitsInCastRay); |
367 | m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); | 367 | m_maxHitsPerPrimInCastRay = lslConfig.GetInt("MaxHitsPerPrimInLlCastRay", m_maxHitsPerPrimInCastRay); |
368 | m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); | 368 | m_maxHitsPerObjectInCastRay = lslConfig.GetInt("MaxHitsPerObjectInLlCastRay", m_maxHitsPerObjectInCastRay); |
369 | m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); | 369 | m_detectExitsInCastRay = lslConfig.GetBoolean("DetectExitHitsInLlCastRay", m_detectExitsInCastRay); |
370 | m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); | 370 | m_filterPartsInCastRay = lslConfig.GetBoolean("FilterPartsInLlCastRay", m_filterPartsInCastRay); |
371 | m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); | 371 | m_doAttachmentsInCastRay = lslConfig.GetBoolean("DoAttachmentsInLlCastRay", m_doAttachmentsInCastRay); |
372 | m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay); | 372 | m_msThrottleInCastRay = lslConfig.GetInt("ThrottleTimeInMsInLlCastRay", m_msThrottleInCastRay); |
373 | m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay); | 373 | m_msPerRegionInCastRay = lslConfig.GetInt("AvailableTimeInMsPerRegionInLlCastRay", m_msPerRegionInCastRay); |
374 | m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay); | 374 | m_msPerAvatarInCastRay = lslConfig.GetInt("AvailableTimeInMsPerAvatarInLlCastRay", m_msPerAvatarInCastRay); |
375 | m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay); | 375 | m_msMinInCastRay = lslConfig.GetInt("RequiredAvailableTimeInMsInLlCastRay", m_msMinInCastRay); |
376 | m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay); | 376 | m_msMaxInCastRay = lslConfig.GetInt("MaximumAvailableTimeInMsInLlCastRay", m_msMaxInCastRay); |
377 | m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay); | 377 | m_useMeshCacheInCastRay = lslConfig.GetBoolean("UseMeshCacheInLlCastRay", m_useMeshCacheInCastRay); |
378 | } | 378 | } |
379 | 379 | ||
380 | IConfig smtpConfig = seConfigSource.Configs["SMTP"]; | 380 | IConfig smtpConfig = seConfigSource.Configs["SMTP"]; |
381 | if (smtpConfig != null) | 381 | if (smtpConfig != null) |
382 | { | 382 | { |
383 | // there's an smtp config, so load in the snooze time. | 383 | // there's an smtp config, so load in the snooze time. |
384 | EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); | 384 | EMAIL_PAUSE_TIME = smtpConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); |
385 | 385 | ||
386 | m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost); | 386 | m_internalObjectHost = smtpConfig.GetString("internal_object_host", m_internalObjectHost); |
387 | } | 387 | } |
388 | } | 388 | } |
389 | m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000; | 389 | m_sleepMsOnEmail = EMAIL_PAUSE_TIME * 1000; |
390 | } | 390 | } |
391 | 391 | ||
392 | public override Object InitializeLifetimeService() | 392 | public override Object InitializeLifetimeService() |
393 | { | 393 | { |
394 | ILease lease = (ILease)base.InitializeLifetimeService(); | 394 | ILease lease = (ILease)base.InitializeLifetimeService(); |
395 | 395 | ||
396 | if (lease.CurrentState == LeaseState.Initial) | 396 | if (lease.CurrentState == LeaseState.Initial) |
397 | { | 397 | { |
398 | lease.InitialLeaseTime = TimeSpan.FromMinutes(0); | 398 | lease.InitialLeaseTime = TimeSpan.FromMinutes(0); |
399 | // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); | 399 | // lease.RenewOnCallTime = TimeSpan.FromSeconds(10.0); |
400 | // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); | 400 | // lease.SponsorshipTimeout = TimeSpan.FromMinutes(1.0); |
401 | } | 401 | } |
402 | return lease; | 402 | return lease; |
403 | } | 403 | } |
404 | 404 | ||
405 | protected virtual void ScriptSleep(int delay) | 405 | protected virtual void ScriptSleep(int delay) |
406 | { | 406 | { |
407 | delay = (int)((float)delay * m_ScriptDelayFactor); | 407 | delay = (int)((float)delay * m_ScriptDelayFactor); |
408 | if (delay == 0) | 408 | if (delay == 0) |
409 | return; | 409 | return; |
410 | 410 | ||
411 | Sleep(delay); | 411 | Sleep(delay); |
412 | } | 412 | } |
413 | 413 | ||
414 | protected virtual void Sleep(int delay) | 414 | protected virtual void Sleep(int delay) |
415 | { | 415 | { |
416 | if (m_executionTimer != null) | 416 | if (m_executionTimer != null) |
417 | m_executionTimer.Stop(); // sleep time doesn't count as execution time, since it doesn't use the CPU | 417 | m_executionTimer.Stop(); // sleep time doesn't count as execution time, since it doesn't use the CPU |
418 | 418 | ||
419 | try | 419 | try |
420 | { | 420 | { |
421 | if (m_coopSleepHandle == null) | 421 | if (m_coopSleepHandle == null) |
422 | System.Threading.Thread.Sleep(delay); | 422 | System.Threading.Thread.Sleep(delay); |
423 | else | 423 | else |
424 | CheckForCoopTermination(delay); | 424 | CheckForCoopTermination(delay); |
425 | } | 425 | } |
426 | finally | 426 | finally |
427 | { | 427 | { |
428 | if (m_executionTimer != null) | 428 | if (m_executionTimer != null) |
429 | m_executionTimer.Start(); | 429 | m_executionTimer.Start(); |
430 | } | 430 | } |
431 | } | 431 | } |
432 | 432 | ||
433 | /// <summary> | 433 | /// <summary> |
434 | /// Check for co-operative termination. | 434 | /// Check for co-operative termination. |
435 | /// </summary> | 435 | /// </summary> |
436 | /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param> | 436 | /// <param name='delay'>If called with 0, then just the check is performed with no wait.</param> |
437 | protected virtual void CheckForCoopTermination(int delay) | 437 | protected virtual void CheckForCoopTermination(int delay) |
438 | { | 438 | { |
439 | if (m_coopSleepHandle.WaitOne(delay)) | 439 | if (m_coopSleepHandle.WaitOne(delay)) |
440 | throw new ScriptCoopStopException(); | 440 | throw new ScriptCoopStopException(); |
441 | } | 441 | } |
442 | 442 | ||
443 | public Scene World | 443 | public Scene World |
444 | { | 444 | { |
445 | get { return m_ScriptEngine.World; } | 445 | get { return m_ScriptEngine.World; } |
446 | } | 446 | } |
447 | 447 | ||
448 | public void state(string newState) | 448 | public void state(string newState) |
449 | { | 449 | { |
450 | m_ScriptEngine.SetState(m_item.ItemID, newState); | 450 | m_ScriptEngine.SetState(m_item.ItemID, newState); |
451 | } | 451 | } |
452 | 452 | ||
453 | /// <summary> | 453 | /// <summary> |
454 | /// Reset the named script. The script must be present | 454 | /// Reset the named script. The script must be present |
455 | /// in the same prim. | 455 | /// in the same prim. |
456 | /// </summary> | 456 | /// </summary> |
457 | public void llResetScript() | 457 | public void llResetScript() |
458 | { | 458 | { |
459 | m_host.AddScriptLPS(1); | 459 | m_host.AddScriptLPS(1); |
460 | 460 | ||
461 | // We need to tell the URL module, if we hav one, to release | 461 | // We need to tell the URL module, if we hav one, to release |
462 | // the allocated URLs | 462 | // the allocated URLs |
463 | if (m_UrlModule != null) | 463 | if (m_UrlModule != null) |
464 | m_UrlModule.ScriptRemoved(m_item.ItemID); | 464 | m_UrlModule.ScriptRemoved(m_item.ItemID); |
465 | 465 | ||
466 | m_ScriptEngine.ApiResetScript(m_item.ItemID); | 466 | m_ScriptEngine.ApiResetScript(m_item.ItemID); |
467 | } | 467 | } |
468 | 468 | ||
469 | public void llResetOtherScript(string name) | 469 | public void llResetOtherScript(string name) |
470 | { | 470 | { |
471 | UUID item; | 471 | UUID item; |
472 | 472 | ||
473 | m_host.AddScriptLPS(1); | 473 | m_host.AddScriptLPS(1); |
474 | 474 | ||
475 | if ((item = GetScriptByName(name)) != UUID.Zero) | 475 | if ((item = GetScriptByName(name)) != UUID.Zero) |
476 | m_ScriptEngine.ResetScript(item); | 476 | m_ScriptEngine.ResetScript(item); |
477 | else | 477 | else |
478 | Error("llResetOtherScript", "Can't find script '" + name + "'"); | 478 | Error("llResetOtherScript", "Can't find script '" + name + "'"); |
479 | } | 479 | } |
480 | 480 | ||
481 | public LSL_Integer llGetScriptState(string name) | 481 | public LSL_Integer llGetScriptState(string name) |
482 | { | 482 | { |
483 | UUID item; | 483 | UUID item; |
484 | 484 | ||
485 | m_host.AddScriptLPS(1); | 485 | m_host.AddScriptLPS(1); |
486 | 486 | ||
487 | if ((item = GetScriptByName(name)) != UUID.Zero) | 487 | if ((item = GetScriptByName(name)) != UUID.Zero) |
488 | { | 488 | { |
489 | return m_ScriptEngine.GetScriptState(item) ?1:0; | 489 | return m_ScriptEngine.GetScriptState(item) ?1:0; |
490 | } | 490 | } |
491 | 491 | ||
492 | Error("llGetScriptState", "Can't find script '" + name + "'"); | 492 | Error("llGetScriptState", "Can't find script '" + name + "'"); |
493 | 493 | ||
494 | // If we didn't find it, then it's safe to | 494 | // If we didn't find it, then it's safe to |
495 | // assume it is not running. | 495 | // assume it is not running. |
496 | 496 | ||
497 | return 0; | 497 | return 0; |
498 | } | 498 | } |
499 | 499 | ||
500 | public void llSetScriptState(string name, int run) | 500 | public void llSetScriptState(string name, int run) |
501 | { | 501 | { |
502 | UUID item; | 502 | UUID item; |
503 | 503 | ||
504 | m_host.AddScriptLPS(1); | 504 | m_host.AddScriptLPS(1); |
505 | 505 | ||
506 | // These functions are supposed to be robust, | 506 | // These functions are supposed to be robust, |
507 | // so get the state one step at a time. | 507 | // so get the state one step at a time. |
508 | 508 | ||
509 | if ((item = GetScriptByName(name)) != UUID.Zero) | 509 | if ((item = GetScriptByName(name)) != UUID.Zero) |
510 | { | 510 | { |
511 | m_ScriptEngine.SetScriptState(item, run == 0 ? false : true); | 511 | m_ScriptEngine.SetScriptState(item, run == 0 ? false : true); |
512 | } | 512 | } |
513 | else | 513 | else |
514 | { | 514 | { |
515 | Error("llSetScriptState", "Can't find script '" + name + "'"); | 515 | Error("llSetScriptState", "Can't find script '" + name + "'"); |
516 | } | 516 | } |
517 | } | 517 | } |
518 | 518 | ||
519 | /// <summary> | 519 | /// <summary> |
520 | /// Get a given link entity from a linkset (linked objects and any sitting avatars). | 520 | /// Get a given link entity from a linkset (linked objects and any sitting avatars). |
521 | /// </summary> | 521 | /// </summary> |
522 | /// <remarks> | 522 | /// <remarks> |
523 | /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then | 523 | /// If there are any ScenePresence's in the linkset (i.e. because they are sat upon one of the prims), then |
524 | /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset. | 524 | /// these are counted as extra entities that correspond to linknums beyond the number of prims in the linkset. |
525 | /// The ScenePresences receive linknums in the order in which they sat. | 525 | /// The ScenePresences receive linknums in the order in which they sat. |
526 | /// </remarks> | 526 | /// </remarks> |
527 | /// <returns> | 527 | /// <returns> |
528 | /// The link entity. null if not found. | 528 | /// The link entity. null if not found. |
529 | /// </returns> | 529 | /// </returns> |
530 | /// <param name='part'></param> | 530 | /// <param name='part'></param> |
531 | /// <param name='linknum'> | 531 | /// <param name='linknum'> |
532 | /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4). | 532 | /// Can be either a non-negative integer or ScriptBaseClass.LINK_THIS (-4). |
533 | /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned. | 533 | /// If ScriptBaseClass.LINK_THIS then the entity containing the script is returned. |
534 | /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned. If any | 534 | /// If the linkset has one entity and a linknum of zero is given, then the single entity is returned. If any |
535 | /// positive integer is given in this case then null is returned. | 535 | /// positive integer is given in this case then null is returned. |
536 | /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number | 536 | /// If the linkset has more than one entity and a linknum greater than zero but equal to or less than the number |
537 | /// of entities, then the entity which corresponds to that linknum is returned. | 537 | /// of entities, then the entity which corresponds to that linknum is returned. |
538 | /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then | 538 | /// Otherwise, if a positive linknum is given which is greater than the number of entities in the linkset, then |
539 | /// null is returned. | 539 | /// null is returned. |
540 | /// </param> | 540 | /// </param> |
541 | public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum) | 541 | public ISceneEntity GetLinkEntity(SceneObjectPart part, int linknum) |
542 | { | 542 | { |
543 | if (linknum < 0) | 543 | if (linknum < 0) |
544 | { | 544 | { |
545 | if (linknum == ScriptBaseClass.LINK_THIS) | 545 | if (linknum == ScriptBaseClass.LINK_THIS) |
546 | return part; | 546 | return part; |
547 | else | 547 | else |
548 | return null; | 548 | return null; |
549 | } | 549 | } |
550 | 550 | ||
551 | int actualPrimCount = part.ParentGroup.PrimCount; | 551 | int actualPrimCount = part.ParentGroup.PrimCount; |
552 | List<ScenePresence> sittingAvatars = part.ParentGroup.GetSittingAvatars(); | 552 | List<ScenePresence> sittingAvatars = part.ParentGroup.GetSittingAvatars(); |
553 | int adjustedPrimCount = actualPrimCount + sittingAvatars.Count; | 553 | int adjustedPrimCount = actualPrimCount + sittingAvatars.Count; |
554 | 554 | ||
555 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single | 555 | // Special case for a single prim. In this case the linknum is zero. However, this will not match a single |
556 | // prim that has any avatars sat upon it (in which case the root prim is link 1). | 556 | // prim that has any avatars sat upon it (in which case the root prim is link 1). |
557 | if (linknum == 0) | 557 | if (linknum == 0) |
558 | { | 558 | { |
559 | if (actualPrimCount == 1 && sittingAvatars.Count == 0) | 559 | if (actualPrimCount == 1 && sittingAvatars.Count == 0) |
560 | return part; | 560 | return part; |
561 | 561 | ||
562 | return null; | 562 | return null; |
563 | } | 563 | } |
564 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but | 564 | // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but |
565 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). | 565 | // here we must match 1 (ScriptBaseClass.LINK_ROOT). |
566 | else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1) | 566 | else if (linknum == ScriptBaseClass.LINK_ROOT && actualPrimCount == 1) |
567 | { | 567 | { |
568 | if (sittingAvatars.Count > 0) | 568 | if (sittingAvatars.Count > 0) |
569 | return part.ParentGroup.RootPart; | 569 | return part.ParentGroup.RootPart; |
570 | else | 570 | else |
571 | return null; | 571 | return null; |
572 | } | 572 | } |
573 | else if (linknum <= adjustedPrimCount) | 573 | else if (linknum <= adjustedPrimCount) |
574 | { | 574 | { |
575 | if (linknum <= actualPrimCount) | 575 | if (linknum <= actualPrimCount) |
576 | { | 576 | { |
577 | return part.ParentGroup.GetLinkNumPart(linknum); | 577 | return part.ParentGroup.GetLinkNumPart(linknum); |
578 | } | 578 | } |
579 | else | 579 | else |
580 | { | 580 | { |
581 | return sittingAvatars[linknum - actualPrimCount - 1]; | 581 | return sittingAvatars[linknum - actualPrimCount - 1]; |
582 | } | 582 | } |
583 | } | 583 | } |
584 | else | 584 | else |
585 | { | 585 | { |
586 | return null; | 586 | return null; |
587 | } | 587 | } |
588 | } | 588 | } |
589 | 589 | ||
590 | public List<SceneObjectPart> GetLinkParts(int linkType) | 590 | public List<SceneObjectPart> GetLinkParts(int linkType) |
591 | { | 591 | { |
592 | return GetLinkParts(m_host, linkType); | 592 | return GetLinkParts(m_host, linkType); |
593 | } | 593 | } |
594 | 594 | ||
595 | public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) | 595 | public static List<SceneObjectPart> GetLinkParts(SceneObjectPart part, int linkType) |
596 | { | 596 | { |
597 | List<SceneObjectPart> ret = new List<SceneObjectPart>(); | 597 | List<SceneObjectPart> ret = new List<SceneObjectPart>(); |
598 | ret.Add(part); | 598 | ret.Add(part); |
599 | 599 | ||
600 | switch (linkType) | 600 | switch (linkType) |
601 | { | 601 | { |
602 | case ScriptBaseClass.LINK_SET: | 602 | case ScriptBaseClass.LINK_SET: |
603 | return new List<SceneObjectPart>(part.ParentGroup.Parts); | 603 | return new List<SceneObjectPart>(part.ParentGroup.Parts); |
604 | 604 | ||
605 | case ScriptBaseClass.LINK_ROOT: | 605 | case ScriptBaseClass.LINK_ROOT: |
606 | ret = new List<SceneObjectPart>(); | 606 | ret = new List<SceneObjectPart>(); |
607 | ret.Add(part.ParentGroup.RootPart); | 607 | ret.Add(part.ParentGroup.RootPart); |
608 | return ret; | 608 | return ret; |
609 | 609 | ||
610 | case ScriptBaseClass.LINK_ALL_OTHERS: | 610 | case ScriptBaseClass.LINK_ALL_OTHERS: |
611 | ret = new List<SceneObjectPart>(part.ParentGroup.Parts); | 611 | ret = new List<SceneObjectPart>(part.ParentGroup.Parts); |
612 | 612 | ||
613 | if (ret.Contains(part)) | 613 | if (ret.Contains(part)) |
614 | ret.Remove(part); | 614 | ret.Remove(part); |
615 | 615 | ||
616 | return ret; | 616 | return ret; |
617 | 617 | ||
618 | case ScriptBaseClass.LINK_ALL_CHILDREN: | 618 | case ScriptBaseClass.LINK_ALL_CHILDREN: |
619 | ret = new List<SceneObjectPart>(part.ParentGroup.Parts); | 619 | ret = new List<SceneObjectPart>(part.ParentGroup.Parts); |
620 | 620 | ||
621 | if (ret.Contains(part.ParentGroup.RootPart)) | 621 | if (ret.Contains(part.ParentGroup.RootPart)) |
622 | ret.Remove(part.ParentGroup.RootPart); | 622 | ret.Remove(part.ParentGroup.RootPart); |
623 | return ret; | 623 | return ret; |
624 | 624 | ||
625 | case ScriptBaseClass.LINK_THIS: | 625 | case ScriptBaseClass.LINK_THIS: |
626 | return ret; | 626 | return ret; |
627 | 627 | ||
628 | default: | 628 | default: |
629 | if (linkType < 0) | 629 | if (linkType < 0) |
630 | return new List<SceneObjectPart>(); | 630 | return new List<SceneObjectPart>(); |
631 | 631 | ||
632 | SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType); | 632 | SceneObjectPart target = part.ParentGroup.GetLinkNumPart(linkType); |
633 | if (target == null) | 633 | if (target == null) |
634 | return new List<SceneObjectPart>(); | 634 | return new List<SceneObjectPart>(); |
635 | ret = new List<SceneObjectPart>(); | 635 | ret = new List<SceneObjectPart>(); |
636 | ret.Add(target); | 636 | ret.Add(target); |
637 | return ret; | 637 | return ret; |
638 | } | 638 | } |
639 | } | 639 | } |
640 | 640 | ||
641 | public List<ISceneEntity> GetLinkEntities(int linkType) | 641 | public List<ISceneEntity> GetLinkEntities(int linkType) |
642 | { | 642 | { |
643 | return GetLinkEntities(m_host, linkType); | 643 | return GetLinkEntities(m_host, linkType); |
644 | } | 644 | } |
645 | 645 | ||
646 | public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType) | 646 | public List<ISceneEntity> GetLinkEntities(SceneObjectPart part, int linkType) |
647 | { | 647 | { |
648 | List<ISceneEntity> ret; | 648 | List<ISceneEntity> ret; |
649 | 649 | ||
650 | switch (linkType) | 650 | switch (linkType) |
651 | { | 651 | { |
652 | case ScriptBaseClass.LINK_SET: | 652 | case ScriptBaseClass.LINK_SET: |
653 | return new List<ISceneEntity>(part.ParentGroup.Parts); | 653 | return new List<ISceneEntity>(part.ParentGroup.Parts); |
654 | 654 | ||
655 | case ScriptBaseClass.LINK_ROOT: | 655 | case ScriptBaseClass.LINK_ROOT: |
656 | return new List<ISceneEntity>() { part.ParentGroup.RootPart }; | 656 | return new List<ISceneEntity>() { part.ParentGroup.RootPart }; |
657 | 657 | ||
658 | case ScriptBaseClass.LINK_ALL_OTHERS: | 658 | case ScriptBaseClass.LINK_ALL_OTHERS: |
659 | ret = new List<ISceneEntity>(part.ParentGroup.Parts); | 659 | ret = new List<ISceneEntity>(part.ParentGroup.Parts); |
660 | 660 | ||
661 | if (ret.Contains(part)) | 661 | if (ret.Contains(part)) |
662 | ret.Remove(part); | 662 | ret.Remove(part); |
663 | 663 | ||
664 | return ret; | 664 | return ret; |
665 | 665 | ||
666 | case ScriptBaseClass.LINK_ALL_CHILDREN: | 666 | case ScriptBaseClass.LINK_ALL_CHILDREN: |
667 | ret = new List<ISceneEntity>(part.ParentGroup.Parts); | 667 | ret = new List<ISceneEntity>(part.ParentGroup.Parts); |
668 | 668 | ||
669 | if (ret.Contains(part.ParentGroup.RootPart)) | 669 | if (ret.Contains(part.ParentGroup.RootPart)) |
670 | ret.Remove(part.ParentGroup.RootPart); | 670 | ret.Remove(part.ParentGroup.RootPart); |
671 | 671 | ||
672 | return ret; | 672 | return ret; |
673 | 673 | ||
674 | case ScriptBaseClass.LINK_THIS: | 674 | case ScriptBaseClass.LINK_THIS: |
675 | return new List<ISceneEntity>() { part }; | 675 | return new List<ISceneEntity>() { part }; |
676 | 676 | ||
677 | default: | 677 | default: |
678 | if (linkType < 0) | 678 | if (linkType < 0) |
679 | return new List<ISceneEntity>(); | 679 | return new List<ISceneEntity>(); |
680 | 680 | ||
681 | ISceneEntity target = GetLinkEntity(part, linkType); | 681 | ISceneEntity target = GetLinkEntity(part, linkType); |
682 | if (target == null) | 682 | if (target == null) |
683 | return new List<ISceneEntity>(); | 683 | return new List<ISceneEntity>(); |
684 | 684 | ||
685 | return new List<ISceneEntity>() { target }; | 685 | return new List<ISceneEntity>() { target }; |
686 | } | 686 | } |
687 | } | 687 | } |
688 | 688 | ||
689 | //These are the implementations of the various ll-functions used by the LSL scripts. | 689 | //These are the implementations of the various ll-functions used by the LSL scripts. |
690 | public LSL_Float llSin(double f) | 690 | public LSL_Float llSin(double f) |
691 | { | 691 | { |
692 | m_host.AddScriptLPS(1); | 692 | m_host.AddScriptLPS(1); |
693 | return (double)Math.Sin(f); | 693 | return (double)Math.Sin(f); |
694 | } | 694 | } |
695 | 695 | ||
696 | public LSL_Float llCos(double f) | 696 | public LSL_Float llCos(double f) |
697 | { | 697 | { |
698 | m_host.AddScriptLPS(1); | 698 | m_host.AddScriptLPS(1); |
699 | return (double)Math.Cos(f); | 699 | return (double)Math.Cos(f); |
700 | } | 700 | } |
701 | 701 | ||
702 | public LSL_Float llTan(double f) | 702 | public LSL_Float llTan(double f) |
703 | { | 703 | { |
704 | m_host.AddScriptLPS(1); | 704 | m_host.AddScriptLPS(1); |
705 | return (double)Math.Tan(f); | 705 | return (double)Math.Tan(f); |
706 | } | 706 | } |
707 | 707 | ||
708 | public LSL_Float llAtan2(double x, double y) | 708 | public LSL_Float llAtan2(double x, double y) |
709 | { | 709 | { |
710 | m_host.AddScriptLPS(1); | 710 | m_host.AddScriptLPS(1); |
711 | return (double)Math.Atan2(x, y); | 711 | return (double)Math.Atan2(x, y); |
712 | } | 712 | } |
713 | 713 | ||
714 | public LSL_Float llSqrt(double f) | 714 | public LSL_Float llSqrt(double f) |
715 | { | 715 | { |
716 | m_host.AddScriptLPS(1); | 716 | m_host.AddScriptLPS(1); |
717 | return (double)Math.Sqrt(f); | 717 | return (double)Math.Sqrt(f); |
718 | } | 718 | } |
719 | 719 | ||
720 | public LSL_Float llPow(double fbase, double fexponent) | 720 | public LSL_Float llPow(double fbase, double fexponent) |
721 | { | 721 | { |
722 | m_host.AddScriptLPS(1); | 722 | m_host.AddScriptLPS(1); |
723 | return (double)Math.Pow(fbase, fexponent); | 723 | return (double)Math.Pow(fbase, fexponent); |
724 | } | 724 | } |
725 | 725 | ||
726 | public LSL_Integer llAbs(int i) | 726 | public LSL_Integer llAbs(int i) |
727 | { | 727 | { |
728 | // changed to replicate LSL behaviour whereby minimum int value is returned untouched. | 728 | // changed to replicate LSL behaviour whereby minimum int value is returned untouched. |
729 | m_host.AddScriptLPS(1); | 729 | m_host.AddScriptLPS(1); |
730 | if (i == Int32.MinValue) | 730 | if (i == Int32.MinValue) |
731 | return i; | 731 | return i; |
732 | else | 732 | else |
733 | return (int)Math.Abs(i); | 733 | return (int)Math.Abs(i); |
734 | } | 734 | } |
735 | 735 | ||
736 | public LSL_Float llFabs(double f) | 736 | public LSL_Float llFabs(double f) |
737 | { | 737 | { |
738 | m_host.AddScriptLPS(1); | 738 | m_host.AddScriptLPS(1); |
739 | return (double)Math.Abs(f); | 739 | return (double)Math.Abs(f); |
740 | } | 740 | } |
741 | 741 | ||
742 | public LSL_Float llFrand(double mag) | 742 | public LSL_Float llFrand(double mag) |
743 | { | 743 | { |
744 | m_host.AddScriptLPS(1); | 744 | m_host.AddScriptLPS(1); |
745 | 745 | ||
746 | return Util.RandomClass.NextDouble() * mag; | 746 | return Util.RandomClass.NextDouble() * mag; |
747 | } | 747 | } |
748 | 748 | ||
749 | public LSL_Integer llFloor(double f) | 749 | public LSL_Integer llFloor(double f) |
750 | { | 750 | { |
751 | m_host.AddScriptLPS(1); | 751 | m_host.AddScriptLPS(1); |
752 | return (int)Math.Floor(f); | 752 | return (int)Math.Floor(f); |
753 | } | 753 | } |
754 | 754 | ||
755 | public LSL_Integer llCeil(double f) | 755 | public LSL_Integer llCeil(double f) |
756 | { | 756 | { |
757 | m_host.AddScriptLPS(1); | 757 | m_host.AddScriptLPS(1); |
758 | return (int)Math.Ceiling(f); | 758 | return (int)Math.Ceiling(f); |
759 | } | 759 | } |
760 | 760 | ||
761 | // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven) | 761 | // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven) |
762 | public LSL_Integer llRound(double f) | 762 | public LSL_Integer llRound(double f) |
763 | { | 763 | { |
764 | m_host.AddScriptLPS(1); | 764 | m_host.AddScriptLPS(1); |
765 | return (int)Math.Round(f, MidpointRounding.AwayFromZero); | 765 | return (int)Math.Round(f, MidpointRounding.AwayFromZero); |
766 | } | 766 | } |
767 | 767 | ||
768 | //This next group are vector operations involving squaring and square root. ckrinke | 768 | //This next group are vector operations involving squaring and square root. ckrinke |
769 | public LSL_Float llVecMag(LSL_Vector v) | 769 | public LSL_Float llVecMag(LSL_Vector v) |
770 | { | 770 | { |
771 | m_host.AddScriptLPS(1); | 771 | m_host.AddScriptLPS(1); |
772 | return LSL_Vector.Mag(v); | 772 | return LSL_Vector.Mag(v); |
773 | } | 773 | } |
774 | 774 | ||
775 | public LSL_Vector llVecNorm(LSL_Vector v) | 775 | public LSL_Vector llVecNorm(LSL_Vector v) |
776 | { | 776 | { |
777 | m_host.AddScriptLPS(1); | 777 | m_host.AddScriptLPS(1); |
778 | return LSL_Vector.Norm(v); | 778 | return LSL_Vector.Norm(v); |
779 | } | 779 | } |
780 | 780 | ||
781 | private double VecDist(LSL_Vector a, LSL_Vector b) | 781 | private double VecDist(LSL_Vector a, LSL_Vector b) |
782 | { | 782 | { |
783 | double dx = a.x - b.x; | 783 | double dx = a.x - b.x; |
784 | double dy = a.y - b.y; | 784 | double dy = a.y - b.y; |
785 | double dz = a.z - b.z; | 785 | double dz = a.z - b.z; |
786 | return Math.Sqrt(dx * dx + dy * dy + dz * dz); | 786 | return Math.Sqrt(dx * dx + dy * dy + dz * dz); |
787 | } | 787 | } |
788 | 788 | ||
789 | public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) | 789 | public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) |
790 | { | 790 | { |
791 | m_host.AddScriptLPS(1); | 791 | m_host.AddScriptLPS(1); |
792 | return VecDist(a, b); | 792 | return VecDist(a, b); |
793 | } | 793 | } |
794 | 794 | ||
795 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke | 795 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke |
796 | 796 | ||
797 | /// <summary> | 797 | /// <summary> |
798 | /// Convert an LSL rotation to a Euler vector. | 798 | /// Convert an LSL rotation to a Euler vector. |
799 | /// </summary> | 799 | /// </summary> |
800 | /// <remarks> | 800 | /// <remarks> |
801 | /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf | 801 | /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf |
802 | /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2 | 802 | /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2 |
803 | /// </remarks> | 803 | /// </remarks> |
804 | /// <param name="r"></param> | 804 | /// <param name="r"></param> |
805 | /// <returns></returns> | 805 | /// <returns></returns> |
806 | public LSL_Vector llRot2Euler(LSL_Rotation r) | 806 | public LSL_Vector llRot2Euler(LSL_Rotation r) |
807 | { | 807 | { |
808 | m_host.AddScriptLPS(1); | 808 | m_host.AddScriptLPS(1); |
809 | 809 | ||
810 | LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. | 810 | LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. |
811 | double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. | 811 | double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. |
812 | if (m == 0.0) return new LSL_Vector(); | 812 | if (m == 0.0) return new LSL_Vector(); |
813 | double x = Math.Atan2(-v.y, v.z); | 813 | double x = Math.Atan2(-v.y, v.z); |
814 | double sin = v.x / m; | 814 | double sin = v.x / m; |
815 | if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. | 815 | if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. |
816 | double y = Math.Asin(sin); | 816 | double y = Math.Asin(sin); |
817 | // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation | 817 | // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation |
818 | v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); | 818 | v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); |
819 | double z = Math.Atan2(v.y, v.x); | 819 | double z = Math.Atan2(v.y, v.x); |
820 | 820 | ||
821 | return new LSL_Vector(x, y, z); | 821 | return new LSL_Vector(x, y, z); |
822 | } | 822 | } |
823 | 823 | ||
824 | /* From wiki: | 824 | /* From wiki: |
825 | The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes | 825 | The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes |
826 | in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, | 826 | in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, |
827 | a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting | 827 | a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting |
828 | vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. | 828 | vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. |
829 | */ | 829 | */ |
830 | 830 | ||
831 | /* How we arrived at this llEuler2Rot | 831 | /* How we arrived at this llEuler2Rot |
832 | * | 832 | * |
833 | * Experiment in SL to determine conventions: | 833 | * Experiment in SL to determine conventions: |
834 | * llEuler2Rot(<PI,0,0>)=<1,0,0,0> | 834 | * llEuler2Rot(<PI,0,0>)=<1,0,0,0> |
835 | * llEuler2Rot(<0,PI,0>)=<0,1,0,0> | 835 | * llEuler2Rot(<0,PI,0>)=<0,1,0,0> |
836 | * llEuler2Rot(<0,0,PI>)=<0,0,1,0> | 836 | * llEuler2Rot(<0,0,PI>)=<0,0,1,0> |
837 | * | 837 | * |
838 | * Important facts about Quaternions | 838 | * Important facts about Quaternions |
839 | * - multiplication is non-commutative (a*b != b*a) | 839 | * - multiplication is non-commutative (a*b != b*a) |
840 | * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication | 840 | * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication |
841 | * | 841 | * |
842 | * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot): | 842 | * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot): |
843 | * Qx = c1+i*s1 | 843 | * Qx = c1+i*s1 |
844 | * Qy = c2+j*s2; | 844 | * Qy = c2+j*s2; |
845 | * Qz = c3+k*s3; | 845 | * Qz = c3+k*s3; |
846 | * | 846 | * |
847 | * Rotations applied in order (from above) Z, Y, X | 847 | * Rotations applied in order (from above) Z, Y, X |
848 | * Q = (Qz * Qy) * Qx | 848 | * Q = (Qz * Qy) * Qx |
849 | * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3) | 849 | * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3) |
850 | * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3) | 850 | * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3) |
851 | * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3) | 851 | * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3) |
852 | * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3 | 852 | * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3+ik*s1*c2*s3+jk*c1*s2*s3+kk*s1*s2*s3 |
853 | * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3 | 853 | * c1*c2*c3+i*s1*c2*c3+j*c1*s2*c3+k*s1*s2*c3+k*c1*c2*s3 -j*s1*c2*s3 +i*c1*s2*s3 -s1*s2*s3 |
854 | * regroup: x=i*(s1*c2*c3+c1*s2*s3) | 854 | * regroup: x=i*(s1*c2*c3+c1*s2*s3) |
855 | * y=j*(c1*s2*c3-s1*c2*s3) | 855 | * y=j*(c1*s2*c3-s1*c2*s3) |
856 | * z=k*(s1*s2*c3+c1*c2*s3) | 856 | * z=k*(s1*s2*c3+c1*c2*s3) |
857 | * s= c1*c2*c3-s1*s2*s3 | 857 | * s= c1*c2*c3-s1*s2*s3 |
858 | * | 858 | * |
859 | * This implementation agrees with the functions found here: | 859 | * This implementation agrees with the functions found here: |
860 | * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions | 860 | * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions |
861 | * And with the results in SL. | 861 | * And with the results in SL. |
862 | * | 862 | * |
863 | * It's also possible to calculate llEuler2Rot by direct multiplication of | 863 | * It's also possible to calculate llEuler2Rot by direct multiplication of |
864 | * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function | 864 | * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function |
865 | * from the wiki). | 865 | * from the wiki). |
866 | * Apparently in some cases this is better from a numerical precision perspective? | 866 | * Apparently in some cases this is better from a numerical precision perspective? |
867 | */ | 867 | */ |
868 | 868 | ||
869 | public LSL_Rotation llEuler2Rot(LSL_Vector v) | 869 | public LSL_Rotation llEuler2Rot(LSL_Vector v) |
870 | { | 870 | { |
871 | m_host.AddScriptLPS(1); | 871 | m_host.AddScriptLPS(1); |
872 | 872 | ||
873 | double x,y,z,s; | 873 | double x,y,z,s; |
874 | 874 | ||
875 | double c1 = Math.Cos(v.x * 0.5); | 875 | double c1 = Math.Cos(v.x * 0.5); |
876 | double c2 = Math.Cos(v.y * 0.5); | 876 | double c2 = Math.Cos(v.y * 0.5); |
877 | double c3 = Math.Cos(v.z * 0.5); | 877 | double c3 = Math.Cos(v.z * 0.5); |
878 | double s1 = Math.Sin(v.x * 0.5); | 878 | double s1 = Math.Sin(v.x * 0.5); |
879 | double s2 = Math.Sin(v.y * 0.5); | 879 | double s2 = Math.Sin(v.y * 0.5); |
880 | double s3 = Math.Sin(v.z * 0.5); | 880 | double s3 = Math.Sin(v.z * 0.5); |
881 | 881 | ||
882 | x = s1 * c2 * c3 + c1 * s2 * s3; | 882 | x = s1 * c2 * c3 + c1 * s2 * s3; |
883 | y = c1 * s2 * c3 - s1 * c2 * s3; | 883 | y = c1 * s2 * c3 - s1 * c2 * s3; |
884 | z = s1 * s2 * c3 + c1 * c2 * s3; | 884 | z = s1 * s2 * c3 + c1 * c2 * s3; |
885 | s = c1 * c2 * c3 - s1 * s2 * s3; | 885 | s = c1 * c2 * c3 - s1 * s2 * s3; |
886 | 886 | ||
887 | return new LSL_Rotation(x, y, z, s); | 887 | return new LSL_Rotation(x, y, z, s); |
888 | } | 888 | } |
889 | 889 | ||
890 | public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up) | 890 | public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up) |
891 | { | 891 | { |
892 | m_host.AddScriptLPS(1); | 892 | m_host.AddScriptLPS(1); |
893 | double s; | 893 | double s; |
894 | double tr = fwd.x + left.y + up.z + 1.0; | 894 | double tr = fwd.x + left.y + up.z + 1.0; |
895 | 895 | ||
896 | if (tr >= 1.0) | 896 | if (tr >= 1.0) |
897 | { | 897 | { |
898 | s = 0.5 / Math.Sqrt(tr); | 898 | s = 0.5 / Math.Sqrt(tr); |
899 | return new LSL_Rotation( | 899 | return new LSL_Rotation( |
900 | (left.z - up.y) * s, | 900 | (left.z - up.y) * s, |
901 | (up.x - fwd.z) * s, | 901 | (up.x - fwd.z) * s, |
902 | (fwd.y - left.x) * s, | 902 | (fwd.y - left.x) * s, |
903 | 0.25 / s); | 903 | 0.25 / s); |
904 | } | 904 | } |
905 | else | 905 | else |
906 | { | 906 | { |
907 | double max = (left.y > up.z) ? left.y : up.z; | 907 | double max = (left.y > up.z) ? left.y : up.z; |
908 | 908 | ||
909 | if (max < fwd.x) | 909 | if (max < fwd.x) |
910 | { | 910 | { |
911 | s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0); | 911 | s = Math.Sqrt(fwd.x - (left.y + up.z) + 1.0); |
912 | double x = s * 0.5; | 912 | double x = s * 0.5; |
913 | s = 0.5 / s; | 913 | s = 0.5 / s; |
914 | return new LSL_Rotation( | 914 | return new LSL_Rotation( |
915 | x, | 915 | x, |
916 | (fwd.y + left.x) * s, | 916 | (fwd.y + left.x) * s, |
917 | (up.x + fwd.z) * s, | 917 | (up.x + fwd.z) * s, |
918 | (left.z - up.y) * s); | 918 | (left.z - up.y) * s); |
919 | } | 919 | } |
920 | else if (max == left.y) | 920 | else if (max == left.y) |
921 | { | 921 | { |
922 | s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0); | 922 | s = Math.Sqrt(left.y - (up.z + fwd.x) + 1.0); |
923 | double y = s * 0.5; | 923 | double y = s * 0.5; |
924 | s = 0.5 / s; | 924 | s = 0.5 / s; |
925 | return new LSL_Rotation( | 925 | return new LSL_Rotation( |
926 | (fwd.y + left.x) * s, | 926 | (fwd.y + left.x) * s, |
927 | y, | 927 | y, |
928 | (left.z + up.y) * s, | 928 | (left.z + up.y) * s, |
929 | (up.x - fwd.z) * s); | 929 | (up.x - fwd.z) * s); |
930 | } | 930 | } |
931 | else | 931 | else |
932 | { | 932 | { |
933 | s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0); | 933 | s = Math.Sqrt(up.z - (fwd.x + left.y) + 1.0); |
934 | double z = s * 0.5; | 934 | double z = s * 0.5; |
935 | s = 0.5 / s; | 935 | s = 0.5 / s; |
936 | return new LSL_Rotation( | 936 | return new LSL_Rotation( |
937 | (up.x + fwd.z) * s, | 937 | (up.x + fwd.z) * s, |
938 | (left.z + up.y) * s, | 938 | (left.z + up.y) * s, |
939 | z, | 939 | z, |
940 | (fwd.y - left.x) * s); | 940 | (fwd.y - left.x) * s); |
941 | } | 941 | } |
942 | } | 942 | } |
943 | } | 943 | } |
944 | 944 | ||
945 | public LSL_Vector llRot2Fwd(LSL_Rotation r) | 945 | public LSL_Vector llRot2Fwd(LSL_Rotation r) |
946 | { | 946 | { |
947 | m_host.AddScriptLPS(1); | 947 | m_host.AddScriptLPS(1); |
948 | 948 | ||
949 | double x, y, z, m; | 949 | double x, y, z, m; |
950 | 950 | ||
951 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | 951 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; |
952 | // m is always greater than zero | 952 | // m is always greater than zero |
953 | // if m is not equal to 1 then Rotation needs to be normalized | 953 | // if m is not equal to 1 then Rotation needs to be normalized |
954 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | 954 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision |
955 | { | 955 | { |
956 | m = 1.0 / Math.Sqrt(m); | 956 | m = 1.0 / Math.Sqrt(m); |
957 | r.x *= m; | 957 | r.x *= m; |
958 | r.y *= m; | 958 | r.y *= m; |
959 | r.z *= m; | 959 | r.z *= m; |
960 | r.s *= m; | 960 | r.s *= m; |
961 | } | 961 | } |
962 | 962 | ||
963 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | 963 | // Fast Algebric Calculations instead of Vectors & Quaternions Product |
964 | x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s; | 964 | x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s; |
965 | y = 2 * (r.x * r.y + r.z * r.s); | 965 | y = 2 * (r.x * r.y + r.z * r.s); |
966 | z = 2 * (r.x * r.z - r.y * r.s); | 966 | z = 2 * (r.x * r.z - r.y * r.s); |
967 | return (new LSL_Vector(x, y, z)); | 967 | return (new LSL_Vector(x, y, z)); |
968 | } | 968 | } |
969 | 969 | ||
970 | public LSL_Vector llRot2Left(LSL_Rotation r) | 970 | public LSL_Vector llRot2Left(LSL_Rotation r) |
971 | { | 971 | { |
972 | m_host.AddScriptLPS(1); | 972 | m_host.AddScriptLPS(1); |
973 | 973 | ||
974 | double x, y, z, m; | 974 | double x, y, z, m; |
975 | 975 | ||
976 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | 976 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; |
977 | // m is always greater than zero | 977 | // m is always greater than zero |
978 | // if m is not equal to 1 then Rotation needs to be normalized | 978 | // if m is not equal to 1 then Rotation needs to be normalized |
979 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | 979 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision |
980 | { | 980 | { |
981 | m = 1.0 / Math.Sqrt(m); | 981 | m = 1.0 / Math.Sqrt(m); |
982 | r.x *= m; | 982 | r.x *= m; |
983 | r.y *= m; | 983 | r.y *= m; |
984 | r.z *= m; | 984 | r.z *= m; |
985 | r.s *= m; | 985 | r.s *= m; |
986 | } | 986 | } |
987 | 987 | ||
988 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | 988 | // Fast Algebric Calculations instead of Vectors & Quaternions Product |
989 | x = 2 * (r.x * r.y - r.z * r.s); | 989 | x = 2 * (r.x * r.y - r.z * r.s); |
990 | y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s; | 990 | y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s; |
991 | z = 2 * (r.x * r.s + r.y * r.z); | 991 | z = 2 * (r.x * r.s + r.y * r.z); |
992 | return (new LSL_Vector(x, y, z)); | 992 | return (new LSL_Vector(x, y, z)); |
993 | } | 993 | } |
994 | 994 | ||
995 | public LSL_Vector llRot2Up(LSL_Rotation r) | 995 | public LSL_Vector llRot2Up(LSL_Rotation r) |
996 | { | 996 | { |
997 | m_host.AddScriptLPS(1); | 997 | m_host.AddScriptLPS(1); |
998 | double x, y, z, m; | 998 | double x, y, z, m; |
999 | 999 | ||
1000 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | 1000 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; |
1001 | // m is always greater than zero | 1001 | // m is always greater than zero |
1002 | // if m is not equal to 1 then Rotation needs to be normalized | 1002 | // if m is not equal to 1 then Rotation needs to be normalized |
1003 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | 1003 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision |
1004 | { | 1004 | { |
1005 | m = 1.0 / Math.Sqrt(m); | 1005 | m = 1.0 / Math.Sqrt(m); |
1006 | r.x *= m; | 1006 | r.x *= m; |
1007 | r.y *= m; | 1007 | r.y *= m; |
1008 | r.z *= m; | 1008 | r.z *= m; |
1009 | r.s *= m; | 1009 | r.s *= m; |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | 1012 | // Fast Algebric Calculations instead of Vectors & Quaternions Product |
1013 | x = 2 * (r.x * r.z + r.y * r.s); | 1013 | x = 2 * (r.x * r.z + r.y * r.s); |
1014 | y = 2 * (-r.x * r.s + r.y * r.z); | 1014 | y = 2 * (-r.x * r.s + r.y * r.z); |
1015 | z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s; | 1015 | z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s; |
1016 | return (new LSL_Vector(x, y, z)); | 1016 | return (new LSL_Vector(x, y, z)); |
1017 | } | 1017 | } |
1018 | 1018 | ||
1019 | public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b) | 1019 | public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b) |
1020 | { | 1020 | { |
1021 | //A and B should both be normalized | 1021 | //A and B should both be normalized |
1022 | m_host.AddScriptLPS(1); | 1022 | m_host.AddScriptLPS(1); |
1023 | LSL_Rotation rotBetween; | 1023 | LSL_Rotation rotBetween; |
1024 | // Check for zero vectors. If either is zero, return zero rotation. Otherwise, | 1024 | // Check for zero vectors. If either is zero, return zero rotation. Otherwise, |
1025 | // continue calculation. | 1025 | // continue calculation. |
1026 | if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) | 1026 | if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) |
1027 | { | 1027 | { |
1028 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); | 1028 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); |
1029 | } | 1029 | } |
1030 | else | 1030 | else |
1031 | { | 1031 | { |
1032 | a = LSL_Vector.Norm(a); | 1032 | a = LSL_Vector.Norm(a); |
1033 | b = LSL_Vector.Norm(b); | 1033 | b = LSL_Vector.Norm(b); |
1034 | double dotProduct = LSL_Vector.Dot(a, b); | 1034 | double dotProduct = LSL_Vector.Dot(a, b); |
1035 | // There are two degenerate cases possible. These are for vectors 180 or | 1035 | // There are two degenerate cases possible. These are for vectors 180 or |
1036 | // 0 degrees apart. These have to be detected and handled individually. | 1036 | // 0 degrees apart. These have to be detected and handled individually. |
1037 | // | 1037 | // |
1038 | // Check for vectors 180 degrees apart. | 1038 | // Check for vectors 180 degrees apart. |
1039 | // A dot product of -1 would mean the angle between vectors is 180 degrees. | 1039 | // A dot product of -1 would mean the angle between vectors is 180 degrees. |
1040 | if (dotProduct < -0.9999999f) | 1040 | if (dotProduct < -0.9999999f) |
1041 | { | 1041 | { |
1042 | // First assume X axis is orthogonal to the vectors. | 1042 | // First assume X axis is orthogonal to the vectors. |
1043 | LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); | 1043 | LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); |
1044 | orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); | 1044 | orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); |
1045 | // Check for near zero vector. A very small non-zero number here will create | 1045 | // Check for near zero vector. A very small non-zero number here will create |
1046 | // a rotation in an undesired direction. | 1046 | // a rotation in an undesired direction. |
1047 | if (LSL_Vector.Mag(orthoVector) > 0.0001) | 1047 | if (LSL_Vector.Mag(orthoVector) > 0.0001) |
1048 | { | 1048 | { |
1049 | rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); | 1049 | rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); |
1050 | } | 1050 | } |
1051 | // If the magnitude of the vector was near zero, then assume the X axis is not | 1051 | // If the magnitude of the vector was near zero, then assume the X axis is not |
1052 | // orthogonal and use the Z axis instead. | 1052 | // orthogonal and use the Z axis instead. |
1053 | else | 1053 | else |
1054 | { | 1054 | { |
1055 | // Set 180 z rotation. | 1055 | // Set 180 z rotation. |
1056 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f); | 1056 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f); |
1057 | } | 1057 | } |
1058 | } | 1058 | } |
1059 | // Check for parallel vectors. | 1059 | // Check for parallel vectors. |
1060 | // A dot product of 1 would mean the angle between vectors is 0 degrees. | 1060 | // A dot product of 1 would mean the angle between vectors is 0 degrees. |
1061 | else if (dotProduct > 0.9999999f) | 1061 | else if (dotProduct > 0.9999999f) |
1062 | { | 1062 | { |
1063 | // Set zero rotation. | 1063 | // Set zero rotation. |
1064 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); | 1064 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); |
1065 | } | 1065 | } |
1066 | else | 1066 | else |
1067 | { | 1067 | { |
1068 | // All special checks have been performed so get the axis of rotation. | 1068 | // All special checks have been performed so get the axis of rotation. |
1069 | LSL_Vector crossProduct = LSL_Vector.Cross(a, b); | 1069 | LSL_Vector crossProduct = LSL_Vector.Cross(a, b); |
1070 | // Quarternion s value is the length of the unit vector + dot product. | 1070 | // Quarternion s value is the length of the unit vector + dot product. |
1071 | double qs = 1.0 + dotProduct; | 1071 | double qs = 1.0 + dotProduct; |
1072 | rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs); | 1072 | rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs); |
1073 | // Normalize the rotation. | 1073 | // Normalize the rotation. |
1074 | double mag = LSL_Rotation.Mag(rotBetween); | 1074 | double mag = LSL_Rotation.Mag(rotBetween); |
1075 | // We shouldn't have to worry about a divide by zero here. The qs value will be | 1075 | // We shouldn't have to worry about a divide by zero here. The qs value will be |
1076 | // non-zero because we already know if we're here, then the dotProduct is not -1 so | 1076 | // non-zero because we already know if we're here, then the dotProduct is not -1 so |
1077 | // qs will not be zero. Also, we've already handled the input vectors being zero so the | 1077 | // qs will not be zero. Also, we've already handled the input vectors being zero so the |
1078 | // crossProduct vector should also not be zero. | 1078 | // crossProduct vector should also not be zero. |
1079 | rotBetween.x = rotBetween.x / mag; | 1079 | rotBetween.x = rotBetween.x / mag; |
1080 | rotBetween.y = rotBetween.y / mag; | 1080 | rotBetween.y = rotBetween.y / mag; |
1081 | rotBetween.z = rotBetween.z / mag; | 1081 | rotBetween.z = rotBetween.z / mag; |
1082 | rotBetween.s = rotBetween.s / mag; | 1082 | rotBetween.s = rotBetween.s / mag; |
1083 | // Check for undefined values and set zero rotation if any found. This code might not actually be required | 1083 | // Check for undefined values and set zero rotation if any found. This code might not actually be required |
1084 | // any longer since zero vectors are checked for at the top. | 1084 | // any longer since zero vectors are checked for at the top. |
1085 | if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s)) | 1085 | if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s)) |
1086 | { | 1086 | { |
1087 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); | 1087 | rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); |
1088 | } | 1088 | } |
1089 | } | 1089 | } |
1090 | } | 1090 | } |
1091 | return rotBetween; | 1091 | return rotBetween; |
1092 | } | 1092 | } |
1093 | 1093 | ||
1094 | public void llWhisper(int channelID, string text) | 1094 | public void llWhisper(int channelID, string text) |
1095 | { | 1095 | { |
1096 | m_host.AddScriptLPS(1); | 1096 | m_host.AddScriptLPS(1); |
1097 | 1097 | ||
1098 | if (text.Length > 1023) | 1098 | if (text.Length > 1023) |
1099 | text = text.Substring(0, 1023); | 1099 | text = text.Substring(0, 1023); |
1100 | 1100 | ||
1101 | World.SimChat(Utils.StringToBytes(text), | 1101 | World.SimChat(Utils.StringToBytes(text), |
1102 | ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); | 1102 | ChatTypeEnum.Whisper, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); |
1103 | 1103 | ||
1104 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1104 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1105 | if (wComm != null) | 1105 | if (wComm != null) |
1106 | wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); | 1106 | wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); |
1107 | } | 1107 | } |
1108 | 1108 | ||
1109 | public void llSay(int channelID, string text) | 1109 | public void llSay(int channelID, string text) |
1110 | { | 1110 | { |
1111 | m_host.AddScriptLPS(1); | 1111 | m_host.AddScriptLPS(1); |
1112 | 1112 | ||
1113 | if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) | 1113 | if (m_scriptConsoleChannelEnabled && (channelID == m_scriptConsoleChannel)) |
1114 | { | 1114 | { |
1115 | Console.WriteLine(text); | 1115 | Console.WriteLine(text); |
1116 | } | 1116 | } |
1117 | else | 1117 | else |
1118 | { | 1118 | { |
1119 | if (text.Length > 1023) | 1119 | if (text.Length > 1023) |
1120 | text = text.Substring(0, 1023); | 1120 | text = text.Substring(0, 1023); |
1121 | 1121 | ||
1122 | World.SimChat(Utils.StringToBytes(text), | 1122 | World.SimChat(Utils.StringToBytes(text), |
1123 | ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); | 1123 | ChatTypeEnum.Say, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); |
1124 | 1124 | ||
1125 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1125 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1126 | if (wComm != null) | 1126 | if (wComm != null) |
1127 | wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text); | 1127 | wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text); |
1128 | } | 1128 | } |
1129 | } | 1129 | } |
1130 | 1130 | ||
1131 | public void llShout(int channelID, string text) | 1131 | public void llShout(int channelID, string text) |
1132 | { | 1132 | { |
1133 | m_host.AddScriptLPS(1); | 1133 | m_host.AddScriptLPS(1); |
1134 | 1134 | ||
1135 | if (text.Length > 1023) | 1135 | if (text.Length > 1023) |
1136 | text = text.Substring(0, 1023); | 1136 | text = text.Substring(0, 1023); |
1137 | 1137 | ||
1138 | World.SimChat(Utils.StringToBytes(text), | 1138 | World.SimChat(Utils.StringToBytes(text), |
1139 | ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); | 1139 | ChatTypeEnum.Shout, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); |
1140 | 1140 | ||
1141 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1141 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1142 | if (wComm != null) | 1142 | if (wComm != null) |
1143 | wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text); | 1143 | wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text); |
1144 | } | 1144 | } |
1145 | 1145 | ||
1146 | public void llRegionSay(int channelID, string text) | 1146 | public void llRegionSay(int channelID, string text) |
1147 | { | 1147 | { |
1148 | if (channelID == 0) | 1148 | if (channelID == 0) |
1149 | { | 1149 | { |
1150 | Error("llRegionSay", "Cannot use on channel 0"); | 1150 | Error("llRegionSay", "Cannot use on channel 0"); |
1151 | return; | 1151 | return; |
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | if (text.Length > 1023) | 1154 | if (text.Length > 1023) |
1155 | text = text.Substring(0, 1023); | 1155 | text = text.Substring(0, 1023); |
1156 | 1156 | ||
1157 | m_host.AddScriptLPS(1); | 1157 | m_host.AddScriptLPS(1); |
1158 | 1158 | ||
1159 | World.SimChat(Utils.StringToBytes(text), | 1159 | World.SimChat(Utils.StringToBytes(text), |
1160 | ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); | 1160 | ChatTypeEnum.Region, channelID, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); |
1161 | 1161 | ||
1162 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1162 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1163 | if (wComm != null) | 1163 | if (wComm != null) |
1164 | wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); | 1164 | wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); |
1165 | } | 1165 | } |
1166 | 1166 | ||
1167 | public void llRegionSayTo(string target, int channel, string msg) | 1167 | public void llRegionSayTo(string target, int channel, string msg) |
1168 | { | 1168 | { |
1169 | if (msg.Length > 1023) | 1169 | if (msg.Length > 1023) |
1170 | msg = msg.Substring(0, 1023); | 1170 | msg = msg.Substring(0, 1023); |
1171 | 1171 | ||
1172 | m_host.AddScriptLPS(1); | 1172 | m_host.AddScriptLPS(1); |
1173 | 1173 | ||
1174 | if (channel == ScriptBaseClass.DEBUG_CHANNEL) | 1174 | if (channel == ScriptBaseClass.DEBUG_CHANNEL) |
1175 | { | 1175 | { |
1176 | return; | 1176 | return; |
1177 | } | 1177 | } |
1178 | 1178 | ||
1179 | UUID TargetID; | 1179 | UUID TargetID; |
1180 | UUID.TryParse(target, out TargetID); | 1180 | UUID.TryParse(target, out TargetID); |
1181 | 1181 | ||
1182 | World.SimChatToAgent(TargetID, Utils.StringToBytes(msg), | 1182 | World.SimChatToAgent(TargetID, Utils.StringToBytes(msg), |
1183 | channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); | 1183 | channel, m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, true); |
1184 | 1184 | ||
1185 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1185 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1186 | if (wComm != null) | 1186 | if (wComm != null) |
1187 | wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); | 1187 | wComm.DeliverMessageTo(TargetID, channel, m_host.AbsolutePosition, m_host.Name, m_host.UUID, msg); |
1188 | } | 1188 | } |
1189 | 1189 | ||
1190 | public LSL_Integer llListen(int channelID, string name, string ID, string msg) | 1190 | public LSL_Integer llListen(int channelID, string name, string ID, string msg) |
1191 | { | 1191 | { |
1192 | m_host.AddScriptLPS(1); | 1192 | m_host.AddScriptLPS(1); |
1193 | UUID keyID; | 1193 | UUID keyID; |
1194 | UUID.TryParse(ID, out keyID); | 1194 | UUID.TryParse(ID, out keyID); |
1195 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1195 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1196 | if (wComm != null) | 1196 | if (wComm != null) |
1197 | return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg); | 1197 | return wComm.Listen(m_host.LocalId, m_item.ItemID, m_host.UUID, channelID, name, keyID, msg); |
1198 | else | 1198 | else |
1199 | return -1; | 1199 | return -1; |
1200 | } | 1200 | } |
1201 | 1201 | ||
1202 | public void llListenControl(int number, int active) | 1202 | public void llListenControl(int number, int active) |
1203 | { | 1203 | { |
1204 | m_host.AddScriptLPS(1); | 1204 | m_host.AddScriptLPS(1); |
1205 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1205 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1206 | if (wComm != null) | 1206 | if (wComm != null) |
1207 | wComm.ListenControl(m_item.ItemID, number, active); | 1207 | wComm.ListenControl(m_item.ItemID, number, active); |
1208 | } | 1208 | } |
1209 | 1209 | ||
1210 | public void llListenRemove(int number) | 1210 | public void llListenRemove(int number) |
1211 | { | 1211 | { |
1212 | m_host.AddScriptLPS(1); | 1212 | m_host.AddScriptLPS(1); |
1213 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 1213 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
1214 | if (wComm != null) | 1214 | if (wComm != null) |
1215 | wComm.ListenRemove(m_item.ItemID, number); | 1215 | wComm.ListenRemove(m_item.ItemID, number); |
1216 | } | 1216 | } |
1217 | 1217 | ||
1218 | public void llSensor(string name, string id, int type, double range, double arc) | 1218 | public void llSensor(string name, string id, int type, double range, double arc) |
1219 | { | 1219 | { |
1220 | m_host.AddScriptLPS(1); | 1220 | m_host.AddScriptLPS(1); |
1221 | UUID keyID = UUID.Zero; | 1221 | UUID keyID = UUID.Zero; |
1222 | UUID.TryParse(id, out keyID); | 1222 | UUID.TryParse(id, out keyID); |
1223 | 1223 | ||
1224 | AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host); | 1224 | AsyncCommands.SensorRepeatPlugin.SenseOnce(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, m_host); |
1225 | } | 1225 | } |
1226 | 1226 | ||
1227 | public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) | 1227 | public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) |
1228 | { | 1228 | { |
1229 | m_host.AddScriptLPS(1); | 1229 | m_host.AddScriptLPS(1); |
1230 | UUID keyID = UUID.Zero; | 1230 | UUID keyID = UUID.Zero; |
1231 | UUID.TryParse(id, out keyID); | 1231 | UUID.TryParse(id, out keyID); |
1232 | 1232 | ||
1233 | AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host); | 1233 | AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_host.LocalId, m_item.ItemID, name, keyID, type, range, arc, rate, m_host); |
1234 | } | 1234 | } |
1235 | 1235 | ||
1236 | public void llSensorRemove() | 1236 | public void llSensorRemove() |
1237 | { | 1237 | { |
1238 | m_host.AddScriptLPS(1); | 1238 | m_host.AddScriptLPS(1); |
1239 | AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID); | 1239 | AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_host.LocalId, m_item.ItemID); |
1240 | } | 1240 | } |
1241 | 1241 | ||
1242 | public string resolveName(UUID objecUUID) | 1242 | public string resolveName(UUID objecUUID) |
1243 | { | 1243 | { |
1244 | // try avatar username surname | 1244 | // try avatar username surname |
1245 | UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID); | 1245 | UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, objecUUID); |
1246 | if (account != null) | 1246 | if (account != null) |
1247 | { | 1247 | { |
1248 | string avatarname = account.Name; | 1248 | string avatarname = account.Name; |
1249 | return avatarname; | 1249 | return avatarname; |
1250 | } | 1250 | } |
1251 | // try an scene object | 1251 | // try an scene object |
1252 | SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID); | 1252 | SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID); |
1253 | if (SOP != null) | 1253 | if (SOP != null) |
1254 | { | 1254 | { |
1255 | string objectname = SOP.Name; | 1255 | string objectname = SOP.Name; |
1256 | return objectname; | 1256 | return objectname; |
1257 | } | 1257 | } |
1258 | 1258 | ||
1259 | EntityBase SensedObject; | 1259 | EntityBase SensedObject; |
1260 | World.Entities.TryGetValue(objecUUID, out SensedObject); | 1260 | World.Entities.TryGetValue(objecUUID, out SensedObject); |
1261 | 1261 | ||
1262 | if (SensedObject == null) | 1262 | if (SensedObject == null) |
1263 | { | 1263 | { |
1264 | IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>(); | 1264 | IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>(); |
1265 | if (groups != null) | 1265 | if (groups != null) |
1266 | { | 1266 | { |
1267 | GroupRecord gr = groups.GetGroupRecord(objecUUID); | 1267 | GroupRecord gr = groups.GetGroupRecord(objecUUID); |
1268 | if (gr != null) | 1268 | if (gr != null) |
1269 | return gr.GroupName; | 1269 | return gr.GroupName; |
1270 | } | 1270 | } |
1271 | return String.Empty; | 1271 | return String.Empty; |
1272 | } | 1272 | } |
1273 | 1273 | ||
1274 | return SensedObject.Name; | 1274 | return SensedObject.Name; |
1275 | } | 1275 | } |
1276 | 1276 | ||
1277 | public LSL_String llDetectedName(int number) | 1277 | public LSL_String llDetectedName(int number) |
1278 | { | 1278 | { |
1279 | m_host.AddScriptLPS(1); | 1279 | m_host.AddScriptLPS(1); |
1280 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1280 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1281 | if (detectedParams == null) | 1281 | if (detectedParams == null) |
1282 | return String.Empty; | 1282 | return String.Empty; |
1283 | return detectedParams.Name; | 1283 | return detectedParams.Name; |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | public LSL_String llDetectedKey(int number) | 1286 | public LSL_String llDetectedKey(int number) |
1287 | { | 1287 | { |
1288 | m_host.AddScriptLPS(1); | 1288 | m_host.AddScriptLPS(1); |
1289 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1289 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1290 | if (detectedParams == null) | 1290 | if (detectedParams == null) |
1291 | return String.Empty; | 1291 | return String.Empty; |
1292 | return detectedParams.Key.ToString(); | 1292 | return detectedParams.Key.ToString(); |
1293 | } | 1293 | } |
1294 | 1294 | ||
1295 | public LSL_String llDetectedOwner(int number) | 1295 | public LSL_String llDetectedOwner(int number) |
1296 | { | 1296 | { |
1297 | m_host.AddScriptLPS(1); | 1297 | m_host.AddScriptLPS(1); |
1298 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1298 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1299 | if (detectedParams == null) | 1299 | if (detectedParams == null) |
1300 | return String.Empty; | 1300 | return String.Empty; |
1301 | return detectedParams.Owner.ToString(); | 1301 | return detectedParams.Owner.ToString(); |
1302 | } | 1302 | } |
1303 | 1303 | ||
1304 | public LSL_Integer llDetectedType(int number) | 1304 | public LSL_Integer llDetectedType(int number) |
1305 | { | 1305 | { |
1306 | m_host.AddScriptLPS(1); | 1306 | m_host.AddScriptLPS(1); |
1307 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1307 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1308 | if (detectedParams == null) | 1308 | if (detectedParams == null) |
1309 | return 0; | 1309 | return 0; |
1310 | return new LSL_Integer(detectedParams.Type); | 1310 | return new LSL_Integer(detectedParams.Type); |
1311 | } | 1311 | } |
1312 | 1312 | ||
1313 | public LSL_Vector llDetectedPos(int number) | 1313 | public LSL_Vector llDetectedPos(int number) |
1314 | { | 1314 | { |
1315 | m_host.AddScriptLPS(1); | 1315 | m_host.AddScriptLPS(1); |
1316 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1316 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1317 | if (detectedParams == null) | 1317 | if (detectedParams == null) |
1318 | return new LSL_Vector(); | 1318 | return new LSL_Vector(); |
1319 | return detectedParams.Position; | 1319 | return detectedParams.Position; |
1320 | } | 1320 | } |
1321 | 1321 | ||
1322 | public LSL_Vector llDetectedVel(int number) | 1322 | public LSL_Vector llDetectedVel(int number) |
1323 | { | 1323 | { |
1324 | m_host.AddScriptLPS(1); | 1324 | m_host.AddScriptLPS(1); |
1325 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1325 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1326 | if (detectedParams == null) | 1326 | if (detectedParams == null) |
1327 | return new LSL_Vector(); | 1327 | return new LSL_Vector(); |
1328 | return detectedParams.Velocity; | 1328 | return detectedParams.Velocity; |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | public LSL_Vector llDetectedGrab(int number) | 1331 | public LSL_Vector llDetectedGrab(int number) |
1332 | { | 1332 | { |
1333 | m_host.AddScriptLPS(1); | 1333 | m_host.AddScriptLPS(1); |
1334 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1334 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1335 | if (parms == null) | 1335 | if (parms == null) |
1336 | return new LSL_Vector(0, 0, 0); | 1336 | return new LSL_Vector(0, 0, 0); |
1337 | 1337 | ||
1338 | return parms.OffsetPos; | 1338 | return parms.OffsetPos; |
1339 | } | 1339 | } |
1340 | 1340 | ||
1341 | public LSL_Rotation llDetectedRot(int number) | 1341 | public LSL_Rotation llDetectedRot(int number) |
1342 | { | 1342 | { |
1343 | m_host.AddScriptLPS(1); | 1343 | m_host.AddScriptLPS(1); |
1344 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1344 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1345 | if (detectedParams == null) | 1345 | if (detectedParams == null) |
1346 | return new LSL_Rotation(); | 1346 | return new LSL_Rotation(); |
1347 | return detectedParams.Rotation; | 1347 | return detectedParams.Rotation; |
1348 | } | 1348 | } |
1349 | 1349 | ||
1350 | public LSL_Integer llDetectedGroup(int number) | 1350 | public LSL_Integer llDetectedGroup(int number) |
1351 | { | 1351 | { |
1352 | m_host.AddScriptLPS(1); | 1352 | m_host.AddScriptLPS(1); |
1353 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1353 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1354 | if (detectedParams == null) | 1354 | if (detectedParams == null) |
1355 | return new LSL_Integer(0); | 1355 | return new LSL_Integer(0); |
1356 | if (m_host.GroupID == detectedParams.Group) | 1356 | if (m_host.GroupID == detectedParams.Group) |
1357 | return new LSL_Integer(1); | 1357 | return new LSL_Integer(1); |
1358 | return new LSL_Integer(0); | 1358 | return new LSL_Integer(0); |
1359 | } | 1359 | } |
1360 | 1360 | ||
1361 | public LSL_Integer llDetectedLinkNumber(int number) | 1361 | public LSL_Integer llDetectedLinkNumber(int number) |
1362 | { | 1362 | { |
1363 | m_host.AddScriptLPS(1); | 1363 | m_host.AddScriptLPS(1); |
1364 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); | 1364 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_item.ItemID, number); |
1365 | if (parms == null) | 1365 | if (parms == null) |
1366 | return new LSL_Integer(0); | 1366 | return new LSL_Integer(0); |
1367 | 1367 | ||
1368 | return new LSL_Integer(parms.LinkNum); | 1368 | return new LSL_Integer(parms.LinkNum); |
1369 | } | 1369 | } |
1370 | 1370 | ||
1371 | /// <summary> | 1371 | /// <summary> |
1372 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details | 1372 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchBinormal for details |
1373 | /// </summary> | 1373 | /// </summary> |
1374 | public LSL_Vector llDetectedTouchBinormal(int index) | 1374 | public LSL_Vector llDetectedTouchBinormal(int index) |
1375 | { | 1375 | { |
1376 | m_host.AddScriptLPS(1); | 1376 | m_host.AddScriptLPS(1); |
1377 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); | 1377 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); |
1378 | if (detectedParams == null) | 1378 | if (detectedParams == null) |
1379 | return new LSL_Vector(); | 1379 | return new LSL_Vector(); |
1380 | return detectedParams.TouchBinormal; | 1380 | return detectedParams.TouchBinormal; |
1381 | } | 1381 | } |
1382 | 1382 | ||
1383 | /// <summary> | 1383 | /// <summary> |
1384 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details | 1384 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchFace for details |
1385 | /// </summary> | 1385 | /// </summary> |
1386 | public LSL_Integer llDetectedTouchFace(int index) | 1386 | public LSL_Integer llDetectedTouchFace(int index) |
1387 | { | 1387 | { |
1388 | m_host.AddScriptLPS(1); | 1388 | m_host.AddScriptLPS(1); |
1389 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); | 1389 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); |
1390 | if (detectedParams == null) | 1390 | if (detectedParams == null) |
1391 | return new LSL_Integer(-1); | 1391 | return new LSL_Integer(-1); |
1392 | return new LSL_Integer(detectedParams.TouchFace); | 1392 | return new LSL_Integer(detectedParams.TouchFace); |
1393 | } | 1393 | } |
1394 | 1394 | ||
1395 | /// <summary> | 1395 | /// <summary> |
1396 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details | 1396 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchNormal for details |
1397 | /// </summary> | 1397 | /// </summary> |
1398 | public LSL_Vector llDetectedTouchNormal(int index) | 1398 | public LSL_Vector llDetectedTouchNormal(int index) |
1399 | { | 1399 | { |
1400 | m_host.AddScriptLPS(1); | 1400 | m_host.AddScriptLPS(1); |
1401 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); | 1401 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); |
1402 | if (detectedParams == null) | 1402 | if (detectedParams == null) |
1403 | return new LSL_Vector(); | 1403 | return new LSL_Vector(); |
1404 | return detectedParams.TouchNormal; | 1404 | return detectedParams.TouchNormal; |
1405 | } | 1405 | } |
1406 | 1406 | ||
1407 | /// <summary> | 1407 | /// <summary> |
1408 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details | 1408 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchPos for details |
1409 | /// </summary> | 1409 | /// </summary> |
1410 | public LSL_Vector llDetectedTouchPos(int index) | 1410 | public LSL_Vector llDetectedTouchPos(int index) |
1411 | { | 1411 | { |
1412 | m_host.AddScriptLPS(1); | 1412 | m_host.AddScriptLPS(1); |
1413 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); | 1413 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); |
1414 | if (detectedParams == null) | 1414 | if (detectedParams == null) |
1415 | return new LSL_Vector(); | 1415 | return new LSL_Vector(); |
1416 | return detectedParams.TouchPos; | 1416 | return detectedParams.TouchPos; |
1417 | } | 1417 | } |
1418 | 1418 | ||
1419 | /// <summary> | 1419 | /// <summary> |
1420 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details | 1420 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchST for details |
1421 | /// </summary> | 1421 | /// </summary> |
1422 | public LSL_Vector llDetectedTouchST(int index) | 1422 | public LSL_Vector llDetectedTouchST(int index) |
1423 | { | 1423 | { |
1424 | m_host.AddScriptLPS(1); | 1424 | m_host.AddScriptLPS(1); |
1425 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); | 1425 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); |
1426 | if (detectedParams == null) | 1426 | if (detectedParams == null) |
1427 | return new LSL_Vector(-1.0, -1.0, 0.0); | 1427 | return new LSL_Vector(-1.0, -1.0, 0.0); |
1428 | return detectedParams.TouchST; | 1428 | return detectedParams.TouchST; |
1429 | } | 1429 | } |
1430 | 1430 | ||
1431 | /// <summary> | 1431 | /// <summary> |
1432 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details | 1432 | /// See http://wiki.secondlife.com/wiki/LlDetectedTouchUV for details |
1433 | /// </summary> | 1433 | /// </summary> |
1434 | public LSL_Vector llDetectedTouchUV(int index) | 1434 | public LSL_Vector llDetectedTouchUV(int index) |
1435 | { | 1435 | { |
1436 | m_host.AddScriptLPS(1); | 1436 | m_host.AddScriptLPS(1); |
1437 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); | 1437 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, index); |
1438 | if (detectedParams == null) | 1438 | if (detectedParams == null) |
1439 | return new LSL_Vector(-1.0, -1.0, 0.0); | 1439 | return new LSL_Vector(-1.0, -1.0, 0.0); |
1440 | return detectedParams.TouchUV; | 1440 | return detectedParams.TouchUV; |
1441 | } | 1441 | } |
1442 | 1442 | ||
1443 | public virtual void llDie() | 1443 | public virtual void llDie() |
1444 | { | 1444 | { |
1445 | m_host.AddScriptLPS(1); | 1445 | m_host.AddScriptLPS(1); |
1446 | throw new SelfDeleteException(); | 1446 | throw new SelfDeleteException(); |
1447 | } | 1447 | } |
1448 | 1448 | ||
1449 | public LSL_Float llGround(LSL_Vector offset) | 1449 | public LSL_Float llGround(LSL_Vector offset) |
1450 | { | 1450 | { |
1451 | m_host.AddScriptLPS(1); | 1451 | m_host.AddScriptLPS(1); |
1452 | Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; | 1452 | Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; |
1453 | 1453 | ||
1454 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. | 1454 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. |
1455 | LSL_Vector vsn = llGroundNormal(offset); | 1455 | LSL_Vector vsn = llGroundNormal(offset); |
1456 | 1456 | ||
1457 | // Clamp to valid position | 1457 | // Clamp to valid position |
1458 | if (pos.X < 0) | 1458 | if (pos.X < 0) |
1459 | pos.X = 0; | 1459 | pos.X = 0; |
1460 | else if (pos.X >= World.Heightmap.Width) | 1460 | else if (pos.X >= World.Heightmap.Width) |
1461 | pos.X = World.Heightmap.Width - 1; | 1461 | pos.X = World.Heightmap.Width - 1; |
1462 | if (pos.Y < 0) | 1462 | if (pos.Y < 0) |
1463 | pos.Y = 0; | 1463 | pos.Y = 0; |
1464 | else if (pos.Y >= World.Heightmap.Height) | 1464 | else if (pos.Y >= World.Heightmap.Height) |
1465 | pos.Y = World.Heightmap.Height - 1; | 1465 | pos.Y = World.Heightmap.Height - 1; |
1466 | 1466 | ||
1467 | //Get the height for the integer coordinates from the Heightmap | 1467 | //Get the height for the integer coordinates from the Heightmap |
1468 | float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y]; | 1468 | float baseheight = (float)World.Heightmap[(int)pos.X, (int)pos.Y]; |
1469 | 1469 | ||
1470 | //Calculate the difference between the actual coordinates and the integer coordinates | 1470 | //Calculate the difference between the actual coordinates and the integer coordinates |
1471 | float xdiff = pos.X - (float)((int)pos.X); | 1471 | float xdiff = pos.X - (float)((int)pos.X); |
1472 | float ydiff = pos.Y - (float)((int)pos.Y); | 1472 | float ydiff = pos.Y - (float)((int)pos.Y); |
1473 | 1473 | ||
1474 | //Use the equation of the tangent plane to adjust the height to account for slope | 1474 | //Use the equation of the tangent plane to adjust the height to account for slope |
1475 | 1475 | ||
1476 | return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight; | 1476 | return (((vsn.x * xdiff) + (vsn.y * ydiff)) / (-1 * vsn.z)) + baseheight; |
1477 | } | 1477 | } |
1478 | 1478 | ||
1479 | public LSL_Float llCloud(LSL_Vector offset) | 1479 | public LSL_Float llCloud(LSL_Vector offset) |
1480 | { | 1480 | { |
1481 | m_host.AddScriptLPS(1); | 1481 | m_host.AddScriptLPS(1); |
1482 | float cloudCover = 0f; | 1482 | float cloudCover = 0f; |
1483 | ICloudModule module = World.RequestModuleInterface<ICloudModule>(); | 1483 | ICloudModule module = World.RequestModuleInterface<ICloudModule>(); |
1484 | if (module != null) | 1484 | if (module != null) |
1485 | { | 1485 | { |
1486 | Vector3 pos = m_host.GetWorldPosition(); | 1486 | Vector3 pos = m_host.GetWorldPosition(); |
1487 | int x = (int)(pos.X + offset.x); | 1487 | int x = (int)(pos.X + offset.x); |
1488 | int y = (int)(pos.Y + offset.y); | 1488 | int y = (int)(pos.Y + offset.y); |
1489 | 1489 | ||
1490 | cloudCover = module.CloudCover(x, y, 0); | 1490 | cloudCover = module.CloudCover(x, y, 0); |
1491 | 1491 | ||
1492 | } | 1492 | } |
1493 | return cloudCover; | 1493 | return cloudCover; |
1494 | } | 1494 | } |
1495 | 1495 | ||
1496 | public LSL_Vector llWind(LSL_Vector offset) | 1496 | public LSL_Vector llWind(LSL_Vector offset) |
1497 | { | 1497 | { |
1498 | m_host.AddScriptLPS(1); | 1498 | m_host.AddScriptLPS(1); |
1499 | LSL_Vector wind = new LSL_Vector(0, 0, 0); | 1499 | LSL_Vector wind = new LSL_Vector(0, 0, 0); |
1500 | IWindModule module = World.RequestModuleInterface<IWindModule>(); | 1500 | IWindModule module = World.RequestModuleInterface<IWindModule>(); |
1501 | if (module != null) | 1501 | if (module != null) |
1502 | { | 1502 | { |
1503 | Vector3 pos = m_host.GetWorldPosition(); | 1503 | Vector3 pos = m_host.GetWorldPosition(); |
1504 | int x = (int)(pos.X + offset.x); | 1504 | int x = (int)(pos.X + offset.x); |
1505 | int y = (int)(pos.Y + offset.y); | 1505 | int y = (int)(pos.Y + offset.y); |
1506 | 1506 | ||
1507 | Vector3 windSpeed = module.WindSpeed(x, y, 0); | 1507 | Vector3 windSpeed = module.WindSpeed(x, y, 0); |
1508 | 1508 | ||
1509 | wind.x = windSpeed.X; | 1509 | wind.x = windSpeed.X; |
1510 | wind.y = windSpeed.Y; | 1510 | wind.y = windSpeed.Y; |
1511 | } | 1511 | } |
1512 | return wind; | 1512 | return wind; |
1513 | } | 1513 | } |
1514 | 1514 | ||
1515 | public void llSetStatus(int status, int value) | 1515 | public void llSetStatus(int status, int value) |
1516 | { | 1516 | { |
1517 | m_host.AddScriptLPS(1); | 1517 | m_host.AddScriptLPS(1); |
1518 | 1518 | ||
1519 | int statusrotationaxis = 0; | 1519 | int statusrotationaxis = 0; |
1520 | 1520 | ||
1521 | if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS) | 1521 | if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS) |
1522 | { | 1522 | { |
1523 | if (value != 0) | 1523 | if (value != 0) |
1524 | { | 1524 | { |
1525 | SceneObjectGroup group = m_host.ParentGroup; | 1525 | SceneObjectGroup group = m_host.ParentGroup; |
1526 | bool allow = true; | 1526 | bool allow = true; |
1527 | 1527 | ||
1528 | foreach (SceneObjectPart part in group.Parts) | 1528 | foreach (SceneObjectPart part in group.Parts) |
1529 | { | 1529 | { |
1530 | if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) | 1530 | if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) |
1531 | { | 1531 | { |
1532 | allow = false; | 1532 | allow = false; |
1533 | break; | 1533 | break; |
1534 | } | 1534 | } |
1535 | } | 1535 | } |
1536 | 1536 | ||
1537 | if (!allow) | 1537 | if (!allow) |
1538 | return; | 1538 | return; |
1539 | 1539 | ||
1540 | m_host.ScriptSetPhysicsStatus(true); | 1540 | m_host.ScriptSetPhysicsStatus(true); |
1541 | } | 1541 | } |
1542 | else | 1542 | else |
1543 | { | 1543 | { |
1544 | m_host.ScriptSetPhysicsStatus(false); | 1544 | m_host.ScriptSetPhysicsStatus(false); |
1545 | } | 1545 | } |
1546 | } | 1546 | } |
1547 | 1547 | ||
1548 | if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM) | 1548 | if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM) |
1549 | { | 1549 | { |
1550 | m_host.ParentGroup.ScriptSetPhantomStatus(value != 0); | 1550 | m_host.ParentGroup.ScriptSetPhantomStatus(value != 0); |
1551 | } | 1551 | } |
1552 | 1552 | ||
1553 | if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS) | 1553 | if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS) |
1554 | { | 1554 | { |
1555 | m_host.AddFlag(PrimFlags.CastShadows); | 1555 | m_host.AddFlag(PrimFlags.CastShadows); |
1556 | } | 1556 | } |
1557 | 1557 | ||
1558 | if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X) | 1558 | if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X) |
1559 | { | 1559 | { |
1560 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X; | 1560 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X; |
1561 | } | 1561 | } |
1562 | 1562 | ||
1563 | if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y) | 1563 | if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y) |
1564 | { | 1564 | { |
1565 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y; | 1565 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y; |
1566 | } | 1566 | } |
1567 | 1567 | ||
1568 | if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z) | 1568 | if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z) |
1569 | { | 1569 | { |
1570 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z; | 1570 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z; |
1571 | } | 1571 | } |
1572 | 1572 | ||
1573 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) | 1573 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) |
1574 | m_host.BlockGrab = value != 0; | 1574 | m_host.BlockGrab = value != 0; |
1575 | 1575 | ||
1576 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) | 1576 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) == ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT) |
1577 | m_host.ParentGroup.BlockGrabOverride = value != 0; | 1577 | m_host.ParentGroup.BlockGrabOverride = value != 0; |
1578 | 1578 | ||
1579 | if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) | 1579 | if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) |
1580 | { | 1580 | { |
1581 | if (value != 0) | 1581 | if (value != 0) |
1582 | m_host.SetDieAtEdge(true); | 1582 | m_host.SetDieAtEdge(true); |
1583 | else | 1583 | else |
1584 | m_host.SetDieAtEdge(false); | 1584 | m_host.SetDieAtEdge(false); |
1585 | } | 1585 | } |
1586 | 1586 | ||
1587 | if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE) | 1587 | if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE) |
1588 | { | 1588 | { |
1589 | if (value != 0) | 1589 | if (value != 0) |
1590 | m_host.SetReturnAtEdge(true); | 1590 | m_host.SetReturnAtEdge(true); |
1591 | else | 1591 | else |
1592 | m_host.SetReturnAtEdge(false); | 1592 | m_host.SetReturnAtEdge(false); |
1593 | } | 1593 | } |
1594 | 1594 | ||
1595 | if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX) | 1595 | if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX) |
1596 | { | 1596 | { |
1597 | if (value != 0) | 1597 | if (value != 0) |
1598 | m_host.SetStatusSandbox(true); | 1598 | m_host.SetStatusSandbox(true); |
1599 | else | 1599 | else |
1600 | m_host.SetStatusSandbox(false); | 1600 | m_host.SetStatusSandbox(false); |
1601 | } | 1601 | } |
1602 | 1602 | ||
1603 | if (statusrotationaxis != 0) | 1603 | if (statusrotationaxis != 0) |
1604 | { | 1604 | { |
1605 | m_host.SetAxisRotation(statusrotationaxis, value); | 1605 | m_host.SetAxisRotation(statusrotationaxis, value); |
1606 | } | 1606 | } |
1607 | } | 1607 | } |
1608 | 1608 | ||
1609 | private bool IsPhysical() | 1609 | private bool IsPhysical() |
1610 | { | 1610 | { |
1611 | return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics); | 1611 | return ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics); |
1612 | } | 1612 | } |
1613 | 1613 | ||
1614 | public LSL_Integer llGetStatus(int status) | 1614 | public LSL_Integer llGetStatus(int status) |
1615 | { | 1615 | { |
1616 | m_host.AddScriptLPS(1); | 1616 | m_host.AddScriptLPS(1); |
1617 | // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString()); | 1617 | // m_log.Debug(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString()); |
1618 | switch (status) | 1618 | switch (status) |
1619 | { | 1619 | { |
1620 | case ScriptBaseClass.STATUS_PHYSICS: | 1620 | case ScriptBaseClass.STATUS_PHYSICS: |
1621 | return IsPhysical() ? 1 : 0; | 1621 | return IsPhysical() ? 1 : 0; |
1622 | 1622 | ||
1623 | case ScriptBaseClass.STATUS_PHANTOM: | 1623 | case ScriptBaseClass.STATUS_PHANTOM: |
1624 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) | 1624 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) |
1625 | { | 1625 | { |
1626 | return 1; | 1626 | return 1; |
1627 | } | 1627 | } |
1628 | return 0; | 1628 | return 0; |
1629 | 1629 | ||
1630 | case ScriptBaseClass.STATUS_CAST_SHADOWS: | 1630 | case ScriptBaseClass.STATUS_CAST_SHADOWS: |
1631 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows) | 1631 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows) |
1632 | { | 1632 | { |
1633 | return 1; | 1633 | return 1; |
1634 | } | 1634 | } |
1635 | return 0; | 1635 | return 0; |
1636 | 1636 | ||
1637 | case ScriptBaseClass.STATUS_BLOCK_GRAB: | 1637 | case ScriptBaseClass.STATUS_BLOCK_GRAB: |
1638 | return m_host.BlockGrab ? 1 : 0; | 1638 | return m_host.BlockGrab ? 1 : 0; |
1639 | 1639 | ||
1640 | case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT: | 1640 | case ScriptBaseClass.STATUS_BLOCK_GRAB_OBJECT: |
1641 | return m_host.ParentGroup.BlockGrabOverride ? 1 : 0; | 1641 | return m_host.ParentGroup.BlockGrabOverride ? 1 : 0; |
1642 | 1642 | ||
1643 | case ScriptBaseClass.STATUS_DIE_AT_EDGE: | 1643 | case ScriptBaseClass.STATUS_DIE_AT_EDGE: |
1644 | if (m_host.GetDieAtEdge()) | 1644 | if (m_host.GetDieAtEdge()) |
1645 | return 1; | 1645 | return 1; |
1646 | else | 1646 | else |
1647 | return 0; | 1647 | return 0; |
1648 | 1648 | ||
1649 | case ScriptBaseClass.STATUS_RETURN_AT_EDGE: | 1649 | case ScriptBaseClass.STATUS_RETURN_AT_EDGE: |
1650 | if (m_host.GetReturnAtEdge()) | 1650 | if (m_host.GetReturnAtEdge()) |
1651 | return 1; | 1651 | return 1; |
1652 | else | 1652 | else |
1653 | return 0; | 1653 | return 0; |
1654 | 1654 | ||
1655 | case ScriptBaseClass.STATUS_ROTATE_X: | 1655 | case ScriptBaseClass.STATUS_ROTATE_X: |
1656 | // if (m_host.GetAxisRotation(2) != 0) | 1656 | // if (m_host.GetAxisRotation(2) != 0) |
1657 | if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0) | 1657 | if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0) |
1658 | return 1; | 1658 | return 1; |
1659 | else | 1659 | else |
1660 | return 0; | 1660 | return 0; |
1661 | 1661 | ||
1662 | case ScriptBaseClass.STATUS_ROTATE_Y: | 1662 | case ScriptBaseClass.STATUS_ROTATE_Y: |
1663 | if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0) | 1663 | if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0) |
1664 | return 1; | 1664 | return 1; |
1665 | else | 1665 | else |
1666 | return 0; | 1666 | return 0; |
1667 | 1667 | ||
1668 | case ScriptBaseClass.STATUS_ROTATE_Z: | 1668 | case ScriptBaseClass.STATUS_ROTATE_Z: |
1669 | if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0) | 1669 | if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0) |
1670 | return 1; | 1670 | return 1; |
1671 | else | 1671 | else |
1672 | return 0; | 1672 | return 0; |
1673 | 1673 | ||
1674 | case ScriptBaseClass.STATUS_SANDBOX: | 1674 | case ScriptBaseClass.STATUS_SANDBOX: |
1675 | if (m_host.GetStatusSandbox()) | 1675 | if (m_host.GetStatusSandbox()) |
1676 | return 1; | 1676 | return 1; |
1677 | else | 1677 | else |
1678 | return 0; | 1678 | return 0; |
1679 | } | 1679 | } |
1680 | return 0; | 1680 | return 0; |
1681 | } | 1681 | } |
1682 | 1682 | ||
1683 | public void llSetScale(LSL_Vector scale) | 1683 | public void llSetScale(LSL_Vector scale) |
1684 | { | 1684 | { |
1685 | m_host.AddScriptLPS(1); | 1685 | m_host.AddScriptLPS(1); |
1686 | SetScale(m_host, scale); | 1686 | SetScale(m_host, scale); |
1687 | } | 1687 | } |
1688 | 1688 | ||
1689 | protected void SetScale(SceneObjectPart part, LSL_Vector scale) | 1689 | protected void SetScale(SceneObjectPart part, LSL_Vector scale) |
1690 | { | 1690 | { |
1691 | // TODO: this needs to trigger a persistance save as well | 1691 | // TODO: this needs to trigger a persistance save as well |
1692 | if (part == null || part.ParentGroup.IsDeleted) | 1692 | if (part == null || part.ParentGroup.IsDeleted) |
1693 | return; | 1693 | return; |
1694 | 1694 | ||
1695 | // First we need to check whether or not we need to clamp the size of a physics-enabled prim | 1695 | // First we need to check whether or not we need to clamp the size of a physics-enabled prim |
1696 | PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; | 1696 | PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; |
1697 | if (pa != null && pa.IsPhysical) | 1697 | if (pa != null && pa.IsPhysical) |
1698 | { | 1698 | { |
1699 | scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); | 1699 | scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); |
1700 | scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); | 1700 | scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); |
1701 | scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); | 1701 | scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); |
1702 | } | 1702 | } |
1703 | else | 1703 | else |
1704 | { | 1704 | { |
1705 | // If not physical, then we clamp the scale to the non-physical min/max | 1705 | // If not physical, then we clamp the scale to the non-physical min/max |
1706 | scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); | 1706 | scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); |
1707 | scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); | 1707 | scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); |
1708 | scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); | 1708 | scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); |
1709 | } | 1709 | } |
1710 | 1710 | ||
1711 | Vector3 tmp = part.Scale; | 1711 | Vector3 tmp = part.Scale; |
1712 | tmp.X = (float)scale.x; | 1712 | tmp.X = (float)scale.x; |
1713 | tmp.Y = (float)scale.y; | 1713 | tmp.Y = (float)scale.y; |
1714 | tmp.Z = (float)scale.z; | 1714 | tmp.Z = (float)scale.z; |
1715 | part.Scale = tmp; | 1715 | part.Scale = tmp; |
1716 | part.SendFullUpdateToAllClients(); | 1716 | part.SendFullUpdateToAllClients(); |
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | public LSL_Vector llGetScale() | 1719 | public LSL_Vector llGetScale() |
1720 | { | 1720 | { |
1721 | m_host.AddScriptLPS(1); | 1721 | m_host.AddScriptLPS(1); |
1722 | return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); | 1722 | return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); |
1723 | } | 1723 | } |
1724 | 1724 | ||
1725 | public void llSetClickAction(int action) | 1725 | public void llSetClickAction(int action) |
1726 | { | 1726 | { |
1727 | m_host.AddScriptLPS(1); | 1727 | m_host.AddScriptLPS(1); |
1728 | m_host.ClickAction = (byte)action; | 1728 | m_host.ClickAction = (byte)action; |
1729 | m_host.ParentGroup.HasGroupChanged = true; | 1729 | m_host.ParentGroup.HasGroupChanged = true; |
1730 | m_host.ScheduleFullUpdate(); | 1730 | m_host.ScheduleFullUpdate(); |
1731 | return; | 1731 | return; |
1732 | } | 1732 | } |
1733 | 1733 | ||
1734 | public void llSetColor(LSL_Vector color, int face) | 1734 | public void llSetColor(LSL_Vector color, int face) |
1735 | { | 1735 | { |
1736 | m_host.AddScriptLPS(1); | 1736 | m_host.AddScriptLPS(1); |
1737 | 1737 | ||
1738 | if (face == ScriptBaseClass.ALL_SIDES) | 1738 | if (face == ScriptBaseClass.ALL_SIDES) |
1739 | face = SceneObjectPart.ALL_SIDES; | 1739 | face = SceneObjectPart.ALL_SIDES; |
1740 | 1740 | ||
1741 | m_host.SetFaceColorAlpha(face, color, null); | 1741 | m_host.SetFaceColorAlpha(face, color, null); |
1742 | } | 1742 | } |
1743 | 1743 | ||
1744 | public void llSetContentType(LSL_Key id, LSL_Integer type) | 1744 | public void llSetContentType(LSL_Key id, LSL_Integer type) |
1745 | { | 1745 | { |
1746 | m_host.AddScriptLPS(1); | 1746 | m_host.AddScriptLPS(1); |
1747 | 1747 | ||
1748 | if (m_UrlModule == null) | 1748 | if (m_UrlModule == null) |
1749 | return; | 1749 | return; |
1750 | 1750 | ||
1751 | // Make sure the content type is text/plain to start with | 1751 | // Make sure the content type is text/plain to start with |
1752 | m_UrlModule.HttpContentType(new UUID(id), "text/plain"); | 1752 | m_UrlModule.HttpContentType(new UUID(id), "text/plain"); |
1753 | 1753 | ||
1754 | // Is the object owner online and in the region | 1754 | // Is the object owner online and in the region |
1755 | ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID); | 1755 | ScenePresence agent = World.GetScenePresence(m_host.ParentGroup.OwnerID); |
1756 | if (agent == null || agent.IsChildAgent) | 1756 | if (agent == null || agent.IsChildAgent) |
1757 | return; // Fail if the owner is not in the same region | 1757 | return; // Fail if the owner is not in the same region |
1758 | 1758 | ||
1759 | // Is it the embeded browser? | 1759 | // Is it the embeded browser? |
1760 | string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent"); | 1760 | string userAgent = m_UrlModule.GetHttpHeader(new UUID(id), "user-agent"); |
1761 | if (userAgent.IndexOf("SecondLife") < 0) | 1761 | if (userAgent.IndexOf("SecondLife") < 0) |
1762 | return; // Not the embedded browser. Is this check good enough? | 1762 | return; // Not the embedded browser. Is this check good enough? |
1763 | 1763 | ||
1764 | // Use the IP address of the client and check against the request | 1764 | // Use the IP address of the client and check against the request |
1765 | // seperate logins from the same IP will allow all of them to get non-text/plain as long | 1765 | // seperate logins from the same IP will allow all of them to get non-text/plain as long |
1766 | // as the owner is in the region. Same as SL! | 1766 | // as the owner is in the region. Same as SL! |
1767 | string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString(); | 1767 | string logonFromIPAddress = agent.ControllingClient.RemoteEndPoint.Address.ToString(); |
1768 | string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr"); | 1768 | string requestFromIPAddress = m_UrlModule.GetHttpHeader(new UUID(id), "remote_addr"); |
1769 | //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'"); | 1769 | //m_log.Debug("IP from header='" + requestFromIPAddress + "' IP from endpoint='" + logonFromIPAddress + "'"); |
1770 | if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "") | 1770 | if (requestFromIPAddress == null || requestFromIPAddress.Trim() == "") |
1771 | return; | 1771 | return; |
1772 | if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "") | 1772 | if (logonFromIPAddress == null || logonFromIPAddress.Trim() == "") |
1773 | return; | 1773 | return; |
1774 | 1774 | ||
1775 | // If the request isnt from the same IP address then the request cannot be from the owner | 1775 | // If the request isnt from the same IP address then the request cannot be from the owner |
1776 | if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim())) | 1776 | if (!requestFromIPAddress.Trim().Equals(logonFromIPAddress.Trim())) |
1777 | return; | 1777 | return; |
1778 | 1778 | ||
1779 | switch (type) | 1779 | switch (type) |
1780 | { | 1780 | { |
1781 | case ScriptBaseClass.CONTENT_TYPE_HTML: | 1781 | case ScriptBaseClass.CONTENT_TYPE_HTML: |
1782 | m_UrlModule.HttpContentType(new UUID(id), "text/html"); | 1782 | m_UrlModule.HttpContentType(new UUID(id), "text/html"); |
1783 | break; | 1783 | break; |
1784 | case ScriptBaseClass.CONTENT_TYPE_XML: | 1784 | case ScriptBaseClass.CONTENT_TYPE_XML: |
1785 | m_UrlModule.HttpContentType(new UUID(id), "application/xml"); | 1785 | m_UrlModule.HttpContentType(new UUID(id), "application/xml"); |
1786 | break; | 1786 | break; |
1787 | case ScriptBaseClass.CONTENT_TYPE_XHTML: | 1787 | case ScriptBaseClass.CONTENT_TYPE_XHTML: |
1788 | m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml"); | 1788 | m_UrlModule.HttpContentType(new UUID(id), "application/xhtml+xml"); |
1789 | break; | 1789 | break; |
1790 | case ScriptBaseClass.CONTENT_TYPE_ATOM: | 1790 | case ScriptBaseClass.CONTENT_TYPE_ATOM: |
1791 | m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml"); | 1791 | m_UrlModule.HttpContentType(new UUID(id), "application/atom+xml"); |
1792 | break; | 1792 | break; |
1793 | case ScriptBaseClass.CONTENT_TYPE_JSON: | 1793 | case ScriptBaseClass.CONTENT_TYPE_JSON: |
1794 | m_UrlModule.HttpContentType(new UUID(id), "application/json"); | 1794 | m_UrlModule.HttpContentType(new UUID(id), "application/json"); |
1795 | break; | 1795 | break; |
1796 | case ScriptBaseClass.CONTENT_TYPE_LLSD: | 1796 | case ScriptBaseClass.CONTENT_TYPE_LLSD: |
1797 | m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml"); | 1797 | m_UrlModule.HttpContentType(new UUID(id), "application/llsd+xml"); |
1798 | break; | 1798 | break; |
1799 | case ScriptBaseClass.CONTENT_TYPE_FORM: | 1799 | case ScriptBaseClass.CONTENT_TYPE_FORM: |
1800 | m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded"); | 1800 | m_UrlModule.HttpContentType(new UUID(id), "application/x-www-form-urlencoded"); |
1801 | break; | 1801 | break; |
1802 | case ScriptBaseClass.CONTENT_TYPE_RSS: | 1802 | case ScriptBaseClass.CONTENT_TYPE_RSS: |
1803 | m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml"); | 1803 | m_UrlModule.HttpContentType(new UUID(id), "application/rss+xml"); |
1804 | break; | 1804 | break; |
1805 | default: | 1805 | default: |
1806 | m_UrlModule.HttpContentType(new UUID(id), "text/plain"); | 1806 | m_UrlModule.HttpContentType(new UUID(id), "text/plain"); |
1807 | break; | 1807 | break; |
1808 | } | 1808 | } |
1809 | } | 1809 | } |
1810 | 1810 | ||
1811 | public void SetTexGen(SceneObjectPart part, int face,int style) | 1811 | public void SetTexGen(SceneObjectPart part, int face,int style) |
1812 | { | 1812 | { |
1813 | Primitive.TextureEntry tex = part.Shape.Textures; | 1813 | Primitive.TextureEntry tex = part.Shape.Textures; |
1814 | MappingType textype; | 1814 | MappingType textype; |
1815 | textype = MappingType.Default; | 1815 | textype = MappingType.Default; |
1816 | if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR) | 1816 | if (style == (int)ScriptBaseClass.PRIM_TEXGEN_PLANAR) |
1817 | textype = MappingType.Planar; | 1817 | textype = MappingType.Planar; |
1818 | 1818 | ||
1819 | if (face >= 0 && face < GetNumberOfSides(part)) | 1819 | if (face >= 0 && face < GetNumberOfSides(part)) |
1820 | { | 1820 | { |
1821 | tex.CreateFace((uint) face); | 1821 | tex.CreateFace((uint) face); |
1822 | tex.FaceTextures[face].TexMapType = textype; | 1822 | tex.FaceTextures[face].TexMapType = textype; |
1823 | part.UpdateTextureEntry(tex.GetBytes()); | 1823 | part.UpdateTextureEntry(tex.GetBytes()); |
1824 | return; | 1824 | return; |
1825 | } | 1825 | } |
1826 | else if (face == ScriptBaseClass.ALL_SIDES) | 1826 | else if (face == ScriptBaseClass.ALL_SIDES) |
1827 | { | 1827 | { |
1828 | for (uint i = 0; i < GetNumberOfSides(part); i++) | 1828 | for (uint i = 0; i < GetNumberOfSides(part); i++) |
1829 | { | 1829 | { |
1830 | if (tex.FaceTextures[i] != null) | 1830 | if (tex.FaceTextures[i] != null) |
1831 | { | 1831 | { |
1832 | tex.FaceTextures[i].TexMapType = textype; | 1832 | tex.FaceTextures[i].TexMapType = textype; |
1833 | } | 1833 | } |
1834 | tex.DefaultTexture.TexMapType = textype; | 1834 | tex.DefaultTexture.TexMapType = textype; |
1835 | } | 1835 | } |
1836 | part.UpdateTextureEntry(tex.GetBytes()); | 1836 | part.UpdateTextureEntry(tex.GetBytes()); |
1837 | return; | 1837 | return; |
1838 | } | 1838 | } |
1839 | } | 1839 | } |
1840 | 1840 | ||
1841 | public void SetGlow(SceneObjectPart part, int face, float glow) | 1841 | public void SetGlow(SceneObjectPart part, int face, float glow) |
1842 | { | 1842 | { |
1843 | Primitive.TextureEntry tex = part.Shape.Textures; | 1843 | Primitive.TextureEntry tex = part.Shape.Textures; |
1844 | if (face >= 0 && face < GetNumberOfSides(part)) | 1844 | if (face >= 0 && face < GetNumberOfSides(part)) |
1845 | { | 1845 | { |
1846 | tex.CreateFace((uint) face); | 1846 | tex.CreateFace((uint) face); |
1847 | tex.FaceTextures[face].Glow = glow; | 1847 | tex.FaceTextures[face].Glow = glow; |
1848 | part.UpdateTextureEntry(tex.GetBytes()); | 1848 | part.UpdateTextureEntry(tex.GetBytes()); |
1849 | return; | 1849 | return; |
1850 | } | 1850 | } |
1851 | else if (face == ScriptBaseClass.ALL_SIDES) | 1851 | else if (face == ScriptBaseClass.ALL_SIDES) |
1852 | { | 1852 | { |
1853 | for (uint i = 0; i < GetNumberOfSides(part); i++) | 1853 | for (uint i = 0; i < GetNumberOfSides(part); i++) |
1854 | { | 1854 | { |
1855 | if (tex.FaceTextures[i] != null) | 1855 | if (tex.FaceTextures[i] != null) |
1856 | { | 1856 | { |
1857 | tex.FaceTextures[i].Glow = glow; | 1857 | tex.FaceTextures[i].Glow = glow; |
1858 | } | 1858 | } |
1859 | tex.DefaultTexture.Glow = glow; | 1859 | tex.DefaultTexture.Glow = glow; |
1860 | } | 1860 | } |
1861 | part.UpdateTextureEntry(tex.GetBytes()); | 1861 | part.UpdateTextureEntry(tex.GetBytes()); |
1862 | return; | 1862 | return; |
1863 | } | 1863 | } |
1864 | } | 1864 | } |
1865 | 1865 | ||
1866 | public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) | 1866 | public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) |
1867 | { | 1867 | { |
1868 | 1868 | ||
1869 | Shininess sval = new Shininess(); | 1869 | Shininess sval = new Shininess(); |
1870 | 1870 | ||
1871 | switch (shiny) | 1871 | switch (shiny) |
1872 | { | 1872 | { |
1873 | case 0: | 1873 | case 0: |
1874 | sval = Shininess.None; | 1874 | sval = Shininess.None; |
1875 | break; | 1875 | break; |
1876 | case 1: | 1876 | case 1: |
1877 | sval = Shininess.Low; | 1877 | sval = Shininess.Low; |
1878 | break; | 1878 | break; |
1879 | case 2: | 1879 | case 2: |
1880 | sval = Shininess.Medium; | 1880 | sval = Shininess.Medium; |
1881 | break; | 1881 | break; |
1882 | case 3: | 1882 | case 3: |
1883 | sval = Shininess.High; | 1883 | sval = Shininess.High; |
1884 | break; | 1884 | break; |
1885 | default: | 1885 | default: |
1886 | sval = Shininess.None; | 1886 | sval = Shininess.None; |
1887 | break; | 1887 | break; |
1888 | } | 1888 | } |
1889 | 1889 | ||
1890 | Primitive.TextureEntry tex = part.Shape.Textures; | 1890 | Primitive.TextureEntry tex = part.Shape.Textures; |
1891 | if (face >= 0 && face < GetNumberOfSides(part)) | 1891 | if (face >= 0 && face < GetNumberOfSides(part)) |
1892 | { | 1892 | { |
1893 | tex.CreateFace((uint) face); | 1893 | tex.CreateFace((uint) face); |
1894 | tex.FaceTextures[face].Shiny = sval; | 1894 | tex.FaceTextures[face].Shiny = sval; |
1895 | tex.FaceTextures[face].Bump = bump; | 1895 | tex.FaceTextures[face].Bump = bump; |
1896 | part.UpdateTextureEntry(tex.GetBytes()); | 1896 | part.UpdateTextureEntry(tex.GetBytes()); |
1897 | return; | 1897 | return; |
1898 | } | 1898 | } |
1899 | else if (face == ScriptBaseClass.ALL_SIDES) | 1899 | else if (face == ScriptBaseClass.ALL_SIDES) |
1900 | { | 1900 | { |
1901 | for (uint i = 0; i < GetNumberOfSides(part); i++) | 1901 | for (uint i = 0; i < GetNumberOfSides(part); i++) |
1902 | { | 1902 | { |
1903 | if (tex.FaceTextures[i] != null) | 1903 | if (tex.FaceTextures[i] != null) |
1904 | { | 1904 | { |
1905 | tex.FaceTextures[i].Shiny = sval; | 1905 | tex.FaceTextures[i].Shiny = sval; |
1906 | tex.FaceTextures[i].Bump = bump; | 1906 | tex.FaceTextures[i].Bump = bump; |
1907 | } | 1907 | } |
1908 | tex.DefaultTexture.Shiny = sval; | 1908 | tex.DefaultTexture.Shiny = sval; |
1909 | tex.DefaultTexture.Bump = bump; | 1909 | tex.DefaultTexture.Bump = bump; |
1910 | } | 1910 | } |
1911 | part.UpdateTextureEntry(tex.GetBytes()); | 1911 | part.UpdateTextureEntry(tex.GetBytes()); |
1912 | return; | 1912 | return; |
1913 | } | 1913 | } |
1914 | } | 1914 | } |
1915 | 1915 | ||
1916 | public void SetFullBright(SceneObjectPart part, int face, bool bright) | 1916 | public void SetFullBright(SceneObjectPart part, int face, bool bright) |
1917 | { | 1917 | { |
1918 | Primitive.TextureEntry tex = part.Shape.Textures; | 1918 | Primitive.TextureEntry tex = part.Shape.Textures; |
1919 | if (face >= 0 && face < GetNumberOfSides(part)) | 1919 | if (face >= 0 && face < GetNumberOfSides(part)) |
1920 | { | 1920 | { |
1921 | tex.CreateFace((uint) face); | 1921 | tex.CreateFace((uint) face); |
1922 | tex.FaceTextures[face].Fullbright = bright; | 1922 | tex.FaceTextures[face].Fullbright = bright; |
1923 | part.UpdateTextureEntry(tex.GetBytes()); | 1923 | part.UpdateTextureEntry(tex.GetBytes()); |
1924 | return; | 1924 | return; |
1925 | } | 1925 | } |
1926 | else if (face == ScriptBaseClass.ALL_SIDES) | 1926 | else if (face == ScriptBaseClass.ALL_SIDES) |
1927 | { | 1927 | { |
1928 | for (uint i = 0; i < GetNumberOfSides(part); i++) | 1928 | for (uint i = 0; i < GetNumberOfSides(part); i++) |
1929 | { | 1929 | { |
1930 | if (tex.FaceTextures[i] != null) | 1930 | if (tex.FaceTextures[i] != null) |
1931 | { | 1931 | { |
1932 | tex.FaceTextures[i].Fullbright = bright; | 1932 | tex.FaceTextures[i].Fullbright = bright; |
1933 | } | 1933 | } |
1934 | } | 1934 | } |
1935 | tex.DefaultTexture.Fullbright = bright; | 1935 | tex.DefaultTexture.Fullbright = bright; |
1936 | part.UpdateTextureEntry(tex.GetBytes()); | 1936 | part.UpdateTextureEntry(tex.GetBytes()); |
1937 | return; | 1937 | return; |
1938 | } | 1938 | } |
1939 | } | 1939 | } |
1940 | 1940 | ||
1941 | public LSL_Float llGetAlpha(int face) | 1941 | public LSL_Float llGetAlpha(int face) |
1942 | { | 1942 | { |
1943 | m_host.AddScriptLPS(1); | 1943 | m_host.AddScriptLPS(1); |
1944 | 1944 | ||
1945 | return GetAlpha(m_host, face); | 1945 | return GetAlpha(m_host, face); |
1946 | } | 1946 | } |
1947 | 1947 | ||
1948 | protected LSL_Float GetAlpha(SceneObjectPart part, int face) | 1948 | protected LSL_Float GetAlpha(SceneObjectPart part, int face) |
1949 | { | 1949 | { |
1950 | Primitive.TextureEntry tex = part.Shape.Textures; | 1950 | Primitive.TextureEntry tex = part.Shape.Textures; |
1951 | if (face == ScriptBaseClass.ALL_SIDES) | 1951 | if (face == ScriptBaseClass.ALL_SIDES) |
1952 | { | 1952 | { |
1953 | int i; | 1953 | int i; |
1954 | double sum = 0.0; | 1954 | double sum = 0.0; |
1955 | for (i = 0 ; i < GetNumberOfSides(part); i++) | 1955 | for (i = 0 ; i < GetNumberOfSides(part); i++) |
1956 | sum += (double)tex.GetFace((uint)i).RGBA.A; | 1956 | sum += (double)tex.GetFace((uint)i).RGBA.A; |
1957 | return sum; | 1957 | return sum; |
1958 | } | 1958 | } |
1959 | if (face >= 0 && face < GetNumberOfSides(part)) | 1959 | if (face >= 0 && face < GetNumberOfSides(part)) |
1960 | { | 1960 | { |
1961 | return (double)tex.GetFace((uint)face).RGBA.A; | 1961 | return (double)tex.GetFace((uint)face).RGBA.A; |
1962 | } | 1962 | } |
1963 | return 0.0; | 1963 | return 0.0; |
1964 | } | 1964 | } |
1965 | 1965 | ||
1966 | public void llSetAlpha(double alpha, int face) | 1966 | public void llSetAlpha(double alpha, int face) |
1967 | { | 1967 | { |
1968 | m_host.AddScriptLPS(1); | 1968 | m_host.AddScriptLPS(1); |
1969 | 1969 | ||
1970 | SetAlpha(m_host, alpha, face); | 1970 | SetAlpha(m_host, alpha, face); |
1971 | } | 1971 | } |
1972 | 1972 | ||
1973 | public void llSetLinkAlpha(int linknumber, double alpha, int face) | 1973 | public void llSetLinkAlpha(int linknumber, double alpha, int face) |
1974 | { | 1974 | { |
1975 | m_host.AddScriptLPS(1); | 1975 | m_host.AddScriptLPS(1); |
1976 | 1976 | ||
1977 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 1977 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
1978 | 1978 | ||
1979 | foreach (SceneObjectPart part in parts) | 1979 | foreach (SceneObjectPart part in parts) |
1980 | SetAlpha(part, alpha, face); | 1980 | SetAlpha(part, alpha, face); |
1981 | } | 1981 | } |
1982 | 1982 | ||
1983 | protected void SetAlpha(SceneObjectPart part, double alpha, int face) | 1983 | protected void SetAlpha(SceneObjectPart part, double alpha, int face) |
1984 | { | 1984 | { |
1985 | Primitive.TextureEntry tex = part.Shape.Textures; | 1985 | Primitive.TextureEntry tex = part.Shape.Textures; |
1986 | Color4 texcolor; | 1986 | Color4 texcolor; |
1987 | if (face >= 0 && face < GetNumberOfSides(part)) | 1987 | if (face >= 0 && face < GetNumberOfSides(part)) |
1988 | { | 1988 | { |
1989 | texcolor = tex.CreateFace((uint)face).RGBA; | 1989 | texcolor = tex.CreateFace((uint)face).RGBA; |
1990 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | 1990 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); |
1991 | tex.FaceTextures[face].RGBA = texcolor; | 1991 | tex.FaceTextures[face].RGBA = texcolor; |
1992 | part.UpdateTextureEntry(tex.GetBytes()); | 1992 | part.UpdateTextureEntry(tex.GetBytes()); |
1993 | return; | 1993 | return; |
1994 | } | 1994 | } |
1995 | else if (face == ScriptBaseClass.ALL_SIDES) | 1995 | else if (face == ScriptBaseClass.ALL_SIDES) |
1996 | { | 1996 | { |
1997 | for (int i = 0; i < GetNumberOfSides(part); i++) | 1997 | for (int i = 0; i < GetNumberOfSides(part); i++) |
1998 | { | 1998 | { |
1999 | if (tex.FaceTextures[i] != null) | 1999 | if (tex.FaceTextures[i] != null) |
2000 | { | 2000 | { |
2001 | texcolor = tex.FaceTextures[i].RGBA; | 2001 | texcolor = tex.FaceTextures[i].RGBA; |
2002 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | 2002 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); |
2003 | tex.FaceTextures[i].RGBA = texcolor; | 2003 | tex.FaceTextures[i].RGBA = texcolor; |
2004 | } | 2004 | } |
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | // In some cases, the default texture can be null, eg when every face | 2007 | // In some cases, the default texture can be null, eg when every face |
2008 | // has a unique texture | 2008 | // has a unique texture |
2009 | if (tex.DefaultTexture != null) | 2009 | if (tex.DefaultTexture != null) |
2010 | { | 2010 | { |
2011 | texcolor = tex.DefaultTexture.RGBA; | 2011 | texcolor = tex.DefaultTexture.RGBA; |
2012 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | 2012 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); |
2013 | tex.DefaultTexture.RGBA = texcolor; | 2013 | tex.DefaultTexture.RGBA = texcolor; |
2014 | } | 2014 | } |
2015 | 2015 | ||
2016 | part.UpdateTextureEntry(tex.GetBytes()); | 2016 | part.UpdateTextureEntry(tex.GetBytes()); |
2017 | return; | 2017 | return; |
2018 | } | 2018 | } |
2019 | } | 2019 | } |
2020 | 2020 | ||
2021 | /// <summary> | 2021 | /// <summary> |
2022 | /// Set flexi parameters of a part. | 2022 | /// Set flexi parameters of a part. |
2023 | /// | 2023 | /// |
2024 | /// FIXME: Much of this code should probably be within the part itself. | 2024 | /// FIXME: Much of this code should probably be within the part itself. |
2025 | /// </summary> | 2025 | /// </summary> |
2026 | /// <param name="part"></param> | 2026 | /// <param name="part"></param> |
2027 | /// <param name="flexi"></param> | 2027 | /// <param name="flexi"></param> |
2028 | /// <param name="softness"></param> | 2028 | /// <param name="softness"></param> |
2029 | /// <param name="gravity"></param> | 2029 | /// <param name="gravity"></param> |
2030 | /// <param name="friction"></param> | 2030 | /// <param name="friction"></param> |
2031 | /// <param name="wind"></param> | 2031 | /// <param name="wind"></param> |
2032 | /// <param name="tension"></param> | 2032 | /// <param name="tension"></param> |
2033 | /// <param name="Force"></param> | 2033 | /// <param name="Force"></param> |
2034 | protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, | 2034 | protected void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, |
2035 | float wind, float tension, LSL_Vector Force) | 2035 | float wind, float tension, LSL_Vector Force) |
2036 | { | 2036 | { |
2037 | if (part == null) | 2037 | if (part == null) |
2038 | return; | 2038 | return; |
2039 | 2039 | ||
2040 | if (flexi) | 2040 | if (flexi) |
2041 | { | 2041 | { |
2042 | part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do | 2042 | part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do |
2043 | // work once the prim is already flexi | 2043 | // work once the prim is already flexi |
2044 | part.Shape.FlexiSoftness = softness; | 2044 | part.Shape.FlexiSoftness = softness; |
2045 | part.Shape.FlexiGravity = gravity; | 2045 | part.Shape.FlexiGravity = gravity; |
2046 | part.Shape.FlexiDrag = friction; | 2046 | part.Shape.FlexiDrag = friction; |
2047 | part.Shape.FlexiWind = wind; | 2047 | part.Shape.FlexiWind = wind; |
2048 | part.Shape.FlexiTension = tension; | 2048 | part.Shape.FlexiTension = tension; |
2049 | part.Shape.FlexiForceX = (float)Force.x; | 2049 | part.Shape.FlexiForceX = (float)Force.x; |
2050 | part.Shape.FlexiForceY = (float)Force.y; | 2050 | part.Shape.FlexiForceY = (float)Force.y; |
2051 | part.Shape.FlexiForceZ = (float)Force.z; | 2051 | part.Shape.FlexiForceZ = (float)Force.z; |
2052 | part.Shape.PathCurve = (byte)Extrusion.Flexible; | 2052 | part.Shape.PathCurve = (byte)Extrusion.Flexible; |
2053 | } | 2053 | } |
2054 | else | 2054 | else |
2055 | { | 2055 | { |
2056 | // Other values not set, they do not seem to be sent to the viewer | 2056 | // Other values not set, they do not seem to be sent to the viewer |
2057 | // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off | 2057 | // Setting PathCurve appears to be what actually toggles the check box and turns Flexi on and off |
2058 | part.Shape.PathCurve = (byte)Extrusion.Straight; | 2058 | part.Shape.PathCurve = (byte)Extrusion.Straight; |
2059 | part.Shape.FlexiEntry = false; | 2059 | part.Shape.FlexiEntry = false; |
2060 | } | 2060 | } |
2061 | part.ParentGroup.HasGroupChanged = true; | 2061 | part.ParentGroup.HasGroupChanged = true; |
2062 | part.ScheduleFullUpdate(); | 2062 | part.ScheduleFullUpdate(); |
2063 | } | 2063 | } |
2064 | 2064 | ||
2065 | /// <summary> | 2065 | /// <summary> |
2066 | /// Set a light point on a part | 2066 | /// Set a light point on a part |
2067 | /// </summary> | 2067 | /// </summary> |
2068 | /// FIXME: Much of this code should probably be in SceneObjectGroup | 2068 | /// FIXME: Much of this code should probably be in SceneObjectGroup |
2069 | /// | 2069 | /// |
2070 | /// <param name="part"></param> | 2070 | /// <param name="part"></param> |
2071 | /// <param name="light"></param> | 2071 | /// <param name="light"></param> |
2072 | /// <param name="color"></param> | 2072 | /// <param name="color"></param> |
2073 | /// <param name="intensity"></param> | 2073 | /// <param name="intensity"></param> |
2074 | /// <param name="radius"></param> | 2074 | /// <param name="radius"></param> |
2075 | /// <param name="falloff"></param> | 2075 | /// <param name="falloff"></param> |
2076 | protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) | 2076 | protected void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) |
2077 | { | 2077 | { |
2078 | if (part == null) | 2078 | if (part == null) |
2079 | return; | 2079 | return; |
2080 | 2080 | ||
2081 | if (light) | 2081 | if (light) |
2082 | { | 2082 | { |
2083 | part.Shape.LightEntry = true; | 2083 | part.Shape.LightEntry = true; |
2084 | part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); | 2084 | part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); |
2085 | part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); | 2085 | part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); |
2086 | part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); | 2086 | part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); |
2087 | part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f); | 2087 | part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f); |
2088 | part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f); | 2088 | part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f); |
2089 | part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f); | 2089 | part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f); |
2090 | } | 2090 | } |
2091 | else | 2091 | else |
2092 | { | 2092 | { |
2093 | part.Shape.LightEntry = false; | 2093 | part.Shape.LightEntry = false; |
2094 | } | 2094 | } |
2095 | 2095 | ||
2096 | part.ParentGroup.HasGroupChanged = true; | 2096 | part.ParentGroup.HasGroupChanged = true; |
2097 | part.ScheduleFullUpdate(); | 2097 | part.ScheduleFullUpdate(); |
2098 | } | 2098 | } |
2099 | 2099 | ||
2100 | public LSL_Vector llGetColor(int face) | 2100 | public LSL_Vector llGetColor(int face) |
2101 | { | 2101 | { |
2102 | m_host.AddScriptLPS(1); | 2102 | m_host.AddScriptLPS(1); |
2103 | return GetColor(m_host, face); | 2103 | return GetColor(m_host, face); |
2104 | } | 2104 | } |
2105 | 2105 | ||
2106 | protected LSL_Vector GetColor(SceneObjectPart part, int face) | 2106 | protected LSL_Vector GetColor(SceneObjectPart part, int face) |
2107 | { | 2107 | { |
2108 | Primitive.TextureEntry tex = part.Shape.Textures; | 2108 | Primitive.TextureEntry tex = part.Shape.Textures; |
2109 | Color4 texcolor; | 2109 | Color4 texcolor; |
2110 | LSL_Vector rgb = new LSL_Vector(); | 2110 | LSL_Vector rgb = new LSL_Vector(); |
2111 | if (face == ScriptBaseClass.ALL_SIDES) | 2111 | if (face == ScriptBaseClass.ALL_SIDES) |
2112 | { | 2112 | { |
2113 | int i; | 2113 | int i; |
2114 | 2114 | ||
2115 | for (i = 0 ; i < GetNumberOfSides(part); i++) | 2115 | for (i = 0 ; i < GetNumberOfSides(part); i++) |
2116 | { | 2116 | { |
2117 | texcolor = tex.GetFace((uint)i).RGBA; | 2117 | texcolor = tex.GetFace((uint)i).RGBA; |
2118 | rgb.x += texcolor.R; | 2118 | rgb.x += texcolor.R; |
2119 | rgb.y += texcolor.G; | 2119 | rgb.y += texcolor.G; |
2120 | rgb.z += texcolor.B; | 2120 | rgb.z += texcolor.B; |
2121 | } | 2121 | } |
2122 | 2122 | ||
2123 | rgb.x /= (float)GetNumberOfSides(part); | 2123 | rgb.x /= (float)GetNumberOfSides(part); |
2124 | rgb.y /= (float)GetNumberOfSides(part); | 2124 | rgb.y /= (float)GetNumberOfSides(part); |
2125 | rgb.z /= (float)GetNumberOfSides(part); | 2125 | rgb.z /= (float)GetNumberOfSides(part); |
2126 | 2126 | ||
2127 | return rgb; | 2127 | return rgb; |
2128 | } | 2128 | } |
2129 | 2129 | ||
2130 | if (face >= 0 && face < GetNumberOfSides(part)) | 2130 | if (face >= 0 && face < GetNumberOfSides(part)) |
2131 | { | 2131 | { |
2132 | texcolor = tex.GetFace((uint)face).RGBA; | 2132 | texcolor = tex.GetFace((uint)face).RGBA; |
2133 | rgb.x = texcolor.R; | 2133 | rgb.x = texcolor.R; |
2134 | rgb.y = texcolor.G; | 2134 | rgb.y = texcolor.G; |
2135 | rgb.z = texcolor.B; | 2135 | rgb.z = texcolor.B; |
2136 | 2136 | ||
2137 | return rgb; | 2137 | return rgb; |
2138 | } | 2138 | } |
2139 | else | 2139 | else |
2140 | { | 2140 | { |
2141 | return new LSL_Vector(); | 2141 | return new LSL_Vector(); |
2142 | } | 2142 | } |
2143 | } | 2143 | } |
2144 | 2144 | ||
2145 | public void llSetTexture(string texture, int face) | 2145 | public void llSetTexture(string texture, int face) |
2146 | { | 2146 | { |
2147 | m_host.AddScriptLPS(1); | 2147 | m_host.AddScriptLPS(1); |
2148 | SetTexture(m_host, texture, face); | 2148 | SetTexture(m_host, texture, face); |
2149 | ScriptSleep(m_sleepMsOnSetTexture); | 2149 | ScriptSleep(m_sleepMsOnSetTexture); |
2150 | } | 2150 | } |
2151 | 2151 | ||
2152 | public void llSetLinkTexture(int linknumber, string texture, int face) | 2152 | public void llSetLinkTexture(int linknumber, string texture, int face) |
2153 | { | 2153 | { |
2154 | m_host.AddScriptLPS(1); | 2154 | m_host.AddScriptLPS(1); |
2155 | 2155 | ||
2156 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 2156 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
2157 | 2157 | ||
2158 | foreach (SceneObjectPart part in parts) | 2158 | foreach (SceneObjectPart part in parts) |
2159 | SetTexture(part, texture, face); | 2159 | SetTexture(part, texture, face); |
2160 | 2160 | ||
2161 | ScriptSleep(m_sleepMsOnSetLinkTexture); | 2161 | ScriptSleep(m_sleepMsOnSetLinkTexture); |
2162 | } | 2162 | } |
2163 | 2163 | ||
2164 | protected void SetTexture(SceneObjectPart part, string texture, int face) | 2164 | protected void SetTexture(SceneObjectPart part, string texture, int face) |
2165 | { | 2165 | { |
2166 | UUID textureID = new UUID(); | 2166 | UUID textureID = new UUID(); |
2167 | 2167 | ||
2168 | textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); | 2168 | textureID = ScriptUtils.GetAssetIdFromItemName(m_host, texture, (int)AssetType.Texture); |
2169 | if (textureID == UUID.Zero) | 2169 | if (textureID == UUID.Zero) |
2170 | { | 2170 | { |
2171 | if (!UUID.TryParse(texture, out textureID)) | 2171 | if (!UUID.TryParse(texture, out textureID)) |
2172 | return; | 2172 | return; |
2173 | } | 2173 | } |
2174 | 2174 | ||
2175 | Primitive.TextureEntry tex = part.Shape.Textures; | 2175 | Primitive.TextureEntry tex = part.Shape.Textures; |
2176 | 2176 | ||
2177 | if (face >= 0 && face < GetNumberOfSides(part)) | 2177 | if (face >= 0 && face < GetNumberOfSides(part)) |
2178 | { | 2178 | { |
2179 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | 2179 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); |
2180 | texface.TextureID = textureID; | 2180 | texface.TextureID = textureID; |
2181 | tex.FaceTextures[face] = texface; | 2181 | tex.FaceTextures[face] = texface; |
2182 | part.UpdateTextureEntry(tex.GetBytes()); | 2182 | part.UpdateTextureEntry(tex.GetBytes()); |
2183 | return; | 2183 | return; |
2184 | } | 2184 | } |
2185 | else if (face == ScriptBaseClass.ALL_SIDES) | 2185 | else if (face == ScriptBaseClass.ALL_SIDES) |
2186 | { | 2186 | { |
2187 | for (uint i = 0; i < GetNumberOfSides(part); i++) | 2187 | for (uint i = 0; i < GetNumberOfSides(part); i++) |
2188 | { | 2188 | { |
2189 | if (tex.FaceTextures[i] != null) | 2189 | if (tex.FaceTextures[i] != null) |
2190 | { | 2190 | { |
2191 | tex.FaceTextures[i].TextureID = textureID; | 2191 | tex.FaceTextures[i].TextureID = textureID; |
2192 | } | 2192 | } |
2193 | } | 2193 | } |
2194 | tex.DefaultTexture.TextureID = textureID; | 2194 | tex.DefaultTexture.TextureID = textureID; |
2195 | part.UpdateTextureEntry(tex.GetBytes()); | 2195 | part.UpdateTextureEntry(tex.GetBytes()); |
2196 | return; | 2196 | return; |
2197 | } | 2197 | } |
2198 | } | 2198 | } |
2199 | 2199 | ||
2200 | public void llScaleTexture(double u, double v, int face) | 2200 | public void llScaleTexture(double u, double v, int face) |
2201 | { | 2201 | { |
2202 | m_host.AddScriptLPS(1); | 2202 | m_host.AddScriptLPS(1); |
2203 | 2203 | ||
2204 | ScaleTexture(m_host, u, v, face); | 2204 | ScaleTexture(m_host, u, v, face); |
2205 | ScriptSleep(m_sleepMsOnScaleTexture); | 2205 | ScriptSleep(m_sleepMsOnScaleTexture); |
2206 | } | 2206 | } |
2207 | 2207 | ||
2208 | protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) | 2208 | protected void ScaleTexture(SceneObjectPart part, double u, double v, int face) |
2209 | { | 2209 | { |
2210 | Primitive.TextureEntry tex = part.Shape.Textures; | 2210 | Primitive.TextureEntry tex = part.Shape.Textures; |
2211 | if (face >= 0 && face < GetNumberOfSides(part)) | 2211 | if (face >= 0 && face < GetNumberOfSides(part)) |
2212 | { | 2212 | { |
2213 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | 2213 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); |
2214 | texface.RepeatU = (float)u; | 2214 | texface.RepeatU = (float)u; |
2215 | texface.RepeatV = (float)v; | 2215 | texface.RepeatV = (float)v; |
2216 | tex.FaceTextures[face] = texface; | 2216 | tex.FaceTextures[face] = texface; |
2217 | part.UpdateTextureEntry(tex.GetBytes()); | 2217 | part.UpdateTextureEntry(tex.GetBytes()); |
2218 | return; | 2218 | return; |
2219 | } | 2219 | } |
2220 | if (face == ScriptBaseClass.ALL_SIDES) | 2220 | if (face == ScriptBaseClass.ALL_SIDES) |
2221 | { | 2221 | { |
2222 | for (int i = 0; i < GetNumberOfSides(part); i++) | 2222 | for (int i = 0; i < GetNumberOfSides(part); i++) |
2223 | { | 2223 | { |
2224 | if (tex.FaceTextures[i] != null) | 2224 | if (tex.FaceTextures[i] != null) |
2225 | { | 2225 | { |
2226 | tex.FaceTextures[i].RepeatU = (float)u; | 2226 | tex.FaceTextures[i].RepeatU = (float)u; |
2227 | tex.FaceTextures[i].RepeatV = (float)v; | 2227 | tex.FaceTextures[i].RepeatV = (float)v; |
2228 | } | 2228 | } |
2229 | } | 2229 | } |
2230 | tex.DefaultTexture.RepeatU = (float)u; | 2230 | tex.DefaultTexture.RepeatU = (float)u; |
2231 | tex.DefaultTexture.RepeatV = (float)v; | 2231 | tex.DefaultTexture.RepeatV = (float)v; |
2232 | part.UpdateTextureEntry(tex.GetBytes()); | 2232 | part.UpdateTextureEntry(tex.GetBytes()); |
2233 | return; | 2233 | return; |
2234 | } | 2234 | } |
2235 | } | 2235 | } |
2236 | 2236 | ||
2237 | public void llOffsetTexture(double u, double v, int face) | 2237 | public void llOffsetTexture(double u, double v, int face) |
2238 | { | 2238 | { |
2239 | m_host.AddScriptLPS(1); | 2239 | m_host.AddScriptLPS(1); |
2240 | OffsetTexture(m_host, u, v, face); | 2240 | OffsetTexture(m_host, u, v, face); |
2241 | ScriptSleep(m_sleepMsOnOffsetTexture); | 2241 | ScriptSleep(m_sleepMsOnOffsetTexture); |
2242 | } | 2242 | } |
2243 | 2243 | ||
2244 | protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) | 2244 | protected void OffsetTexture(SceneObjectPart part, double u, double v, int face) |
2245 | { | 2245 | { |
2246 | Primitive.TextureEntry tex = part.Shape.Textures; | 2246 | Primitive.TextureEntry tex = part.Shape.Textures; |
2247 | if (face >= 0 && face < GetNumberOfSides(part)) | 2247 | if (face >= 0 && face < GetNumberOfSides(part)) |
2248 | { | 2248 | { |
2249 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | 2249 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); |
2250 | texface.OffsetU = (float)u; | 2250 | texface.OffsetU = (float)u; |
2251 | texface.OffsetV = (float)v; | 2251 | texface.OffsetV = (float)v; |
2252 | tex.FaceTextures[face] = texface; | 2252 | tex.FaceTextures[face] = texface; |
2253 | part.UpdateTextureEntry(tex.GetBytes()); | 2253 | part.UpdateTextureEntry(tex.GetBytes()); |
2254 | return; | 2254 | return; |
2255 | } | 2255 | } |
2256 | if (face == ScriptBaseClass.ALL_SIDES) | 2256 | if (face == ScriptBaseClass.ALL_SIDES) |
2257 | { | 2257 | { |
2258 | for (int i = 0; i < GetNumberOfSides(part); i++) | 2258 | for (int i = 0; i < GetNumberOfSides(part); i++) |
2259 | { | 2259 | { |
2260 | if (tex.FaceTextures[i] != null) | 2260 | if (tex.FaceTextures[i] != null) |
2261 | { | 2261 | { |
2262 | tex.FaceTextures[i].OffsetU = (float)u; | 2262 | tex.FaceTextures[i].OffsetU = (float)u; |
2263 | tex.FaceTextures[i].OffsetV = (float)v; | 2263 | tex.FaceTextures[i].OffsetV = (float)v; |
2264 | } | 2264 | } |
2265 | } | 2265 | } |
2266 | tex.DefaultTexture.OffsetU = (float)u; | 2266 | tex.DefaultTexture.OffsetU = (float)u; |
2267 | tex.DefaultTexture.OffsetV = (float)v; | 2267 | tex.DefaultTexture.OffsetV = (float)v; |
2268 | part.UpdateTextureEntry(tex.GetBytes()); | 2268 | part.UpdateTextureEntry(tex.GetBytes()); |
2269 | return; | 2269 | return; |
2270 | } | 2270 | } |
2271 | } | 2271 | } |
2272 | 2272 | ||
2273 | public void llRotateTexture(double rotation, int face) | 2273 | public void llRotateTexture(double rotation, int face) |
2274 | { | 2274 | { |
2275 | m_host.AddScriptLPS(1); | 2275 | m_host.AddScriptLPS(1); |
2276 | RotateTexture(m_host, rotation, face); | 2276 | RotateTexture(m_host, rotation, face); |
2277 | ScriptSleep(m_sleepMsOnRotateTexture); | 2277 | ScriptSleep(m_sleepMsOnRotateTexture); |
2278 | } | 2278 | } |
2279 | 2279 | ||
2280 | protected void RotateTexture(SceneObjectPart part, double rotation, int face) | 2280 | protected void RotateTexture(SceneObjectPart part, double rotation, int face) |
2281 | { | 2281 | { |
2282 | Primitive.TextureEntry tex = part.Shape.Textures; | 2282 | Primitive.TextureEntry tex = part.Shape.Textures; |
2283 | if (face >= 0 && face < GetNumberOfSides(part)) | 2283 | if (face >= 0 && face < GetNumberOfSides(part)) |
2284 | { | 2284 | { |
2285 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | 2285 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); |
2286 | texface.Rotation = (float)rotation; | 2286 | texface.Rotation = (float)rotation; |
2287 | tex.FaceTextures[face] = texface; | 2287 | tex.FaceTextures[face] = texface; |
2288 | part.UpdateTextureEntry(tex.GetBytes()); | 2288 | part.UpdateTextureEntry(tex.GetBytes()); |
2289 | return; | 2289 | return; |
2290 | } | 2290 | } |
2291 | if (face == ScriptBaseClass.ALL_SIDES) | 2291 | if (face == ScriptBaseClass.ALL_SIDES) |
2292 | { | 2292 | { |
2293 | for (int i = 0; i < GetNumberOfSides(part); i++) | 2293 | for (int i = 0; i < GetNumberOfSides(part); i++) |
2294 | { | 2294 | { |
2295 | if (tex.FaceTextures[i] != null) | 2295 | if (tex.FaceTextures[i] != null) |
2296 | { | 2296 | { |
2297 | tex.FaceTextures[i].Rotation = (float)rotation; | 2297 | tex.FaceTextures[i].Rotation = (float)rotation; |
2298 | } | 2298 | } |
2299 | } | 2299 | } |
2300 | tex.DefaultTexture.Rotation = (float)rotation; | 2300 | tex.DefaultTexture.Rotation = (float)rotation; |
2301 | part.UpdateTextureEntry(tex.GetBytes()); | 2301 | part.UpdateTextureEntry(tex.GetBytes()); |
2302 | return; | 2302 | return; |
2303 | } | 2303 | } |
2304 | } | 2304 | } |
2305 | 2305 | ||
2306 | public LSL_String llGetTexture(int face) | 2306 | public LSL_String llGetTexture(int face) |
2307 | { | 2307 | { |
2308 | m_host.AddScriptLPS(1); | 2308 | m_host.AddScriptLPS(1); |
2309 | return GetTexture(m_host, face); | 2309 | return GetTexture(m_host, face); |
2310 | } | 2310 | } |
2311 | 2311 | ||
2312 | protected LSL_String GetTexture(SceneObjectPart part, int face) | 2312 | protected LSL_String GetTexture(SceneObjectPart part, int face) |
2313 | { | 2313 | { |
2314 | Primitive.TextureEntry tex = part.Shape.Textures; | 2314 | Primitive.TextureEntry tex = part.Shape.Textures; |
2315 | if (face == ScriptBaseClass.ALL_SIDES) | 2315 | if (face == ScriptBaseClass.ALL_SIDES) |
2316 | { | 2316 | { |
2317 | face = 0; | 2317 | face = 0; |
2318 | } | 2318 | } |
2319 | 2319 | ||
2320 | if (face >= 0 && face < GetNumberOfSides(part)) | 2320 | if (face >= 0 && face < GetNumberOfSides(part)) |
2321 | { | 2321 | { |
2322 | Primitive.TextureEntryFace texface; | 2322 | Primitive.TextureEntryFace texface; |
2323 | texface = tex.GetFace((uint)face); | 2323 | texface = tex.GetFace((uint)face); |
2324 | string texture = texface.TextureID.ToString(); | 2324 | string texture = texface.TextureID.ToString(); |
2325 | 2325 | ||
2326 | lock (part.TaskInventory) | 2326 | lock (part.TaskInventory) |
2327 | { | 2327 | { |
2328 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory) | 2328 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in part.TaskInventory) |
2329 | { | 2329 | { |
2330 | if (inv.Value.AssetID == texface.TextureID) | 2330 | if (inv.Value.AssetID == texface.TextureID) |
2331 | { | 2331 | { |
2332 | texture = inv.Value.Name.ToString(); | 2332 | texture = inv.Value.Name.ToString(); |
2333 | break; | 2333 | break; |
2334 | } | 2334 | } |
2335 | } | 2335 | } |
2336 | } | 2336 | } |
2337 | 2337 | ||
2338 | return texture; | 2338 | return texture; |
2339 | } | 2339 | } |
2340 | else | 2340 | else |
2341 | { | 2341 | { |
2342 | return UUID.Zero.ToString(); | 2342 | return UUID.Zero.ToString(); |
2343 | } | 2343 | } |
2344 | } | 2344 | } |
2345 | 2345 | ||
2346 | public void llSetPos(LSL_Vector pos) | 2346 | public void llSetPos(LSL_Vector pos) |
2347 | { | 2347 | { |
2348 | m_host.AddScriptLPS(1); | 2348 | m_host.AddScriptLPS(1); |
2349 | 2349 | ||
2350 | SetPos(m_host, pos, true); | 2350 | SetPos(m_host, pos, true); |
2351 | 2351 | ||
2352 | ScriptSleep(m_sleepMsOnSetPos); | 2352 | ScriptSleep(m_sleepMsOnSetPos); |
2353 | } | 2353 | } |
2354 | 2354 | ||
2355 | /// <summary> | 2355 | /// <summary> |
2356 | /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos | 2356 | /// Tries to move the entire object so that the root prim is within 0.1m of position. http://wiki.secondlife.com/wiki/LlSetRegionPos |
2357 | /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into. | 2357 | /// Documentation indicates that the use of x/y coordinates up to 10 meters outside the bounds of a region will work but do not specify what happens if there is no adjacent region for the object to move into. |
2358 | /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking. | 2358 | /// Uses the RegionSize constant here rather than hard-coding 266.0 to alert any developer modifying OpenSim to support variable-sized regions that this method will need tweaking. |
2359 | /// </summary> | 2359 | /// </summary> |
2360 | /// <param name="pos"></param> | 2360 | /// <param name="pos"></param> |
2361 | /// <returns>1 if successful, 0 otherwise.</returns> | 2361 | /// <returns>1 if successful, 0 otherwise.</returns> |
2362 | public LSL_Integer llSetRegionPos(LSL_Vector pos) | 2362 | public LSL_Integer llSetRegionPos(LSL_Vector pos) |
2363 | { | 2363 | { |
2364 | m_host.AddScriptLPS(1); | 2364 | m_host.AddScriptLPS(1); |
2365 | 2365 | ||
2366 | // BEGIN WORKAROUND | 2366 | // BEGIN WORKAROUND |
2367 | // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. | 2367 | // IF YOU GET REGION CROSSINGS WORKING WITH THIS FUNCTION, REPLACE THE WORKAROUND. |
2368 | // | 2368 | // |
2369 | // This workaround is to prevent silent failure of this function. | 2369 | // This workaround is to prevent silent failure of this function. |
2370 | // According to the specification on the SL Wiki, providing a position outside of the | 2370 | // According to the specification on the SL Wiki, providing a position outside of the |
2371 | if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY) | 2371 | if (pos.x < 0 || pos.x > World.RegionInfo.RegionSizeX || pos.y < 0 || pos.y > World.RegionInfo.RegionSizeY) |
2372 | { | 2372 | { |
2373 | return 0; | 2373 | return 0; |
2374 | } | 2374 | } |
2375 | // END WORK AROUND | 2375 | // END WORK AROUND |
2376 | else if ( // this is not part of the workaround if-block because it's not related to the workaround. | 2376 | else if ( // this is not part of the workaround if-block because it's not related to the workaround. |
2377 | IsPhysical() || | 2377 | IsPhysical() || |
2378 | m_host.ParentGroup.IsAttachment || // return FALSE if attachment | 2378 | m_host.ParentGroup.IsAttachment || // return FALSE if attachment |
2379 | ( | 2379 | ( |
2380 | pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. | 2380 | pos.x < -10.0 || // return FALSE if more than 10 meters into a west-adjacent region. |
2381 | pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region. | 2381 | pos.x > (World.RegionInfo.RegionSizeX + 10) || // return FALSE if more than 10 meters into a east-adjacent region. |
2382 | pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. | 2382 | pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. |
2383 | pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region. | 2383 | pos.y > (World.RegionInfo.RegionSizeY + 10) || // return FALSE if more than 10 meters into a north-adjacent region. |
2384 | pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m | 2384 | pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m |
2385 | ) | 2385 | ) |
2386 | ) | 2386 | ) |
2387 | { | 2387 | { |
2388 | return 0; | 2388 | return 0; |
2389 | } | 2389 | } |
2390 | 2390 | ||
2391 | // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range. | 2391 | // if we reach this point, then the object is not physical, it's not an attachment, and the destination is within the valid range. |
2392 | // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. | 2392 | // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. |
2393 | 2393 | ||
2394 | Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; | 2394 | Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; |
2395 | LandData here = World.GetLandData(objectPos); | 2395 | LandData here = World.GetLandData(objectPos); |
2396 | LandData there = World.GetLandData(pos); | 2396 | LandData there = World.GetLandData(pos); |
2397 | 2397 | ||
2398 | // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. | 2398 | // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. |
2399 | 2399 | ||
2400 | bool sameParcel = here.GlobalID == there.GlobalID; | 2400 | bool sameParcel = here.GlobalID == there.GlobalID; |
2401 | 2401 | ||
2402 | if (!sameParcel && !World.Permissions.CanRezObject( | 2402 | if (!sameParcel && !World.Permissions.CanRezObject( |
2403 | m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) | 2403 | m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) |
2404 | { | 2404 | { |
2405 | return 0; | 2405 | return 0; |
2406 | } | 2406 | } |
2407 | 2407 | ||
2408 | SetPos(m_host.ParentGroup.RootPart, pos, false); | 2408 | SetPos(m_host.ParentGroup.RootPart, pos, false); |
2409 | 2409 | ||
2410 | return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0; | 2410 | return VecDist(pos, llGetRootPosition()) <= 0.1 ? 1 : 0; |
2411 | } | 2411 | } |
2412 | 2412 | ||
2413 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) | 2413 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) |
2414 | // note linked setpos is capped "differently" | 2414 | // note linked setpos is capped "differently" |
2415 | private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end) | 2415 | private LSL_Vector SetPosAdjust(LSL_Vector start, LSL_Vector end) |
2416 | { | 2416 | { |
2417 | if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor) | 2417 | if (llVecDist(start, end) > 10.0f * m_ScriptDistanceFactor) |
2418 | return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start); | 2418 | return start + m_ScriptDistanceFactor * 10.0f * llVecNorm(end - start); |
2419 | else | 2419 | else |
2420 | return end; | 2420 | return end; |
2421 | } | 2421 | } |
2422 | 2422 | ||
2423 | protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) | 2423 | protected LSL_Vector GetSetPosTarget(SceneObjectPart part, LSL_Vector targetPos, LSL_Vector fromPos) |
2424 | { | 2424 | { |
2425 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) | 2425 | if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) |
2426 | return fromPos; | 2426 | return fromPos; |
2427 | 2427 | ||
2428 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) | 2428 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) |
2429 | 2429 | ||
2430 | 2430 | ||
2431 | float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); | 2431 | float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); |
2432 | bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); | 2432 | bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); |
2433 | 2433 | ||
2434 | if (part.ParentGroup.RootPart == part) | 2434 | if (part.ParentGroup.RootPart == part) |
2435 | { | 2435 | { |
2436 | if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) | 2436 | if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) |
2437 | targetPos.z = ground; | 2437 | targetPos.z = ground; |
2438 | } | 2438 | } |
2439 | LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); | 2439 | LSL_Vector real_vec = SetPosAdjust(fromPos, targetPos); |
2440 | 2440 | ||
2441 | return real_vec; | 2441 | return real_vec; |
2442 | } | 2442 | } |
2443 | 2443 | ||
2444 | /// <summary> | 2444 | /// <summary> |
2445 | /// set object position, optionally capping the distance. | 2445 | /// set object position, optionally capping the distance. |
2446 | /// </summary> | 2446 | /// </summary> |
2447 | /// <param name="part"></param> | 2447 | /// <param name="part"></param> |
2448 | /// <param name="targetPos"></param> | 2448 | /// <param name="targetPos"></param> |
2449 | /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> | 2449 | /// <param name="adjust">if TRUE, will cap the distance to 10m.</param> |
2450 | protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) | 2450 | protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) |
2451 | { | 2451 | { |
2452 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) | 2452 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) |
2453 | LSL_Vector currentPos = GetPartLocalPos(part); | 2453 | LSL_Vector currentPos = GetPartLocalPos(part); |
2454 | 2454 | ||
2455 | float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); | 2455 | float ground = World.GetGroundHeight((float)targetPos.x, (float)targetPos.y); |
2456 | bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); | 2456 | bool disable_underground_movement = m_ScriptEngine.Config.GetBoolean("DisableUndergroundMovement", true); |
2457 | 2457 | ||
2458 | if (part.ParentGroup.RootPart == part) | 2458 | if (part.ParentGroup.RootPart == part) |
2459 | { | 2459 | { |
2460 | if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) | 2460 | if ((targetPos.z < ground) && disable_underground_movement && m_host.ParentGroup.AttachmentPoint == 0) |
2461 | targetPos.z = ground; | 2461 | targetPos.z = ground; |
2462 | SceneObjectGroup parent = part.ParentGroup; | 2462 | SceneObjectGroup parent = part.ParentGroup; |
2463 | parent.UpdateGroupPosition(!adjust ? targetPos : | 2463 | parent.UpdateGroupPosition(!adjust ? targetPos : |
2464 | SetPosAdjust(currentPos, targetPos)); | 2464 | SetPosAdjust(currentPos, targetPos)); |
2465 | } | 2465 | } |
2466 | else | 2466 | else |
2467 | { | 2467 | { |
2468 | part.OffsetPosition = !adjust ? targetPos : | 2468 | part.OffsetPosition = !adjust ? targetPos : |
2469 | SetPosAdjust(currentPos, targetPos); | 2469 | SetPosAdjust(currentPos, targetPos); |
2470 | SceneObjectGroup parent = part.ParentGroup; | 2470 | SceneObjectGroup parent = part.ParentGroup; |
2471 | parent.HasGroupChanged = true; | 2471 | parent.HasGroupChanged = true; |
2472 | parent.ScheduleGroupForTerseUpdate(); | 2472 | parent.ScheduleGroupForTerseUpdate(); |
2473 | } | 2473 | } |
2474 | } | 2474 | } |
2475 | 2475 | ||
2476 | public LSL_Vector llGetPos() | 2476 | public LSL_Vector llGetPos() |
2477 | { | 2477 | { |
2478 | m_host.AddScriptLPS(1); | 2478 | m_host.AddScriptLPS(1); |
2479 | return m_host.GetWorldPosition(); | 2479 | return m_host.GetWorldPosition(); |
2480 | } | 2480 | } |
2481 | 2481 | ||
2482 | public LSL_Vector llGetLocalPos() | 2482 | public LSL_Vector llGetLocalPos() |
2483 | { | 2483 | { |
2484 | m_host.AddScriptLPS(1); | 2484 | m_host.AddScriptLPS(1); |
2485 | return GetPartLocalPos(m_host); | 2485 | return GetPartLocalPos(m_host); |
2486 | } | 2486 | } |
2487 | 2487 | ||
2488 | protected LSL_Vector GetPartLocalPos(SceneObjectPart part) | 2488 | protected LSL_Vector GetPartLocalPos(SceneObjectPart part) |
2489 | { | 2489 | { |
2490 | m_host.AddScriptLPS(1); | 2490 | m_host.AddScriptLPS(1); |
2491 | 2491 | ||
2492 | Vector3 pos; | 2492 | Vector3 pos; |
2493 | 2493 | ||
2494 | if (!part.IsRoot) | 2494 | if (!part.IsRoot) |
2495 | { | 2495 | { |
2496 | pos = part.OffsetPosition; | 2496 | pos = part.OffsetPosition; |
2497 | } | 2497 | } |
2498 | else | 2498 | else |
2499 | { | 2499 | { |
2500 | if (part.ParentGroup.IsAttachment) | 2500 | if (part.ParentGroup.IsAttachment) |
2501 | { | 2501 | { |
2502 | pos = part.AttachedPos; | 2502 | pos = part.AttachedPos; |
2503 | } | 2503 | } |
2504 | else | 2504 | else |
2505 | { | 2505 | { |
2506 | pos = part.AbsolutePosition; | 2506 | pos = part.AbsolutePosition; |
2507 | } | 2507 | } |
2508 | } | 2508 | } |
2509 | 2509 | ||
2510 | // m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); | 2510 | // m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); |
2511 | 2511 | ||
2512 | return new LSL_Vector(pos); | 2512 | return new LSL_Vector(pos); |
2513 | } | 2513 | } |
2514 | 2514 | ||
2515 | public void llSetRot(LSL_Rotation rot) | 2515 | public void llSetRot(LSL_Rotation rot) |
2516 | { | 2516 | { |
2517 | m_host.AddScriptLPS(1); | 2517 | m_host.AddScriptLPS(1); |
2518 | 2518 | ||
2519 | // try to let this work as in SL... | 2519 | // try to let this work as in SL... |
2520 | if (m_host.ParentID == 0) | 2520 | if (m_host.ParentID == 0) |
2521 | { | 2521 | { |
2522 | // special case: If we are root, rotate complete SOG to new rotation | 2522 | // special case: If we are root, rotate complete SOG to new rotation |
2523 | SetRot(m_host, rot); | 2523 | SetRot(m_host, rot); |
2524 | } | 2524 | } |
2525 | else | 2525 | else |
2526 | { | 2526 | { |
2527 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. | 2527 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. |
2528 | SceneObjectPart rootPart = m_host.ParentGroup.RootPart; | 2528 | SceneObjectPart rootPart = m_host.ParentGroup.RootPart; |
2529 | if (rootPart != null) // better safe than sorry | 2529 | if (rootPart != null) // better safe than sorry |
2530 | { | 2530 | { |
2531 | SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); | 2531 | SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); |
2532 | } | 2532 | } |
2533 | } | 2533 | } |
2534 | 2534 | ||
2535 | ScriptSleep(m_sleepMsOnSetRot); | 2535 | ScriptSleep(m_sleepMsOnSetRot); |
2536 | } | 2536 | } |
2537 | 2537 | ||
2538 | public void llSetLocalRot(LSL_Rotation rot) | 2538 | public void llSetLocalRot(LSL_Rotation rot) |
2539 | { | 2539 | { |
2540 | m_host.AddScriptLPS(1); | 2540 | m_host.AddScriptLPS(1); |
2541 | SetRot(m_host, rot); | 2541 | SetRot(m_host, rot); |
2542 | ScriptSleep(m_sleepMsOnSetLocalRot); | 2542 | ScriptSleep(m_sleepMsOnSetLocalRot); |
2543 | } | 2543 | } |
2544 | 2544 | ||
2545 | protected void SetRot(SceneObjectPart part, Quaternion rot) | 2545 | protected void SetRot(SceneObjectPart part, Quaternion rot) |
2546 | { | 2546 | { |
2547 | part.UpdateRotation(rot); | 2547 | part.UpdateRotation(rot); |
2548 | // Update rotation does not move the object in the physics scene if it's a linkset. | 2548 | // Update rotation does not move the object in the physics scene if it's a linkset. |
2549 | 2549 | ||
2550 | //KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type | 2550 | //KF: Do NOT use this next line if using ODE physics engine. This need a switch based on .ini Phys Engine type |
2551 | // part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; | 2551 | // part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; |
2552 | 2552 | ||
2553 | // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line | 2553 | // So, after thinking about this for a bit, the issue with the part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition line |
2554 | // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt | 2554 | // is it isn't compatible with vehicles because it causes the vehicle body to have to be broken down and rebuilt |
2555 | // It's perfectly okay when the object is not an active physical body though. | 2555 | // It's perfectly okay when the object is not an active physical body though. |
2556 | // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against | 2556 | // So, part.ParentGroup.ResetChildPrimPhysicsPositions(); does the thing that Kitto is warning against |
2557 | // but only if the object is not physial and active. This is important for rotating doors. | 2557 | // but only if the object is not physial and active. This is important for rotating doors. |
2558 | // without the absoluteposition = absoluteposition happening, the doors do not move in the physics | 2558 | // without the absoluteposition = absoluteposition happening, the doors do not move in the physics |
2559 | // scene | 2559 | // scene |
2560 | PhysicsActor pa = part.PhysActor; | 2560 | PhysicsActor pa = part.PhysActor; |
2561 | 2561 | ||
2562 | if (pa != null && !pa.IsPhysical) | 2562 | if (pa != null && !pa.IsPhysical) |
2563 | { | 2563 | { |
2564 | part.ParentGroup.ResetChildPrimPhysicsPositions(); | 2564 | part.ParentGroup.ResetChildPrimPhysicsPositions(); |
2565 | } | 2565 | } |
2566 | } | 2566 | } |
2567 | 2567 | ||
2568 | /// <summary> | 2568 | /// <summary> |
2569 | /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation | 2569 | /// See http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation |
2570 | /// </summary> | 2570 | /// </summary> |
2571 | public LSL_Rotation llGetRot() | 2571 | public LSL_Rotation llGetRot() |
2572 | { | 2572 | { |
2573 | // unlinked or root prim then use llRootRotation | 2573 | // unlinked or root prim then use llRootRotation |
2574 | // see llRootRotaion for references. | 2574 | // see llRootRotaion for references. |
2575 | if (m_host.LinkNum == 0 || m_host.LinkNum == 1) | 2575 | if (m_host.LinkNum == 0 || m_host.LinkNum == 1) |
2576 | { | 2576 | { |
2577 | return llGetRootRotation(); | 2577 | return llGetRootRotation(); |
2578 | } | 2578 | } |
2579 | 2579 | ||
2580 | m_host.AddScriptLPS(1); | 2580 | m_host.AddScriptLPS(1); |
2581 | Quaternion q = m_host.GetWorldRotation(); | 2581 | Quaternion q = m_host.GetWorldRotation(); |
2582 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | 2582 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); |
2583 | } | 2583 | } |
2584 | 2584 | ||
2585 | private LSL_Rotation GetPartRot(SceneObjectPart part) | 2585 | private LSL_Rotation GetPartRot(SceneObjectPart part) |
2586 | { | 2586 | { |
2587 | Quaternion q; | 2587 | Quaternion q; |
2588 | if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim | 2588 | if (part.LinkNum == 0 || part.LinkNum == 1) // unlinked or root prim |
2589 | { | 2589 | { |
2590 | if (part.ParentGroup.AttachmentPoint != 0) | 2590 | if (part.ParentGroup.AttachmentPoint != 0) |
2591 | { | 2591 | { |
2592 | ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar); | 2592 | ScenePresence avatar = World.GetScenePresence(part.ParentGroup.AttachedAvatar); |
2593 | if (avatar != null) | 2593 | if (avatar != null) |
2594 | { | 2594 | { |
2595 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) | 2595 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) |
2596 | q = avatar.CameraRotation; // Mouselook | 2596 | q = avatar.CameraRotation; // Mouselook |
2597 | else | 2597 | else |
2598 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate | 2598 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate |
2599 | } | 2599 | } |
2600 | else | 2600 | else |
2601 | q = part.ParentGroup.GroupRotation; // Likely never get here but just in case | 2601 | q = part.ParentGroup.GroupRotation; // Likely never get here but just in case |
2602 | } | 2602 | } |
2603 | else | 2603 | else |
2604 | q = part.ParentGroup.GroupRotation; // just the group rotation | 2604 | q = part.ParentGroup.GroupRotation; // just the group rotation |
2605 | 2605 | ||
2606 | return new LSL_Rotation(q); | 2606 | return new LSL_Rotation(q); |
2607 | } | 2607 | } |
2608 | 2608 | ||
2609 | return new LSL_Rotation(part.GetWorldRotation()); | 2609 | return new LSL_Rotation(part.GetWorldRotation()); |
2610 | } | 2610 | } |
2611 | 2611 | ||
2612 | public LSL_Rotation llGetLocalRot() | 2612 | public LSL_Rotation llGetLocalRot() |
2613 | { | 2613 | { |
2614 | m_host.AddScriptLPS(1); | 2614 | m_host.AddScriptLPS(1); |
2615 | 2615 | ||
2616 | return new LSL_Rotation(m_host.RotationOffset); | 2616 | return new LSL_Rotation(m_host.RotationOffset); |
2617 | } | 2617 | } |
2618 | 2618 | ||
2619 | public void llSetForce(LSL_Vector force, int local) | 2619 | public void llSetForce(LSL_Vector force, int local) |
2620 | { | 2620 | { |
2621 | m_host.AddScriptLPS(1); | 2621 | m_host.AddScriptLPS(1); |
2622 | 2622 | ||
2623 | if (!m_host.ParentGroup.IsDeleted) | 2623 | if (!m_host.ParentGroup.IsDeleted) |
2624 | { | 2624 | { |
2625 | if (local != 0) | 2625 | if (local != 0) |
2626 | force *= llGetRot(); | 2626 | force *= llGetRot(); |
2627 | 2627 | ||
2628 | m_host.ParentGroup.RootPart.SetForce(force); | 2628 | m_host.ParentGroup.RootPart.SetForce(force); |
2629 | } | 2629 | } |
2630 | } | 2630 | } |
2631 | 2631 | ||
2632 | public LSL_Vector llGetForce() | 2632 | public LSL_Vector llGetForce() |
2633 | { | 2633 | { |
2634 | LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0); | 2634 | LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0); |
2635 | 2635 | ||
2636 | m_host.AddScriptLPS(1); | 2636 | m_host.AddScriptLPS(1); |
2637 | 2637 | ||
2638 | if (!m_host.ParentGroup.IsDeleted) | 2638 | if (!m_host.ParentGroup.IsDeleted) |
2639 | { | 2639 | { |
2640 | force = m_host.ParentGroup.RootPart.GetForce(); | 2640 | force = m_host.ParentGroup.RootPart.GetForce(); |
2641 | } | 2641 | } |
2642 | 2642 | ||
2643 | return force; | 2643 | return force; |
2644 | } | 2644 | } |
2645 | 2645 | ||
2646 | public void llSetVelocity(LSL_Vector velocity, int local) | 2646 | public void llSetVelocity(LSL_Vector velocity, int local) |
2647 | { | 2647 | { |
2648 | m_host.AddScriptLPS(1); | 2648 | m_host.AddScriptLPS(1); |
2649 | 2649 | ||
2650 | if (!m_host.ParentGroup.IsDeleted) | 2650 | if (!m_host.ParentGroup.IsDeleted) |
2651 | { | 2651 | { |
2652 | if (local != 0) | 2652 | if (local != 0) |
2653 | velocity *= llGetRot(); | 2653 | velocity *= llGetRot(); |
2654 | 2654 | ||
2655 | m_host.ParentGroup.RootPart.Velocity = velocity; | 2655 | m_host.ParentGroup.RootPart.Velocity = velocity; |
2656 | } | 2656 | } |
2657 | } | 2657 | } |
2658 | 2658 | ||
2659 | public void llSetAngularVelocity(LSL_Vector angularVelocity, int local) | 2659 | public void llSetAngularVelocity(LSL_Vector angularVelocity, int local) |
2660 | { | 2660 | { |
2661 | m_host.AddScriptLPS(1); | 2661 | m_host.AddScriptLPS(1); |
2662 | 2662 | ||
2663 | if (!m_host.ParentGroup.IsDeleted) | 2663 | if (!m_host.ParentGroup.IsDeleted) |
2664 | { | 2664 | { |
2665 | if (local != 0) | 2665 | if (local != 0) |
2666 | angularVelocity *= llGetRot(); | 2666 | angularVelocity *= llGetRot(); |
2667 | 2667 | ||
2668 | m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity; | 2668 | m_host.ParentGroup.RootPart.AngularVelocity = angularVelocity; |
2669 | } | 2669 | } |
2670 | } | 2670 | } |
2671 | 2671 | ||
2672 | public LSL_Integer llTarget(LSL_Vector position, double range) | 2672 | public LSL_Integer llTarget(LSL_Vector position, double range) |
2673 | { | 2673 | { |
2674 | m_host.AddScriptLPS(1); | 2674 | m_host.AddScriptLPS(1); |
2675 | return m_host.ParentGroup.registerTargetWaypoint(position, | 2675 | return m_host.ParentGroup.registerTargetWaypoint(position, |
2676 | (float)range); | 2676 | (float)range); |
2677 | } | 2677 | } |
2678 | 2678 | ||
2679 | public void llTargetRemove(int number) | 2679 | public void llTargetRemove(int number) |
2680 | { | 2680 | { |
2681 | m_host.AddScriptLPS(1); | 2681 | m_host.AddScriptLPS(1); |
2682 | m_host.ParentGroup.unregisterTargetWaypoint(number); | 2682 | m_host.ParentGroup.unregisterTargetWaypoint(number); |
2683 | } | 2683 | } |
2684 | 2684 | ||
2685 | public LSL_Integer llRotTarget(LSL_Rotation rot, double error) | 2685 | public LSL_Integer llRotTarget(LSL_Rotation rot, double error) |
2686 | { | 2686 | { |
2687 | m_host.AddScriptLPS(1); | 2687 | m_host.AddScriptLPS(1); |
2688 | return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); | 2688 | return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); |
2689 | } | 2689 | } |
2690 | 2690 | ||
2691 | public void llRotTargetRemove(int number) | 2691 | public void llRotTargetRemove(int number) |
2692 | { | 2692 | { |
2693 | m_host.AddScriptLPS(1); | 2693 | m_host.AddScriptLPS(1); |
2694 | m_host.ParentGroup.unregisterRotTargetWaypoint(number); | 2694 | m_host.ParentGroup.unregisterRotTargetWaypoint(number); |
2695 | } | 2695 | } |
2696 | 2696 | ||
2697 | public void llMoveToTarget(LSL_Vector target, double tau) | 2697 | public void llMoveToTarget(LSL_Vector target, double tau) |
2698 | { | 2698 | { |
2699 | m_host.AddScriptLPS(1); | 2699 | m_host.AddScriptLPS(1); |
2700 | m_host.MoveToTarget(target, (float)tau); | 2700 | m_host.MoveToTarget(target, (float)tau); |
2701 | } | 2701 | } |
2702 | 2702 | ||
2703 | public void llStopMoveToTarget() | 2703 | public void llStopMoveToTarget() |
2704 | { | 2704 | { |
2705 | m_host.AddScriptLPS(1); | 2705 | m_host.AddScriptLPS(1); |
2706 | m_host.StopMoveToTarget(); | 2706 | m_host.StopMoveToTarget(); |
2707 | } | 2707 | } |
2708 | 2708 | ||
2709 | public void llApplyImpulse(LSL_Vector force, int local) | 2709 | public void llApplyImpulse(LSL_Vector force, int local) |
2710 | { | 2710 | { |
2711 | m_host.AddScriptLPS(1); | 2711 | m_host.AddScriptLPS(1); |
2712 | //No energy force yet | 2712 | //No energy force yet |
2713 | Vector3 v = force; | 2713 | Vector3 v = force; |
2714 | if (v.Length() > 20000.0f) | 2714 | if (v.Length() > 20000.0f) |
2715 | { | 2715 | { |
2716 | v.Normalize(); | 2716 | v.Normalize(); |
2717 | v = v * 20000.0f; | 2717 | v = v * 20000.0f; |
2718 | } | 2718 | } |
2719 | m_host.ApplyImpulse(v, local != 0); | 2719 | m_host.ApplyImpulse(v, local != 0); |
2720 | } | 2720 | } |
2721 | 2721 | ||
2722 | public void llApplyRotationalImpulse(LSL_Vector force, int local) | 2722 | public void llApplyRotationalImpulse(LSL_Vector force, int local) |
2723 | { | 2723 | { |
2724 | m_host.AddScriptLPS(1); | 2724 | m_host.AddScriptLPS(1); |
2725 | m_host.ApplyAngularImpulse(force, local != 0); | 2725 | m_host.ApplyAngularImpulse(force, local != 0); |
2726 | } | 2726 | } |
2727 | 2727 | ||
2728 | public void llSetTorque(LSL_Vector torque, int local) | 2728 | public void llSetTorque(LSL_Vector torque, int local) |
2729 | { | 2729 | { |
2730 | m_host.AddScriptLPS(1); | 2730 | m_host.AddScriptLPS(1); |
2731 | m_host.SetAngularImpulse(torque, local != 0); | 2731 | m_host.SetAngularImpulse(torque, local != 0); |
2732 | } | 2732 | } |
2733 | 2733 | ||
2734 | public LSL_Vector llGetTorque() | 2734 | public LSL_Vector llGetTorque() |
2735 | { | 2735 | { |
2736 | m_host.AddScriptLPS(1); | 2736 | m_host.AddScriptLPS(1); |
2737 | 2737 | ||
2738 | return new LSL_Vector(m_host.ParentGroup.GetTorque()); | 2738 | return new LSL_Vector(m_host.ParentGroup.GetTorque()); |
2739 | } | 2739 | } |
2740 | 2740 | ||
2741 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) | 2741 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) |
2742 | { | 2742 | { |
2743 | m_host.AddScriptLPS(1); | 2743 | m_host.AddScriptLPS(1); |
2744 | llSetForce(force, local); | 2744 | llSetForce(force, local); |
2745 | llSetTorque(torque, local); | 2745 | llSetTorque(torque, local); |
2746 | } | 2746 | } |
2747 | 2747 | ||
2748 | public LSL_Vector llGetVel() | 2748 | public LSL_Vector llGetVel() |
2749 | { | 2749 | { |
2750 | m_host.AddScriptLPS(1); | 2750 | m_host.AddScriptLPS(1); |
2751 | 2751 | ||
2752 | Vector3 vel; | 2752 | Vector3 vel; |
2753 | 2753 | ||
2754 | if (m_host.ParentGroup.IsAttachment) | 2754 | if (m_host.ParentGroup.IsAttachment) |
2755 | { | 2755 | { |
2756 | ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); | 2756 | ScenePresence avatar = m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.AttachedAvatar); |
2757 | vel = avatar.GetWorldVelocity(); | 2757 | vel = avatar.GetWorldVelocity(); |
2758 | } | 2758 | } |
2759 | else | 2759 | else |
2760 | { | 2760 | { |
2761 | vel = m_host.Velocity; | 2761 | vel = m_host.Velocity; |
2762 | } | 2762 | } |
2763 | 2763 | ||
2764 | return new LSL_Vector(vel); | 2764 | return new LSL_Vector(vel); |
2765 | } | 2765 | } |
2766 | 2766 | ||
2767 | public LSL_Vector llGetAccel() | 2767 | public LSL_Vector llGetAccel() |
2768 | { | 2768 | { |
2769 | m_host.AddScriptLPS(1); | 2769 | m_host.AddScriptLPS(1); |
2770 | 2770 | ||
2771 | return new LSL_Vector(m_host.Acceleration); | 2771 | return new LSL_Vector(m_host.Acceleration); |
2772 | } | 2772 | } |
2773 | 2773 | ||
2774 | public LSL_Vector llGetOmega() | 2774 | public LSL_Vector llGetOmega() |
2775 | { | 2775 | { |
2776 | m_host.AddScriptLPS(1); | 2776 | m_host.AddScriptLPS(1); |
2777 | 2777 | ||
2778 | return new LSL_Vector(m_host.AngularVelocity); | 2778 | return new LSL_Vector(m_host.AngularVelocity); |
2779 | } | 2779 | } |
2780 | 2780 | ||
2781 | public LSL_Float llGetTimeOfDay() | 2781 | public LSL_Float llGetTimeOfDay() |
2782 | { | 2782 | { |
2783 | m_host.AddScriptLPS(1); | 2783 | m_host.AddScriptLPS(1); |
2784 | return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)); | 2784 | return (double)((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)); |
2785 | } | 2785 | } |
2786 | 2786 | ||
2787 | public LSL_Float llGetWallclock() | 2787 | public LSL_Float llGetWallclock() |
2788 | { | 2788 | { |
2789 | m_host.AddScriptLPS(1); | 2789 | m_host.AddScriptLPS(1); |
2790 | return DateTime.Now.TimeOfDay.TotalSeconds; | 2790 | return DateTime.Now.TimeOfDay.TotalSeconds; |
2791 | } | 2791 | } |
2792 | 2792 | ||
2793 | public LSL_Float llGetTime() | 2793 | public LSL_Float llGetTime() |
2794 | { | 2794 | { |
2795 | m_host.AddScriptLPS(1); | 2795 | m_host.AddScriptLPS(1); |
2796 | TimeSpan ScriptTime = DateTime.Now - m_timer; | 2796 | TimeSpan ScriptTime = DateTime.Now - m_timer; |
2797 | return (double)(ScriptTime.TotalMilliseconds / 1000); | 2797 | return (double)(ScriptTime.TotalMilliseconds / 1000); |
2798 | } | 2798 | } |
2799 | 2799 | ||
2800 | public void llResetTime() | 2800 | public void llResetTime() |
2801 | { | 2801 | { |
2802 | m_host.AddScriptLPS(1); | 2802 | m_host.AddScriptLPS(1); |
2803 | m_timer = DateTime.Now; | 2803 | m_timer = DateTime.Now; |
2804 | } | 2804 | } |
2805 | 2805 | ||
2806 | public LSL_Float llGetAndResetTime() | 2806 | public LSL_Float llGetAndResetTime() |
2807 | { | 2807 | { |
2808 | m_host.AddScriptLPS(1); | 2808 | m_host.AddScriptLPS(1); |
2809 | TimeSpan ScriptTime = DateTime.Now - m_timer; | 2809 | TimeSpan ScriptTime = DateTime.Now - m_timer; |
2810 | m_timer = DateTime.Now; | 2810 | m_timer = DateTime.Now; |
2811 | return (double)(ScriptTime.TotalMilliseconds / 1000); | 2811 | return (double)(ScriptTime.TotalMilliseconds / 1000); |
2812 | } | 2812 | } |
2813 | 2813 | ||
2814 | public void llSound(string sound, double volume, int queue, int loop) | 2814 | public void llSound(string sound, double volume, int queue, int loop) |
2815 | { | 2815 | { |
2816 | m_host.AddScriptLPS(1); | 2816 | m_host.AddScriptLPS(1); |
2817 | Deprecated("llSound", "Use llPlaySound instead"); | 2817 | Deprecated("llSound", "Use llPlaySound instead"); |
2818 | } | 2818 | } |
2819 | 2819 | ||
2820 | // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound | 2820 | // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound |
2821 | // 20080530 Updated to remove code duplication | 2821 | // 20080530 Updated to remove code duplication |
2822 | public void llPlaySound(string sound, double volume) | 2822 | public void llPlaySound(string sound, double volume) |
2823 | { | 2823 | { |
2824 | m_host.AddScriptLPS(1); | 2824 | m_host.AddScriptLPS(1); |
2825 | 2825 | ||
2826 | // send the sound, once, to all clients in range | 2826 | // send the sound, once, to all clients in range |
2827 | if (m_SoundModule != null) | 2827 | if (m_SoundModule != null) |
2828 | { | 2828 | { |
2829 | m_SoundModule.SendSound( | 2829 | m_SoundModule.SendSound( |
2830 | m_host.UUID, | 2830 | m_host.UUID, |
2831 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), | 2831 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), |
2832 | volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None, | 2832 | volume, false, m_host.SoundQueueing ? (byte)SoundFlags.Queue : (byte)SoundFlags.None, |
2833 | 0, false, false); | 2833 | 0, false, false); |
2834 | } | 2834 | } |
2835 | } | 2835 | } |
2836 | 2836 | ||
2837 | public void llLoopSound(string sound, double volume) | 2837 | public void llLoopSound(string sound, double volume) |
2838 | { | 2838 | { |
2839 | m_host.AddScriptLPS(1); | 2839 | m_host.AddScriptLPS(1); |
2840 | if (m_SoundModule != null) | 2840 | if (m_SoundModule != null) |
2841 | { | 2841 | { |
2842 | m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), | 2842 | m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), |
2843 | volume, 20, false); | 2843 | volume, 20, false); |
2844 | } | 2844 | } |
2845 | } | 2845 | } |
2846 | 2846 | ||
2847 | public void llLoopSoundMaster(string sound, double volume) | 2847 | public void llLoopSoundMaster(string sound, double volume) |
2848 | { | 2848 | { |
2849 | m_host.AddScriptLPS(1); | 2849 | m_host.AddScriptLPS(1); |
2850 | if (m_SoundModule != null) | 2850 | if (m_SoundModule != null) |
2851 | { | 2851 | { |
2852 | m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), | 2852 | m_SoundModule.LoopSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), |
2853 | volume, 20, true); | 2853 | volume, 20, true); |
2854 | } | 2854 | } |
2855 | } | 2855 | } |
2856 | 2856 | ||
2857 | public void llLoopSoundSlave(string sound, double volume) | 2857 | public void llLoopSoundSlave(string sound, double volume) |
2858 | { | 2858 | { |
2859 | m_host.AddScriptLPS(1); | 2859 | m_host.AddScriptLPS(1); |
2860 | lock (m_host.ParentGroup.LoopSoundSlavePrims) | 2860 | lock (m_host.ParentGroup.LoopSoundSlavePrims) |
2861 | { | 2861 | { |
2862 | m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host); | 2862 | m_host.ParentGroup.LoopSoundSlavePrims.Add(m_host); |
2863 | } | 2863 | } |
2864 | } | 2864 | } |
2865 | 2865 | ||
2866 | public void llPlaySoundSlave(string sound, double volume) | 2866 | public void llPlaySoundSlave(string sound, double volume) |
2867 | { | 2867 | { |
2868 | m_host.AddScriptLPS(1); | 2868 | m_host.AddScriptLPS(1); |
2869 | 2869 | ||
2870 | // send the sound, once, to all clients in range | 2870 | // send the sound, once, to all clients in range |
2871 | if (m_SoundModule != null) | 2871 | if (m_SoundModule != null) |
2872 | { | 2872 | { |
2873 | m_SoundModule.SendSound(m_host.UUID, | 2873 | m_SoundModule.SendSound(m_host.UUID, |
2874 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, | 2874 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, false, 0, |
2875 | 0, true, false); | 2875 | 0, true, false); |
2876 | } | 2876 | } |
2877 | } | 2877 | } |
2878 | 2878 | ||
2879 | public void llTriggerSound(string sound, double volume) | 2879 | public void llTriggerSound(string sound, double volume) |
2880 | { | 2880 | { |
2881 | m_host.AddScriptLPS(1); | 2881 | m_host.AddScriptLPS(1); |
2882 | // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. | 2882 | // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. |
2883 | if (m_SoundModule != null) | 2883 | if (m_SoundModule != null) |
2884 | { | 2884 | { |
2885 | m_SoundModule.SendSound(m_host.UUID, | 2885 | m_SoundModule.SendSound(m_host.UUID, |
2886 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0, | 2886 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, true, 0, 0, |
2887 | false, false); | 2887 | false, false); |
2888 | } | 2888 | } |
2889 | } | 2889 | } |
2890 | 2890 | ||
2891 | public void llStopSound() | 2891 | public void llStopSound() |
2892 | { | 2892 | { |
2893 | m_host.AddScriptLPS(1); | 2893 | m_host.AddScriptLPS(1); |
2894 | 2894 | ||
2895 | if (m_SoundModule != null) | 2895 | if (m_SoundModule != null) |
2896 | m_SoundModule.StopSound(m_host.UUID); | 2896 | m_SoundModule.StopSound(m_host.UUID); |
2897 | } | 2897 | } |
2898 | 2898 | ||
2899 | public void llPreloadSound(string sound) | 2899 | public void llPreloadSound(string sound) |
2900 | { | 2900 | { |
2901 | m_host.AddScriptLPS(1); | 2901 | m_host.AddScriptLPS(1); |
2902 | if (m_SoundModule != null) | 2902 | if (m_SoundModule != null) |
2903 | m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0); | 2903 | m_SoundModule.PreloadSound(m_host.UUID, ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound), 0); |
2904 | ScriptSleep(m_sleepMsOnPreloadSound); | 2904 | ScriptSleep(m_sleepMsOnPreloadSound); |
2905 | } | 2905 | } |
2906 | 2906 | ||
2907 | /// <summary> | 2907 | /// <summary> |
2908 | /// Return a portion of the designated string bounded by | 2908 | /// Return a portion of the designated string bounded by |
2909 | /// inclusive indices (start and end). As usual, the negative | 2909 | /// inclusive indices (start and end). As usual, the negative |
2910 | /// indices, and the tolerance for out-of-bound values, makes | 2910 | /// indices, and the tolerance for out-of-bound values, makes |
2911 | /// this more complicated than it might otherwise seem. | 2911 | /// this more complicated than it might otherwise seem. |
2912 | /// </summary> | 2912 | /// </summary> |
2913 | public LSL_String llGetSubString(string src, int start, int end) | 2913 | public LSL_String llGetSubString(string src, int start, int end) |
2914 | { | 2914 | { |
2915 | m_host.AddScriptLPS(1); | 2915 | m_host.AddScriptLPS(1); |
2916 | 2916 | ||
2917 | // Normalize indices (if negative). | 2917 | // Normalize indices (if negative). |
2918 | // After normlaization they may still be | 2918 | // After normlaization they may still be |
2919 | // negative, but that is now relative to | 2919 | // negative, but that is now relative to |
2920 | // the start, rather than the end, of the | 2920 | // the start, rather than the end, of the |
2921 | // sequence. | 2921 | // sequence. |
2922 | 2922 | ||
2923 | if (start < 0) | 2923 | if (start < 0) |
2924 | { | 2924 | { |
2925 | start = src.Length+start; | 2925 | start = src.Length+start; |
2926 | } | 2926 | } |
2927 | if (end < 0) | 2927 | if (end < 0) |
2928 | { | 2928 | { |
2929 | end = src.Length+end; | 2929 | end = src.Length+end; |
2930 | } | 2930 | } |
2931 | 2931 | ||
2932 | // Conventional substring | 2932 | // Conventional substring |
2933 | if (start <= end) | 2933 | if (start <= end) |
2934 | { | 2934 | { |
2935 | // Implies both bounds are out-of-range. | 2935 | // Implies both bounds are out-of-range. |
2936 | if (end < 0 || start >= src.Length) | 2936 | if (end < 0 || start >= src.Length) |
2937 | { | 2937 | { |
2938 | return String.Empty; | 2938 | return String.Empty; |
2939 | } | 2939 | } |
2940 | // If end is positive, then it directly | 2940 | // If end is positive, then it directly |
2941 | // corresponds to the lengt of the substring | 2941 | // corresponds to the lengt of the substring |
2942 | // needed (plus one of course). BUT, it | 2942 | // needed (plus one of course). BUT, it |
2943 | // must be within bounds. | 2943 | // must be within bounds. |
2944 | if (end >= src.Length) | 2944 | if (end >= src.Length) |
2945 | { | 2945 | { |
2946 | end = src.Length-1; | 2946 | end = src.Length-1; |
2947 | } | 2947 | } |
2948 | 2948 | ||
2949 | if (start < 0) | 2949 | if (start < 0) |
2950 | { | 2950 | { |
2951 | return src.Substring(0,end+1); | 2951 | return src.Substring(0,end+1); |
2952 | } | 2952 | } |
2953 | // Both indices are positive | 2953 | // Both indices are positive |
2954 | return src.Substring(start, (end+1) - start); | 2954 | return src.Substring(start, (end+1) - start); |
2955 | } | 2955 | } |
2956 | 2956 | ||
2957 | // Inverted substring (end < start) | 2957 | // Inverted substring (end < start) |
2958 | else | 2958 | else |
2959 | { | 2959 | { |
2960 | // Implies both indices are below the | 2960 | // Implies both indices are below the |
2961 | // lower bound. In the inverted case, that | 2961 | // lower bound. In the inverted case, that |
2962 | // means the entire string will be returned | 2962 | // means the entire string will be returned |
2963 | // unchanged. | 2963 | // unchanged. |
2964 | if (start < 0) | 2964 | if (start < 0) |
2965 | { | 2965 | { |
2966 | return src; | 2966 | return src; |
2967 | } | 2967 | } |
2968 | // If both indices are greater than the upper | 2968 | // If both indices are greater than the upper |
2969 | // bound the result may seem initially counter | 2969 | // bound the result may seem initially counter |
2970 | // intuitive. | 2970 | // intuitive. |
2971 | if (end >= src.Length) | 2971 | if (end >= src.Length) |
2972 | { | 2972 | { |
2973 | return src; | 2973 | return src; |
2974 | } | 2974 | } |
2975 | 2975 | ||
2976 | if (end < 0) | 2976 | if (end < 0) |
2977 | { | 2977 | { |
2978 | if (start < src.Length) | 2978 | if (start < src.Length) |
2979 | { | 2979 | { |
2980 | return src.Substring(start); | 2980 | return src.Substring(start); |
2981 | } | 2981 | } |
2982 | else | 2982 | else |
2983 | { | 2983 | { |
2984 | return String.Empty; | 2984 | return String.Empty; |
2985 | } | 2985 | } |
2986 | } | 2986 | } |
2987 | else | 2987 | else |
2988 | { | 2988 | { |
2989 | if (start < src.Length) | 2989 | if (start < src.Length) |
2990 | { | 2990 | { |
2991 | return src.Substring(0,end+1) + src.Substring(start); | 2991 | return src.Substring(0,end+1) + src.Substring(start); |
2992 | } | 2992 | } |
2993 | else | 2993 | else |
2994 | { | 2994 | { |
2995 | return src.Substring(0,end+1); | 2995 | return src.Substring(0,end+1); |
2996 | } | 2996 | } |
2997 | } | 2997 | } |
2998 | } | 2998 | } |
2999 | } | 2999 | } |
3000 | 3000 | ||
3001 | /// <summary> | 3001 | /// <summary> |
3002 | /// Delete substring removes the specified substring bounded | 3002 | /// Delete substring removes the specified substring bounded |
3003 | /// by the inclusive indices start and end. Indices may be | 3003 | /// by the inclusive indices start and end. Indices may be |
3004 | /// negative (indicating end-relative) and may be inverted, | 3004 | /// negative (indicating end-relative) and may be inverted, |
3005 | /// i.e. end < start. | 3005 | /// i.e. end < start. |
3006 | /// </summary> | 3006 | /// </summary> |
3007 | public LSL_String llDeleteSubString(string src, int start, int end) | 3007 | public LSL_String llDeleteSubString(string src, int start, int end) |
3008 | { | 3008 | { |
3009 | m_host.AddScriptLPS(1); | 3009 | m_host.AddScriptLPS(1); |
3010 | 3010 | ||
3011 | // Normalize indices (if negative). | 3011 | // Normalize indices (if negative). |
3012 | // After normlaization they may still be | 3012 | // After normlaization they may still be |
3013 | // negative, but that is now relative to | 3013 | // negative, but that is now relative to |
3014 | // the start, rather than the end, of the | 3014 | // the start, rather than the end, of the |
3015 | // sequence. | 3015 | // sequence. |
3016 | if (start < 0) | 3016 | if (start < 0) |
3017 | { | 3017 | { |
3018 | start = src.Length+start; | 3018 | start = src.Length+start; |
3019 | } | 3019 | } |
3020 | if (end < 0) | 3020 | if (end < 0) |
3021 | { | 3021 | { |
3022 | end = src.Length+end; | 3022 | end = src.Length+end; |
3023 | } | 3023 | } |
3024 | // Conventionally delimited substring | 3024 | // Conventionally delimited substring |
3025 | if (start <= end) | 3025 | if (start <= end) |
3026 | { | 3026 | { |
3027 | // If both bounds are outside of the existing | 3027 | // If both bounds are outside of the existing |
3028 | // string, then return unchanges. | 3028 | // string, then return unchanges. |
3029 | if (end < 0 || start >= src.Length) | 3029 | if (end < 0 || start >= src.Length) |
3030 | { | 3030 | { |
3031 | return src; | 3031 | return src; |
3032 | } | 3032 | } |
3033 | // At least one bound is in-range, so we | 3033 | // At least one bound is in-range, so we |
3034 | // need to clip the out-of-bound argument. | 3034 | // need to clip the out-of-bound argument. |
3035 | if (start < 0) | 3035 | if (start < 0) |
3036 | { | 3036 | { |
3037 | start = 0; | 3037 | start = 0; |
3038 | } | 3038 | } |
3039 | 3039 | ||
3040 | if (end >= src.Length) | 3040 | if (end >= src.Length) |
3041 | { | 3041 | { |
3042 | end = src.Length-1; | 3042 | end = src.Length-1; |
3043 | } | 3043 | } |
3044 | 3044 | ||
3045 | return src.Remove(start,end-start+1); | 3045 | return src.Remove(start,end-start+1); |
3046 | } | 3046 | } |
3047 | // Inverted substring | 3047 | // Inverted substring |
3048 | else | 3048 | else |
3049 | { | 3049 | { |
3050 | // In this case, out of bounds means that | 3050 | // In this case, out of bounds means that |
3051 | // the existing string is part of the cut. | 3051 | // the existing string is part of the cut. |
3052 | if (start < 0 || end >= src.Length) | 3052 | if (start < 0 || end >= src.Length) |
3053 | { | 3053 | { |
3054 | return String.Empty; | 3054 | return String.Empty; |
3055 | } | 3055 | } |
3056 | 3056 | ||
3057 | if (end > 0) | 3057 | if (end > 0) |
3058 | { | 3058 | { |
3059 | if (start < src.Length) | 3059 | if (start < src.Length) |
3060 | { | 3060 | { |
3061 | return src.Remove(start).Remove(0,end+1); | 3061 | return src.Remove(start).Remove(0,end+1); |
3062 | } | 3062 | } |
3063 | else | 3063 | else |
3064 | { | 3064 | { |
3065 | return src.Remove(0,end+1); | 3065 | return src.Remove(0,end+1); |
3066 | } | 3066 | } |
3067 | } | 3067 | } |
3068 | else | 3068 | else |
3069 | { | 3069 | { |
3070 | if (start < src.Length) | 3070 | if (start < src.Length) |
3071 | { | 3071 | { |
3072 | return src.Remove(start); | 3072 | return src.Remove(start); |
3073 | } | 3073 | } |
3074 | else | 3074 | else |
3075 | { | 3075 | { |
3076 | return src; | 3076 | return src; |
3077 | } | 3077 | } |
3078 | } | 3078 | } |
3079 | } | 3079 | } |
3080 | } | 3080 | } |
3081 | 3081 | ||
3082 | /// <summary> | 3082 | /// <summary> |
3083 | /// Insert string inserts the specified string identified by src | 3083 | /// Insert string inserts the specified string identified by src |
3084 | /// at the index indicated by index. Index may be negative, in | 3084 | /// at the index indicated by index. Index may be negative, in |
3085 | /// which case it is end-relative. The index may exceed either | 3085 | /// which case it is end-relative. The index may exceed either |
3086 | /// string bound, with the result being a concatenation. | 3086 | /// string bound, with the result being a concatenation. |
3087 | /// </summary> | 3087 | /// </summary> |
3088 | public LSL_String llInsertString(string dest, int index, string src) | 3088 | public LSL_String llInsertString(string dest, int index, string src) |
3089 | { | 3089 | { |
3090 | m_host.AddScriptLPS(1); | 3090 | m_host.AddScriptLPS(1); |
3091 | 3091 | ||
3092 | // Normalize indices (if negative). | 3092 | // Normalize indices (if negative). |
3093 | // After normlaization they may still be | 3093 | // After normlaization they may still be |
3094 | // negative, but that is now relative to | 3094 | // negative, but that is now relative to |
3095 | // the start, rather than the end, of the | 3095 | // the start, rather than the end, of the |
3096 | // sequence. | 3096 | // sequence. |
3097 | if (index < 0) | 3097 | if (index < 0) |
3098 | { | 3098 | { |
3099 | index = dest.Length+index; | 3099 | index = dest.Length+index; |
3100 | 3100 | ||
3101 | // Negative now means it is less than the lower | 3101 | // Negative now means it is less than the lower |
3102 | // bound of the string. | 3102 | // bound of the string. |
3103 | 3103 | ||
3104 | if (index < 0) | 3104 | if (index < 0) |
3105 | { | 3105 | { |
3106 | return src+dest; | 3106 | return src+dest; |
3107 | } | 3107 | } |
3108 | 3108 | ||
3109 | } | 3109 | } |
3110 | 3110 | ||
3111 | if (index >= dest.Length) | 3111 | if (index >= dest.Length) |
3112 | { | 3112 | { |
3113 | return dest+src; | 3113 | return dest+src; |
3114 | } | 3114 | } |
3115 | 3115 | ||
3116 | // The index is in bounds. | 3116 | // The index is in bounds. |
3117 | // In this case the index refers to the index that will | 3117 | // In this case the index refers to the index that will |
3118 | // be assigned to the first character of the inserted string. | 3118 | // be assigned to the first character of the inserted string. |
3119 | // So unlike the other string operations, we do not add one | 3119 | // So unlike the other string operations, we do not add one |
3120 | // to get the correct string length. | 3120 | // to get the correct string length. |
3121 | return dest.Substring(0,index)+src+dest.Substring(index); | 3121 | return dest.Substring(0,index)+src+dest.Substring(index); |
3122 | 3122 | ||
3123 | } | 3123 | } |
3124 | 3124 | ||
3125 | public LSL_String llToUpper(string src) | 3125 | public LSL_String llToUpper(string src) |
3126 | { | 3126 | { |
3127 | m_host.AddScriptLPS(1); | 3127 | m_host.AddScriptLPS(1); |
3128 | return src.ToUpper(); | 3128 | return src.ToUpper(); |
3129 | } | 3129 | } |
3130 | 3130 | ||
3131 | public LSL_String llToLower(string src) | 3131 | public LSL_String llToLower(string src) |
3132 | { | 3132 | { |
3133 | m_host.AddScriptLPS(1); | 3133 | m_host.AddScriptLPS(1); |
3134 | return src.ToLower(); | 3134 | return src.ToLower(); |
3135 | } | 3135 | } |
3136 | 3136 | ||
3137 | public void llGiveMoney(string destination, int amount) | 3137 | public void llGiveMoney(string destination, int amount) |
3138 | { | 3138 | { |
3139 | Util.FireAndForget(x => | 3139 | Util.FireAndForget(x => |
3140 | { | 3140 | { |
3141 | m_host.AddScriptLPS(1); | 3141 | m_host.AddScriptLPS(1); |
3142 | 3142 | ||
3143 | if (m_item.PermsGranter == UUID.Zero) | 3143 | if (m_item.PermsGranter == UUID.Zero) |
3144 | return; | 3144 | return; |
3145 | 3145 | ||
3146 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) | 3146 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) |
3147 | { | 3147 | { |
3148 | Error("llGiveMoney", "No permissions to give money"); | 3148 | Error("llGiveMoney", "No permissions to give money"); |
3149 | return; | 3149 | return; |
3150 | } | 3150 | } |
3151 | 3151 | ||
3152 | UUID toID = new UUID(); | 3152 | UUID toID = new UUID(); |
3153 | 3153 | ||
3154 | if (!UUID.TryParse(destination, out toID)) | 3154 | if (!UUID.TryParse(destination, out toID)) |
3155 | { | 3155 | { |
3156 | Error("llGiveMoney", "Bad key in llGiveMoney"); | 3156 | Error("llGiveMoney", "Bad key in llGiveMoney"); |
3157 | return; | 3157 | return; |
3158 | } | 3158 | } |
3159 | 3159 | ||
3160 | IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); | 3160 | IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); |
3161 | 3161 | ||
3162 | if (money == null) | 3162 | if (money == null) |
3163 | { | 3163 | { |
3164 | NotImplemented("llGiveMoney"); | 3164 | NotImplemented("llGiveMoney"); |
3165 | return; | 3165 | return; |
3166 | } | 3166 | } |
3167 | 3167 | ||
3168 | money.ObjectGiveMoney( | 3168 | money.ObjectGiveMoney( |
3169 | m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); | 3169 | m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); |
3170 | }, null, "LSL_Api.llGiveMoney"); | 3170 | }, null, "LSL_Api.llGiveMoney"); |
3171 | } | 3171 | } |
3172 | 3172 | ||
3173 | public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) | 3173 | public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) |
3174 | { | 3174 | { |
3175 | m_host.AddScriptLPS(1); | 3175 | m_host.AddScriptLPS(1); |
3176 | Deprecated("llMakeExplosion", "Use llParticleSystem instead"); | 3176 | Deprecated("llMakeExplosion", "Use llParticleSystem instead"); |
3177 | ScriptSleep(m_sleepMsOnMakeExplosion); | 3177 | ScriptSleep(m_sleepMsOnMakeExplosion); |
3178 | } | 3178 | } |
3179 | 3179 | ||
3180 | public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset) | 3180 | public void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset) |
3181 | { | 3181 | { |
3182 | m_host.AddScriptLPS(1); | 3182 | m_host.AddScriptLPS(1); |
3183 | Deprecated("llMakeFountain", "Use llParticleSystem instead"); | 3183 | Deprecated("llMakeFountain", "Use llParticleSystem instead"); |
3184 | ScriptSleep(m_sleepMsOnMakeFountain); | 3184 | ScriptSleep(m_sleepMsOnMakeFountain); |
3185 | } | 3185 | } |
3186 | 3186 | ||
3187 | public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) | 3187 | public void llMakeSmoke(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) |
3188 | { | 3188 | { |
3189 | m_host.AddScriptLPS(1); | 3189 | m_host.AddScriptLPS(1); |
3190 | Deprecated("llMakeSmoke", "Use llParticleSystem instead"); | 3190 | Deprecated("llMakeSmoke", "Use llParticleSystem instead"); |
3191 | ScriptSleep(m_sleepMsOnMakeSmoke); | 3191 | ScriptSleep(m_sleepMsOnMakeSmoke); |
3192 | } | 3192 | } |
3193 | 3193 | ||
3194 | public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) | 3194 | public void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) |
3195 | { | 3195 | { |
3196 | m_host.AddScriptLPS(1); | 3196 | m_host.AddScriptLPS(1); |
3197 | Deprecated("llMakeFire", "Use llParticleSystem instead"); | 3197 | Deprecated("llMakeFire", "Use llParticleSystem instead"); |
3198 | ScriptSleep(m_sleepMsOnMakeFire); | 3198 | ScriptSleep(m_sleepMsOnMakeFire); |
3199 | } | 3199 | } |
3200 | 3200 | ||
3201 | public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | 3201 | public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) |
3202 | { | 3202 | { |
3203 | m_host.AddScriptLPS(1); | 3203 | m_host.AddScriptLPS(1); |
3204 | 3204 | ||
3205 | Util.FireAndForget(x => | 3205 | Util.FireAndForget(x => |
3206 | { | 3206 | { |
3207 | if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) | 3207 | if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) |
3208 | return; | 3208 | return; |
3209 | 3209 | ||
3210 | float dist = (float)llVecDist(llGetPos(), pos); | 3210 | float dist = (float)llVecDist(llGetPos(), pos); |
3211 | 3211 | ||
3212 | if (dist > m_ScriptDistanceFactor * 10.0f) | 3212 | if (dist > m_ScriptDistanceFactor * 10.0f) |
3213 | return; | 3213 | return; |
3214 | 3214 | ||
3215 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); | 3215 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); |
3216 | 3216 | ||
3217 | if (item == null) | 3217 | if (item == null) |
3218 | { | 3218 | { |
3219 | Error("llRezAtRoot", "Can't find object '" + inventory + "'"); | 3219 | Error("llRezAtRoot", "Can't find object '" + inventory + "'"); |
3220 | return; | 3220 | return; |
3221 | } | 3221 | } |
3222 | 3222 | ||
3223 | if (item.InvType != (int)InventoryType.Object) | 3223 | if (item.InvType != (int)InventoryType.Object) |
3224 | { | 3224 | { |
3225 | Error("llRezAtRoot", "Can't create requested object; object is missing from database"); | 3225 | Error("llRezAtRoot", "Can't create requested object; object is missing from database"); |
3226 | return; | 3226 | return; |
3227 | } | 3227 | } |
3228 | 3228 | ||
3229 | // need the magnitude later | 3229 | // need the magnitude later |
3230 | // float velmag = (float)Util.GetMagnitude(llvel); | 3230 | // float velmag = (float)Util.GetMagnitude(llvel); |
3231 | 3231 | ||
3232 | List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param); | 3232 | List<SceneObjectGroup> new_groups = World.RezObject(m_host, item, pos, rot, vel, param); |
3233 | 3233 | ||
3234 | // If either of these are null, then there was an unknown error. | 3234 | // If either of these are null, then there was an unknown error. |
3235 | if (new_groups == null) | 3235 | if (new_groups == null) |
3236 | return; | 3236 | return; |
3237 | 3237 | ||
3238 | foreach (SceneObjectGroup group in new_groups) | 3238 | foreach (SceneObjectGroup group in new_groups) |
3239 | { | 3239 | { |
3240 | // objects rezzed with this method are die_at_edge by default. | 3240 | // objects rezzed with this method are die_at_edge by default. |
3241 | group.RootPart.SetDieAtEdge(true); | 3241 | group.RootPart.SetDieAtEdge(true); |
3242 | 3242 | ||
3243 | group.ResumeScripts(); | 3243 | group.ResumeScripts(); |
3244 | 3244 | ||
3245 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( | 3245 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( |
3246 | "object_rez", new Object[] { | 3246 | "object_rez", new Object[] { |
3247 | new LSL_String( | 3247 | new LSL_String( |
3248 | group.RootPart.UUID.ToString()) }, | 3248 | group.RootPart.UUID.ToString()) }, |
3249 | new DetectParams[0])); | 3249 | new DetectParams[0])); |
3250 | 3250 | ||
3251 | float groupmass = group.GetMass(); | 3251 | float groupmass = group.GetMass(); |
3252 | 3252 | ||
3253 | PhysicsActor pa = group.RootPart.PhysActor; | 3253 | PhysicsActor pa = group.RootPart.PhysActor; |
3254 | 3254 | ||
3255 | //Recoil. | 3255 | //Recoil. |
3256 | if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) | 3256 | if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) |
3257 | { | 3257 | { |
3258 | Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; | 3258 | Vector3 recoil = -vel * groupmass * m_recoilScaleFactor; |
3259 | if (recoil != Vector3.Zero) | 3259 | if (recoil != Vector3.Zero) |
3260 | { | 3260 | { |
3261 | llApplyImpulse(recoil, 0); | 3261 | llApplyImpulse(recoil, 0); |
3262 | } | 3262 | } |
3263 | } | 3263 | } |
3264 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) | 3264 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) |
3265 | } | 3265 | } |
3266 | }, null, "LSL_Api.llRezAtRoot"); | 3266 | }, null, "LSL_Api.llRezAtRoot"); |
3267 | 3267 | ||
3268 | //ScriptSleep((int)((groupmass * velmag) / 10)); | 3268 | //ScriptSleep((int)((groupmass * velmag) / 10)); |
3269 | ScriptSleep(m_sleepMsOnRezAtRoot); | 3269 | ScriptSleep(m_sleepMsOnRezAtRoot); |
3270 | } | 3270 | } |
3271 | 3271 | ||
3272 | public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | 3272 | public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) |
3273 | { | 3273 | { |
3274 | llRezAtRoot(inventory, pos, vel, rot, param); | 3274 | llRezAtRoot(inventory, pos, vel, rot, param); |
3275 | } | 3275 | } |
3276 | 3276 | ||
3277 | public void llLookAt(LSL_Vector target, double strength, double damping) | 3277 | public void llLookAt(LSL_Vector target, double strength, double damping) |
3278 | { | 3278 | { |
3279 | m_host.AddScriptLPS(1); | 3279 | m_host.AddScriptLPS(1); |
3280 | // Determine where we are looking from | 3280 | // Determine where we are looking from |
3281 | LSL_Vector from = llGetPos(); | 3281 | LSL_Vector from = llGetPos(); |
3282 | 3282 | ||
3283 | // normalized direction to target | 3283 | // normalized direction to target |
3284 | LSL_Vector dir = llVecNorm(target - from); | 3284 | LSL_Vector dir = llVecNorm(target - from); |
3285 | // use vertical to help compute left axis | 3285 | // use vertical to help compute left axis |
3286 | LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0); | 3286 | LSL_Vector up = new LSL_Vector(0.0, 0.0, 1.0); |
3287 | // find normalized left axis parallel to horizon | 3287 | // find normalized left axis parallel to horizon |
3288 | LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir)); | 3288 | LSL_Vector left = llVecNorm(LSL_Vector.Cross(up, dir)); |
3289 | // make up orthogonal to left and dir | 3289 | // make up orthogonal to left and dir |
3290 | up = LSL_Vector.Cross(dir, left); | 3290 | up = LSL_Vector.Cross(dir, left); |
3291 | 3291 | ||
3292 | // compute rotation based on orthogonal axes | 3292 | // compute rotation based on orthogonal axes |
3293 | LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up); | 3293 | LSL_Rotation rot = new LSL_Rotation(0.0, 0.707107, 0.0, 0.707107) * llAxes2Rot(dir, left, up); |
3294 | 3294 | ||
3295 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply | 3295 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply |
3296 | // set the rotation of the object, copy that behavior | 3296 | // set the rotation of the object, copy that behavior |
3297 | PhysicsActor pa = m_host.PhysActor; | 3297 | PhysicsActor pa = m_host.PhysActor; |
3298 | 3298 | ||
3299 | if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical) | 3299 | if (m_host.ParentGroup.IsAttachment || strength == 0 || pa == null || !pa.IsPhysical) |
3300 | { | 3300 | { |
3301 | llSetRot(rot); | 3301 | llSetRot(rot); |
3302 | } | 3302 | } |
3303 | else | 3303 | else |
3304 | { | 3304 | { |
3305 | m_host.StartLookAt(rot, (float)strength, (float)damping); | 3305 | m_host.StartLookAt(rot, (float)strength, (float)damping); |
3306 | } | 3306 | } |
3307 | } | 3307 | } |
3308 | 3308 | ||
3309 | public void llStopLookAt() | 3309 | public void llStopLookAt() |
3310 | { | 3310 | { |
3311 | m_host.AddScriptLPS(1); | 3311 | m_host.AddScriptLPS(1); |
3312 | m_host.StopLookAt(); | 3312 | m_host.StopLookAt(); |
3313 | } | 3313 | } |
3314 | 3314 | ||
3315 | public void llSetTimerEvent(double sec) | 3315 | public void llSetTimerEvent(double sec) |
3316 | { | 3316 | { |
3317 | if (sec != 0.0 && sec < m_MinTimerInterval) | 3317 | if (sec != 0.0 && sec < m_MinTimerInterval) |
3318 | sec = m_MinTimerInterval; | 3318 | sec = m_MinTimerInterval; |
3319 | m_host.AddScriptLPS(1); | 3319 | m_host.AddScriptLPS(1); |
3320 | // Setting timer repeat | 3320 | // Setting timer repeat |
3321 | AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec); | 3321 | AsyncCommands.TimerPlugin.SetTimerEvent(m_host.LocalId, m_item.ItemID, sec); |
3322 | } | 3322 | } |
3323 | 3323 | ||
3324 | public virtual void llSleep(double sec) | 3324 | public virtual void llSleep(double sec) |
3325 | { | 3325 | { |
3326 | // m_log.Info("llSleep snoozing " + sec + "s."); | 3326 | // m_log.Info("llSleep snoozing " + sec + "s."); |
3327 | m_host.AddScriptLPS(1); | 3327 | m_host.AddScriptLPS(1); |
3328 | 3328 | ||
3329 | Sleep((int)(sec * 1000)); | 3329 | Sleep((int)(sec * 1000)); |
3330 | } | 3330 | } |
3331 | 3331 | ||
3332 | public LSL_Float llGetMass() | 3332 | public LSL_Float llGetMass() |
3333 | { | 3333 | { |
3334 | m_host.AddScriptLPS(1); | 3334 | m_host.AddScriptLPS(1); |
3335 | 3335 | ||
3336 | if (m_host.ParentGroup.IsAttachment) | 3336 | if (m_host.ParentGroup.IsAttachment) |
3337 | { | 3337 | { |
3338 | ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); | 3338 | ScenePresence attachedAvatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); |
3339 | 3339 | ||
3340 | if (attachedAvatar != null) | 3340 | if (attachedAvatar != null) |
3341 | { | 3341 | { |
3342 | return attachedAvatar.GetMass(); | 3342 | return attachedAvatar.GetMass(); |
3343 | } | 3343 | } |
3344 | else | 3344 | else |
3345 | { | 3345 | { |
3346 | return 0; | 3346 | return 0; |
3347 | } | 3347 | } |
3348 | } | 3348 | } |
3349 | else | 3349 | else |
3350 | { | 3350 | { |
3351 | if (m_host.IsRoot) | 3351 | if (m_host.IsRoot) |
3352 | { | 3352 | { |
3353 | return m_host.ParentGroup.GetMass(); | 3353 | return m_host.ParentGroup.GetMass(); |
3354 | } | 3354 | } |
3355 | else | 3355 | else |
3356 | { | 3356 | { |
3357 | return m_host.GetMass(); | 3357 | return m_host.GetMass(); |
3358 | } | 3358 | } |
3359 | } | 3359 | } |
3360 | } | 3360 | } |
3361 | 3361 | ||
3362 | public LSL_Float llGetMassMKS() | 3362 | public LSL_Float llGetMassMKS() |
3363 | { | 3363 | { |
3364 | // this is what the wiki says it does! | 3364 | // this is what the wiki says it does! |
3365 | // http://wiki.secondlife.com/wiki/LlGetMassMKS | 3365 | // http://wiki.secondlife.com/wiki/LlGetMassMKS |
3366 | return llGetMass() * 100.0; | 3366 | return llGetMass() * 100.0; |
3367 | } | 3367 | } |
3368 | 3368 | ||
3369 | public void llCollisionFilter(string name, string id, int accept) | 3369 | public void llCollisionFilter(string name, string id, int accept) |
3370 | { | 3370 | { |
3371 | m_host.AddScriptLPS(1); | 3371 | m_host.AddScriptLPS(1); |
3372 | m_host.CollisionFilter.Clear(); | 3372 | m_host.CollisionFilter.Clear(); |
3373 | UUID objectID; | 3373 | UUID objectID; |
3374 | 3374 | ||
3375 | if (!UUID.TryParse(id, out objectID)) | 3375 | if (!UUID.TryParse(id, out objectID)) |
3376 | objectID = UUID.Zero; | 3376 | objectID = UUID.Zero; |
3377 | 3377 | ||
3378 | if (objectID == UUID.Zero && name == "") | 3378 | if (objectID == UUID.Zero && name == "") |
3379 | return; | 3379 | return; |
3380 | 3380 | ||
3381 | m_host.CollisionFilter.Add(accept,objectID.ToString() + name); | 3381 | m_host.CollisionFilter.Add(accept,objectID.ToString() + name); |
3382 | } | 3382 | } |
3383 | 3383 | ||
3384 | public void llTakeControls(int controls, int accept, int pass_on) | 3384 | public void llTakeControls(int controls, int accept, int pass_on) |
3385 | { | 3385 | { |
3386 | if (m_item.PermsGranter != UUID.Zero) | 3386 | if (m_item.PermsGranter != UUID.Zero) |
3387 | { | 3387 | { |
3388 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); | 3388 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); |
3389 | 3389 | ||
3390 | if (presence != null) | 3390 | if (presence != null) |
3391 | { | 3391 | { |
3392 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) | 3392 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) |
3393 | { | 3393 | { |
3394 | presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID); | 3394 | presence.RegisterControlEventsToScript(controls, accept, pass_on, m_host.LocalId, m_item.ItemID); |
3395 | } | 3395 | } |
3396 | } | 3396 | } |
3397 | } | 3397 | } |
3398 | 3398 | ||
3399 | m_host.AddScriptLPS(1); | 3399 | m_host.AddScriptLPS(1); |
3400 | } | 3400 | } |
3401 | 3401 | ||
3402 | public void llReleaseControls() | 3402 | public void llReleaseControls() |
3403 | { | 3403 | { |
3404 | m_host.AddScriptLPS(1); | 3404 | m_host.AddScriptLPS(1); |
3405 | 3405 | ||
3406 | if (m_item.PermsGranter != UUID.Zero) | 3406 | if (m_item.PermsGranter != UUID.Zero) |
3407 | { | 3407 | { |
3408 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); | 3408 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); |
3409 | 3409 | ||
3410 | if (presence != null) | 3410 | if (presence != null) |
3411 | { | 3411 | { |
3412 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) | 3412 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) |
3413 | { | 3413 | { |
3414 | // Unregister controls from Presence | 3414 | // Unregister controls from Presence |
3415 | presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); | 3415 | presence.UnRegisterControlEventsToScript(m_host.LocalId, m_item.ItemID); |
3416 | // Remove Take Control permission. | 3416 | // Remove Take Control permission. |
3417 | m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; | 3417 | m_item.PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; |
3418 | } | 3418 | } |
3419 | } | 3419 | } |
3420 | } | 3420 | } |
3421 | } | 3421 | } |
3422 | 3422 | ||
3423 | public void llReleaseURL(string url) | 3423 | public void llReleaseURL(string url) |
3424 | { | 3424 | { |
3425 | m_host.AddScriptLPS(1); | 3425 | m_host.AddScriptLPS(1); |
3426 | if (m_UrlModule != null) | 3426 | if (m_UrlModule != null) |
3427 | m_UrlModule.ReleaseURL(url); | 3427 | m_UrlModule.ReleaseURL(url); |
3428 | } | 3428 | } |
3429 | 3429 | ||
3430 | /// <summary> | 3430 | /// <summary> |
3431 | /// Attach the object containing this script to the avatar that owns it. | 3431 | /// Attach the object containing this script to the avatar that owns it. |
3432 | /// </summary> | 3432 | /// </summary> |
3433 | /// <param name='attachmentPoint'> | 3433 | /// <param name='attachmentPoint'> |
3434 | /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>) | 3434 | /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>) |
3435 | /// </param> | 3435 | /// </param> |
3436 | /// <returns>true if the attach suceeded, false if it did not</returns> | 3436 | /// <returns>true if the attach suceeded, false if it did not</returns> |
3437 | public bool AttachToAvatar(int attachmentPoint) | 3437 | public bool AttachToAvatar(int attachmentPoint) |
3438 | { | 3438 | { |
3439 | SceneObjectGroup grp = m_host.ParentGroup; | 3439 | SceneObjectGroup grp = m_host.ParentGroup; |
3440 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | 3440 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); |
3441 | 3441 | ||
3442 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; | 3442 | IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; |
3443 | 3443 | ||
3444 | if (attachmentsModule != null) | 3444 | if (attachmentsModule != null) |
3445 | return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true); | 3445 | return attachmentsModule.AttachObject(presence, grp, (uint)attachmentPoint, false, true, true); |
3446 | else | 3446 | else |
3447 | return false; | 3447 | return false; |
3448 | } | 3448 | } |
3449 | 3449 | ||
3450 | /// <summary> | 3450 | /// <summary> |
3451 | /// Detach the object containing this script from the avatar it is attached to. | 3451 | /// Detach the object containing this script from the avatar it is attached to. |
3452 | /// </summary> | 3452 | /// </summary> |
3453 | /// <remarks> | 3453 | /// <remarks> |
3454 | /// Nothing happens if the object is not attached. | 3454 | /// Nothing happens if the object is not attached. |
3455 | /// </remarks> | 3455 | /// </remarks> |
3456 | public void DetachFromAvatar() | 3456 | public void DetachFromAvatar() |
3457 | { | 3457 | { |
3458 | Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar"); | 3458 | Util.FireAndForget(DetachWrapper, m_host, "LSL_Api.DetachFromAvatar"); |
3459 | } | 3459 | } |
3460 | 3460 | ||
3461 | private void DetachWrapper(object o) | 3461 | private void DetachWrapper(object o) |
3462 | { | 3462 | { |
3463 | if (World.AttachmentsModule != null) | 3463 | if (World.AttachmentsModule != null) |
3464 | { | 3464 | { |
3465 | SceneObjectPart host = (SceneObjectPart)o; | 3465 | SceneObjectPart host = (SceneObjectPart)o; |
3466 | ScenePresence presence = World.GetScenePresence(host.OwnerID); | 3466 | ScenePresence presence = World.GetScenePresence(host.OwnerID); |
3467 | World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup); | 3467 | World.AttachmentsModule.DetachSingleAttachmentToInv(presence, host.ParentGroup); |
3468 | } | 3468 | } |
3469 | } | 3469 | } |
3470 | 3470 | ||
3471 | public void llAttachToAvatar(int attachmentPoint) | 3471 | public void llAttachToAvatar(int attachmentPoint) |
3472 | { | 3472 | { |
3473 | m_host.AddScriptLPS(1); | 3473 | m_host.AddScriptLPS(1); |
3474 | 3474 | ||
3475 | // if (m_host.ParentGroup.RootPart.AttachmentPoint == 0) | 3475 | // if (m_host.ParentGroup.RootPart.AttachmentPoint == 0) |
3476 | // return; | 3476 | // return; |
3477 | 3477 | ||
3478 | if (m_item.PermsGranter != m_host.OwnerID) | 3478 | if (m_item.PermsGranter != m_host.OwnerID) |
3479 | return; | 3479 | return; |
3480 | 3480 | ||
3481 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) | 3481 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) |
3482 | AttachToAvatar(attachmentPoint); | 3482 | AttachToAvatar(attachmentPoint); |
3483 | } | 3483 | } |
3484 | 3484 | ||
3485 | public void llDetachFromAvatar() | 3485 | public void llDetachFromAvatar() |
3486 | { | 3486 | { |
3487 | m_host.AddScriptLPS(1); | 3487 | m_host.AddScriptLPS(1); |
3488 | 3488 | ||
3489 | if (m_host.ParentGroup.AttachmentPoint == 0) | 3489 | if (m_host.ParentGroup.AttachmentPoint == 0) |
3490 | return; | 3490 | return; |
3491 | 3491 | ||
3492 | if (m_item.PermsGranter != m_host.OwnerID) | 3492 | if (m_item.PermsGranter != m_host.OwnerID) |
3493 | return; | 3493 | return; |
3494 | 3494 | ||
3495 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) | 3495 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_ATTACH) != 0) |
3496 | DetachFromAvatar(); | 3496 | DetachFromAvatar(); |
3497 | } | 3497 | } |
3498 | 3498 | ||
3499 | public void llTakeCamera(string avatar) | 3499 | public void llTakeCamera(string avatar) |
3500 | { | 3500 | { |
3501 | m_host.AddScriptLPS(1); | 3501 | m_host.AddScriptLPS(1); |
3502 | Deprecated("llTakeCamera", "Use llSetCameraParams instead"); | 3502 | Deprecated("llTakeCamera", "Use llSetCameraParams instead"); |
3503 | } | 3503 | } |
3504 | 3504 | ||
3505 | public void llReleaseCamera(string avatar) | 3505 | public void llReleaseCamera(string avatar) |
3506 | { | 3506 | { |
3507 | m_host.AddScriptLPS(1); | 3507 | m_host.AddScriptLPS(1); |
3508 | Deprecated("llReleaseCamera", "Use llClearCameraParams instead"); | 3508 | Deprecated("llReleaseCamera", "Use llClearCameraParams instead"); |
3509 | } | 3509 | } |
3510 | 3510 | ||
3511 | public LSL_String llGetOwner() | 3511 | public LSL_String llGetOwner() |
3512 | { | 3512 | { |
3513 | m_host.AddScriptLPS(1); | 3513 | m_host.AddScriptLPS(1); |
3514 | 3514 | ||
3515 | return m_host.OwnerID.ToString(); | 3515 | return m_host.OwnerID.ToString(); |
3516 | } | 3516 | } |
3517 | 3517 | ||
3518 | public void llInstantMessage(string user, string message) | 3518 | public void llInstantMessage(string user, string message) |
3519 | { | 3519 | { |
3520 | m_host.AddScriptLPS(1); | 3520 | m_host.AddScriptLPS(1); |
3521 | 3521 | ||
3522 | // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. | 3522 | // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. |
3523 | // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, | 3523 | // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, |
3524 | // but I don't think we have a list of scenes available from here. | 3524 | // but I don't think we have a list of scenes available from here. |
3525 | // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.) | 3525 | // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.) |
3526 | 3526 | ||
3527 | // user is a UUID | 3527 | // user is a UUID |
3528 | 3528 | ||
3529 | // TODO: figure out values for client, fromSession, and imSessionID | 3529 | // TODO: figure out values for client, fromSession, and imSessionID |
3530 | // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); | 3530 | // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); |
3531 | 3531 | ||
3532 | GridInstantMessage msg = new GridInstantMessage(); | 3532 | GridInstantMessage msg = new GridInstantMessage(); |
3533 | msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid; | 3533 | msg.fromAgentID = new Guid(m_host.OwnerID.ToString()); // fromAgentID.Guid; |
3534 | msg.toAgentID = new Guid(user); // toAgentID.Guid; | 3534 | msg.toAgentID = new Guid(user); // toAgentID.Guid; |
3535 | msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here | 3535 | msg.imSessionID = new Guid(m_host.UUID.ToString()); // This is the item we're mucking with here |
3536 | // m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); | 3536 | // m_log.Debug("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); |
3537 | // m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); | 3537 | // m_log.Debug("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); |
3538 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; | 3538 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; |
3539 | //if (client != null) | 3539 | //if (client != null) |
3540 | //{ | 3540 | //{ |
3541 | msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; | 3541 | msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; |
3542 | //} | 3542 | //} |
3543 | //else | 3543 | //else |
3544 | //{ | 3544 | //{ |
3545 | // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it | 3545 | // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it |
3546 | //} | 3546 | //} |
3547 | // Cap the message length at 1024. | 3547 | // Cap the message length at 1024. |
3548 | if (message != null && message.Length > 1024) | 3548 | if (message != null && message.Length > 1024) |
3549 | msg.message = message.Substring(0, 1024); | 3549 | msg.message = message.Substring(0, 1024); |
3550 | else | 3550 | else |
3551 | msg.message = message; | 3551 | msg.message = message; |
3552 | msg.dialog = (byte)19; // messgage from script ??? // dialog; | 3552 | msg.dialog = (byte)19; // messgage from script ??? // dialog; |
3553 | msg.fromGroup = false;// fromGroup; | 3553 | msg.fromGroup = false;// fromGroup; |
3554 | msg.offline = (byte)0; //offline; | 3554 | msg.offline = (byte)0; //offline; |
3555 | msg.ParentEstateID = 0; //ParentEstateID; | 3555 | msg.ParentEstateID = 0; //ParentEstateID; |
3556 | msg.Position = new Vector3(m_host.AbsolutePosition); | 3556 | msg.Position = new Vector3(m_host.AbsolutePosition); |
3557 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; | 3557 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; |
3558 | 3558 | ||
3559 | Vector3 pos = m_host.AbsolutePosition; | 3559 | Vector3 pos = m_host.AbsolutePosition; |
3560 | msg.binaryBucket | 3560 | msg.binaryBucket |
3561 | = Util.StringToBytes256( | 3561 | = Util.StringToBytes256( |
3562 | "{0}/{1}/{2}/{3}", | 3562 | "{0}/{1}/{2}/{3}", |
3563 | World.RegionInfo.RegionName, | 3563 | World.RegionInfo.RegionName, |
3564 | (int)Math.Floor(pos.X), | 3564 | (int)Math.Floor(pos.X), |
3565 | (int)Math.Floor(pos.Y), | 3565 | (int)Math.Floor(pos.Y), |
3566 | (int)Math.Floor(pos.Z)); | 3566 | (int)Math.Floor(pos.Z)); |
3567 | 3567 | ||
3568 | if (m_TransferModule != null) | 3568 | if (m_TransferModule != null) |
3569 | { | 3569 | { |
3570 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 3570 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
3571 | } | 3571 | } |
3572 | 3572 | ||
3573 | ScriptSleep(m_sleepMsOnInstantMessage); | 3573 | ScriptSleep(m_sleepMsOnInstantMessage); |
3574 | } | 3574 | } |
3575 | 3575 | ||
3576 | public void llEmail(string address, string subject, string message) | 3576 | public void llEmail(string address, string subject, string message) |
3577 | { | 3577 | { |
3578 | m_host.AddScriptLPS(1); | 3578 | m_host.AddScriptLPS(1); |
3579 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | 3579 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); |
3580 | if (emailModule == null) | 3580 | if (emailModule == null) |
3581 | { | 3581 | { |
3582 | Error("llEmail", "Email module not configured"); | 3582 | Error("llEmail", "Email module not configured"); |
3583 | return; | 3583 | return; |
3584 | } | 3584 | } |
3585 | 3585 | ||
3586 | //Restrict email destination to the avatars registered email address? | 3586 | //Restrict email destination to the avatars registered email address? |
3587 | //The restriction only applies if the destination address is not local. | 3587 | //The restriction only applies if the destination address is not local. |
3588 | if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false) | 3588 | if (m_restrictEmail == true && address.Contains(m_internalObjectHost) == false) |
3589 | { | 3589 | { |
3590 | UserAccount account = | 3590 | UserAccount account = |
3591 | World.UserAccountService.GetUserAccount( | 3591 | World.UserAccountService.GetUserAccount( |
3592 | World.RegionInfo.ScopeID, | 3592 | World.RegionInfo.ScopeID, |
3593 | m_host.OwnerID); | 3593 | m_host.OwnerID); |
3594 | 3594 | ||
3595 | if (account == null) | 3595 | if (account == null) |
3596 | { | 3596 | { |
3597 | Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'"); | 3597 | Error("llEmail", "Can't find user account for '" + m_host.OwnerID.ToString() + "'"); |
3598 | return; | 3598 | return; |
3599 | } | 3599 | } |
3600 | 3600 | ||
3601 | if (String.IsNullOrEmpty(account.Email)) | 3601 | if (String.IsNullOrEmpty(account.Email)) |
3602 | { | 3602 | { |
3603 | Error("llEmail", "User account has not registered an email address."); | 3603 | Error("llEmail", "User account has not registered an email address."); |
3604 | return; | 3604 | return; |
3605 | } | 3605 | } |
3606 | 3606 | ||
3607 | address = account.Email; | 3607 | address = account.Email; |
3608 | } | 3608 | } |
3609 | 3609 | ||
3610 | emailModule.SendEmail(m_host.UUID, address, subject, message); | 3610 | emailModule.SendEmail(m_host.UUID, address, subject, message); |
3611 | ScriptSleep(m_sleepMsOnEmail); | 3611 | ScriptSleep(m_sleepMsOnEmail); |
3612 | } | 3612 | } |
3613 | 3613 | ||
3614 | public void llGetNextEmail(string address, string subject) | 3614 | public void llGetNextEmail(string address, string subject) |
3615 | { | 3615 | { |
3616 | m_host.AddScriptLPS(1); | 3616 | m_host.AddScriptLPS(1); |
3617 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | 3617 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); |
3618 | if (emailModule == null) | 3618 | if (emailModule == null) |
3619 | { | 3619 | { |
3620 | Error("llGetNextEmail", "Email module not configured"); | 3620 | Error("llGetNextEmail", "Email module not configured"); |
3621 | return; | 3621 | return; |
3622 | } | 3622 | } |
3623 | Email email; | 3623 | Email email; |
3624 | 3624 | ||
3625 | email = emailModule.GetNextEmail(m_host.UUID, address, subject); | 3625 | email = emailModule.GetNextEmail(m_host.UUID, address, subject); |
3626 | 3626 | ||
3627 | if (email == null) | 3627 | if (email == null) |
3628 | return; | 3628 | return; |
3629 | 3629 | ||
3630 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, | 3630 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, |
3631 | new EventParams("email", | 3631 | new EventParams("email", |
3632 | new Object[] { | 3632 | new Object[] { |
3633 | new LSL_String(email.time), | 3633 | new LSL_String(email.time), |
3634 | new LSL_String(email.sender), | 3634 | new LSL_String(email.sender), |
3635 | new LSL_String(email.subject), | 3635 | new LSL_String(email.subject), |
3636 | new LSL_String(email.message), | 3636 | new LSL_String(email.message), |
3637 | new LSL_Integer(email.numLeft)}, | 3637 | new LSL_Integer(email.numLeft)}, |
3638 | new DetectParams[0])); | 3638 | new DetectParams[0])); |
3639 | 3639 | ||
3640 | } | 3640 | } |
3641 | 3641 | ||
3642 | public LSL_String llGetKey() | 3642 | public LSL_String llGetKey() |
3643 | { | 3643 | { |
3644 | m_host.AddScriptLPS(1); | 3644 | m_host.AddScriptLPS(1); |
3645 | return m_host.UUID.ToString(); | 3645 | return m_host.UUID.ToString(); |
3646 | } | 3646 | } |
3647 | 3647 | ||
3648 | public LSL_Key llGenerateKey() | 3648 | public LSL_Key llGenerateKey() |
3649 | { | 3649 | { |
3650 | m_host.AddScriptLPS(1); | 3650 | m_host.AddScriptLPS(1); |
3651 | return UUID.Random().ToString(); | 3651 | return UUID.Random().ToString(); |
3652 | } | 3652 | } |
3653 | 3653 | ||
3654 | public void llSetBuoyancy(double buoyancy) | 3654 | public void llSetBuoyancy(double buoyancy) |
3655 | { | 3655 | { |
3656 | m_host.AddScriptLPS(1); | 3656 | m_host.AddScriptLPS(1); |
3657 | 3657 | ||
3658 | if (!m_host.ParentGroup.IsDeleted) | 3658 | if (!m_host.ParentGroup.IsDeleted) |
3659 | { | 3659 | { |
3660 | m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy); | 3660 | m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy); |
3661 | } | 3661 | } |
3662 | } | 3662 | } |
3663 | 3663 | ||
3664 | /// <summary> | 3664 | /// <summary> |
3665 | /// Attempt to clamp the object on the Z axis at the given height over tau seconds. | 3665 | /// Attempt to clamp the object on the Z axis at the given height over tau seconds. |
3666 | /// </summary> | 3666 | /// </summary> |
3667 | /// <param name="height">Height to hover. Height of zero disables hover.</param> | 3667 | /// <param name="height">Height to hover. Height of zero disables hover.</param> |
3668 | /// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param> | 3668 | /// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param> |
3669 | /// <param name="tau">Number of seconds over which to reach target</param> | 3669 | /// <param name="tau">Number of seconds over which to reach target</param> |
3670 | public void llSetHoverHeight(double height, int water, double tau) | 3670 | public void llSetHoverHeight(double height, int water, double tau) |
3671 | { | 3671 | { |
3672 | m_host.AddScriptLPS(1); | 3672 | m_host.AddScriptLPS(1); |
3673 | 3673 | ||
3674 | if (m_host.PhysActor != null) | 3674 | if (m_host.PhysActor != null) |
3675 | { | 3675 | { |
3676 | PIDHoverType hoverType = PIDHoverType.Ground; | 3676 | PIDHoverType hoverType = PIDHoverType.Ground; |
3677 | if (water != 0) | 3677 | if (water != 0) |
3678 | { | 3678 | { |
3679 | hoverType = PIDHoverType.GroundAndWater; | 3679 | hoverType = PIDHoverType.GroundAndWater; |
3680 | } | 3680 | } |
3681 | 3681 | ||
3682 | m_host.SetHoverHeight((float)height, hoverType, (float)tau); | 3682 | m_host.SetHoverHeight((float)height, hoverType, (float)tau); |
3683 | } | 3683 | } |
3684 | } | 3684 | } |
3685 | 3685 | ||
3686 | public void llStopHover() | 3686 | public void llStopHover() |
3687 | { | 3687 | { |
3688 | m_host.AddScriptLPS(1); | 3688 | m_host.AddScriptLPS(1); |
3689 | if (m_host.PhysActor != null) | 3689 | if (m_host.PhysActor != null) |
3690 | { | 3690 | { |
3691 | m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f); | 3691 | m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f); |
3692 | } | 3692 | } |
3693 | } | 3693 | } |
3694 | 3694 | ||
3695 | public void llMinEventDelay(double delay) | 3695 | public void llMinEventDelay(double delay) |
3696 | { | 3696 | { |
3697 | m_host.AddScriptLPS(1); | 3697 | m_host.AddScriptLPS(1); |
3698 | try | 3698 | try |
3699 | { | 3699 | { |
3700 | m_ScriptEngine.SetMinEventDelay(m_item.ItemID, delay); | 3700 | m_ScriptEngine.SetMinEventDelay(m_item.ItemID, delay); |
3701 | } | 3701 | } |
3702 | catch (NotImplementedException) | 3702 | catch (NotImplementedException) |
3703 | { | 3703 | { |
3704 | // Currently not implemented in DotNetEngine only XEngine | 3704 | // Currently not implemented in DotNetEngine only XEngine |
3705 | NotImplemented("llMinEventDelay", "In DotNetEngine"); | 3705 | NotImplemented("llMinEventDelay", "In DotNetEngine"); |
3706 | } | 3706 | } |
3707 | } | 3707 | } |
3708 | 3708 | ||
3709 | public void llSoundPreload(string sound) | 3709 | public void llSoundPreload(string sound) |
3710 | { | 3710 | { |
3711 | m_host.AddScriptLPS(1); | 3711 | m_host.AddScriptLPS(1); |
3712 | Deprecated("llSoundPreload", "Use llPreloadSound instead"); | 3712 | Deprecated("llSoundPreload", "Use llPreloadSound instead"); |
3713 | } | 3713 | } |
3714 | 3714 | ||
3715 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) | 3715 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) |
3716 | { | 3716 | { |
3717 | m_host.AddScriptLPS(1); | 3717 | m_host.AddScriptLPS(1); |
3718 | 3718 | ||
3719 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply | 3719 | // Per discussion with Melanie, for non-physical objects llLookAt appears to simply |
3720 | // set the rotation of the object, copy that behavior | 3720 | // set the rotation of the object, copy that behavior |
3721 | PhysicsActor pa = m_host.PhysActor; | 3721 | PhysicsActor pa = m_host.PhysActor; |
3722 | 3722 | ||
3723 | if (strength == 0 || pa == null || !pa.IsPhysical) | 3723 | if (strength == 0 || pa == null || !pa.IsPhysical) |
3724 | { | 3724 | { |
3725 | llSetLocalRot(target); | 3725 | llSetLocalRot(target); |
3726 | } | 3726 | } |
3727 | else | 3727 | else |
3728 | { | 3728 | { |
3729 | m_host.RotLookAt(target, (float)strength, (float)damping); | 3729 | m_host.RotLookAt(target, (float)strength, (float)damping); |
3730 | } | 3730 | } |
3731 | } | 3731 | } |
3732 | 3732 | ||
3733 | public LSL_Integer llStringLength(string str) | 3733 | public LSL_Integer llStringLength(string str) |
3734 | { | 3734 | { |
3735 | m_host.AddScriptLPS(1); | 3735 | m_host.AddScriptLPS(1); |
3736 | if (str.Length > 0) | 3736 | if (str.Length > 0) |
3737 | { | 3737 | { |
3738 | return str.Length; | 3738 | return str.Length; |
3739 | } | 3739 | } |
3740 | else | 3740 | else |
3741 | { | 3741 | { |
3742 | return 0; | 3742 | return 0; |
3743 | } | 3743 | } |
3744 | } | 3744 | } |
3745 | 3745 | ||
3746 | public void llStartAnimation(string anim) | 3746 | public void llStartAnimation(string anim) |
3747 | { | 3747 | { |
3748 | m_host.AddScriptLPS(1); | 3748 | m_host.AddScriptLPS(1); |
3749 | 3749 | ||
3750 | if (m_item.PermsGranter == UUID.Zero) | 3750 | if (m_item.PermsGranter == UUID.Zero) |
3751 | return; | 3751 | return; |
3752 | 3752 | ||
3753 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) | 3753 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) |
3754 | { | 3754 | { |
3755 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); | 3755 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); |
3756 | 3756 | ||
3757 | if (presence != null) | 3757 | if (presence != null) |
3758 | { | 3758 | { |
3759 | // Do NOT try to parse UUID, animations cannot be triggered by ID | 3759 | // Do NOT try to parse UUID, animations cannot be triggered by ID |
3760 | UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation); | 3760 | UUID animID = ScriptUtils.GetAssetIdFromItemName(m_host, anim, (int)AssetType.Animation); |
3761 | if (animID == UUID.Zero) | 3761 | if (animID == UUID.Zero) |
3762 | presence.Animator.AddAnimation(anim, m_host.UUID); | 3762 | presence.Animator.AddAnimation(anim, m_host.UUID); |
3763 | else | 3763 | else |
3764 | presence.Animator.AddAnimation(animID, m_host.UUID); | 3764 | presence.Animator.AddAnimation(animID, m_host.UUID); |
3765 | } | 3765 | } |
3766 | } | 3766 | } |
3767 | } | 3767 | } |
3768 | 3768 | ||
3769 | public void llStopAnimation(string anim) | 3769 | public void llStopAnimation(string anim) |
3770 | { | 3770 | { |
3771 | m_host.AddScriptLPS(1); | 3771 | m_host.AddScriptLPS(1); |
3772 | 3772 | ||
3773 | if (m_item.PermsGranter == UUID.Zero) | 3773 | if (m_item.PermsGranter == UUID.Zero) |
3774 | return; | 3774 | return; |
3775 | 3775 | ||
3776 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) | 3776 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) |
3777 | { | 3777 | { |
3778 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); | 3778 | ScenePresence presence = World.GetScenePresence(m_item.PermsGranter); |
3779 | 3779 | ||
3780 | if (presence != null) | 3780 | if (presence != null) |
3781 | { | 3781 | { |
3782 | UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim); | 3782 | UUID animID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, anim); |
3783 | 3783 | ||
3784 | if (animID == UUID.Zero) | 3784 | if (animID == UUID.Zero) |
3785 | presence.Animator.RemoveAnimation(anim); | 3785 | presence.Animator.RemoveAnimation(anim); |
3786 | else | 3786 | else |
3787 | presence.Animator.RemoveAnimation(animID, true); | 3787 | presence.Animator.RemoveAnimation(animID, true); |
3788 | } | 3788 | } |
3789 | } | 3789 | } |
3790 | } | 3790 | } |
3791 | 3791 | ||
3792 | public void llPointAt(LSL_Vector pos) | 3792 | public void llPointAt(LSL_Vector pos) |
3793 | { | 3793 | { |
3794 | m_host.AddScriptLPS(1); | 3794 | m_host.AddScriptLPS(1); |
3795 | } | 3795 | } |
3796 | 3796 | ||
3797 | public void llStopPointAt() | 3797 | public void llStopPointAt() |
3798 | { | 3798 | { |
3799 | m_host.AddScriptLPS(1); | 3799 | m_host.AddScriptLPS(1); |
3800 | } | 3800 | } |
3801 | 3801 | ||
3802 | public void llTargetOmega(LSL_Vector axis, double spinrate, double gain) | 3802 | public void llTargetOmega(LSL_Vector axis, double spinrate, double gain) |
3803 | { | 3803 | { |
3804 | m_host.AddScriptLPS(1); | 3804 | m_host.AddScriptLPS(1); |
3805 | TargetOmega(m_host, axis, spinrate, gain); | 3805 | TargetOmega(m_host, axis, spinrate, gain); |
3806 | } | 3806 | } |
3807 | 3807 | ||
3808 | protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) | 3808 | protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) |
3809 | { | 3809 | { |
3810 | PhysicsActor pa = part.PhysActor; | 3810 | PhysicsActor pa = part.PhysActor; |
3811 | if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d ) | 3811 | if ( ( pa == null || !pa.IsPhysical ) && gain == 0.0d ) |
3812 | spinrate = 0.0d; | 3812 | spinrate = 0.0d; |
3813 | part.UpdateAngularVelocity(axis * spinrate); | 3813 | part.UpdateAngularVelocity(axis * spinrate); |
3814 | } | 3814 | } |
3815 | 3815 | ||
3816 | public LSL_Integer llGetStartParameter() | 3816 | public LSL_Integer llGetStartParameter() |
3817 | { | 3817 | { |
3818 | m_host.AddScriptLPS(1); | 3818 | m_host.AddScriptLPS(1); |
3819 | return m_ScriptEngine.GetStartParameter(m_item.ItemID); | 3819 | return m_ScriptEngine.GetStartParameter(m_item.ItemID); |
3820 | } | 3820 | } |
3821 | 3821 | ||
3822 | public void llRequestPermissions(string agent, int perm) | 3822 | public void llRequestPermissions(string agent, int perm) |
3823 | { | 3823 | { |
3824 | UUID agentID; | 3824 | UUID agentID; |
3825 | 3825 | ||
3826 | if (!UUID.TryParse(agent, out agentID)) | 3826 | if (!UUID.TryParse(agent, out agentID)) |
3827 | return; | 3827 | return; |
3828 | 3828 | ||
3829 | if (agentID == UUID.Zero || perm == 0) // Releasing permissions | 3829 | if (agentID == UUID.Zero || perm == 0) // Releasing permissions |
3830 | { | 3830 | { |
3831 | llReleaseControls(); | 3831 | llReleaseControls(); |
3832 | 3832 | ||
3833 | m_item.PermsGranter = UUID.Zero; | 3833 | m_item.PermsGranter = UUID.Zero; |
3834 | m_item.PermsMask = 0; | 3834 | m_item.PermsMask = 0; |
3835 | 3835 | ||
3836 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( | 3836 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( |
3837 | "run_time_permissions", new Object[] { | 3837 | "run_time_permissions", new Object[] { |
3838 | new LSL_Integer(0) }, | 3838 | new LSL_Integer(0) }, |
3839 | new DetectParams[0])); | 3839 | new DetectParams[0])); |
3840 | 3840 | ||
3841 | return; | 3841 | return; |
3842 | } | 3842 | } |
3843 | 3843 | ||
3844 | if (m_item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) | 3844 | if (m_item.PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) |
3845 | llReleaseControls(); | 3845 | llReleaseControls(); |
3846 | 3846 | ||
3847 | m_host.AddScriptLPS(1); | 3847 | m_host.AddScriptLPS(1); |
3848 | 3848 | ||
3849 | int implicitPerms = 0; | 3849 | int implicitPerms = 0; |
3850 | 3850 | ||
3851 | if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar) | 3851 | if (m_host.ParentGroup.IsAttachment && (UUID)agent == m_host.ParentGroup.AttachedAvatar) |
3852 | { | 3852 | { |
3853 | // When attached, certain permissions are implicit if requested from owner | 3853 | // When attached, certain permissions are implicit if requested from owner |
3854 | implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | | 3854 | implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | |
3855 | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | 3855 | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | |
3856 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | | 3856 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | |
3857 | ScriptBaseClass.PERMISSION_TRACK_CAMERA | | 3857 | ScriptBaseClass.PERMISSION_TRACK_CAMERA | |
3858 | ScriptBaseClass.PERMISSION_ATTACH; | 3858 | ScriptBaseClass.PERMISSION_ATTACH; |
3859 | } | 3859 | } |
3860 | else | 3860 | else |
3861 | { | 3861 | { |
3862 | if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null) | 3862 | if (m_host.ParentGroup.GetSittingAvatars().SingleOrDefault(sp => sp.UUID == agentID) != null) |
3863 | { | 3863 | { |
3864 | // When agent is sitting, certain permissions are implicit if requested from sitting agent | 3864 | // When agent is sitting, certain permissions are implicit if requested from sitting agent |
3865 | implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | 3865 | implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | |
3866 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | | 3866 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | |
3867 | ScriptBaseClass.PERMISSION_TRACK_CAMERA | | 3867 | ScriptBaseClass.PERMISSION_TRACK_CAMERA | |
3868 | ScriptBaseClass.PERMISSION_TAKE_CONTROLS; | 3868 | ScriptBaseClass.PERMISSION_TAKE_CONTROLS; |
3869 | } | 3869 | } |
3870 | else | 3870 | else |
3871 | { | 3871 | { |
3872 | if (World.GetExtraSetting("auto_grant_attach_perms") == "true") | 3872 | if (World.GetExtraSetting("auto_grant_attach_perms") == "true") |
3873 | implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; | 3873 | implicitPerms = ScriptBaseClass.PERMISSION_ATTACH; |
3874 | } | 3874 | } |
3875 | } | 3875 | } |
3876 | 3876 | ||
3877 | if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms | 3877 | if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms |
3878 | { | 3878 | { |
3879 | lock (m_host.TaskInventory) | 3879 | lock (m_host.TaskInventory) |
3880 | { | 3880 | { |
3881 | m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; | 3881 | m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; |
3882 | m_host.TaskInventory[m_item.ItemID].PermsMask = perm; | 3882 | m_host.TaskInventory[m_item.ItemID].PermsMask = perm; |
3883 | } | 3883 | } |
3884 | 3884 | ||
3885 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( | 3885 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( |
3886 | "run_time_permissions", new Object[] { | 3886 | "run_time_permissions", new Object[] { |
3887 | new LSL_Integer(perm) }, | 3887 | new LSL_Integer(perm) }, |
3888 | new DetectParams[0])); | 3888 | new DetectParams[0])); |
3889 | 3889 | ||
3890 | return; | 3890 | return; |
3891 | } | 3891 | } |
3892 | 3892 | ||
3893 | ScenePresence presence = World.GetScenePresence(agentID); | 3893 | ScenePresence presence = World.GetScenePresence(agentID); |
3894 | 3894 | ||
3895 | if (presence != null) | 3895 | if (presence != null) |
3896 | { | 3896 | { |
3897 | // If permissions are being requested from an NPC and were not implicitly granted above then | 3897 | // If permissions are being requested from an NPC and were not implicitly granted above then |
3898 | // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner | 3898 | // auto grant all requested permissions if the script is owned by the NPC or the NPCs owner |
3899 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); | 3899 | INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); |
3900 | if (npcModule != null && npcModule.IsNPC(agentID, World)) | 3900 | if (npcModule != null && npcModule.IsNPC(agentID, World)) |
3901 | { | 3901 | { |
3902 | if (npcModule.CheckPermissions(agentID, m_host.OwnerID)) | 3902 | if (npcModule.CheckPermissions(agentID, m_host.OwnerID)) |
3903 | { | 3903 | { |
3904 | lock (m_host.TaskInventory) | 3904 | lock (m_host.TaskInventory) |
3905 | { | 3905 | { |
3906 | m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; | 3906 | m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; |
3907 | m_host.TaskInventory[m_item.ItemID].PermsMask = perm; | 3907 | m_host.TaskInventory[m_item.ItemID].PermsMask = perm; |
3908 | } | 3908 | } |
3909 | 3909 | ||
3910 | m_ScriptEngine.PostScriptEvent( | 3910 | m_ScriptEngine.PostScriptEvent( |
3911 | m_item.ItemID, | 3911 | m_item.ItemID, |
3912 | new EventParams( | 3912 | new EventParams( |
3913 | "run_time_permissions", new Object[] { new LSL_Integer(perm) }, new DetectParams[0])); | 3913 | "run_time_permissions", new Object[] { new LSL_Integer(perm) }, new DetectParams[0])); |
3914 | } | 3914 | } |
3915 | 3915 | ||
3916 | // it is an NPC, exit even if the permissions werent granted above, they are not going to answer | 3916 | // it is an NPC, exit even if the permissions werent granted above, they are not going to answer |
3917 | // the question! | 3917 | // the question! |
3918 | return; | 3918 | return; |
3919 | } | 3919 | } |
3920 | 3920 | ||
3921 | string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID); | 3921 | string ownerName = resolveName(m_host.ParentGroup.RootPart.OwnerID); |
3922 | if (ownerName == String.Empty) | 3922 | if (ownerName == String.Empty) |
3923 | ownerName = "(hippos)"; | 3923 | ownerName = "(hippos)"; |
3924 | 3924 | ||
3925 | if (!m_waitingForScriptAnswer) | 3925 | if (!m_waitingForScriptAnswer) |
3926 | { | 3926 | { |
3927 | lock (m_host.TaskInventory) | 3927 | lock (m_host.TaskInventory) |
3928 | { | 3928 | { |
3929 | m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; | 3929 | m_host.TaskInventory[m_item.ItemID].PermsGranter = agentID; |
3930 | m_host.TaskInventory[m_item.ItemID].PermsMask = 0; | 3930 | m_host.TaskInventory[m_item.ItemID].PermsMask = 0; |
3931 | } | 3931 | } |
3932 | 3932 | ||
3933 | presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; | 3933 | presence.ControllingClient.OnScriptAnswer += handleScriptAnswer; |
3934 | m_waitingForScriptAnswer=true; | 3934 | m_waitingForScriptAnswer=true; |
3935 | } | 3935 | } |
3936 | 3936 | ||
3937 | presence.ControllingClient.SendScriptQuestion( | 3937 | presence.ControllingClient.SendScriptQuestion( |
3938 | m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, m_item.ItemID, perm); | 3938 | m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, m_item.ItemID, perm); |
3939 | 3939 | ||
3940 | return; | 3940 | return; |
3941 | } | 3941 | } |
3942 | 3942 | ||
3943 | // Requested agent is not in range, refuse perms | 3943 | // Requested agent is not in range, refuse perms |
3944 | m_ScriptEngine.PostScriptEvent( | 3944 | m_ScriptEngine.PostScriptEvent( |
3945 | m_item.ItemID, | 3945 | m_item.ItemID, |
3946 | new EventParams("run_time_permissions", new Object[] { new LSL_Integer(0) }, new DetectParams[0])); | 3946 | new EventParams("run_time_permissions", new Object[] { new LSL_Integer(0) }, new DetectParams[0])); |
3947 | } | 3947 | } |
3948 | 3948 | ||
3949 | void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer) | 3949 | void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer) |
3950 | { | 3950 | { |
3951 | if (taskID != m_host.UUID) | 3951 | if (taskID != m_host.UUID) |
3952 | return; | 3952 | return; |
3953 | 3953 | ||
3954 | client.OnScriptAnswer -= handleScriptAnswer; | 3954 | client.OnScriptAnswer -= handleScriptAnswer; |
3955 | m_waitingForScriptAnswer = false; | 3955 | m_waitingForScriptAnswer = false; |
3956 | 3956 | ||
3957 | if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) | 3957 | if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) |
3958 | llReleaseControls(); | 3958 | llReleaseControls(); |
3959 | 3959 | ||
3960 | lock (m_host.TaskInventory) | 3960 | lock (m_host.TaskInventory) |
3961 | { | 3961 | { |
3962 | m_host.TaskInventory[m_item.ItemID].PermsMask = answer; | 3962 | m_host.TaskInventory[m_item.ItemID].PermsMask = answer; |
3963 | } | 3963 | } |
3964 | 3964 | ||
3965 | m_ScriptEngine.PostScriptEvent( | 3965 | m_ScriptEngine.PostScriptEvent( |
3966 | m_item.ItemID, | 3966 | m_item.ItemID, |
3967 | new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); | 3967 | new EventParams("run_time_permissions", new Object[] { new LSL_Integer(answer) }, new DetectParams[0])); |
3968 | } | 3968 | } |
3969 | 3969 | ||
3970 | public LSL_String llGetPermissionsKey() | 3970 | public LSL_String llGetPermissionsKey() |
3971 | { | 3971 | { |
3972 | m_host.AddScriptLPS(1); | 3972 | m_host.AddScriptLPS(1); |
3973 | 3973 | ||
3974 | return m_item.PermsGranter.ToString(); | 3974 | return m_item.PermsGranter.ToString(); |
3975 | } | 3975 | } |
3976 | 3976 | ||
3977 | public LSL_Integer llGetPermissions() | 3977 | public LSL_Integer llGetPermissions() |
3978 | { | 3978 | { |
3979 | m_host.AddScriptLPS(1); | 3979 | m_host.AddScriptLPS(1); |
3980 | 3980 | ||
3981 | int perms = m_item.PermsMask; | 3981 | int perms = m_item.PermsMask; |
3982 | 3982 | ||
3983 | if (m_automaticLinkPermission) | 3983 | if (m_automaticLinkPermission) |
3984 | perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; | 3984 | perms |= ScriptBaseClass.PERMISSION_CHANGE_LINKS; |
3985 | 3985 | ||
3986 | return perms; | 3986 | return perms; |
3987 | } | 3987 | } |
3988 | 3988 | ||
3989 | public LSL_Integer llGetLinkNumber() | 3989 | public LSL_Integer llGetLinkNumber() |
3990 | { | 3990 | { |
3991 | m_host.AddScriptLPS(1); | 3991 | m_host.AddScriptLPS(1); |
3992 | 3992 | ||
3993 | if (m_host.ParentGroup.PrimCount > 1) | 3993 | if (m_host.ParentGroup.PrimCount > 1) |
3994 | { | 3994 | { |
3995 | return m_host.LinkNum; | 3995 | return m_host.LinkNum; |
3996 | } | 3996 | } |
3997 | else | 3997 | else |
3998 | { | 3998 | { |
3999 | return 0; | 3999 | return 0; |
4000 | } | 4000 | } |
4001 | } | 4001 | } |
4002 | 4002 | ||
4003 | public void llSetLinkColor(int linknumber, LSL_Vector color, int face) | 4003 | public void llSetLinkColor(int linknumber, LSL_Vector color, int face) |
4004 | { | 4004 | { |
4005 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 4005 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
4006 | 4006 | ||
4007 | foreach (SceneObjectPart part in parts) | 4007 | foreach (SceneObjectPart part in parts) |
4008 | part.SetFaceColorAlpha(face, color, null); | 4008 | part.SetFaceColorAlpha(face, color, null); |
4009 | } | 4009 | } |
4010 | 4010 | ||
4011 | public void llCreateLink(string target, int parent) | 4011 | public void llCreateLink(string target, int parent) |
4012 | { | 4012 | { |
4013 | m_host.AddScriptLPS(1); | 4013 | m_host.AddScriptLPS(1); |
4014 | 4014 | ||
4015 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 | 4015 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 |
4016 | && !m_automaticLinkPermission) | 4016 | && !m_automaticLinkPermission) |
4017 | { | 4017 | { |
4018 | Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set"); | 4018 | Error("llCreateLink", "PERMISSION_CHANGE_LINKS permission not set"); |
4019 | return; | 4019 | return; |
4020 | } | 4020 | } |
4021 | 4021 | ||
4022 | CreateLink(target, parent); | 4022 | CreateLink(target, parent); |
4023 | } | 4023 | } |
4024 | 4024 | ||
4025 | public void CreateLink(string target, int parent) | 4025 | public void CreateLink(string target, int parent) |
4026 | { | 4026 | { |
4027 | UUID targetID; | 4027 | UUID targetID; |
4028 | 4028 | ||
4029 | if (!UUID.TryParse(target, out targetID)) | 4029 | if (!UUID.TryParse(target, out targetID)) |
4030 | return; | 4030 | return; |
4031 | 4031 | ||
4032 | SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); | 4032 | SceneObjectPart targetPart = World.GetSceneObjectPart((UUID)targetID); |
4033 | 4033 | ||
4034 | if (targetPart.ParentGroup.AttachmentPoint != 0) | 4034 | if (targetPart.ParentGroup.AttachmentPoint != 0) |
4035 | return; // Fail silently if attached | 4035 | return; // Fail silently if attached |
4036 | 4036 | ||
4037 | if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID) | 4037 | if (targetPart.ParentGroup.RootPart.OwnerID != m_host.ParentGroup.RootPart.OwnerID) |
4038 | return; | 4038 | return; |
4039 | 4039 | ||
4040 | SceneObjectGroup parentPrim = null, childPrim = null; | 4040 | SceneObjectGroup parentPrim = null, childPrim = null; |
4041 | 4041 | ||
4042 | if (targetPart != null) | 4042 | if (targetPart != null) |
4043 | { | 4043 | { |
4044 | if (parent != 0) | 4044 | if (parent != 0) |
4045 | { | 4045 | { |
4046 | parentPrim = m_host.ParentGroup; | 4046 | parentPrim = m_host.ParentGroup; |
4047 | childPrim = targetPart.ParentGroup; | 4047 | childPrim = targetPart.ParentGroup; |
4048 | } | 4048 | } |
4049 | else | 4049 | else |
4050 | { | 4050 | { |
4051 | parentPrim = targetPart.ParentGroup; | 4051 | parentPrim = targetPart.ParentGroup; |
4052 | childPrim = m_host.ParentGroup; | 4052 | childPrim = m_host.ParentGroup; |
4053 | } | 4053 | } |
4054 | 4054 | ||
4055 | // Required for linking | 4055 | // Required for linking |
4056 | childPrim.RootPart.ClearUpdateSchedule(); | 4056 | childPrim.RootPart.ClearUpdateSchedule(); |
4057 | parentPrim.LinkToGroup(childPrim, true); | 4057 | parentPrim.LinkToGroup(childPrim, true); |
4058 | } | 4058 | } |
4059 | 4059 | ||
4060 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | 4060 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); |
4061 | parentPrim.RootPart.CreateSelected = true; | 4061 | parentPrim.RootPart.CreateSelected = true; |
4062 | parentPrim.HasGroupChanged = true; | 4062 | parentPrim.HasGroupChanged = true; |
4063 | parentPrim.ScheduleGroupForFullUpdate(); | 4063 | parentPrim.ScheduleGroupForFullUpdate(); |
4064 | 4064 | ||
4065 | IClientAPI client = null; | 4065 | IClientAPI client = null; |
4066 | ScenePresence sp = World.GetScenePresence(m_host.OwnerID); | 4066 | ScenePresence sp = World.GetScenePresence(m_host.OwnerID); |
4067 | if (sp != null) | 4067 | if (sp != null) |
4068 | client = sp.ControllingClient; | 4068 | client = sp.ControllingClient; |
4069 | 4069 | ||
4070 | if (client != null) | 4070 | if (client != null) |
4071 | parentPrim.SendPropertiesToClient(client); | 4071 | parentPrim.SendPropertiesToClient(client); |
4072 | 4072 | ||
4073 | ScriptSleep(m_sleepMsOnCreateLink); | 4073 | ScriptSleep(m_sleepMsOnCreateLink); |
4074 | } | 4074 | } |
4075 | 4075 | ||
4076 | public void llBreakLink(int linknum) | 4076 | public void llBreakLink(int linknum) |
4077 | { | 4077 | { |
4078 | m_host.AddScriptLPS(1); | 4078 | m_host.AddScriptLPS(1); |
4079 | 4079 | ||
4080 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 | 4080 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 |
4081 | && !m_automaticLinkPermission) | 4081 | && !m_automaticLinkPermission) |
4082 | { | 4082 | { |
4083 | Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set"); | 4083 | Error("llBreakLink", "PERMISSION_CHANGE_LINKS permission not set"); |
4084 | return; | 4084 | return; |
4085 | } | 4085 | } |
4086 | 4086 | ||
4087 | BreakLink(linknum); | 4087 | BreakLink(linknum); |
4088 | } | 4088 | } |
4089 | 4089 | ||
4090 | public void BreakLink(int linknum) | 4090 | public void BreakLink(int linknum) |
4091 | { | 4091 | { |
4092 | if (linknum < ScriptBaseClass.LINK_THIS) | 4092 | if (linknum < ScriptBaseClass.LINK_THIS) |
4093 | return; | 4093 | return; |
4094 | 4094 | ||
4095 | SceneObjectGroup parentPrim = m_host.ParentGroup; | 4095 | SceneObjectGroup parentPrim = m_host.ParentGroup; |
4096 | 4096 | ||
4097 | if (parentPrim.AttachmentPoint != 0) | 4097 | if (parentPrim.AttachmentPoint != 0) |
4098 | return; // Fail silently if attached | 4098 | return; // Fail silently if attached |
4099 | SceneObjectPart childPrim = null; | 4099 | SceneObjectPart childPrim = null; |
4100 | 4100 | ||
4101 | switch (linknum) | 4101 | switch (linknum) |
4102 | { | 4102 | { |
4103 | case ScriptBaseClass.LINK_ROOT: | 4103 | case ScriptBaseClass.LINK_ROOT: |
4104 | break; | 4104 | break; |
4105 | case ScriptBaseClass.LINK_SET: | 4105 | case ScriptBaseClass.LINK_SET: |
4106 | case ScriptBaseClass.LINK_ALL_OTHERS: | 4106 | case ScriptBaseClass.LINK_ALL_OTHERS: |
4107 | case ScriptBaseClass.LINK_ALL_CHILDREN: | 4107 | case ScriptBaseClass.LINK_ALL_CHILDREN: |
4108 | case ScriptBaseClass.LINK_THIS: | 4108 | case ScriptBaseClass.LINK_THIS: |
4109 | foreach (SceneObjectPart part in parentPrim.Parts) | 4109 | foreach (SceneObjectPart part in parentPrim.Parts) |
4110 | { | 4110 | { |
4111 | if (part.UUID != m_host.UUID) | 4111 | if (part.UUID != m_host.UUID) |
4112 | { | 4112 | { |
4113 | childPrim = part; | 4113 | childPrim = part; |
4114 | break; | 4114 | break; |
4115 | } | 4115 | } |
4116 | } | 4116 | } |
4117 | break; | 4117 | break; |
4118 | default: | 4118 | default: |
4119 | childPrim = parentPrim.GetLinkNumPart(linknum); | 4119 | childPrim = parentPrim.GetLinkNumPart(linknum); |
4120 | if (childPrim.UUID == m_host.UUID) | 4120 | if (childPrim.UUID == m_host.UUID) |
4121 | childPrim = null; | 4121 | childPrim = null; |
4122 | break; | 4122 | break; |
4123 | } | 4123 | } |
4124 | 4124 | ||
4125 | if (linknum == ScriptBaseClass.LINK_ROOT) | 4125 | if (linknum == ScriptBaseClass.LINK_ROOT) |
4126 | { | 4126 | { |
4127 | // Restructuring Multiple Prims. | 4127 | // Restructuring Multiple Prims. |
4128 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); | 4128 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); |
4129 | parts.Remove(parentPrim.RootPart); | 4129 | parts.Remove(parentPrim.RootPart); |
4130 | foreach (SceneObjectPart part in parts) | 4130 | foreach (SceneObjectPart part in parts) |
4131 | { | 4131 | { |
4132 | parentPrim.DelinkFromGroup(part.LocalId, true); | 4132 | parentPrim.DelinkFromGroup(part.LocalId, true); |
4133 | } | 4133 | } |
4134 | parentPrim.HasGroupChanged = true; | 4134 | parentPrim.HasGroupChanged = true; |
4135 | parentPrim.ScheduleGroupForFullUpdate(); | 4135 | parentPrim.ScheduleGroupForFullUpdate(); |
4136 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | 4136 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); |
4137 | 4137 | ||
4138 | if (parts.Count > 0) | 4138 | if (parts.Count > 0) |
4139 | { | 4139 | { |
4140 | SceneObjectPart newRoot = parts[0]; | 4140 | SceneObjectPart newRoot = parts[0]; |
4141 | parts.Remove(newRoot); | 4141 | parts.Remove(newRoot); |
4142 | foreach (SceneObjectPart part in parts) | 4142 | foreach (SceneObjectPart part in parts) |
4143 | { | 4143 | { |
4144 | // Required for linking | 4144 | // Required for linking |
4145 | part.ClearUpdateSchedule(); | 4145 | part.ClearUpdateSchedule(); |
4146 | newRoot.ParentGroup.LinkToGroup(part.ParentGroup); | 4146 | newRoot.ParentGroup.LinkToGroup(part.ParentGroup); |
4147 | } | 4147 | } |
4148 | newRoot.ParentGroup.HasGroupChanged = true; | 4148 | newRoot.ParentGroup.HasGroupChanged = true; |
4149 | newRoot.ParentGroup.ScheduleGroupForFullUpdate(); | 4149 | newRoot.ParentGroup.ScheduleGroupForFullUpdate(); |
4150 | } | 4150 | } |
4151 | } | 4151 | } |
4152 | else | 4152 | else |
4153 | { | 4153 | { |
4154 | if (childPrim == null) | 4154 | if (childPrim == null) |
4155 | return; | 4155 | return; |
4156 | 4156 | ||
4157 | parentPrim.DelinkFromGroup(childPrim.LocalId, true); | 4157 | parentPrim.DelinkFromGroup(childPrim.LocalId, true); |
4158 | parentPrim.HasGroupChanged = true; | 4158 | parentPrim.HasGroupChanged = true; |
4159 | parentPrim.ScheduleGroupForFullUpdate(); | 4159 | parentPrim.ScheduleGroupForFullUpdate(); |
4160 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | 4160 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); |
4161 | } | 4161 | } |
4162 | } | 4162 | } |
4163 | 4163 | ||
4164 | public void llBreakAllLinks() | 4164 | public void llBreakAllLinks() |
4165 | { | 4165 | { |
4166 | m_host.AddScriptLPS(1); | 4166 | m_host.AddScriptLPS(1); |
4167 | 4167 | ||
4168 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 | 4168 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0 |
4169 | && !m_automaticLinkPermission) | 4169 | && !m_automaticLinkPermission) |
4170 | { | 4170 | { |
4171 | Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set"); | 4171 | Error("llBreakAllLinks", "PERMISSION_CHANGE_LINKS permission not set"); |
4172 | return; | 4172 | return; |
4173 | } | 4173 | } |
4174 | 4174 | ||
4175 | BreakAllLinks(); | 4175 | BreakAllLinks(); |
4176 | } | 4176 | } |
4177 | 4177 | ||
4178 | public void BreakAllLinks() | 4178 | public void BreakAllLinks() |
4179 | { | 4179 | { |
4180 | SceneObjectGroup parentPrim = m_host.ParentGroup; | 4180 | SceneObjectGroup parentPrim = m_host.ParentGroup; |
4181 | if (parentPrim.AttachmentPoint != 0) | 4181 | if (parentPrim.AttachmentPoint != 0) |
4182 | return; // Fail silently if attached | 4182 | return; // Fail silently if attached |
4183 | 4183 | ||
4184 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); | 4184 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Parts); |
4185 | parts.Remove(parentPrim.RootPart); | 4185 | parts.Remove(parentPrim.RootPart); |
4186 | 4186 | ||
4187 | foreach (SceneObjectPart part in parts) | 4187 | foreach (SceneObjectPart part in parts) |
4188 | { | 4188 | { |
4189 | parentPrim.DelinkFromGroup(part.LocalId, true); | 4189 | parentPrim.DelinkFromGroup(part.LocalId, true); |
4190 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | 4190 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); |
4191 | } | 4191 | } |
4192 | parentPrim.HasGroupChanged = true; | 4192 | parentPrim.HasGroupChanged = true; |
4193 | parentPrim.ScheduleGroupForFullUpdate(); | 4193 | parentPrim.ScheduleGroupForFullUpdate(); |
4194 | } | 4194 | } |
4195 | 4195 | ||
4196 | public LSL_String llGetLinkKey(int linknum) | 4196 | public LSL_String llGetLinkKey(int linknum) |
4197 | { | 4197 | { |
4198 | m_host.AddScriptLPS(1); | 4198 | m_host.AddScriptLPS(1); |
4199 | 4199 | ||
4200 | ISceneEntity entity = GetLinkEntity(m_host, linknum); | 4200 | ISceneEntity entity = GetLinkEntity(m_host, linknum); |
4201 | 4201 | ||
4202 | if (entity != null) | 4202 | if (entity != null) |
4203 | return entity.UUID.ToString(); | 4203 | return entity.UUID.ToString(); |
4204 | else | 4204 | else |
4205 | return ScriptBaseClass.NULL_KEY; | 4205 | return ScriptBaseClass.NULL_KEY; |
4206 | } | 4206 | } |
4207 | 4207 | ||
4208 | /// <summary> | 4208 | /// <summary> |
4209 | /// Returns the name of the child prim or seated avatar matching the | 4209 | /// Returns the name of the child prim or seated avatar matching the |
4210 | /// specified link number. | 4210 | /// specified link number. |
4211 | /// </summary> | 4211 | /// </summary> |
4212 | /// <param name="linknum"> | 4212 | /// <param name="linknum"> |
4213 | /// The number of a link in the linkset or a link-related constant. | 4213 | /// The number of a link in the linkset or a link-related constant. |
4214 | /// </param> | 4214 | /// </param> |
4215 | /// <returns> | 4215 | /// <returns> |
4216 | /// The name determined to match the specified link number. | 4216 | /// The name determined to match the specified link number. |
4217 | /// </returns> | 4217 | /// </returns> |
4218 | /// <remarks> | 4218 | /// <remarks> |
4219 | /// The rules governing the returned name are not simple. The only | 4219 | /// The rules governing the returned name are not simple. The only |
4220 | /// time a blank name is returned is if the target prim has a blank | 4220 | /// time a blank name is returned is if the target prim has a blank |
4221 | /// name. If no prim with the given link number can be found then | 4221 | /// name. If no prim with the given link number can be found then |
4222 | /// usually NULL_KEY is returned but there are exceptions. | 4222 | /// usually NULL_KEY is returned but there are exceptions. |
4223 | /// | 4223 | /// |
4224 | /// In a single unlinked prim, A call with 0 returns the name, all | 4224 | /// In a single unlinked prim, A call with 0 returns the name, all |
4225 | /// other values for link number return NULL_KEY | 4225 | /// other values for link number return NULL_KEY |
4226 | /// | 4226 | /// |
4227 | /// In link sets it is more complicated. | 4227 | /// In link sets it is more complicated. |
4228 | /// | 4228 | /// |
4229 | /// If the script is in the root prim:- | 4229 | /// If the script is in the root prim:- |
4230 | /// A zero link number returns NULL_KEY. | 4230 | /// A zero link number returns NULL_KEY. |
4231 | /// Positive link numbers return the name of the prim, or NULL_KEY | 4231 | /// Positive link numbers return the name of the prim, or NULL_KEY |
4232 | /// if a prim does not exist at that position. | 4232 | /// if a prim does not exist at that position. |
4233 | /// Negative link numbers return the name of the first child prim. | 4233 | /// Negative link numbers return the name of the first child prim. |
4234 | /// | 4234 | /// |
4235 | /// If the script is in a child prim:- | 4235 | /// If the script is in a child prim:- |
4236 | /// Link numbers 0 or 1 return the name of the root prim. | 4236 | /// Link numbers 0 or 1 return the name of the root prim. |
4237 | /// Positive link numbers return the name of the prim or NULL_KEY | 4237 | /// Positive link numbers return the name of the prim or NULL_KEY |
4238 | /// if a prim does not exist at that position. | 4238 | /// if a prim does not exist at that position. |
4239 | /// Negative numbers return the name of the root prim. | 4239 | /// Negative numbers return the name of the root prim. |
4240 | /// | 4240 | /// |
4241 | /// References | 4241 | /// References |
4242 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName | 4242 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetLinkName |
4243 | /// Mentions NULL_KEY being returned | 4243 | /// Mentions NULL_KEY being returned |
4244 | /// http://wiki.secondlife.com/wiki/LlGetLinkName | 4244 | /// http://wiki.secondlife.com/wiki/LlGetLinkName |
4245 | /// Mentions using the LINK_* constants, some of which are negative | 4245 | /// Mentions using the LINK_* constants, some of which are negative |
4246 | /// </remarks> | 4246 | /// </remarks> |
4247 | public LSL_String llGetLinkName(int linknum) | 4247 | public LSL_String llGetLinkName(int linknum) |
4248 | { | 4248 | { |
4249 | m_host.AddScriptLPS(1); | 4249 | m_host.AddScriptLPS(1); |
4250 | 4250 | ||
4251 | ISceneEntity entity = GetLinkEntity(m_host, linknum); | 4251 | ISceneEntity entity = GetLinkEntity(m_host, linknum); |
4252 | 4252 | ||
4253 | if (entity != null) | 4253 | if (entity != null) |
4254 | return entity.Name; | 4254 | return entity.Name; |
4255 | else | 4255 | else |
4256 | return ScriptBaseClass.NULL_KEY; | 4256 | return ScriptBaseClass.NULL_KEY; |
4257 | } | 4257 | } |
4258 | 4258 | ||
4259 | public LSL_Integer llGetInventoryNumber(int type) | 4259 | public LSL_Integer llGetInventoryNumber(int type) |
4260 | { | 4260 | { |
4261 | m_host.AddScriptLPS(1); | 4261 | m_host.AddScriptLPS(1); |
4262 | int count = 0; | 4262 | int count = 0; |
4263 | 4263 | ||
4264 | lock (m_host.TaskInventory) | 4264 | lock (m_host.TaskInventory) |
4265 | { | 4265 | { |
4266 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | 4266 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) |
4267 | { | 4267 | { |
4268 | if (inv.Value.Type == type || type == -1) | 4268 | if (inv.Value.Type == type || type == -1) |
4269 | { | 4269 | { |
4270 | count = count + 1; | 4270 | count = count + 1; |
4271 | } | 4271 | } |
4272 | } | 4272 | } |
4273 | } | 4273 | } |
4274 | 4274 | ||
4275 | return count; | 4275 | return count; |
4276 | } | 4276 | } |
4277 | 4277 | ||
4278 | public LSL_String llGetInventoryName(int type, int number) | 4278 | public LSL_String llGetInventoryName(int type, int number) |
4279 | { | 4279 | { |
4280 | m_host.AddScriptLPS(1); | 4280 | m_host.AddScriptLPS(1); |
4281 | ArrayList keys = new ArrayList(); | 4281 | ArrayList keys = new ArrayList(); |
4282 | 4282 | ||
4283 | lock (m_host.TaskInventory) | 4283 | lock (m_host.TaskInventory) |
4284 | { | 4284 | { |
4285 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | 4285 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) |
4286 | { | 4286 | { |
4287 | if (inv.Value.Type == type || type == -1) | 4287 | if (inv.Value.Type == type || type == -1) |
4288 | { | 4288 | { |
4289 | keys.Add(inv.Value.Name); | 4289 | keys.Add(inv.Value.Name); |
4290 | } | 4290 | } |
4291 | } | 4291 | } |
4292 | } | 4292 | } |
4293 | 4293 | ||
4294 | if (keys.Count == 0) | 4294 | if (keys.Count == 0) |
4295 | { | 4295 | { |
4296 | return String.Empty; | 4296 | return String.Empty; |
4297 | } | 4297 | } |
4298 | keys.Sort(); | 4298 | keys.Sort(); |
4299 | if (keys.Count > number) | 4299 | if (keys.Count > number) |
4300 | { | 4300 | { |
4301 | return (string)keys[number]; | 4301 | return (string)keys[number]; |
4302 | } | 4302 | } |
4303 | return String.Empty; | 4303 | return String.Empty; |
4304 | } | 4304 | } |
4305 | 4305 | ||
4306 | public LSL_Float llGetEnergy() | 4306 | public LSL_Float llGetEnergy() |
4307 | { | 4307 | { |
4308 | m_host.AddScriptLPS(1); | 4308 | m_host.AddScriptLPS(1); |
4309 | // TODO: figure out real energy value | 4309 | // TODO: figure out real energy value |
4310 | return 1.0f; | 4310 | return 1.0f; |
4311 | } | 4311 | } |
4312 | 4312 | ||
4313 | public void llGiveInventory(string destination, string inventory) | 4313 | public void llGiveInventory(string destination, string inventory) |
4314 | { | 4314 | { |
4315 | m_host.AddScriptLPS(1); | 4315 | m_host.AddScriptLPS(1); |
4316 | 4316 | ||
4317 | UUID destId = UUID.Zero; | 4317 | UUID destId = UUID.Zero; |
4318 | 4318 | ||
4319 | if (!UUID.TryParse(destination, out destId)) | 4319 | if (!UUID.TryParse(destination, out destId)) |
4320 | { | 4320 | { |
4321 | Error("llGiveInventory", "Can't parse destination key '" + destination + "'"); | 4321 | Error("llGiveInventory", "Can't parse destination key '" + destination + "'"); |
4322 | return; | 4322 | return; |
4323 | } | 4323 | } |
4324 | 4324 | ||
4325 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); | 4325 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); |
4326 | 4326 | ||
4327 | if (item == null) | 4327 | if (item == null) |
4328 | { | 4328 | { |
4329 | Error("llGiveInventory", "Can't find inventory object '" + inventory + "'"); | 4329 | Error("llGiveInventory", "Can't find inventory object '" + inventory + "'"); |
4330 | return; | 4330 | return; |
4331 | } | 4331 | } |
4332 | 4332 | ||
4333 | UUID objId = item.ItemID; | 4333 | UUID objId = item.ItemID; |
4334 | 4334 | ||
4335 | // check if destination is an object | 4335 | // check if destination is an object |
4336 | if (World.GetSceneObjectPart(destId) != null) | 4336 | if (World.GetSceneObjectPart(destId) != null) |
4337 | { | 4337 | { |
4338 | // destination is an object | 4338 | // destination is an object |
4339 | World.MoveTaskInventoryItem(destId, m_host, objId); | 4339 | World.MoveTaskInventoryItem(destId, m_host, objId); |
4340 | } | 4340 | } |
4341 | else | 4341 | else |
4342 | { | 4342 | { |
4343 | ScenePresence presence = World.GetScenePresence(destId); | 4343 | ScenePresence presence = World.GetScenePresence(destId); |
4344 | 4344 | ||
4345 | if (presence == null) | 4345 | if (presence == null) |
4346 | { | 4346 | { |
4347 | UserAccount account = | 4347 | UserAccount account = |
4348 | World.UserAccountService.GetUserAccount( | 4348 | World.UserAccountService.GetUserAccount( |
4349 | World.RegionInfo.ScopeID, | 4349 | World.RegionInfo.ScopeID, |
4350 | destId); | 4350 | destId); |
4351 | 4351 | ||
4352 | if (account == null) | 4352 | if (account == null) |
4353 | { | 4353 | { |
4354 | GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString()); | 4354 | GridUserInfo info = World.GridUserService.GetGridUserInfo(destId.ToString()); |
4355 | if(info == null || info.Online == false) | 4355 | if(info == null || info.Online == false) |
4356 | { | 4356 | { |
4357 | Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'"); | 4357 | Error("llGiveInventory", "Can't find destination '" + destId.ToString() + "'"); |
4358 | return; | 4358 | return; |
4359 | } | 4359 | } |
4360 | } | 4360 | } |
4361 | } | 4361 | } |
4362 | // destination is an avatar | 4362 | // destination is an avatar |
4363 | string message; | 4363 | string message; |
4364 | InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message); | 4364 | InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message); |
4365 | 4365 | ||
4366 | if (agentItem == null) | 4366 | if (agentItem == null) |
4367 | { | 4367 | { |
4368 | llSay(0, message); | 4368 | llSay(0, message); |
4369 | return; | 4369 | return; |
4370 | } | 4370 | } |
4371 | 4371 | ||
4372 | if (m_TransferModule != null) | 4372 | if (m_TransferModule != null) |
4373 | { | 4373 | { |
4374 | byte[] bucket = new byte[1]; | 4374 | byte[] bucket = new byte[1]; |
4375 | bucket[0] = (byte)item.Type; | 4375 | bucket[0] = (byte)item.Type; |
4376 | 4376 | ||
4377 | GridInstantMessage msg = new GridInstantMessage(World, | 4377 | GridInstantMessage msg = new GridInstantMessage(World, |
4378 | m_host.OwnerID, m_host.Name, destId, | 4378 | m_host.OwnerID, m_host.Name, destId, |
4379 | (byte)InstantMessageDialog.TaskInventoryOffered, | 4379 | (byte)InstantMessageDialog.TaskInventoryOffered, |
4380 | false, item.Name+". "+m_host.Name+" is located at "+ | 4380 | false, item.Name+". "+m_host.Name+" is located at "+ |
4381 | World.RegionInfo.RegionName+" "+ | 4381 | World.RegionInfo.RegionName+" "+ |
4382 | m_host.AbsolutePosition.ToString(), | 4382 | m_host.AbsolutePosition.ToString(), |
4383 | agentItem.ID, true, m_host.AbsolutePosition, | 4383 | agentItem.ID, true, m_host.AbsolutePosition, |
4384 | bucket, true); | 4384 | bucket, true); |
4385 | 4385 | ||
4386 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 4386 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
4387 | } | 4387 | } |
4388 | 4388 | ||
4389 | ScriptSleep(m_sleepMsOnGiveInventory); | 4389 | ScriptSleep(m_sleepMsOnGiveInventory); |
4390 | } | 4390 | } |
4391 | } | 4391 | } |
4392 | 4392 | ||
4393 | public void llRemoveInventory(string name) | 4393 | public void llRemoveInventory(string name) |
4394 | { | 4394 | { |
4395 | m_host.AddScriptLPS(1); | 4395 | m_host.AddScriptLPS(1); |
4396 | 4396 | ||
4397 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 4397 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); |
4398 | 4398 | ||
4399 | if (item == null) | 4399 | if (item == null) |
4400 | return; | 4400 | return; |
4401 | 4401 | ||
4402 | if (item.ItemID == m_item.ItemID) | 4402 | if (item.ItemID == m_item.ItemID) |
4403 | throw new ScriptDeleteException(); | 4403 | throw new ScriptDeleteException(); |
4404 | else | 4404 | else |
4405 | m_host.Inventory.RemoveInventoryItem(item.ItemID); | 4405 | m_host.Inventory.RemoveInventoryItem(item.ItemID); |
4406 | } | 4406 | } |
4407 | 4407 | ||
4408 | public void llSetText(string text, LSL_Vector color, double alpha) | 4408 | public void llSetText(string text, LSL_Vector color, double alpha) |
4409 | { | 4409 | { |
4410 | m_host.AddScriptLPS(1); | 4410 | m_host.AddScriptLPS(1); |
4411 | Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); | 4411 | Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); |
4412 | if (text.Length > 254) | 4412 | if (text.Length > 254) |
4413 | text = text.Remove(254); | 4413 | text = text.Remove(254); |
4414 | 4414 | ||
4415 | byte[] data; | 4415 | byte[] data; |
4416 | do | 4416 | do |
4417 | { | 4417 | { |
4418 | data = Util.UTF8.GetBytes(text); | 4418 | data = Util.UTF8.GetBytes(text); |
4419 | if (data.Length > 254) | 4419 | if (data.Length > 254) |
4420 | text = text.Substring(0, text.Length - 1); | 4420 | text = text.Substring(0, text.Length - 1); |
4421 | } while (data.Length > 254); | 4421 | } while (data.Length > 254); |
4422 | 4422 | ||
4423 | m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); | 4423 | m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); |
4424 | //m_host.ParentGroup.HasGroupChanged = true; | 4424 | //m_host.ParentGroup.HasGroupChanged = true; |
4425 | //m_host.ParentGroup.ScheduleGroupForFullUpdate(); | 4425 | //m_host.ParentGroup.ScheduleGroupForFullUpdate(); |
4426 | } | 4426 | } |
4427 | 4427 | ||
4428 | public LSL_Float llWater(LSL_Vector offset) | 4428 | public LSL_Float llWater(LSL_Vector offset) |
4429 | { | 4429 | { |
4430 | m_host.AddScriptLPS(1); | 4430 | m_host.AddScriptLPS(1); |
4431 | return World.RegionInfo.RegionSettings.WaterHeight; | 4431 | return World.RegionInfo.RegionSettings.WaterHeight; |
4432 | } | 4432 | } |
4433 | 4433 | ||
4434 | public void llPassTouches(int pass) | 4434 | public void llPassTouches(int pass) |
4435 | { | 4435 | { |
4436 | m_host.AddScriptLPS(1); | 4436 | m_host.AddScriptLPS(1); |
4437 | if (pass != 0) | 4437 | if (pass != 0) |
4438 | m_host.PassTouches = true; | 4438 | m_host.PassTouches = true; |
4439 | else | 4439 | else |
4440 | m_host.PassTouches = false; | 4440 | m_host.PassTouches = false; |
4441 | } | 4441 | } |
4442 | 4442 | ||
4443 | public LSL_String llRequestAgentData(string id, int data) | 4443 | public LSL_String llRequestAgentData(string id, int data) |
4444 | { | 4444 | { |
4445 | m_host.AddScriptLPS(1); | 4445 | m_host.AddScriptLPS(1); |
4446 | 4446 | ||
4447 | UUID uuid = (UUID)id; | 4447 | UUID uuid = (UUID)id; |
4448 | PresenceInfo pinfo = null; | 4448 | PresenceInfo pinfo = null; |
4449 | UserAccount account; | 4449 | UserAccount account; |
4450 | 4450 | ||
4451 | UserInfoCacheEntry ce; | 4451 | UserInfoCacheEntry ce; |
4452 | 4452 | ||
4453 | lock (m_userInfoCache) | 4453 | lock (m_userInfoCache) |
4454 | { | 4454 | { |
4455 | if (!m_userInfoCache.TryGetValue(uuid, out ce)) | 4455 | if (!m_userInfoCache.TryGetValue(uuid, out ce)) |
4456 | { | 4456 | { |
4457 | account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); | 4457 | account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, uuid); |
4458 | if (account == null) | 4458 | if (account == null) |
4459 | { | 4459 | { |
4460 | m_userInfoCache[uuid] = null; // Cache negative | 4460 | m_userInfoCache[uuid] = null; // Cache negative |
4461 | return UUID.Zero.ToString(); | 4461 | return UUID.Zero.ToString(); |
4462 | } | 4462 | } |
4463 | 4463 | ||
4464 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); | 4464 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); |
4465 | if (pinfos != null && pinfos.Length > 0) | 4465 | if (pinfos != null && pinfos.Length > 0) |
4466 | { | 4466 | { |
4467 | foreach (PresenceInfo p in pinfos) | 4467 | foreach (PresenceInfo p in pinfos) |
4468 | { | 4468 | { |
4469 | if (p.RegionID != UUID.Zero) | 4469 | if (p.RegionID != UUID.Zero) |
4470 | { | 4470 | { |
4471 | pinfo = p; | 4471 | pinfo = p; |
4472 | } | 4472 | } |
4473 | } | 4473 | } |
4474 | } | 4474 | } |
4475 | 4475 | ||
4476 | ce = new UserInfoCacheEntry(); | 4476 | ce = new UserInfoCacheEntry(); |
4477 | ce.time = Util.EnvironmentTickCount(); | 4477 | ce.time = Util.EnvironmentTickCount(); |
4478 | ce.account = account; | 4478 | ce.account = account; |
4479 | ce.pinfo = pinfo; | 4479 | ce.pinfo = pinfo; |
4480 | 4480 | ||
4481 | m_userInfoCache[uuid] = ce; | 4481 | m_userInfoCache[uuid] = ce; |
4482 | } | 4482 | } |
4483 | else | 4483 | else |
4484 | { | 4484 | { |
4485 | if (ce == null) | 4485 | if (ce == null) |
4486 | return UUID.Zero.ToString(); | 4486 | return UUID.Zero.ToString(); |
4487 | 4487 | ||
4488 | account = ce.account; | 4488 | account = ce.account; |
4489 | 4489 | ||
4490 | if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) | 4490 | if (Util.EnvironmentTickCount() < ce.time || (Util.EnvironmentTickCount() - ce.time) |
4491 | >= LlRequestAgentDataCacheTimeoutMs) | 4491 | >= LlRequestAgentDataCacheTimeoutMs) |
4492 | { | 4492 | { |
4493 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); | 4493 | PresenceInfo[] pinfos = World.PresenceService.GetAgents(new string[] { uuid.ToString() }); |
4494 | if (pinfos != null && pinfos.Length > 0) | 4494 | if (pinfos != null && pinfos.Length > 0) |
4495 | { | 4495 | { |
4496 | foreach (PresenceInfo p in pinfos) | 4496 | foreach (PresenceInfo p in pinfos) |
4497 | { | 4497 | { |
4498 | if (p.RegionID != UUID.Zero) | 4498 | if (p.RegionID != UUID.Zero) |
4499 | { | 4499 | { |
4500 | pinfo = p; | 4500 | pinfo = p; |
4501 | } | 4501 | } |
4502 | } | 4502 | } |
4503 | } | 4503 | } |
4504 | else | 4504 | else |
4505 | { | 4505 | { |
4506 | pinfo = null; | 4506 | pinfo = null; |
4507 | } | 4507 | } |
4508 | 4508 | ||
4509 | ce.time = Util.EnvironmentTickCount(); | 4509 | ce.time = Util.EnvironmentTickCount(); |
4510 | ce.pinfo = pinfo; | 4510 | ce.pinfo = pinfo; |
4511 | } | 4511 | } |
4512 | else | 4512 | else |
4513 | { | 4513 | { |
4514 | pinfo = ce.pinfo; | 4514 | pinfo = ce.pinfo; |
4515 | } | 4515 | } |
4516 | } | 4516 | } |
4517 | } | 4517 | } |
4518 | 4518 | ||
4519 | string reply = String.Empty; | 4519 | string reply = String.Empty; |
4520 | 4520 | ||
4521 | switch (data) | 4521 | switch (data) |
4522 | { | 4522 | { |
4523 | case ScriptBaseClass.DATA_ONLINE: | 4523 | case ScriptBaseClass.DATA_ONLINE: |
4524 | if (pinfo != null && pinfo.RegionID != UUID.Zero) | 4524 | if (pinfo != null && pinfo.RegionID != UUID.Zero) |
4525 | reply = "1"; | 4525 | reply = "1"; |
4526 | else | 4526 | else |
4527 | reply = "0"; | 4527 | reply = "0"; |
4528 | break; | 4528 | break; |
4529 | case ScriptBaseClass.DATA_NAME: // (First Last) | 4529 | case ScriptBaseClass.DATA_NAME: // (First Last) |
4530 | reply = account.FirstName + " " + account.LastName; | 4530 | reply = account.FirstName + " " + account.LastName; |
4531 | break; | 4531 | break; |
4532 | case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD) | 4532 | case ScriptBaseClass.DATA_BORN: // (YYYY-MM-DD) |
4533 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); | 4533 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); |
4534 | born = born.AddSeconds(account.Created); | 4534 | born = born.AddSeconds(account.Created); |
4535 | reply = born.ToString("yyyy-MM-dd"); | 4535 | reply = born.ToString("yyyy-MM-dd"); |
4536 | break; | 4536 | break; |
4537 | case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0) | 4537 | case ScriptBaseClass.DATA_RATING: // (0,0,0,0,0,0) |
4538 | reply = "0,0,0,0,0,0"; | 4538 | reply = "0,0,0,0,0,0"; |
4539 | break; | 4539 | break; |
4540 | case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant. | 4540 | case 7: // DATA_USERLEVEL (integer). This is not available in LL and so has no constant. |
4541 | reply = account.UserLevel.ToString(); | 4541 | reply = account.UserLevel.ToString(); |
4542 | break; | 4542 | break; |
4543 | case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3) | 4543 | case ScriptBaseClass.DATA_PAYINFO: // (0|1|2|3) |
4544 | reply = "0"; | 4544 | reply = "0"; |
4545 | break; | 4545 | break; |
4546 | default: | 4546 | default: |
4547 | return UUID.Zero.ToString(); // Raise no event | 4547 | return UUID.Zero.ToString(); // Raise no event |
4548 | } | 4548 | } |
4549 | 4549 | ||
4550 | UUID rq = UUID.Random(); | 4550 | UUID rq = UUID.Random(); |
4551 | 4551 | ||
4552 | UUID tid = AsyncCommands. | 4552 | UUID tid = AsyncCommands. |
4553 | DataserverPlugin.RegisterRequest(m_host.LocalId, | 4553 | DataserverPlugin.RegisterRequest(m_host.LocalId, |
4554 | m_item.ItemID, rq.ToString()); | 4554 | m_item.ItemID, rq.ToString()); |
4555 | 4555 | ||
4556 | AsyncCommands. | 4556 | AsyncCommands. |
4557 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | 4557 | DataserverPlugin.DataserverReply(rq.ToString(), reply); |
4558 | 4558 | ||
4559 | ScriptSleep(m_sleepMsOnRequestAgentData); | 4559 | ScriptSleep(m_sleepMsOnRequestAgentData); |
4560 | return tid.ToString(); | 4560 | return tid.ToString(); |
4561 | } | 4561 | } |
4562 | 4562 | ||
4563 | public LSL_String llRequestInventoryData(string name) | 4563 | public LSL_String llRequestInventoryData(string name) |
4564 | { | 4564 | { |
4565 | m_host.AddScriptLPS(1); | 4565 | m_host.AddScriptLPS(1); |
4566 | 4566 | ||
4567 | foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems()) | 4567 | foreach (TaskInventoryItem item in m_host.Inventory.GetInventoryItems()) |
4568 | { | 4568 | { |
4569 | if (item.Type == 3 && item.Name == name) | 4569 | if (item.Type == 3 && item.Name == name) |
4570 | { | 4570 | { |
4571 | UUID tid = AsyncCommands. | 4571 | UUID tid = AsyncCommands. |
4572 | DataserverPlugin.RegisterRequest(m_host.LocalId, | 4572 | DataserverPlugin.RegisterRequest(m_host.LocalId, |
4573 | m_item.ItemID, item.AssetID.ToString()); | 4573 | m_item.ItemID, item.AssetID.ToString()); |
4574 | 4574 | ||
4575 | Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); | 4575 | Vector3 region = new Vector3(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); |
4576 | 4576 | ||
4577 | World.AssetService.Get(item.AssetID.ToString(), this, | 4577 | World.AssetService.Get(item.AssetID.ToString(), this, |
4578 | delegate(string i, object sender, AssetBase a) | 4578 | delegate(string i, object sender, AssetBase a) |
4579 | { | 4579 | { |
4580 | AssetLandmark lm = new AssetLandmark(a); | 4580 | AssetLandmark lm = new AssetLandmark(a); |
4581 | 4581 | ||
4582 | float rx = (uint)(lm.RegionHandle >> 32); | 4582 | float rx = (uint)(lm.RegionHandle >> 32); |
4583 | float ry = (uint)lm.RegionHandle; | 4583 | float ry = (uint)lm.RegionHandle; |
4584 | region = lm.Position + new Vector3(rx, ry, 0) - region; | 4584 | region = lm.Position + new Vector3(rx, ry, 0) - region; |
4585 | 4585 | ||
4586 | string reply = region.ToString(); | 4586 | string reply = region.ToString(); |
4587 | AsyncCommands. | 4587 | AsyncCommands. |
4588 | DataserverPlugin.DataserverReply(i.ToString(), | 4588 | DataserverPlugin.DataserverReply(i.ToString(), |
4589 | reply); | 4589 | reply); |
4590 | }); | 4590 | }); |
4591 | 4591 | ||
4592 | ScriptSleep(m_sleepMsOnRequestInventoryData); | 4592 | ScriptSleep(m_sleepMsOnRequestInventoryData); |
4593 | return tid.ToString(); | 4593 | return tid.ToString(); |
4594 | } | 4594 | } |
4595 | } | 4595 | } |
4596 | 4596 | ||
4597 | ScriptSleep(m_sleepMsOnRequestInventoryData); | 4597 | ScriptSleep(m_sleepMsOnRequestInventoryData); |
4598 | return String.Empty; | 4598 | return String.Empty; |
4599 | } | 4599 | } |
4600 | 4600 | ||
4601 | public void llSetDamage(double damage) | 4601 | public void llSetDamage(double damage) |
4602 | { | 4602 | { |
4603 | m_host.AddScriptLPS(1); | 4603 | m_host.AddScriptLPS(1); |
4604 | m_host.ParentGroup.Damage = (float)damage; | 4604 | m_host.ParentGroup.Damage = (float)damage; |
4605 | } | 4605 | } |
4606 | 4606 | ||
4607 | public void llTeleportAgentHome(string agent) | 4607 | public void llTeleportAgentHome(string agent) |
4608 | { | 4608 | { |
4609 | m_host.AddScriptLPS(1); | 4609 | m_host.AddScriptLPS(1); |
4610 | UUID agentId = new UUID(); | 4610 | UUID agentId = new UUID(); |
4611 | if (UUID.TryParse(agent, out agentId)) | 4611 | if (UUID.TryParse(agent, out agentId)) |
4612 | { | 4612 | { |
4613 | ScenePresence presence = World.GetScenePresence(agentId); | 4613 | ScenePresence presence = World.GetScenePresence(agentId); |
4614 | if (presence != null) | 4614 | if (presence != null) |
4615 | { | 4615 | { |
4616 | // agent must be over the owners land | 4616 | // agent must be over the owners land |
4617 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) | 4617 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4618 | { | 4618 | { |
4619 | World.TeleportClientHome(agentId, presence.ControllingClient); | 4619 | World.TeleportClientHome(agentId, presence.ControllingClient); |
4620 | } | 4620 | } |
4621 | } | 4621 | } |
4622 | } | 4622 | } |
4623 | 4623 | ||
4624 | ScriptSleep(m_sleepMsOnSetDamage); | 4624 | ScriptSleep(m_sleepMsOnSetDamage); |
4625 | } | 4625 | } |
4626 | 4626 | ||
4627 | public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) | 4627 | public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) |
4628 | { | 4628 | { |
4629 | m_host.AddScriptLPS(1); | 4629 | m_host.AddScriptLPS(1); |
4630 | UUID agentId = new UUID(); | 4630 | UUID agentId = new UUID(); |
4631 | 4631 | ||
4632 | if (UUID.TryParse(agent, out agentId)) | 4632 | if (UUID.TryParse(agent, out agentId)) |
4633 | { | 4633 | { |
4634 | ScenePresence presence = World.GetScenePresence(agentId); | 4634 | ScenePresence presence = World.GetScenePresence(agentId); |
4635 | if (presence != null && presence.PresenceType != PresenceType.Npc) | 4635 | if (presence != null && presence.PresenceType != PresenceType.Npc) |
4636 | { | 4636 | { |
4637 | // agent must not be a god | 4637 | // agent must not be a god |
4638 | if (presence.GodLevel >= 200) return; | 4638 | if (presence.GodLevel >= 200) return; |
4639 | 4639 | ||
4640 | if (destination == String.Empty) | 4640 | if (destination == String.Empty) |
4641 | destination = World.RegionInfo.RegionName; | 4641 | destination = World.RegionInfo.RegionName; |
4642 | 4642 | ||
4643 | // agent must be over the owners land | 4643 | // agent must be over the owners land |
4644 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) | 4644 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4645 | { | 4645 | { |
4646 | DoLLTeleport(presence, destination, targetPos, targetLookAt); | 4646 | DoLLTeleport(presence, destination, targetPos, targetLookAt); |
4647 | } | 4647 | } |
4648 | else // or must be wearing the prim | 4648 | else // or must be wearing the prim |
4649 | { | 4649 | { |
4650 | if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) | 4650 | if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) |
4651 | { | 4651 | { |
4652 | DoLLTeleport(presence, destination, targetPos, targetLookAt); | 4652 | DoLLTeleport(presence, destination, targetPos, targetLookAt); |
4653 | } | 4653 | } |
4654 | } | 4654 | } |
4655 | } | 4655 | } |
4656 | } | 4656 | } |
4657 | } | 4657 | } |
4658 | 4658 | ||
4659 | public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) | 4659 | public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) |
4660 | { | 4660 | { |
4661 | m_host.AddScriptLPS(1); | 4661 | m_host.AddScriptLPS(1); |
4662 | UUID agentId = new UUID(); | 4662 | UUID agentId = new UUID(); |
4663 | 4663 | ||
4664 | ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y); | 4664 | ulong regionHandle = Util.RegionWorldLocToHandle((uint)global_coords.x, (uint)global_coords.y); |
4665 | 4665 | ||
4666 | if (UUID.TryParse(agent, out agentId)) | 4666 | if (UUID.TryParse(agent, out agentId)) |
4667 | { | 4667 | { |
4668 | ScenePresence presence = World.GetScenePresence(agentId); | 4668 | ScenePresence presence = World.GetScenePresence(agentId); |
4669 | if (presence != null && presence.PresenceType != PresenceType.Npc) | 4669 | if (presence != null && presence.PresenceType != PresenceType.Npc) |
4670 | { | 4670 | { |
4671 | // agent must not be a god | 4671 | // agent must not be a god |
4672 | if (presence.GodLevel >= 200) return; | 4672 | if (presence.GodLevel >= 200) return; |
4673 | 4673 | ||
4674 | // agent must be over the owners land | 4674 | // agent must be over the owners land |
4675 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) | 4675 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
4676 | { | 4676 | { |
4677 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); | 4677 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); |
4678 | } | 4678 | } |
4679 | else // or must be wearing the prim | 4679 | else // or must be wearing the prim |
4680 | { | 4680 | { |
4681 | if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) | 4681 | if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) |
4682 | { | 4682 | { |
4683 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); | 4683 | World.RequestTeleportLocation(presence.ControllingClient, regionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); |
4684 | } | 4684 | } |
4685 | } | 4685 | } |
4686 | } | 4686 | } |
4687 | } | 4687 | } |
4688 | } | 4688 | } |
4689 | 4689 | ||
4690 | private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) | 4690 | private void DoLLTeleport(ScenePresence sp, string destination, Vector3 targetPos, Vector3 targetLookAt) |
4691 | { | 4691 | { |
4692 | UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination); | 4692 | UUID assetID = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, destination); |
4693 | 4693 | ||
4694 | // The destinaion is not an asset ID and also doesn't name a landmark. | 4694 | // The destinaion is not an asset ID and also doesn't name a landmark. |
4695 | // Use it as a sim name | 4695 | // Use it as a sim name |
4696 | if (assetID == UUID.Zero) | 4696 | if (assetID == UUID.Zero) |
4697 | { | 4697 | { |
4698 | World.RequestTeleportLocation(sp.ControllingClient, destination, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); | 4698 | World.RequestTeleportLocation(sp.ControllingClient, destination, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); |
4699 | return; | 4699 | return; |
4700 | } | 4700 | } |
4701 | 4701 | ||
4702 | AssetBase lma = World.AssetService.Get(assetID.ToString()); | 4702 | AssetBase lma = World.AssetService.Get(assetID.ToString()); |
4703 | if (lma == null) | 4703 | if (lma == null) |
4704 | return; | 4704 | return; |
4705 | 4705 | ||
4706 | if (lma.Type != (sbyte)AssetType.Landmark) | 4706 | if (lma.Type != (sbyte)AssetType.Landmark) |
4707 | return; | 4707 | return; |
4708 | 4708 | ||
4709 | AssetLandmark lm = new AssetLandmark(lma); | 4709 | AssetLandmark lm = new AssetLandmark(lma); |
4710 | 4710 | ||
4711 | World.RequestTeleportLocation(sp.ControllingClient, lm.RegionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); | 4711 | World.RequestTeleportLocation(sp.ControllingClient, lm.RegionHandle, targetPos, targetLookAt, (uint)TeleportFlags.ViaLocation); |
4712 | } | 4712 | } |
4713 | 4713 | ||
4714 | public void llTextBox(string agent, string message, int chatChannel) | 4714 | public void llTextBox(string agent, string message, int chatChannel) |
4715 | { | 4715 | { |
4716 | IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); | 4716 | IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); |
4717 | 4717 | ||
4718 | if (dm == null) | 4718 | if (dm == null) |
4719 | return; | 4719 | return; |
4720 | 4720 | ||
4721 | m_host.AddScriptLPS(1); | 4721 | m_host.AddScriptLPS(1); |
4722 | UUID av = new UUID(); | 4722 | UUID av = new UUID(); |
4723 | if (!UUID.TryParse(agent,out av)) | 4723 | if (!UUID.TryParse(agent,out av)) |
4724 | { | 4724 | { |
4725 | Error("llTextBox", "First parameter must be a key"); | 4725 | Error("llTextBox", "First parameter must be a key"); |
4726 | return; | 4726 | return; |
4727 | } | 4727 | } |
4728 | 4728 | ||
4729 | if (message == string.Empty) | 4729 | if (message == string.Empty) |
4730 | { | 4730 | { |
4731 | Error("llTextBox", "Empty message"); | 4731 | Error("llTextBox", "Empty message"); |
4732 | } | 4732 | } |
4733 | else if (message.Length > 512) | 4733 | else if (message.Length > 512) |
4734 | { | 4734 | { |
4735 | Error("llTextBox", "Message more than 512 characters"); | 4735 | Error("llTextBox", "Message more than 512 characters"); |
4736 | } | 4736 | } |
4737 | else | 4737 | else |
4738 | { | 4738 | { |
4739 | dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID); | 4739 | dm.SendTextBoxToUser(av, message, chatChannel, m_host.Name, m_host.UUID, m_host.OwnerID); |
4740 | ScriptSleep(m_sleepMsOnTextBox); | 4740 | ScriptSleep(m_sleepMsOnTextBox); |
4741 | } | 4741 | } |
4742 | } | 4742 | } |
4743 | 4743 | ||
4744 | public void llModifyLand(int action, int brush) | 4744 | public void llModifyLand(int action, int brush) |
4745 | { | 4745 | { |
4746 | m_host.AddScriptLPS(1); | 4746 | m_host.AddScriptLPS(1); |
4747 | ITerrainModule tm = m_ScriptEngine.World.RequestModuleInterface<ITerrainModule>(); | 4747 | ITerrainModule tm = m_ScriptEngine.World.RequestModuleInterface<ITerrainModule>(); |
4748 | if (tm != null) | 4748 | if (tm != null) |
4749 | { | 4749 | { |
4750 | tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID); | 4750 | tm.ModifyTerrain(m_host.OwnerID, m_host.AbsolutePosition, (byte) brush, (byte) action, m_host.OwnerID); |
4751 | } | 4751 | } |
4752 | } | 4752 | } |
4753 | 4753 | ||
4754 | public void llCollisionSound(string impact_sound, double impact_volume) | 4754 | public void llCollisionSound(string impact_sound, double impact_volume) |
4755 | { | 4755 | { |
4756 | m_host.AddScriptLPS(1); | 4756 | m_host.AddScriptLPS(1); |
4757 | 4757 | ||
4758 | // TODO: Parameter check logic required. | 4758 | // TODO: Parameter check logic required. |
4759 | m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); | 4759 | m_host.CollisionSound = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, impact_sound, AssetType.Sound); |
4760 | m_host.CollisionSoundVolume = (float)impact_volume; | 4760 | m_host.CollisionSoundVolume = (float)impact_volume; |
4761 | } | 4761 | } |
4762 | 4762 | ||
4763 | public LSL_String llGetAnimation(string id) | 4763 | public LSL_String llGetAnimation(string id) |
4764 | { | 4764 | { |
4765 | // This should only return a value if the avatar is in the same region | 4765 | // This should only return a value if the avatar is in the same region |
4766 | m_host.AddScriptLPS(1); | 4766 | m_host.AddScriptLPS(1); |
4767 | UUID avatar = (UUID)id; | 4767 | UUID avatar = (UUID)id; |
4768 | ScenePresence presence = World.GetScenePresence(avatar); | 4768 | ScenePresence presence = World.GetScenePresence(avatar); |
4769 | if (presence == null) | 4769 | if (presence == null) |
4770 | return ""; | 4770 | return ""; |
4771 | 4771 | ||
4772 | if (m_host.RegionHandle == presence.RegionHandle) | 4772 | if (m_host.RegionHandle == presence.RegionHandle) |
4773 | { | 4773 | { |
4774 | Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames; | 4774 | Dictionary<UUID, string> animationstateNames = DefaultAvatarAnimations.AnimStateNames; |
4775 | 4775 | ||
4776 | if (presence != null) | 4776 | if (presence != null) |
4777 | { | 4777 | { |
4778 | AnimationSet currentAnims = presence.Animator.Animations; | 4778 | AnimationSet currentAnims = presence.Animator.Animations; |
4779 | string currentAnimationState = String.Empty; | 4779 | string currentAnimationState = String.Empty; |
4780 | if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) | 4780 | if (animationstateNames.TryGetValue(currentAnims.ImplicitDefaultAnimation.AnimID, out currentAnimationState)) |
4781 | return currentAnimationState; | 4781 | return currentAnimationState; |
4782 | } | 4782 | } |
4783 | } | 4783 | } |
4784 | 4784 | ||
4785 | return String.Empty; | 4785 | return String.Empty; |
4786 | } | 4786 | } |
4787 | 4787 | ||
4788 | public void llMessageLinked(int linknumber, int num, string msg, string id) | 4788 | public void llMessageLinked(int linknumber, int num, string msg, string id) |
4789 | { | 4789 | { |
4790 | m_host.AddScriptLPS(1); | 4790 | m_host.AddScriptLPS(1); |
4791 | 4791 | ||
4792 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 4792 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
4793 | 4793 | ||
4794 | UUID partItemID; | 4794 | UUID partItemID; |
4795 | foreach (SceneObjectPart part in parts) | 4795 | foreach (SceneObjectPart part in parts) |
4796 | { | 4796 | { |
4797 | foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems()) | 4797 | foreach (TaskInventoryItem item in part.Inventory.GetInventoryItems()) |
4798 | { | 4798 | { |
4799 | if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT) | 4799 | if (item.Type == ScriptBaseClass.INVENTORY_SCRIPT) |
4800 | { | 4800 | { |
4801 | partItemID = item.ItemID; | 4801 | partItemID = item.ItemID; |
4802 | int linkNumber = m_host.LinkNum; | 4802 | int linkNumber = m_host.LinkNum; |
4803 | if (m_host.ParentGroup.PrimCount == 1) | 4803 | if (m_host.ParentGroup.PrimCount == 1) |
4804 | linkNumber = 0; | 4804 | linkNumber = 0; |
4805 | 4805 | ||
4806 | object[] resobj = new object[] | 4806 | object[] resobj = new object[] |
4807 | { | 4807 | { |
4808 | new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | 4808 | new LSL_Integer(linkNumber), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) |
4809 | }; | 4809 | }; |
4810 | 4810 | ||
4811 | m_ScriptEngine.PostScriptEvent(partItemID, | 4811 | m_ScriptEngine.PostScriptEvent(partItemID, |
4812 | new EventParams("link_message", | 4812 | new EventParams("link_message", |
4813 | resobj, new DetectParams[0])); | 4813 | resobj, new DetectParams[0])); |
4814 | } | 4814 | } |
4815 | } | 4815 | } |
4816 | } | 4816 | } |
4817 | } | 4817 | } |
4818 | 4818 | ||
4819 | public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local) | 4819 | public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local) |
4820 | { | 4820 | { |
4821 | m_host.AddScriptLPS(1); | 4821 | m_host.AddScriptLPS(1); |
4822 | bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing; | 4822 | bool pushrestricted = World.RegionInfo.RegionSettings.RestrictPushing; |
4823 | bool pushAllowed = false; | 4823 | bool pushAllowed = false; |
4824 | 4824 | ||
4825 | bool pusheeIsAvatar = false; | 4825 | bool pusheeIsAvatar = false; |
4826 | UUID targetID = UUID.Zero; | 4826 | UUID targetID = UUID.Zero; |
4827 | 4827 | ||
4828 | if (!UUID.TryParse(target,out targetID)) | 4828 | if (!UUID.TryParse(target,out targetID)) |
4829 | return; | 4829 | return; |
4830 | 4830 | ||
4831 | ScenePresence pusheeav = null; | 4831 | ScenePresence pusheeav = null; |
4832 | Vector3 PusheePos = Vector3.Zero; | 4832 | Vector3 PusheePos = Vector3.Zero; |
4833 | SceneObjectPart pusheeob = null; | 4833 | SceneObjectPart pusheeob = null; |
4834 | 4834 | ||
4835 | ScenePresence avatar = World.GetScenePresence(targetID); | 4835 | ScenePresence avatar = World.GetScenePresence(targetID); |
4836 | if (avatar != null) | 4836 | if (avatar != null) |
4837 | { | 4837 | { |
4838 | pusheeIsAvatar = true; | 4838 | pusheeIsAvatar = true; |
4839 | 4839 | ||
4840 | // Pushee doesn't have a physics actor | 4840 | // Pushee doesn't have a physics actor |
4841 | if (avatar.PhysicsActor == null) | 4841 | if (avatar.PhysicsActor == null) |
4842 | return; | 4842 | return; |
4843 | 4843 | ||
4844 | // Pushee is in GodMode this pushing object isn't owned by them | 4844 | // Pushee is in GodMode this pushing object isn't owned by them |
4845 | if (avatar.GodLevel > 0 && m_host.OwnerID != targetID) | 4845 | if (avatar.GodLevel > 0 && m_host.OwnerID != targetID) |
4846 | return; | 4846 | return; |
4847 | 4847 | ||
4848 | pusheeav = avatar; | 4848 | pusheeav = avatar; |
4849 | 4849 | ||
4850 | // Find pushee position | 4850 | // Find pushee position |
4851 | // Pushee Linked? | 4851 | // Pushee Linked? |
4852 | SceneObjectPart sitPart = pusheeav.ParentPart; | 4852 | SceneObjectPart sitPart = pusheeav.ParentPart; |
4853 | if (sitPart != null) | 4853 | if (sitPart != null) |
4854 | PusheePos = sitPart.AbsolutePosition; | 4854 | PusheePos = sitPart.AbsolutePosition; |
4855 | else | 4855 | else |
4856 | PusheePos = pusheeav.AbsolutePosition; | 4856 | PusheePos = pusheeav.AbsolutePosition; |
4857 | } | 4857 | } |
4858 | 4858 | ||
4859 | if (!pusheeIsAvatar) | 4859 | if (!pusheeIsAvatar) |
4860 | { | 4860 | { |
4861 | // not an avatar so push is not affected by parcel flags | 4861 | // not an avatar so push is not affected by parcel flags |
4862 | pusheeob = World.GetSceneObjectPart((UUID)target); | 4862 | pusheeob = World.GetSceneObjectPart((UUID)target); |
4863 | 4863 | ||
4864 | // We can't find object | 4864 | // We can't find object |
4865 | if (pusheeob == null) | 4865 | if (pusheeob == null) |
4866 | return; | 4866 | return; |
4867 | 4867 | ||
4868 | // Object not pushable. Not an attachment and has no physics component | 4868 | // Object not pushable. Not an attachment and has no physics component |
4869 | if (!pusheeob.ParentGroup.IsAttachment && pusheeob.PhysActor == null) | 4869 | if (!pusheeob.ParentGroup.IsAttachment && pusheeob.PhysActor == null) |
4870 | return; | 4870 | return; |
4871 | 4871 | ||
4872 | PusheePos = pusheeob.AbsolutePosition; | 4872 | PusheePos = pusheeob.AbsolutePosition; |
4873 | pushAllowed = true; | 4873 | pushAllowed = true; |
4874 | } | 4874 | } |
4875 | else | 4875 | else |
4876 | { | 4876 | { |
4877 | if (pushrestricted) | 4877 | if (pushrestricted) |
4878 | { | 4878 | { |
4879 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); | 4879 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); |
4880 | 4880 | ||
4881 | // We didn't find the parcel but region is push restricted so assume it is NOT ok | 4881 | // We didn't find the parcel but region is push restricted so assume it is NOT ok |
4882 | if (targetlandObj == null) | 4882 | if (targetlandObj == null) |
4883 | return; | 4883 | return; |
4884 | 4884 | ||
4885 | // Need provisions for Group Owned here | 4885 | // Need provisions for Group Owned here |
4886 | if (m_host.OwnerID == targetlandObj.LandData.OwnerID || | 4886 | if (m_host.OwnerID == targetlandObj.LandData.OwnerID || |
4887 | targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID) | 4887 | targetlandObj.LandData.IsGroupOwned || m_host.OwnerID == targetID) |
4888 | { | 4888 | { |
4889 | pushAllowed = true; | 4889 | pushAllowed = true; |
4890 | } | 4890 | } |
4891 | } | 4891 | } |
4892 | else | 4892 | else |
4893 | { | 4893 | { |
4894 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); | 4894 | ILandObject targetlandObj = World.LandChannel.GetLandObject(PusheePos); |
4895 | if (targetlandObj == null) | 4895 | if (targetlandObj == null) |
4896 | { | 4896 | { |
4897 | // We didn't find the parcel but region isn't push restricted so assume it's ok | 4897 | // We didn't find the parcel but region isn't push restricted so assume it's ok |
4898 | pushAllowed = true; | 4898 | pushAllowed = true; |
4899 | } | 4899 | } |
4900 | else | 4900 | else |
4901 | { | 4901 | { |
4902 | // Parcel push restriction | 4902 | // Parcel push restriction |
4903 | if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject) | 4903 | if ((targetlandObj.LandData.Flags & (uint)ParcelFlags.RestrictPushObject) == (uint)ParcelFlags.RestrictPushObject) |
4904 | { | 4904 | { |
4905 | // Need provisions for Group Owned here | 4905 | // Need provisions for Group Owned here |
4906 | if (m_host.OwnerID == targetlandObj.LandData.OwnerID || | 4906 | if (m_host.OwnerID == targetlandObj.LandData.OwnerID || |
4907 | targetlandObj.LandData.IsGroupOwned || | 4907 | targetlandObj.LandData.IsGroupOwned || |
4908 | m_host.OwnerID == targetID) | 4908 | m_host.OwnerID == targetID) |
4909 | { | 4909 | { |
4910 | pushAllowed = true; | 4910 | pushAllowed = true; |
4911 | } | 4911 | } |
4912 | 4912 | ||
4913 | //ParcelFlags.RestrictPushObject | 4913 | //ParcelFlags.RestrictPushObject |
4914 | //pushAllowed = true; | 4914 | //pushAllowed = true; |
4915 | } | 4915 | } |
4916 | else | 4916 | else |
4917 | { | 4917 | { |
4918 | // Parcel isn't push restricted | 4918 | // Parcel isn't push restricted |
4919 | pushAllowed = true; | 4919 | pushAllowed = true; |
4920 | } | 4920 | } |
4921 | } | 4921 | } |
4922 | } | 4922 | } |
4923 | } | 4923 | } |
4924 | 4924 | ||
4925 | if (pushAllowed) | 4925 | if (pushAllowed) |
4926 | { | 4926 | { |
4927 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); | 4927 | float distance = (PusheePos - m_host.AbsolutePosition).Length(); |
4928 | float distance_term = distance * distance * distance; // Script Energy | 4928 | float distance_term = distance * distance * distance; // Script Energy |
4929 | float pusher_mass = m_host.GetMass(); | 4929 | float pusher_mass = m_host.GetMass(); |
4930 | 4930 | ||
4931 | float PUSH_ATTENUATION_DISTANCE = 17f; | 4931 | float PUSH_ATTENUATION_DISTANCE = 17f; |
4932 | float PUSH_ATTENUATION_SCALE = 5f; | 4932 | float PUSH_ATTENUATION_SCALE = 5f; |
4933 | float distance_attenuation = 1f; | 4933 | float distance_attenuation = 1f; |
4934 | if (distance > PUSH_ATTENUATION_DISTANCE) | 4934 | if (distance > PUSH_ATTENUATION_DISTANCE) |
4935 | { | 4935 | { |
4936 | float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE; | 4936 | float normalized_units = 1f + (distance - PUSH_ATTENUATION_DISTANCE) / PUSH_ATTENUATION_SCALE; |
4937 | distance_attenuation = 1f / normalized_units; | 4937 | distance_attenuation = 1f / normalized_units; |
4938 | } | 4938 | } |
4939 | 4939 | ||
4940 | Vector3 applied_linear_impulse = impulse; | 4940 | Vector3 applied_linear_impulse = impulse; |
4941 | { | 4941 | { |
4942 | float impulse_length = applied_linear_impulse.Length(); | 4942 | float impulse_length = applied_linear_impulse.Length(); |
4943 | 4943 | ||
4944 | float desired_energy = impulse_length * pusher_mass; | 4944 | float desired_energy = impulse_length * pusher_mass; |
4945 | if (desired_energy > 0f) | 4945 | if (desired_energy > 0f) |
4946 | desired_energy += distance_term; | 4946 | desired_energy += distance_term; |
4947 | 4947 | ||
4948 | float scaling_factor = 1f; | 4948 | float scaling_factor = 1f; |
4949 | scaling_factor *= distance_attenuation; | 4949 | scaling_factor *= distance_attenuation; |
4950 | applied_linear_impulse *= scaling_factor; | 4950 | applied_linear_impulse *= scaling_factor; |
4951 | 4951 | ||
4952 | } | 4952 | } |
4953 | 4953 | ||
4954 | if (pusheeIsAvatar) | 4954 | if (pusheeIsAvatar) |
4955 | { | 4955 | { |
4956 | if (pusheeav != null) | 4956 | if (pusheeav != null) |
4957 | { | 4957 | { |
4958 | PhysicsActor pa = pusheeav.PhysicsActor; | 4958 | PhysicsActor pa = pusheeav.PhysicsActor; |
4959 | 4959 | ||
4960 | if (pa != null) | 4960 | if (pa != null) |
4961 | { | 4961 | { |
4962 | if (local != 0) | 4962 | if (local != 0) |
4963 | { | 4963 | { |
4964 | applied_linear_impulse *= m_host.GetWorldRotation(); | 4964 | applied_linear_impulse *= m_host.GetWorldRotation(); |
4965 | } | 4965 | } |
4966 | 4966 | ||
4967 | pa.AddForce(applied_linear_impulse, true); | 4967 | pa.AddForce(applied_linear_impulse, true); |
4968 | } | 4968 | } |
4969 | } | 4969 | } |
4970 | } | 4970 | } |
4971 | else | 4971 | else |
4972 | { | 4972 | { |
4973 | if (pusheeob != null) | 4973 | if (pusheeob != null) |
4974 | { | 4974 | { |
4975 | if (pusheeob.PhysActor != null) | 4975 | if (pusheeob.PhysActor != null) |
4976 | { | 4976 | { |
4977 | pusheeob.ApplyImpulse(applied_linear_impulse, local != 0); | 4977 | pusheeob.ApplyImpulse(applied_linear_impulse, local != 0); |
4978 | } | 4978 | } |
4979 | } | 4979 | } |
4980 | } | 4980 | } |
4981 | } | 4981 | } |
4982 | } | 4982 | } |
4983 | 4983 | ||
4984 | public void llPassCollisions(int pass) | 4984 | public void llPassCollisions(int pass) |
4985 | { | 4985 | { |
4986 | m_host.AddScriptLPS(1); | 4986 | m_host.AddScriptLPS(1); |
4987 | if (pass == 0) | 4987 | if (pass == 0) |
4988 | { | 4988 | { |
4989 | m_host.PassCollisions = false; | 4989 | m_host.PassCollisions = false; |
4990 | } | 4990 | } |
4991 | else | 4991 | else |
4992 | { | 4992 | { |
4993 | m_host.PassCollisions = true; | 4993 | m_host.PassCollisions = true; |
4994 | } | 4994 | } |
4995 | } | 4995 | } |
4996 | 4996 | ||
4997 | public LSL_String llGetScriptName() | 4997 | public LSL_String llGetScriptName() |
4998 | { | 4998 | { |
4999 | m_host.AddScriptLPS(1); | 4999 | m_host.AddScriptLPS(1); |
5000 | 5000 | ||
5001 | return m_item.Name != null ? m_item.Name : String.Empty; | 5001 | return m_item.Name != null ? m_item.Name : String.Empty; |
5002 | } | 5002 | } |
5003 | 5003 | ||
5004 | public LSL_Integer llGetLinkNumberOfSides(int link) | 5004 | public LSL_Integer llGetLinkNumberOfSides(int link) |
5005 | { | 5005 | { |
5006 | m_host.AddScriptLPS(1); | 5006 | m_host.AddScriptLPS(1); |
5007 | 5007 | ||
5008 | SceneObjectPart linkedPart; | 5008 | SceneObjectPart linkedPart; |
5009 | 5009 | ||
5010 | if (link == ScriptBaseClass.LINK_ROOT) | 5010 | if (link == ScriptBaseClass.LINK_ROOT) |
5011 | linkedPart = m_host.ParentGroup.RootPart; | 5011 | linkedPart = m_host.ParentGroup.RootPart; |
5012 | else if (link == ScriptBaseClass.LINK_THIS) | 5012 | else if (link == ScriptBaseClass.LINK_THIS) |
5013 | linkedPart = m_host; | 5013 | linkedPart = m_host; |
5014 | else | 5014 | else |
5015 | linkedPart = m_host.ParentGroup.GetLinkNumPart(link); | 5015 | linkedPart = m_host.ParentGroup.GetLinkNumPart(link); |
5016 | 5016 | ||
5017 | return GetNumberOfSides(linkedPart); | 5017 | return GetNumberOfSides(linkedPart); |
5018 | } | 5018 | } |
5019 | 5019 | ||
5020 | public LSL_Integer llGetNumberOfSides() | 5020 | public LSL_Integer llGetNumberOfSides() |
5021 | { | 5021 | { |
5022 | m_host.AddScriptLPS(1); | 5022 | m_host.AddScriptLPS(1); |
5023 | 5023 | ||
5024 | return GetNumberOfSides(m_host); | 5024 | return GetNumberOfSides(m_host); |
5025 | } | 5025 | } |
5026 | 5026 | ||
5027 | protected int GetNumberOfSides(SceneObjectPart part) | 5027 | protected int GetNumberOfSides(SceneObjectPart part) |
5028 | { | 5028 | { |
5029 | int sides = part.GetNumberOfSides(); | 5029 | int sides = part.GetNumberOfSides(); |
5030 | 5030 | ||
5031 | if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0) | 5031 | if (part.GetPrimType() == PrimType.SPHERE && part.Shape.ProfileHollow > 0) |
5032 | { | 5032 | { |
5033 | // Make up for a bug where LSL shows 4 sides rather than 2 | 5033 | // Make up for a bug where LSL shows 4 sides rather than 2 |
5034 | sides += 2; | 5034 | sides += 2; |
5035 | } | 5035 | } |
5036 | 5036 | ||
5037 | return sides; | 5037 | return sides; |
5038 | } | 5038 | } |
5039 | 5039 | ||
5040 | 5040 | ||
5041 | /* The new / changed functions were tested with the following LSL script: | 5041 | /* The new / changed functions were tested with the following LSL script: |
5042 | 5042 | ||
5043 | default | 5043 | default |
5044 | { | 5044 | { |
5045 | state_entry() | 5045 | state_entry() |
5046 | { | 5046 | { |
5047 | rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD); | 5047 | rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD); |
5048 | 5048 | ||
5049 | llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot)); | 5049 | llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot)); |
5050 | llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG)); | 5050 | llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG)); |
5051 | 5051 | ||
5052 | // convert back and forth between quaternion <-> vector and angle | 5052 | // convert back and forth between quaternion <-> vector and angle |
5053 | 5053 | ||
5054 | rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot)); | 5054 | rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot)); |
5055 | 5055 | ||
5056 | llOwnerSay("Old rotation was: "+(string) rot); | 5056 | llOwnerSay("Old rotation was: "+(string) rot); |
5057 | llOwnerSay("re-converted rotation is: "+(string) newrot); | 5057 | llOwnerSay("re-converted rotation is: "+(string) newrot); |
5058 | 5058 | ||
5059 | llSetRot(rot); // to check the parameters in the prim | 5059 | llSetRot(rot); // to check the parameters in the prim |
5060 | } | 5060 | } |
5061 | } | 5061 | } |
5062 | */ | 5062 | */ |
5063 | 5063 | ||
5064 | // Xantor 29/apr/2008 | 5064 | // Xantor 29/apr/2008 |
5065 | // Returns rotation described by rotating angle radians about axis. | 5065 | // Returns rotation described by rotating angle radians about axis. |
5066 | // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2)) | 5066 | // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2)) |
5067 | public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle) | 5067 | public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle) |
5068 | { | 5068 | { |
5069 | m_host.AddScriptLPS(1); | 5069 | m_host.AddScriptLPS(1); |
5070 | 5070 | ||
5071 | double x, y, z, s, t; | 5071 | double x, y, z, s, t; |
5072 | 5072 | ||
5073 | s = Math.Cos(angle * 0.5); | 5073 | s = Math.Cos(angle * 0.5); |
5074 | t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs | 5074 | t = Math.Sin(angle * 0.5); // temp value to avoid 2 more sin() calcs |
5075 | axis = LSL_Vector.Norm(axis); | 5075 | axis = LSL_Vector.Norm(axis); |
5076 | x = axis.x * t; | 5076 | x = axis.x * t; |
5077 | y = axis.y * t; | 5077 | y = axis.y * t; |
5078 | z = axis.z * t; | 5078 | z = axis.z * t; |
5079 | 5079 | ||
5080 | return new LSL_Rotation(x,y,z,s); | 5080 | return new LSL_Rotation(x,y,z,s); |
5081 | } | 5081 | } |
5082 | 5082 | ||
5083 | /// <summary> | 5083 | /// <summary> |
5084 | /// Returns the axis of rotation for a quaternion | 5084 | /// Returns the axis of rotation for a quaternion |
5085 | /// </summary> | 5085 | /// </summary> |
5086 | /// <returns></returns> | 5086 | /// <returns></returns> |
5087 | /// <param name='rot'></param> | 5087 | /// <param name='rot'></param> |
5088 | public LSL_Vector llRot2Axis(LSL_Rotation rot) | 5088 | public LSL_Vector llRot2Axis(LSL_Rotation rot) |
5089 | { | 5089 | { |
5090 | m_host.AddScriptLPS(1); | 5090 | m_host.AddScriptLPS(1); |
5091 | 5091 | ||
5092 | if (Math.Abs(rot.s) > 1) // normalization needed | 5092 | if (Math.Abs(rot.s) > 1) // normalization needed |
5093 | rot.Normalize(); | 5093 | rot.Normalize(); |
5094 | 5094 | ||
5095 | double s = Math.Sqrt(1 - rot.s * rot.s); | 5095 | double s = Math.Sqrt(1 - rot.s * rot.s); |
5096 | if (s < 0.001) | 5096 | if (s < 0.001) |
5097 | { | 5097 | { |
5098 | return new LSL_Vector(1, 0, 0); | 5098 | return new LSL_Vector(1, 0, 0); |
5099 | } | 5099 | } |
5100 | else | 5100 | else |
5101 | { | 5101 | { |
5102 | double invS = 1.0 / s; | 5102 | double invS = 1.0 / s; |
5103 | if (rot.s < 0) invS = -invS; | 5103 | if (rot.s < 0) invS = -invS; |
5104 | return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS); | 5104 | return new LSL_Vector(rot.x * invS, rot.y * invS, rot.z * invS); |
5105 | } | 5105 | } |
5106 | } | 5106 | } |
5107 | 5107 | ||
5108 | 5108 | ||
5109 | // Returns the angle of a quaternion (see llRot2Axis for the axis) | 5109 | // Returns the angle of a quaternion (see llRot2Axis for the axis) |
5110 | public LSL_Float llRot2Angle(LSL_Rotation rot) | 5110 | public LSL_Float llRot2Angle(LSL_Rotation rot) |
5111 | { | 5111 | { |
5112 | m_host.AddScriptLPS(1); | 5112 | m_host.AddScriptLPS(1); |
5113 | 5113 | ||
5114 | if (Math.Abs(rot.s) > 1) // normalization needed | 5114 | if (Math.Abs(rot.s) > 1) // normalization needed |
5115 | rot.Normalize(); | 5115 | rot.Normalize(); |
5116 | 5116 | ||
5117 | double angle = 2 * Math.Acos(rot.s); | 5117 | double angle = 2 * Math.Acos(rot.s); |
5118 | if (angle > Math.PI) | 5118 | if (angle > Math.PI) |
5119 | angle = 2 * Math.PI - angle; | 5119 | angle = 2 * Math.PI - angle; |
5120 | 5120 | ||
5121 | return angle; | 5121 | return angle; |
5122 | } | 5122 | } |
5123 | 5123 | ||
5124 | public LSL_Float llAcos(double val) | 5124 | public LSL_Float llAcos(double val) |
5125 | { | 5125 | { |
5126 | m_host.AddScriptLPS(1); | 5126 | m_host.AddScriptLPS(1); |
5127 | return (double)Math.Acos(val); | 5127 | return (double)Math.Acos(val); |
5128 | } | 5128 | } |
5129 | 5129 | ||
5130 | public LSL_Float llAsin(double val) | 5130 | public LSL_Float llAsin(double val) |
5131 | { | 5131 | { |
5132 | m_host.AddScriptLPS(1); | 5132 | m_host.AddScriptLPS(1); |
5133 | return (double)Math.Asin(val); | 5133 | return (double)Math.Asin(val); |
5134 | } | 5134 | } |
5135 | 5135 | ||
5136 | // jcochran 5/jan/2012 | 5136 | // jcochran 5/jan/2012 |
5137 | public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) | 5137 | public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) |
5138 | { | 5138 | { |
5139 | m_host.AddScriptLPS(1); | 5139 | m_host.AddScriptLPS(1); |
5140 | 5140 | ||
5141 | double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s); | 5141 | double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s); |
5142 | double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s); | 5142 | double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s); |
5143 | double aa_bb = aa * bb; | 5143 | double aa_bb = aa * bb; |
5144 | if (aa_bb == 0) return 0.0; | 5144 | if (aa_bb == 0) return 0.0; |
5145 | double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s); | 5145 | double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s); |
5146 | double quotient = (ab * ab) / aa_bb; | 5146 | double quotient = (ab * ab) / aa_bb; |
5147 | if (quotient >= 1.0) return 0.0; | 5147 | if (quotient >= 1.0) return 0.0; |
5148 | return Math.Acos(2 * quotient - 1); | 5148 | return Math.Acos(2 * quotient - 1); |
5149 | } | 5149 | } |
5150 | 5150 | ||
5151 | public LSL_String llGetInventoryKey(string name) | 5151 | public LSL_String llGetInventoryKey(string name) |
5152 | { | 5152 | { |
5153 | m_host.AddScriptLPS(1); | 5153 | m_host.AddScriptLPS(1); |
5154 | 5154 | ||
5155 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 5155 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); |
5156 | 5156 | ||
5157 | if (item == null) | 5157 | if (item == null) |
5158 | return UUID.Zero.ToString(); | 5158 | return UUID.Zero.ToString(); |
5159 | 5159 | ||
5160 | if ((item.CurrentPermissions | 5160 | if ((item.CurrentPermissions |
5161 | & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) | 5161 | & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) |
5162 | == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) | 5162 | == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) |
5163 | { | 5163 | { |
5164 | return item.AssetID.ToString(); | 5164 | return item.AssetID.ToString(); |
5165 | } | 5165 | } |
5166 | 5166 | ||
5167 | return UUID.Zero.ToString(); | 5167 | return UUID.Zero.ToString(); |
5168 | } | 5168 | } |
5169 | 5169 | ||
5170 | public void llAllowInventoryDrop(int add) | 5170 | public void llAllowInventoryDrop(int add) |
5171 | { | 5171 | { |
5172 | m_host.AddScriptLPS(1); | 5172 | m_host.AddScriptLPS(1); |
5173 | 5173 | ||
5174 | if (add != 0) | 5174 | if (add != 0) |
5175 | m_host.ParentGroup.RootPart.AllowedDrop = true; | 5175 | m_host.ParentGroup.RootPart.AllowedDrop = true; |
5176 | else | 5176 | else |
5177 | m_host.ParentGroup.RootPart.AllowedDrop = false; | 5177 | m_host.ParentGroup.RootPart.AllowedDrop = false; |
5178 | 5178 | ||
5179 | // Update the object flags | 5179 | // Update the object flags |
5180 | m_host.ParentGroup.RootPart.aggregateScriptEvents(); | 5180 | m_host.ParentGroup.RootPart.aggregateScriptEvents(); |
5181 | } | 5181 | } |
5182 | 5182 | ||
5183 | public LSL_Vector llGetSunDirection() | 5183 | public LSL_Vector llGetSunDirection() |
5184 | { | 5184 | { |
5185 | m_host.AddScriptLPS(1); | 5185 | m_host.AddScriptLPS(1); |
5186 | 5186 | ||
5187 | LSL_Vector SunDoubleVector3; | 5187 | LSL_Vector SunDoubleVector3; |
5188 | Vector3 SunFloatVector3; | 5188 | Vector3 SunFloatVector3; |
5189 | 5189 | ||
5190 | // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule | 5190 | // sunPosition estate setting is set in OpenSim.Region.CoreModules.SunModule |
5191 | // have to convert from Vector3 (float) to LSL_Vector (double) | 5191 | // have to convert from Vector3 (float) to LSL_Vector (double) |
5192 | SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector; | 5192 | SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector; |
5193 | SunDoubleVector3.x = (double)SunFloatVector3.X; | 5193 | SunDoubleVector3.x = (double)SunFloatVector3.X; |
5194 | SunDoubleVector3.y = (double)SunFloatVector3.Y; | 5194 | SunDoubleVector3.y = (double)SunFloatVector3.Y; |
5195 | SunDoubleVector3.z = (double)SunFloatVector3.Z; | 5195 | SunDoubleVector3.z = (double)SunFloatVector3.Z; |
5196 | 5196 | ||
5197 | return SunDoubleVector3; | 5197 | return SunDoubleVector3; |
5198 | } | 5198 | } |
5199 | 5199 | ||
5200 | public LSL_Vector llGetTextureOffset(int face) | 5200 | public LSL_Vector llGetTextureOffset(int face) |
5201 | { | 5201 | { |
5202 | m_host.AddScriptLPS(1); | 5202 | m_host.AddScriptLPS(1); |
5203 | return GetTextureOffset(m_host, face); | 5203 | return GetTextureOffset(m_host, face); |
5204 | } | 5204 | } |
5205 | 5205 | ||
5206 | protected LSL_Vector GetTextureOffset(SceneObjectPart part, int face) | 5206 | protected LSL_Vector GetTextureOffset(SceneObjectPart part, int face) |
5207 | { | 5207 | { |
5208 | Primitive.TextureEntry tex = part.Shape.Textures; | 5208 | Primitive.TextureEntry tex = part.Shape.Textures; |
5209 | LSL_Vector offset = new LSL_Vector(); | 5209 | LSL_Vector offset = new LSL_Vector(); |
5210 | if (face == ScriptBaseClass.ALL_SIDES) | 5210 | if (face == ScriptBaseClass.ALL_SIDES) |
5211 | { | 5211 | { |
5212 | face = 0; | 5212 | face = 0; |
5213 | } | 5213 | } |
5214 | if (face >= 0 && face < GetNumberOfSides(part)) | 5214 | if (face >= 0 && face < GetNumberOfSides(part)) |
5215 | { | 5215 | { |
5216 | offset.x = tex.GetFace((uint)face).OffsetU; | 5216 | offset.x = tex.GetFace((uint)face).OffsetU; |
5217 | offset.y = tex.GetFace((uint)face).OffsetV; | 5217 | offset.y = tex.GetFace((uint)face).OffsetV; |
5218 | offset.z = 0.0; | 5218 | offset.z = 0.0; |
5219 | return offset; | 5219 | return offset; |
5220 | } | 5220 | } |
5221 | else | 5221 | else |
5222 | { | 5222 | { |
5223 | return offset; | 5223 | return offset; |
5224 | } | 5224 | } |
5225 | } | 5225 | } |
5226 | 5226 | ||
5227 | public LSL_Vector llGetTextureScale(int side) | 5227 | public LSL_Vector llGetTextureScale(int side) |
5228 | { | 5228 | { |
5229 | m_host.AddScriptLPS(1); | 5229 | m_host.AddScriptLPS(1); |
5230 | Primitive.TextureEntry tex = m_host.Shape.Textures; | 5230 | Primitive.TextureEntry tex = m_host.Shape.Textures; |
5231 | LSL_Vector scale; | 5231 | LSL_Vector scale; |
5232 | if (side == -1) | 5232 | if (side == -1) |
5233 | { | 5233 | { |
5234 | side = 0; | 5234 | side = 0; |
5235 | } | 5235 | } |
5236 | scale.x = tex.GetFace((uint)side).RepeatU; | 5236 | scale.x = tex.GetFace((uint)side).RepeatU; |
5237 | scale.y = tex.GetFace((uint)side).RepeatV; | 5237 | scale.y = tex.GetFace((uint)side).RepeatV; |
5238 | scale.z = 0.0; | 5238 | scale.z = 0.0; |
5239 | return scale; | 5239 | return scale; |
5240 | } | 5240 | } |
5241 | 5241 | ||
5242 | public LSL_Float llGetTextureRot(int face) | 5242 | public LSL_Float llGetTextureRot(int face) |
5243 | { | 5243 | { |
5244 | m_host.AddScriptLPS(1); | 5244 | m_host.AddScriptLPS(1); |
5245 | return GetTextureRot(m_host, face); | 5245 | return GetTextureRot(m_host, face); |
5246 | } | 5246 | } |
5247 | 5247 | ||
5248 | protected LSL_Float GetTextureRot(SceneObjectPart part, int face) | 5248 | protected LSL_Float GetTextureRot(SceneObjectPart part, int face) |
5249 | { | 5249 | { |
5250 | Primitive.TextureEntry tex = part.Shape.Textures; | 5250 | Primitive.TextureEntry tex = part.Shape.Textures; |
5251 | if (face == -1) | 5251 | if (face == -1) |
5252 | { | 5252 | { |
5253 | face = 0; | 5253 | face = 0; |
5254 | } | 5254 | } |
5255 | if (face >= 0 && face < GetNumberOfSides(part)) | 5255 | if (face >= 0 && face < GetNumberOfSides(part)) |
5256 | { | 5256 | { |
5257 | return tex.GetFace((uint)face).Rotation; | 5257 | return tex.GetFace((uint)face).Rotation; |
5258 | } | 5258 | } |
5259 | else | 5259 | else |
5260 | { | 5260 | { |
5261 | return 0.0; | 5261 | return 0.0; |
5262 | } | 5262 | } |
5263 | } | 5263 | } |
5264 | 5264 | ||
5265 | public LSL_Integer llSubStringIndex(string source, string pattern) | 5265 | public LSL_Integer llSubStringIndex(string source, string pattern) |
5266 | { | 5266 | { |
5267 | m_host.AddScriptLPS(1); | 5267 | m_host.AddScriptLPS(1); |
5268 | return source.IndexOf(pattern); | 5268 | return source.IndexOf(pattern); |
5269 | } | 5269 | } |
5270 | 5270 | ||
5271 | public LSL_String llGetOwnerKey(string id) | 5271 | public LSL_String llGetOwnerKey(string id) |
5272 | { | 5272 | { |
5273 | m_host.AddScriptLPS(1); | 5273 | m_host.AddScriptLPS(1); |
5274 | UUID key = new UUID(); | 5274 | UUID key = new UUID(); |
5275 | if (UUID.TryParse(id, out key)) | 5275 | if (UUID.TryParse(id, out key)) |
5276 | { | 5276 | { |
5277 | try | 5277 | try |
5278 | { | 5278 | { |
5279 | SceneObjectPart obj = World.GetSceneObjectPart(key); | 5279 | SceneObjectPart obj = World.GetSceneObjectPart(key); |
5280 | if (obj == null) | 5280 | if (obj == null) |
5281 | return id; // the key is for an agent so just return the key | 5281 | return id; // the key is for an agent so just return the key |
5282 | else | 5282 | else |
5283 | return obj.OwnerID.ToString(); | 5283 | return obj.OwnerID.ToString(); |
5284 | } | 5284 | } |
5285 | catch (KeyNotFoundException) | 5285 | catch (KeyNotFoundException) |
5286 | { | 5286 | { |
5287 | return id; // The Object/Agent not in the region so just return the key | 5287 | return id; // The Object/Agent not in the region so just return the key |
5288 | } | 5288 | } |
5289 | } | 5289 | } |
5290 | else | 5290 | else |
5291 | { | 5291 | { |
5292 | return UUID.Zero.ToString(); | 5292 | return UUID.Zero.ToString(); |
5293 | } | 5293 | } |
5294 | } | 5294 | } |
5295 | 5295 | ||
5296 | public LSL_Vector llGetCenterOfMass() | 5296 | public LSL_Vector llGetCenterOfMass() |
5297 | { | 5297 | { |
5298 | m_host.AddScriptLPS(1); | 5298 | m_host.AddScriptLPS(1); |
5299 | 5299 | ||
5300 | return new LSL_Vector(m_host.GetCenterOfMass()); | 5300 | return new LSL_Vector(m_host.GetCenterOfMass()); |
5301 | } | 5301 | } |
5302 | 5302 | ||
5303 | public LSL_List llListSort(LSL_List src, int stride, int ascending) | 5303 | public LSL_List llListSort(LSL_List src, int stride, int ascending) |
5304 | { | 5304 | { |
5305 | m_host.AddScriptLPS(1); | 5305 | m_host.AddScriptLPS(1); |
5306 | 5306 | ||
5307 | if (stride <= 0) | 5307 | if (stride <= 0) |
5308 | { | 5308 | { |
5309 | stride = 1; | 5309 | stride = 1; |
5310 | } | 5310 | } |
5311 | return src.Sort(stride, ascending); | 5311 | return src.Sort(stride, ascending); |
5312 | } | 5312 | } |
5313 | 5313 | ||
5314 | public LSL_Integer llGetListLength(LSL_List src) | 5314 | public LSL_Integer llGetListLength(LSL_List src) |
5315 | { | 5315 | { |
5316 | m_host.AddScriptLPS(1); | 5316 | m_host.AddScriptLPS(1); |
5317 | 5317 | ||
5318 | if (src == null) | 5318 | if (src == null) |
5319 | { | 5319 | { |
5320 | return 0; | 5320 | return 0; |
5321 | } | 5321 | } |
5322 | else | 5322 | else |
5323 | { | 5323 | { |
5324 | return src.Length; | 5324 | return src.Length; |
5325 | } | 5325 | } |
5326 | } | 5326 | } |
5327 | 5327 | ||
5328 | public LSL_Integer llList2Integer(LSL_List src, int index) | 5328 | public LSL_Integer llList2Integer(LSL_List src, int index) |
5329 | { | 5329 | { |
5330 | m_host.AddScriptLPS(1); | 5330 | m_host.AddScriptLPS(1); |
5331 | if (index < 0) | 5331 | if (index < 0) |
5332 | { | 5332 | { |
5333 | index = src.Length + index; | 5333 | index = src.Length + index; |
5334 | } | 5334 | } |
5335 | if (index >= src.Length || index < 0) | 5335 | if (index >= src.Length || index < 0) |
5336 | { | 5336 | { |
5337 | return 0; | 5337 | return 0; |
5338 | } | 5338 | } |
5339 | 5339 | ||
5340 | // Vectors & Rotations always return zero in SL, but | 5340 | // Vectors & Rotations always return zero in SL, but |
5341 | // keys don't always return zero, it seems to be a bit complex. | 5341 | // keys don't always return zero, it seems to be a bit complex. |
5342 | else if (src.Data[index] is LSL_Vector || | 5342 | else if (src.Data[index] is LSL_Vector || |
5343 | src.Data[index] is LSL_Rotation) | 5343 | src.Data[index] is LSL_Rotation) |
5344 | { | 5344 | { |
5345 | return 0; | 5345 | return 0; |
5346 | } | 5346 | } |
5347 | try | 5347 | try |
5348 | { | 5348 | { |
5349 | 5349 | ||
5350 | if (src.Data[index] is LSL_Integer) | 5350 | if (src.Data[index] is LSL_Integer) |
5351 | return (LSL_Integer)src.Data[index]; | 5351 | return (LSL_Integer)src.Data[index]; |
5352 | else if (src.Data[index] is LSL_Float) | 5352 | else if (src.Data[index] is LSL_Float) |
5353 | return Convert.ToInt32(((LSL_Float)src.Data[index]).value); | 5353 | return Convert.ToInt32(((LSL_Float)src.Data[index]).value); |
5354 | return new LSL_Integer(src.Data[index].ToString()); | 5354 | return new LSL_Integer(src.Data[index].ToString()); |
5355 | } | 5355 | } |
5356 | catch (FormatException) | 5356 | catch (FormatException) |
5357 | { | 5357 | { |
5358 | return 0; | 5358 | return 0; |
5359 | } | 5359 | } |
5360 | } | 5360 | } |
5361 | 5361 | ||
5362 | public LSL_Float llList2Float(LSL_List src, int index) | 5362 | public LSL_Float llList2Float(LSL_List src, int index) |
5363 | { | 5363 | { |
5364 | m_host.AddScriptLPS(1); | 5364 | m_host.AddScriptLPS(1); |
5365 | if (index < 0) | 5365 | if (index < 0) |
5366 | { | 5366 | { |
5367 | index = src.Length + index; | 5367 | index = src.Length + index; |
5368 | } | 5368 | } |
5369 | if (index >= src.Length || index < 0) | 5369 | if (index >= src.Length || index < 0) |
5370 | { | 5370 | { |
5371 | return 0.0; | 5371 | return 0.0; |
5372 | } | 5372 | } |
5373 | 5373 | ||
5374 | // Vectors & Rotations always return zero in SL | 5374 | // Vectors & Rotations always return zero in SL |
5375 | else if (src.Data[index] is LSL_Vector || | 5375 | else if (src.Data[index] is LSL_Vector || |
5376 | src.Data[index] is LSL_Rotation) | 5376 | src.Data[index] is LSL_Rotation) |
5377 | { | 5377 | { |
5378 | return 0; | 5378 | return 0; |
5379 | } | 5379 | } |
5380 | // valid keys seem to get parsed as integers then converted to floats | 5380 | // valid keys seem to get parsed as integers then converted to floats |
5381 | else | 5381 | else |
5382 | { | 5382 | { |
5383 | UUID uuidt; | 5383 | UUID uuidt; |
5384 | if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt)) | 5384 | if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt)) |
5385 | { | 5385 | { |
5386 | return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value); | 5386 | return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value); |
5387 | } | 5387 | } |
5388 | } | 5388 | } |
5389 | try | 5389 | try |
5390 | { | 5390 | { |
5391 | if (src.Data[index] is LSL_Integer) | 5391 | if (src.Data[index] is LSL_Integer) |
5392 | return Convert.ToDouble(((LSL_Integer)src.Data[index]).value); | 5392 | return Convert.ToDouble(((LSL_Integer)src.Data[index]).value); |
5393 | else if (src.Data[index] is LSL_Float) | 5393 | else if (src.Data[index] is LSL_Float) |
5394 | return Convert.ToDouble(((LSL_Float)src.Data[index]).value); | 5394 | return Convert.ToDouble(((LSL_Float)src.Data[index]).value); |
5395 | else if (src.Data[index] is LSL_String) | 5395 | else if (src.Data[index] is LSL_String) |
5396 | return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); | 5396 | return Convert.ToDouble(((LSL_String)src.Data[index]).m_string); |
5397 | return Convert.ToDouble(src.Data[index]); | 5397 | return Convert.ToDouble(src.Data[index]); |
5398 | } | 5398 | } |
5399 | catch (FormatException) | 5399 | catch (FormatException) |
5400 | { | 5400 | { |
5401 | return 0.0; | 5401 | return 0.0; |
5402 | } | 5402 | } |
5403 | } | 5403 | } |
5404 | 5404 | ||
5405 | public LSL_String llList2String(LSL_List src, int index) | 5405 | public LSL_String llList2String(LSL_List src, int index) |
5406 | { | 5406 | { |
5407 | m_host.AddScriptLPS(1); | 5407 | m_host.AddScriptLPS(1); |
5408 | if (index < 0) | 5408 | if (index < 0) |
5409 | { | 5409 | { |
5410 | index = src.Length + index; | 5410 | index = src.Length + index; |
5411 | } | 5411 | } |
5412 | if (index >= src.Length || index < 0) | 5412 | if (index >= src.Length || index < 0) |
5413 | { | 5413 | { |
5414 | return String.Empty; | 5414 | return String.Empty; |
5415 | } | 5415 | } |
5416 | return src.Data[index].ToString(); | 5416 | return src.Data[index].ToString(); |
5417 | } | 5417 | } |
5418 | 5418 | ||
5419 | public LSL_Key llList2Key(LSL_List src, int index) | 5419 | public LSL_Key llList2Key(LSL_List src, int index) |
5420 | { | 5420 | { |
5421 | m_host.AddScriptLPS(1); | 5421 | m_host.AddScriptLPS(1); |
5422 | if (index < 0) | 5422 | if (index < 0) |
5423 | { | 5423 | { |
5424 | index = src.Length + index; | 5424 | index = src.Length + index; |
5425 | } | 5425 | } |
5426 | 5426 | ||
5427 | if (index >= src.Length || index < 0) | 5427 | if (index >= src.Length || index < 0) |
5428 | { | 5428 | { |
5429 | return ""; | 5429 | return ""; |
5430 | } | 5430 | } |
5431 | 5431 | ||
5432 | // SL spits out an empty string for types other than key & string | 5432 | // SL spits out an empty string for types other than key & string |
5433 | // At the time of patching, LSL_Key is currently LSL_String, | 5433 | // At the time of patching, LSL_Key is currently LSL_String, |
5434 | // so the OR check may be a little redundant, but it's being done | 5434 | // so the OR check may be a little redundant, but it's being done |
5435 | // for completion and should LSL_Key ever be implemented | 5435 | // for completion and should LSL_Key ever be implemented |
5436 | // as it's own struct | 5436 | // as it's own struct |
5437 | // NOTE: 3rd case is needed because a NULL_KEY comes through as | 5437 | // NOTE: 3rd case is needed because a NULL_KEY comes through as |
5438 | // type 'obj' and wrongly returns "" | 5438 | // type 'obj' and wrongly returns "" |
5439 | else if (!(src.Data[index] is LSL_String || | 5439 | else if (!(src.Data[index] is LSL_String || |
5440 | src.Data[index] is LSL_Key || | 5440 | src.Data[index] is LSL_Key || |
5441 | src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000")) | 5441 | src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000")) |
5442 | { | 5442 | { |
5443 | return ""; | 5443 | return ""; |
5444 | } | 5444 | } |
5445 | 5445 | ||
5446 | return src.Data[index].ToString(); | 5446 | return src.Data[index].ToString(); |
5447 | } | 5447 | } |
5448 | 5448 | ||
5449 | public LSL_Vector llList2Vector(LSL_List src, int index) | 5449 | public LSL_Vector llList2Vector(LSL_List src, int index) |
5450 | { | 5450 | { |
5451 | m_host.AddScriptLPS(1); | 5451 | m_host.AddScriptLPS(1); |
5452 | if (index < 0) | 5452 | if (index < 0) |
5453 | { | 5453 | { |
5454 | index = src.Length + index; | 5454 | index = src.Length + index; |
5455 | } | 5455 | } |
5456 | if (index >= src.Length || index < 0) | 5456 | if (index >= src.Length || index < 0) |
5457 | { | 5457 | { |
5458 | return new LSL_Vector(0, 0, 0); | 5458 | return new LSL_Vector(0, 0, 0); |
5459 | } | 5459 | } |
5460 | if (src.Data[index].GetType() == typeof(LSL_Vector)) | 5460 | if (src.Data[index].GetType() == typeof(LSL_Vector)) |
5461 | { | 5461 | { |
5462 | return (LSL_Vector)src.Data[index]; | 5462 | return (LSL_Vector)src.Data[index]; |
5463 | } | 5463 | } |
5464 | 5464 | ||
5465 | // SL spits always out ZERO_VECTOR for anything other than | 5465 | // SL spits always out ZERO_VECTOR for anything other than |
5466 | // strings or vectors. Although keys always return ZERO_VECTOR, | 5466 | // strings or vectors. Although keys always return ZERO_VECTOR, |
5467 | // it is currently difficult to make the distinction between | 5467 | // it is currently difficult to make the distinction between |
5468 | // a string, a key as string and a string that by coincidence | 5468 | // a string, a key as string and a string that by coincidence |
5469 | // is a string, so we're going to leave that up to the | 5469 | // is a string, so we're going to leave that up to the |
5470 | // LSL_Vector constructor. | 5470 | // LSL_Vector constructor. |
5471 | else if (!(src.Data[index] is LSL_String || | 5471 | else if (!(src.Data[index] is LSL_String || |
5472 | src.Data[index] is LSL_Vector)) | 5472 | src.Data[index] is LSL_Vector)) |
5473 | { | 5473 | { |
5474 | return new LSL_Vector(0, 0, 0); | 5474 | return new LSL_Vector(0, 0, 0); |
5475 | } | 5475 | } |
5476 | else | 5476 | else |
5477 | { | 5477 | { |
5478 | return new LSL_Vector(src.Data[index].ToString()); | 5478 | return new LSL_Vector(src.Data[index].ToString()); |
5479 | } | 5479 | } |
5480 | } | 5480 | } |
5481 | 5481 | ||
5482 | public LSL_Rotation llList2Rot(LSL_List src, int index) | 5482 | public LSL_Rotation llList2Rot(LSL_List src, int index) |
5483 | { | 5483 | { |
5484 | m_host.AddScriptLPS(1); | 5484 | m_host.AddScriptLPS(1); |
5485 | if (index < 0) | 5485 | if (index < 0) |
5486 | { | 5486 | { |
5487 | index = src.Length + index; | 5487 | index = src.Length + index; |
5488 | } | 5488 | } |
5489 | if (index >= src.Length || index < 0) | 5489 | if (index >= src.Length || index < 0) |
5490 | { | 5490 | { |
5491 | return new LSL_Rotation(0, 0, 0, 1); | 5491 | return new LSL_Rotation(0, 0, 0, 1); |
5492 | } | 5492 | } |
5493 | 5493 | ||
5494 | // SL spits always out ZERO_ROTATION for anything other than | 5494 | // SL spits always out ZERO_ROTATION for anything other than |
5495 | // strings or vectors. Although keys always return ZERO_ROTATION, | 5495 | // strings or vectors. Although keys always return ZERO_ROTATION, |
5496 | // it is currently difficult to make the distinction between | 5496 | // it is currently difficult to make the distinction between |
5497 | // a string, a key as string and a string that by coincidence | 5497 | // a string, a key as string and a string that by coincidence |
5498 | // is a string, so we're going to leave that up to the | 5498 | // is a string, so we're going to leave that up to the |
5499 | // LSL_Rotation constructor. | 5499 | // LSL_Rotation constructor. |
5500 | else if (!(src.Data[index] is LSL_String || | 5500 | else if (!(src.Data[index] is LSL_String || |
5501 | src.Data[index] is LSL_Rotation)) | 5501 | src.Data[index] is LSL_Rotation)) |
5502 | { | 5502 | { |
5503 | return new LSL_Rotation(0, 0, 0, 1); | 5503 | return new LSL_Rotation(0, 0, 0, 1); |
5504 | } | 5504 | } |
5505 | else if (src.Data[index].GetType() == typeof(LSL_Rotation)) | 5505 | else if (src.Data[index].GetType() == typeof(LSL_Rotation)) |
5506 | { | 5506 | { |
5507 | return (LSL_Rotation)src.Data[index]; | 5507 | return (LSL_Rotation)src.Data[index]; |
5508 | } | 5508 | } |
5509 | else | 5509 | else |
5510 | { | 5510 | { |
5511 | return new LSL_Rotation(src.Data[index].ToString()); | 5511 | return new LSL_Rotation(src.Data[index].ToString()); |
5512 | } | 5512 | } |
5513 | } | 5513 | } |
5514 | 5514 | ||
5515 | public LSL_List llList2List(LSL_List src, int start, int end) | 5515 | public LSL_List llList2List(LSL_List src, int start, int end) |
5516 | { | 5516 | { |
5517 | m_host.AddScriptLPS(1); | 5517 | m_host.AddScriptLPS(1); |
5518 | return src.GetSublist(start, end); | 5518 | return src.GetSublist(start, end); |
5519 | } | 5519 | } |
5520 | 5520 | ||
5521 | public LSL_List llDeleteSubList(LSL_List src, int start, int end) | 5521 | public LSL_List llDeleteSubList(LSL_List src, int start, int end) |
5522 | { | 5522 | { |
5523 | return src.DeleteSublist(start, end); | 5523 | return src.DeleteSublist(start, end); |
5524 | } | 5524 | } |
5525 | 5525 | ||
5526 | public LSL_Integer llGetListEntryType(LSL_List src, int index) | 5526 | public LSL_Integer llGetListEntryType(LSL_List src, int index) |
5527 | { | 5527 | { |
5528 | m_host.AddScriptLPS(1); | 5528 | m_host.AddScriptLPS(1); |
5529 | if (index < 0) | 5529 | if (index < 0) |
5530 | { | 5530 | { |
5531 | index = src.Length + index; | 5531 | index = src.Length + index; |
5532 | } | 5532 | } |
5533 | if (index >= src.Length) | 5533 | if (index >= src.Length) |
5534 | { | 5534 | { |
5535 | return 0; | 5535 | return 0; |
5536 | } | 5536 | } |
5537 | 5537 | ||
5538 | if (src.Data[index] is LSL_Integer || src.Data[index] is Int32) | 5538 | if (src.Data[index] is LSL_Integer || src.Data[index] is Int32) |
5539 | return 1; | 5539 | return 1; |
5540 | if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double) | 5540 | if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double) |
5541 | return 2; | 5541 | return 2; |
5542 | if (src.Data[index] is LSL_String || src.Data[index] is String) | 5542 | if (src.Data[index] is LSL_String || src.Data[index] is String) |
5543 | { | 5543 | { |
5544 | UUID tuuid; | 5544 | UUID tuuid; |
5545 | if (UUID.TryParse(src.Data[index].ToString(), out tuuid)) | 5545 | if (UUID.TryParse(src.Data[index].ToString(), out tuuid)) |
5546 | { | 5546 | { |
5547 | return 4; | 5547 | return 4; |
5548 | } | 5548 | } |
5549 | else | 5549 | else |
5550 | { | 5550 | { |
5551 | return 3; | 5551 | return 3; |
5552 | } | 5552 | } |
5553 | } | 5553 | } |
5554 | if (src.Data[index] is LSL_Vector) | 5554 | if (src.Data[index] is LSL_Vector) |
5555 | return 5; | 5555 | return 5; |
5556 | if (src.Data[index] is LSL_Rotation) | 5556 | if (src.Data[index] is LSL_Rotation) |
5557 | return 6; | 5557 | return 6; |
5558 | if (src.Data[index] is LSL_List) | 5558 | if (src.Data[index] is LSL_List) |
5559 | return 7; | 5559 | return 7; |
5560 | return 0; | 5560 | return 0; |
5561 | 5561 | ||
5562 | } | 5562 | } |
5563 | 5563 | ||
5564 | /// <summary> | 5564 | /// <summary> |
5565 | /// Process the supplied list and return the | 5565 | /// Process the supplied list and return the |
5566 | /// content of the list formatted as a comma | 5566 | /// content of the list formatted as a comma |
5567 | /// separated list. There is a space after | 5567 | /// separated list. There is a space after |
5568 | /// each comma. | 5568 | /// each comma. |
5569 | /// </summary> | 5569 | /// </summary> |
5570 | public LSL_String llList2CSV(LSL_List src) | 5570 | public LSL_String llList2CSV(LSL_List src) |
5571 | { | 5571 | { |
5572 | m_host.AddScriptLPS(1); | 5572 | m_host.AddScriptLPS(1); |
5573 | 5573 | ||
5574 | return string.Join(", ", | 5574 | return string.Join(", ", |
5575 | (new List<object>(src.Data)).ConvertAll<string>(o => | 5575 | (new List<object>(src.Data)).ConvertAll<string>(o => |
5576 | { | 5576 | { |
5577 | return o.ToString(); | 5577 | return o.ToString(); |
5578 | }).ToArray()); | 5578 | }).ToArray()); |
5579 | } | 5579 | } |
5580 | 5580 | ||
5581 | /// <summary> | 5581 | /// <summary> |
5582 | /// The supplied string is scanned for commas | 5582 | /// The supplied string is scanned for commas |
5583 | /// and converted into a list. Commas are only | 5583 | /// and converted into a list. Commas are only |
5584 | /// effective if they are encountered outside | 5584 | /// effective if they are encountered outside |
5585 | /// of '<' '>' delimiters. Any whitespace | 5585 | /// of '<' '>' delimiters. Any whitespace |
5586 | /// before or after an element is trimmed. | 5586 | /// before or after an element is trimmed. |
5587 | /// </summary> | 5587 | /// </summary> |
5588 | 5588 | ||
5589 | public LSL_List llCSV2List(string src) | 5589 | public LSL_List llCSV2List(string src) |
5590 | { | 5590 | { |
5591 | 5591 | ||
5592 | LSL_List result = new LSL_List(); | 5592 | LSL_List result = new LSL_List(); |
5593 | int parens = 0; | 5593 | int parens = 0; |
5594 | int start = 0; | 5594 | int start = 0; |
5595 | int length = 0; | 5595 | int length = 0; |
5596 | 5596 | ||
5597 | m_host.AddScriptLPS(1); | 5597 | m_host.AddScriptLPS(1); |
5598 | 5598 | ||
5599 | for (int i = 0; i < src.Length; i++) | 5599 | for (int i = 0; i < src.Length; i++) |
5600 | { | 5600 | { |
5601 | switch (src[i]) | 5601 | switch (src[i]) |
5602 | { | 5602 | { |
5603 | case '<': | 5603 | case '<': |
5604 | parens++; | 5604 | parens++; |
5605 | length++; | 5605 | length++; |
5606 | break; | 5606 | break; |
5607 | case '>': | 5607 | case '>': |
5608 | if (parens > 0) | 5608 | if (parens > 0) |
5609 | parens--; | 5609 | parens--; |
5610 | length++; | 5610 | length++; |
5611 | break; | 5611 | break; |
5612 | case ',': | 5612 | case ',': |
5613 | if (parens == 0) | 5613 | if (parens == 0) |
5614 | { | 5614 | { |
5615 | result.Add(new LSL_String(src.Substring(start,length).Trim())); | 5615 | result.Add(new LSL_String(src.Substring(start,length).Trim())); |
5616 | start += length+1; | 5616 | start += length+1; |
5617 | length = 0; | 5617 | length = 0; |
5618 | } | 5618 | } |
5619 | else | 5619 | else |
5620 | { | 5620 | { |
5621 | length++; | 5621 | length++; |
5622 | } | 5622 | } |
5623 | break; | 5623 | break; |
5624 | default: | 5624 | default: |
5625 | length++; | 5625 | length++; |
5626 | break; | 5626 | break; |
5627 | } | 5627 | } |
5628 | } | 5628 | } |
5629 | 5629 | ||
5630 | result.Add(new LSL_String(src.Substring(start,length).Trim())); | 5630 | result.Add(new LSL_String(src.Substring(start,length).Trim())); |
5631 | 5631 | ||
5632 | return result; | 5632 | return result; |
5633 | } | 5633 | } |
5634 | 5634 | ||
5635 | /// <summary> | 5635 | /// <summary> |
5636 | /// Randomizes the list, be arbitrarily reordering | 5636 | /// Randomizes the list, be arbitrarily reordering |
5637 | /// sublists of stride elements. As the stride approaches | 5637 | /// sublists of stride elements. As the stride approaches |
5638 | /// the size of the list, the options become very | 5638 | /// the size of the list, the options become very |
5639 | /// limited. | 5639 | /// limited. |
5640 | /// </summary> | 5640 | /// </summary> |
5641 | /// <remarks> | 5641 | /// <remarks> |
5642 | /// This could take a while for very large list | 5642 | /// This could take a while for very large list |
5643 | /// sizes. | 5643 | /// sizes. |
5644 | /// </remarks> | 5644 | /// </remarks> |
5645 | 5645 | ||
5646 | public LSL_List llListRandomize(LSL_List src, int stride) | 5646 | public LSL_List llListRandomize(LSL_List src, int stride) |
5647 | { | 5647 | { |
5648 | LSL_List result; | 5648 | LSL_List result; |
5649 | BetterRandom rand = new BetterRandom(); | 5649 | BetterRandom rand = new BetterRandom(); |
5650 | 5650 | ||
5651 | int chunkk; | 5651 | int chunkk; |
5652 | int[] chunks; | 5652 | int[] chunks; |
5653 | 5653 | ||
5654 | m_host.AddScriptLPS(1); | 5654 | m_host.AddScriptLPS(1); |
5655 | 5655 | ||
5656 | if (stride <= 0) | 5656 | if (stride <= 0) |
5657 | { | 5657 | { |
5658 | stride = 1; | 5658 | stride = 1; |
5659 | } | 5659 | } |
5660 | 5660 | ||
5661 | // Stride MUST be a factor of the list length | 5661 | // Stride MUST be a factor of the list length |
5662 | // If not, then return the src list. This also | 5662 | // If not, then return the src list. This also |
5663 | // traps those cases where stride > length. | 5663 | // traps those cases where stride > length. |
5664 | 5664 | ||
5665 | if (src.Length != stride && src.Length % stride == 0) | 5665 | if (src.Length != stride && src.Length % stride == 0) |
5666 | { | 5666 | { |
5667 | chunkk = src.Length/stride; | 5667 | chunkk = src.Length/stride; |
5668 | 5668 | ||
5669 | chunks = new int[chunkk]; | 5669 | chunks = new int[chunkk]; |
5670 | 5670 | ||
5671 | for (int i = 0; i < chunkk; i++) | 5671 | for (int i = 0; i < chunkk; i++) |
5672 | { | 5672 | { |
5673 | chunks[i] = i; | 5673 | chunks[i] = i; |
5674 | } | 5674 | } |
5675 | 5675 | ||
5676 | // Knuth shuffle the chunkk index | 5676 | // Knuth shuffle the chunkk index |
5677 | for (int i = chunkk - 1; i > 0; i--) | 5677 | for (int i = chunkk - 1; i > 0; i--) |
5678 | { | 5678 | { |
5679 | // Elect an unrandomized chunk to swap | 5679 | // Elect an unrandomized chunk to swap |
5680 | int index = rand.Next(i + 1); | 5680 | int index = rand.Next(i + 1); |
5681 | 5681 | ||
5682 | // and swap position with first unrandomized chunk | 5682 | // and swap position with first unrandomized chunk |
5683 | int tmp = chunks[i]; | 5683 | int tmp = chunks[i]; |
5684 | chunks[i] = chunks[index]; | 5684 | chunks[i] = chunks[index]; |
5685 | chunks[index] = tmp; | 5685 | chunks[index] = tmp; |
5686 | } | 5686 | } |
5687 | 5687 | ||
5688 | // Construct the randomized list | 5688 | // Construct the randomized list |
5689 | 5689 | ||
5690 | result = new LSL_List(); | 5690 | result = new LSL_List(); |
5691 | 5691 | ||
5692 | for (int i = 0; i < chunkk; i++) | 5692 | for (int i = 0; i < chunkk; i++) |
5693 | { | 5693 | { |
5694 | for (int j = 0; j < stride; j++) | 5694 | for (int j = 0; j < stride; j++) |
5695 | { | 5695 | { |
5696 | result.Add(src.Data[chunks[i] * stride + j]); | 5696 | result.Add(src.Data[chunks[i] * stride + j]); |
5697 | } | 5697 | } |
5698 | } | 5698 | } |
5699 | } | 5699 | } |
5700 | else { | 5700 | else { |
5701 | object[] array = new object[src.Length]; | 5701 | object[] array = new object[src.Length]; |
5702 | Array.Copy(src.Data, 0, array, 0, src.Length); | 5702 | Array.Copy(src.Data, 0, array, 0, src.Length); |
5703 | result = new LSL_List(array); | 5703 | result = new LSL_List(array); |
5704 | } | 5704 | } |
5705 | 5705 | ||
5706 | return result; | 5706 | return result; |
5707 | } | 5707 | } |
5708 | 5708 | ||
5709 | /// <summary> | 5709 | /// <summary> |
5710 | /// Elements in the source list starting with 0 and then | 5710 | /// Elements in the source list starting with 0 and then |
5711 | /// every i+stride. If the stride is negative then the scan | 5711 | /// every i+stride. If the stride is negative then the scan |
5712 | /// is backwards producing an inverted result. | 5712 | /// is backwards producing an inverted result. |
5713 | /// Only those elements that are also in the specified | 5713 | /// Only those elements that are also in the specified |
5714 | /// range are included in the result. | 5714 | /// range are included in the result. |
5715 | /// </summary> | 5715 | /// </summary> |
5716 | 5716 | ||
5717 | public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride) | 5717 | public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride) |
5718 | { | 5718 | { |
5719 | 5719 | ||
5720 | LSL_List result = new LSL_List(); | 5720 | LSL_List result = new LSL_List(); |
5721 | int[] si = new int[2]; | 5721 | int[] si = new int[2]; |
5722 | int[] ei = new int[2]; | 5722 | int[] ei = new int[2]; |
5723 | bool twopass = false; | 5723 | bool twopass = false; |
5724 | 5724 | ||
5725 | m_host.AddScriptLPS(1); | 5725 | m_host.AddScriptLPS(1); |
5726 | 5726 | ||
5727 | // First step is always to deal with negative indices | 5727 | // First step is always to deal with negative indices |
5728 | 5728 | ||
5729 | if (start < 0) | 5729 | if (start < 0) |
5730 | start = src.Length+start; | 5730 | start = src.Length+start; |
5731 | if (end < 0) | 5731 | if (end < 0) |
5732 | end = src.Length+end; | 5732 | end = src.Length+end; |
5733 | 5733 | ||
5734 | // Out of bounds indices are OK, just trim them | 5734 | // Out of bounds indices are OK, just trim them |
5735 | // accordingly | 5735 | // accordingly |
5736 | 5736 | ||
5737 | if (start > src.Length) | 5737 | if (start > src.Length) |
5738 | start = src.Length; | 5738 | start = src.Length; |
5739 | 5739 | ||
5740 | if (end > src.Length) | 5740 | if (end > src.Length) |
5741 | end = src.Length; | 5741 | end = src.Length; |
5742 | 5742 | ||
5743 | if (stride == 0) | 5743 | if (stride == 0) |
5744 | stride = 1; | 5744 | stride = 1; |
5745 | 5745 | ||
5746 | // There may be one or two ranges to be considered | 5746 | // There may be one or two ranges to be considered |
5747 | 5747 | ||
5748 | if (start != end) | 5748 | if (start != end) |
5749 | { | 5749 | { |
5750 | 5750 | ||
5751 | if (start <= end) | 5751 | if (start <= end) |
5752 | { | 5752 | { |
5753 | si[0] = start; | 5753 | si[0] = start; |
5754 | ei[0] = end; | 5754 | ei[0] = end; |
5755 | } | 5755 | } |
5756 | else | 5756 | else |
5757 | { | 5757 | { |
5758 | si[1] = start; | 5758 | si[1] = start; |
5759 | ei[1] = src.Length; | 5759 | ei[1] = src.Length; |
5760 | si[0] = 0; | 5760 | si[0] = 0; |
5761 | ei[0] = end; | 5761 | ei[0] = end; |
5762 | twopass = true; | 5762 | twopass = true; |
5763 | } | 5763 | } |
5764 | 5764 | ||
5765 | // The scan always starts from the beginning of the | 5765 | // The scan always starts from the beginning of the |
5766 | // source list, but members are only selected if they | 5766 | // source list, but members are only selected if they |
5767 | // fall within the specified sub-range. The specified | 5767 | // fall within the specified sub-range. The specified |
5768 | // range values are inclusive. | 5768 | // range values are inclusive. |
5769 | // A negative stride reverses the direction of the | 5769 | // A negative stride reverses the direction of the |
5770 | // scan producing an inverted list as a result. | 5770 | // scan producing an inverted list as a result. |
5771 | 5771 | ||
5772 | if (stride > 0) | 5772 | if (stride > 0) |
5773 | { | 5773 | { |
5774 | for (int i = 0; i < src.Length; i += stride) | 5774 | for (int i = 0; i < src.Length; i += stride) |
5775 | { | 5775 | { |
5776 | if (i<=ei[0] && i>=si[0]) | 5776 | if (i<=ei[0] && i>=si[0]) |
5777 | result.Add(src.Data[i]); | 5777 | result.Add(src.Data[i]); |
5778 | if (twopass && i>=si[1] && i<=ei[1]) | 5778 | if (twopass && i>=si[1] && i<=ei[1]) |
5779 | result.Add(src.Data[i]); | 5779 | result.Add(src.Data[i]); |
5780 | } | 5780 | } |
5781 | } | 5781 | } |
5782 | else if (stride < 0) | 5782 | else if (stride < 0) |
5783 | { | 5783 | { |
5784 | for (int i = src.Length - 1; i >= 0; i += stride) | 5784 | for (int i = src.Length - 1; i >= 0; i += stride) |
5785 | { | 5785 | { |
5786 | if (i <= ei[0] && i >= si[0]) | 5786 | if (i <= ei[0] && i >= si[0]) |
5787 | result.Add(src.Data[i]); | 5787 | result.Add(src.Data[i]); |
5788 | if (twopass && i >= si[1] && i <= ei[1]) | 5788 | if (twopass && i >= si[1] && i <= ei[1]) |
5789 | result.Add(src.Data[i]); | 5789 | result.Add(src.Data[i]); |
5790 | } | 5790 | } |
5791 | } | 5791 | } |
5792 | } | 5792 | } |
5793 | else | 5793 | else |
5794 | { | 5794 | { |
5795 | if (start%stride == 0) | 5795 | if (start%stride == 0) |
5796 | { | 5796 | { |
5797 | result.Add(src.Data[start]); | 5797 | result.Add(src.Data[start]); |
5798 | } | 5798 | } |
5799 | } | 5799 | } |
5800 | 5800 | ||
5801 | return result; | 5801 | return result; |
5802 | } | 5802 | } |
5803 | 5803 | ||
5804 | public LSL_Integer llGetRegionAgentCount() | 5804 | public LSL_Integer llGetRegionAgentCount() |
5805 | { | 5805 | { |
5806 | m_host.AddScriptLPS(1); | 5806 | m_host.AddScriptLPS(1); |
5807 | return new LSL_Integer(World.GetRootAgentCount()); | 5807 | return new LSL_Integer(World.GetRootAgentCount()); |
5808 | } | 5808 | } |
5809 | 5809 | ||
5810 | public LSL_Vector llGetRegionCorner() | 5810 | public LSL_Vector llGetRegionCorner() |
5811 | { | 5811 | { |
5812 | m_host.AddScriptLPS(1); | 5812 | m_host.AddScriptLPS(1); |
5813 | return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); | 5813 | return new LSL_Vector(World.RegionInfo.WorldLocX, World.RegionInfo.WorldLocY, 0); |
5814 | } | 5814 | } |
5815 | 5815 | ||
5816 | public LSL_String llGetEnv(LSL_String name) | 5816 | public LSL_String llGetEnv(LSL_String name) |
5817 | { | 5817 | { |
5818 | m_host.AddScriptLPS(1); | 5818 | m_host.AddScriptLPS(1); |
5819 | if (name == "agent_limit") | 5819 | if (name == "agent_limit") |
5820 | { | 5820 | { |
5821 | return World.RegionInfo.RegionSettings.AgentLimit.ToString(); | 5821 | return World.RegionInfo.RegionSettings.AgentLimit.ToString(); |
5822 | } | 5822 | } |
5823 | else if (name == "dynamic_pathfinding") | 5823 | else if (name == "dynamic_pathfinding") |
5824 | { | 5824 | { |
5825 | return "0"; | 5825 | return "0"; |
5826 | } | 5826 | } |
5827 | else if (name == "estate_id") | 5827 | else if (name == "estate_id") |
5828 | { | 5828 | { |
5829 | return World.RegionInfo.EstateSettings.EstateID.ToString(); | 5829 | return World.RegionInfo.EstateSettings.EstateID.ToString(); |
5830 | } | 5830 | } |
5831 | else if (name == "estate_name") | 5831 | else if (name == "estate_name") |
5832 | { | 5832 | { |
5833 | return World.RegionInfo.EstateSettings.EstateName; | 5833 | return World.RegionInfo.EstateSettings.EstateName; |
5834 | } | 5834 | } |
5835 | else if (name == "frame_number") | 5835 | else if (name == "frame_number") |
5836 | { | 5836 | { |
5837 | return World.Frame.ToString(); | 5837 | return World.Frame.ToString(); |
5838 | } | 5838 | } |
5839 | else if (name == "region_cpu_ratio") | 5839 | else if (name == "region_cpu_ratio") |
5840 | { | 5840 | { |
5841 | return "1"; | 5841 | return "1"; |
5842 | } | 5842 | } |
5843 | else if (name == "region_idle") | 5843 | else if (name == "region_idle") |
5844 | { | 5844 | { |
5845 | return "0"; | 5845 | return "0"; |
5846 | } | 5846 | } |
5847 | else if (name == "region_product_name") | 5847 | else if (name == "region_product_name") |
5848 | { | 5848 | { |
5849 | if (World.RegionInfo.RegionType != String.Empty) | 5849 | if (World.RegionInfo.RegionType != String.Empty) |
5850 | return World.RegionInfo.RegionType; | 5850 | return World.RegionInfo.RegionType; |
5851 | else | 5851 | else |
5852 | return ""; | 5852 | return ""; |
5853 | } | 5853 | } |
5854 | else if (name == "region_product_sku") | 5854 | else if (name == "region_product_sku") |
5855 | { | 5855 | { |
5856 | return "OpenSim"; | 5856 | return "OpenSim"; |
5857 | } | 5857 | } |
5858 | else if (name == "region_start_time") | 5858 | else if (name == "region_start_time") |
5859 | { | 5859 | { |
5860 | return World.UnixStartTime.ToString(); | 5860 | return World.UnixStartTime.ToString(); |
5861 | } | 5861 | } |
5862 | else if (name == "sim_channel") | 5862 | else if (name == "sim_channel") |
5863 | { | 5863 | { |
5864 | return "OpenSim"; | 5864 | return "OpenSim"; |
5865 | } | 5865 | } |
5866 | else if (name == "sim_version") | 5866 | else if (name == "sim_version") |
5867 | { | 5867 | { |
5868 | return World.GetSimulatorVersion(); | 5868 | return World.GetSimulatorVersion(); |
5869 | } | 5869 | } |
5870 | else if (name == "simulator_hostname") | 5870 | else if (name == "simulator_hostname") |
5871 | { | 5871 | { |
5872 | IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); | 5872 | IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); |
5873 | return UrlModule.ExternalHostNameForLSL; | 5873 | return UrlModule.ExternalHostNameForLSL; |
5874 | } | 5874 | } |
5875 | else | 5875 | else |
5876 | { | 5876 | { |
5877 | return ""; | 5877 | return ""; |
5878 | } | 5878 | } |
5879 | } | 5879 | } |
5880 | 5880 | ||
5881 | /// <summary> | 5881 | /// <summary> |
5882 | /// Insert the list identified by <paramref name="src"/> into the | 5882 | /// Insert the list identified by <paramref name="src"/> into the |
5883 | /// list designated by <paramref name="dest"/> such that the first | 5883 | /// list designated by <paramref name="dest"/> such that the first |
5884 | /// new element has the index specified by <paramref name="index"/> | 5884 | /// new element has the index specified by <paramref name="index"/> |
5885 | /// </summary> | 5885 | /// </summary> |
5886 | 5886 | ||
5887 | public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) | 5887 | public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) |
5888 | { | 5888 | { |
5889 | 5889 | ||
5890 | LSL_List pref = null; | 5890 | LSL_List pref = null; |
5891 | LSL_List suff = null; | 5891 | LSL_List suff = null; |
5892 | 5892 | ||
5893 | m_host.AddScriptLPS(1); | 5893 | m_host.AddScriptLPS(1); |
5894 | 5894 | ||
5895 | if (index < 0) | 5895 | if (index < 0) |
5896 | { | 5896 | { |
5897 | index = index+dest.Length; | 5897 | index = index+dest.Length; |
5898 | if (index < 0) | 5898 | if (index < 0) |
5899 | { | 5899 | { |
5900 | index = 0; | 5900 | index = 0; |
5901 | } | 5901 | } |
5902 | } | 5902 | } |
5903 | 5903 | ||
5904 | if (index != 0) | 5904 | if (index != 0) |
5905 | { | 5905 | { |
5906 | pref = dest.GetSublist(0,index-1); | 5906 | pref = dest.GetSublist(0,index-1); |
5907 | if (index < dest.Length) | 5907 | if (index < dest.Length) |
5908 | { | 5908 | { |
5909 | suff = dest.GetSublist(index,-1); | 5909 | suff = dest.GetSublist(index,-1); |
5910 | return pref + src + suff; | 5910 | return pref + src + suff; |
5911 | } | 5911 | } |
5912 | else | 5912 | else |
5913 | { | 5913 | { |
5914 | return pref + src; | 5914 | return pref + src; |
5915 | } | 5915 | } |
5916 | } | 5916 | } |
5917 | else | 5917 | else |
5918 | { | 5918 | { |
5919 | if (index < dest.Length) | 5919 | if (index < dest.Length) |
5920 | { | 5920 | { |
5921 | suff = dest.GetSublist(index,-1); | 5921 | suff = dest.GetSublist(index,-1); |
5922 | return src + suff; | 5922 | return src + suff; |
5923 | } | 5923 | } |
5924 | else | 5924 | else |
5925 | { | 5925 | { |
5926 | return src; | 5926 | return src; |
5927 | } | 5927 | } |
5928 | } | 5928 | } |
5929 | 5929 | ||
5930 | } | 5930 | } |
5931 | 5931 | ||
5932 | /// <summary> | 5932 | /// <summary> |
5933 | /// Returns the index of the first occurrence of test | 5933 | /// Returns the index of the first occurrence of test |
5934 | /// in src. | 5934 | /// in src. |
5935 | /// </summary> | 5935 | /// </summary> |
5936 | /// <param name="src">Source list</param> | 5936 | /// <param name="src">Source list</param> |
5937 | /// <param name="test">List to search for</param> | 5937 | /// <param name="test">List to search for</param> |
5938 | /// <returns> | 5938 | /// <returns> |
5939 | /// The index number of the point in src where test was found if it was found. | 5939 | /// The index number of the point in src where test was found if it was found. |
5940 | /// Otherwise returns -1 | 5940 | /// Otherwise returns -1 |
5941 | /// </returns> | 5941 | /// </returns> |
5942 | public LSL_Integer llListFindList(LSL_List src, LSL_List test) | 5942 | public LSL_Integer llListFindList(LSL_List src, LSL_List test) |
5943 | { | 5943 | { |
5944 | int index = -1; | 5944 | int index = -1; |
5945 | int length = src.Length - test.Length + 1; | 5945 | int length = src.Length - test.Length + 1; |
5946 | 5946 | ||
5947 | m_host.AddScriptLPS(1); | 5947 | m_host.AddScriptLPS(1); |
5948 | 5948 | ||
5949 | // If either list is empty, do not match | 5949 | // If either list is empty, do not match |
5950 | if (src.Length != 0 && test.Length != 0) | 5950 | if (src.Length != 0 && test.Length != 0) |
5951 | { | 5951 | { |
5952 | for (int i = 0; i < length; i++) | 5952 | for (int i = 0; i < length; i++) |
5953 | { | 5953 | { |
5954 | // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) | 5954 | // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) |
5955 | // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code | 5955 | // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code |
5956 | // and so the comparison fails even if the LSL_Integer conceptually has the same value. | 5956 | // and so the comparison fails even if the LSL_Integer conceptually has the same value. |
5957 | // Therefore, here we test Equals on both the source and destination objects. | 5957 | // Therefore, here we test Equals on both the source and destination objects. |
5958 | // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). | 5958 | // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). |
5959 | if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) | 5959 | if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) |
5960 | { | 5960 | { |
5961 | int j; | 5961 | int j; |
5962 | for (j = 1; j < test.Length; j++) | 5962 | for (j = 1; j < test.Length; j++) |
5963 | if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) | 5963 | if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) |
5964 | break; | 5964 | break; |
5965 | 5965 | ||
5966 | if (j == test.Length) | 5966 | if (j == test.Length) |
5967 | { | 5967 | { |
5968 | index = i; | 5968 | index = i; |
5969 | break; | 5969 | break; |
5970 | } | 5970 | } |
5971 | } | 5971 | } |
5972 | } | 5972 | } |
5973 | } | 5973 | } |
5974 | 5974 | ||
5975 | return index; | 5975 | return index; |
5976 | } | 5976 | } |
5977 | 5977 | ||
5978 | public LSL_String llGetObjectName() | 5978 | public LSL_String llGetObjectName() |
5979 | { | 5979 | { |
5980 | m_host.AddScriptLPS(1); | 5980 | m_host.AddScriptLPS(1); |
5981 | return m_host.Name !=null ? m_host.Name : String.Empty; | 5981 | return m_host.Name !=null ? m_host.Name : String.Empty; |
5982 | } | 5982 | } |
5983 | 5983 | ||
5984 | public void llSetObjectName(string name) | 5984 | public void llSetObjectName(string name) |
5985 | { | 5985 | { |
5986 | m_host.AddScriptLPS(1); | 5986 | m_host.AddScriptLPS(1); |
5987 | m_host.Name = name != null ? name : String.Empty; | 5987 | m_host.Name = name != null ? name : String.Empty; |
5988 | } | 5988 | } |
5989 | 5989 | ||
5990 | public LSL_String llGetDate() | 5990 | public LSL_String llGetDate() |
5991 | { | 5991 | { |
5992 | m_host.AddScriptLPS(1); | 5992 | m_host.AddScriptLPS(1); |
5993 | DateTime date = DateTime.Now.ToUniversalTime(); | 5993 | DateTime date = DateTime.Now.ToUniversalTime(); |
5994 | string result = date.ToString("yyyy-MM-dd"); | 5994 | string result = date.ToString("yyyy-MM-dd"); |
5995 | return result; | 5995 | return result; |
5996 | } | 5996 | } |
5997 | 5997 | ||
5998 | public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir) | 5998 | public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir) |
5999 | { | 5999 | { |
6000 | m_host.AddScriptLPS(1); | 6000 | m_host.AddScriptLPS(1); |
6001 | 6001 | ||
6002 | // edge will be used to pass the Region Coordinates offset | 6002 | // edge will be used to pass the Region Coordinates offset |
6003 | // we want to check for a neighboring sim | 6003 | // we want to check for a neighboring sim |
6004 | LSL_Vector edge = new LSL_Vector(0, 0, 0); | 6004 | LSL_Vector edge = new LSL_Vector(0, 0, 0); |
6005 | 6005 | ||
6006 | if (dir.x == 0) | 6006 | if (dir.x == 0) |
6007 | { | 6007 | { |
6008 | if (dir.y == 0) | 6008 | if (dir.y == 0) |
6009 | { | 6009 | { |
6010 | // Direction vector is 0,0 so return | 6010 | // Direction vector is 0,0 so return |
6011 | // false since we're staying in the sim | 6011 | // false since we're staying in the sim |
6012 | return 0; | 6012 | return 0; |
6013 | } | 6013 | } |
6014 | else | 6014 | else |
6015 | { | 6015 | { |
6016 | // Y is the only valid direction | 6016 | // Y is the only valid direction |
6017 | edge.y = dir.y / Math.Abs(dir.y); | 6017 | edge.y = dir.y / Math.Abs(dir.y); |
6018 | } | 6018 | } |
6019 | } | 6019 | } |
6020 | else | 6020 | else |
6021 | { | 6021 | { |
6022 | LSL_Float mag; | 6022 | LSL_Float mag; |
6023 | if (dir.x > 0) | 6023 | if (dir.x > 0) |
6024 | { | 6024 | { |
6025 | mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x; | 6025 | mag = (World.RegionInfo.RegionSizeX - pos.x) / dir.x; |
6026 | } | 6026 | } |
6027 | else | 6027 | else |
6028 | { | 6028 | { |
6029 | mag = (pos.x/dir.x); | 6029 | mag = (pos.x/dir.x); |
6030 | } | 6030 | } |
6031 | 6031 | ||
6032 | mag = Math.Abs(mag); | 6032 | mag = Math.Abs(mag); |
6033 | 6033 | ||
6034 | edge.y = pos.y + (dir.y * mag); | 6034 | edge.y = pos.y + (dir.y * mag); |
6035 | 6035 | ||
6036 | if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0) | 6036 | if (edge.y > World.RegionInfo.RegionSizeY || edge.y < 0) |
6037 | { | 6037 | { |
6038 | // Y goes out of bounds first | 6038 | // Y goes out of bounds first |
6039 | edge.y = dir.y / Math.Abs(dir.y); | 6039 | edge.y = dir.y / Math.Abs(dir.y); |
6040 | } | 6040 | } |
6041 | else | 6041 | else |
6042 | { | 6042 | { |
6043 | // X goes out of bounds first or its a corner exit | 6043 | // X goes out of bounds first or its a corner exit |
6044 | edge.y = 0; | 6044 | edge.y = 0; |
6045 | edge.x = dir.x / Math.Abs(dir.x); | 6045 | edge.x = dir.x / Math.Abs(dir.x); |
6046 | } | 6046 | } |
6047 | } | 6047 | } |
6048 | 6048 | ||
6049 | List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID); | 6049 | List<GridRegion> neighbors = World.GridService.GetNeighbours(World.RegionInfo.ScopeID, World.RegionInfo.RegionID); |
6050 | 6050 | ||
6051 | uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x; | 6051 | uint neighborX = World.RegionInfo.RegionLocX + (uint)dir.x; |
6052 | uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y; | 6052 | uint neighborY = World.RegionInfo.RegionLocY + (uint)dir.y; |
6053 | 6053 | ||
6054 | foreach (GridRegion sri in neighbors) | 6054 | foreach (GridRegion sri in neighbors) |
6055 | { | 6055 | { |
6056 | if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY) | 6056 | if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY) |
6057 | return 0; | 6057 | return 0; |
6058 | } | 6058 | } |
6059 | 6059 | ||
6060 | return 1; | 6060 | return 1; |
6061 | } | 6061 | } |
6062 | 6062 | ||
6063 | /// <summary> | 6063 | /// <summary> |
6064 | /// Not fully implemented yet. Still to do:- | 6064 | /// Not fully implemented yet. Still to do:- |
6065 | /// AGENT_BUSY | 6065 | /// AGENT_BUSY |
6066 | /// Remove as they are done | 6066 | /// Remove as they are done |
6067 | /// </summary> | 6067 | /// </summary> |
6068 | public LSL_Integer llGetAgentInfo(string id) | 6068 | public LSL_Integer llGetAgentInfo(string id) |
6069 | { | 6069 | { |
6070 | m_host.AddScriptLPS(1); | 6070 | m_host.AddScriptLPS(1); |
6071 | 6071 | ||
6072 | UUID key = new UUID(); | 6072 | UUID key = new UUID(); |
6073 | if (!UUID.TryParse(id, out key)) | 6073 | if (!UUID.TryParse(id, out key)) |
6074 | { | 6074 | { |
6075 | return 0; | 6075 | return 0; |
6076 | } | 6076 | } |
6077 | 6077 | ||
6078 | int flags = 0; | 6078 | int flags = 0; |
6079 | 6079 | ||
6080 | ScenePresence agent = World.GetScenePresence(key); | 6080 | ScenePresence agent = World.GetScenePresence(key); |
6081 | if (agent == null) | 6081 | if (agent == null) |
6082 | { | 6082 | { |
6083 | return 0; | 6083 | return 0; |
6084 | } | 6084 | } |
6085 | 6085 | ||
6086 | if (agent.IsChildAgent) | 6086 | if (agent.IsChildAgent) |
6087 | return 0; // Fail if they are not in the same region | 6087 | return 0; // Fail if they are not in the same region |
6088 | 6088 | ||
6089 | // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL | 6089 | // note: in OpenSim, sitting seems to cancel AGENT_ALWAYS_RUN, unlike SL |
6090 | if (agent.SetAlwaysRun) | 6090 | if (agent.SetAlwaysRun) |
6091 | { | 6091 | { |
6092 | flags |= ScriptBaseClass.AGENT_ALWAYS_RUN; | 6092 | flags |= ScriptBaseClass.AGENT_ALWAYS_RUN; |
6093 | } | 6093 | } |
6094 | 6094 | ||
6095 | if (agent.HasAttachments()) | 6095 | if (agent.HasAttachments()) |
6096 | { | 6096 | { |
6097 | flags |= ScriptBaseClass.AGENT_ATTACHMENTS; | 6097 | flags |= ScriptBaseClass.AGENT_ATTACHMENTS; |
6098 | if (agent.HasScriptedAttachments()) | 6098 | if (agent.HasScriptedAttachments()) |
6099 | flags |= ScriptBaseClass.AGENT_SCRIPTED; | 6099 | flags |= ScriptBaseClass.AGENT_SCRIPTED; |
6100 | } | 6100 | } |
6101 | 6101 | ||
6102 | if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) | 6102 | if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0) |
6103 | { | 6103 | { |
6104 | flags |= ScriptBaseClass.AGENT_FLYING; | 6104 | flags |= ScriptBaseClass.AGENT_FLYING; |
6105 | flags |= ScriptBaseClass.AGENT_IN_AIR; // flying always implies in-air, even if colliding with e.g. a wall | 6105 | flags |= ScriptBaseClass.AGENT_IN_AIR; // flying always implies in-air, even if colliding with e.g. a wall |
6106 | } | 6106 | } |
6107 | 6107 | ||
6108 | if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0) | 6108 | if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AWAY) != 0) |
6109 | { | 6109 | { |
6110 | flags |= ScriptBaseClass.AGENT_AWAY; | 6110 | flags |= ScriptBaseClass.AGENT_AWAY; |
6111 | } | 6111 | } |
6112 | 6112 | ||
6113 | // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? | 6113 | // seems to get unset, even if in mouselook, when avatar is sitting on a prim??? |
6114 | if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) | 6114 | if ((agent.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) |
6115 | { | 6115 | { |
6116 | flags |= ScriptBaseClass.AGENT_MOUSELOOK; | 6116 | flags |= ScriptBaseClass.AGENT_MOUSELOOK; |
6117 | } | 6117 | } |
6118 | 6118 | ||
6119 | if ((agent.State & (byte)AgentState.Typing) != (byte)0) | 6119 | if ((agent.State & (byte)AgentState.Typing) != (byte)0) |
6120 | { | 6120 | { |
6121 | flags |= ScriptBaseClass.AGENT_TYPING; | 6121 | flags |= ScriptBaseClass.AGENT_TYPING; |
6122 | } | 6122 | } |
6123 | 6123 | ||
6124 | string agentMovementAnimation = agent.Animator.CurrentMovementAnimation; | 6124 | string agentMovementAnimation = agent.Animator.CurrentMovementAnimation; |
6125 | 6125 | ||
6126 | if (agentMovementAnimation == "CROUCH") | 6126 | if (agentMovementAnimation == "CROUCH") |
6127 | { | 6127 | { |
6128 | flags |= ScriptBaseClass.AGENT_CROUCHING; | 6128 | flags |= ScriptBaseClass.AGENT_CROUCHING; |
6129 | } | 6129 | } |
6130 | 6130 | ||
6131 | if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK") | 6131 | if (agentMovementAnimation == "WALK" || agentMovementAnimation == "CROUCHWALK") |
6132 | { | 6132 | { |
6133 | flags |= ScriptBaseClass.AGENT_WALKING; | 6133 | flags |= ScriptBaseClass.AGENT_WALKING; |
6134 | } | 6134 | } |
6135 | 6135 | ||
6136 | // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above) | 6136 | // not colliding implies in air. Note: flying also implies in-air, even if colliding (see above) |
6137 | 6137 | ||
6138 | // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL. | 6138 | // note: AGENT_IN_AIR and AGENT_WALKING seem to be mutually exclusive states in SL. |
6139 | 6139 | ||
6140 | // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant | 6140 | // note: this may need some tweaking when walking downhill. you "fall down" for a brief instant |
6141 | // and don't collide when walking downhill, which instantly registers as in-air, briefly. should | 6141 | // and don't collide when walking downhill, which instantly registers as in-air, briefly. should |
6142 | // there be some minimum non-collision threshold time before claiming the avatar is in-air? | 6142 | // there be some minimum non-collision threshold time before claiming the avatar is in-air? |
6143 | if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 && !agent.IsColliding ) | 6143 | if ((flags & ScriptBaseClass.AGENT_WALKING) == 0 && !agent.IsColliding ) |
6144 | { | 6144 | { |
6145 | flags |= ScriptBaseClass.AGENT_IN_AIR; | 6145 | flags |= ScriptBaseClass.AGENT_IN_AIR; |
6146 | } | 6146 | } |
6147 | 6147 | ||
6148 | if (agent.ParentPart != null) | 6148 | if (agent.ParentPart != null) |
6149 | { | 6149 | { |
6150 | flags |= ScriptBaseClass.AGENT_ON_OBJECT; | 6150 | flags |= ScriptBaseClass.AGENT_ON_OBJECT; |
6151 | flags |= ScriptBaseClass.AGENT_SITTING; | 6151 | flags |= ScriptBaseClass.AGENT_SITTING; |
6152 | } | 6152 | } |
6153 | 6153 | ||
6154 | if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID | 6154 | if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID |
6155 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | 6155 | == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) |
6156 | { | 6156 | { |
6157 | flags |= ScriptBaseClass.AGENT_SITTING; | 6157 | flags |= ScriptBaseClass.AGENT_SITTING; |
6158 | } | 6158 | } |
6159 | 6159 | ||
6160 | return flags; | 6160 | return flags; |
6161 | } | 6161 | } |
6162 | 6162 | ||
6163 | public LSL_String llGetAgentLanguage(string id) | 6163 | public LSL_String llGetAgentLanguage(string id) |
6164 | { | 6164 | { |
6165 | // This should only return a value if the avatar is in the same region, but eh. idc. | 6165 | // This should only return a value if the avatar is in the same region, but eh. idc. |
6166 | m_host.AddScriptLPS(1); | 6166 | m_host.AddScriptLPS(1); |
6167 | if (World.AgentPreferencesService == null) | 6167 | if (World.AgentPreferencesService == null) |
6168 | { | 6168 | { |
6169 | Error("llGetAgentLanguage", "No AgentPreferencesService present"); | 6169 | Error("llGetAgentLanguage", "No AgentPreferencesService present"); |
6170 | } | 6170 | } |
6171 | else | 6171 | else |
6172 | { | 6172 | { |
6173 | UUID key = new UUID(); | 6173 | UUID key = new UUID(); |
6174 | if (UUID.TryParse(id, out key)) | 6174 | if (UUID.TryParse(id, out key)) |
6175 | { | 6175 | { |
6176 | return new LSL_String(World.AgentPreferencesService.GetLang(key)); | 6176 | return new LSL_String(World.AgentPreferencesService.GetLang(key)); |
6177 | } | 6177 | } |
6178 | } | 6178 | } |
6179 | return new LSL_String("en-us"); | 6179 | return new LSL_String("en-us"); |
6180 | } | 6180 | } |
6181 | /// <summary> | 6181 | /// <summary> |
6182 | /// http://wiki.secondlife.com/wiki/LlGetAgentList | 6182 | /// http://wiki.secondlife.com/wiki/LlGetAgentList |
6183 | /// The list of options is currently not used in SL | 6183 | /// The list of options is currently not used in SL |
6184 | /// scope is one of:- | 6184 | /// scope is one of:- |
6185 | /// AGENT_LIST_REGION - all in the region | 6185 | /// AGENT_LIST_REGION - all in the region |
6186 | /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object | 6186 | /// AGENT_LIST_PARCEL - all in the same parcel as the scripted object |
6187 | /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the | 6187 | /// AGENT_LIST_PARCEL_OWNER - all in any parcel owned by the owner of the |
6188 | /// current parcel. | 6188 | /// current parcel. |
6189 | /// </summary> | 6189 | /// </summary> |
6190 | public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options) | 6190 | public LSL_List llGetAgentList(LSL_Integer scope, LSL_List options) |
6191 | { | 6191 | { |
6192 | m_host.AddScriptLPS(1); | 6192 | m_host.AddScriptLPS(1); |
6193 | 6193 | ||
6194 | // the constants are 1, 2 and 4 so bits are being set, but you | 6194 | // the constants are 1, 2 and 4 so bits are being set, but you |
6195 | // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4 | 6195 | // get an error "INVALID_SCOPE" if it is anything but 1, 2 and 4 |
6196 | bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION; | 6196 | bool regionWide = scope == ScriptBaseClass.AGENT_LIST_REGION; |
6197 | bool parcelOwned = scope == ScriptBaseClass.AGENT_LIST_PARCEL_OWNER; | 6197 | bool parcelOwned = scope == ScriptBaseClass.AGENT_LIST_PARCEL_OWNER; |
6198 | bool parcel = scope == ScriptBaseClass.AGENT_LIST_PARCEL; | 6198 | bool parcel = scope == ScriptBaseClass.AGENT_LIST_PARCEL; |
6199 | 6199 | ||
6200 | LSL_List result = new LSL_List(); | 6200 | LSL_List result = new LSL_List(); |
6201 | 6201 | ||
6202 | if (!regionWide && !parcelOwned && !parcel) | 6202 | if (!regionWide && !parcelOwned && !parcel) |
6203 | { | 6203 | { |
6204 | result.Add("INVALID_SCOPE"); | 6204 | result.Add("INVALID_SCOPE"); |
6205 | return result; | 6205 | return result; |
6206 | } | 6206 | } |
6207 | 6207 | ||
6208 | ILandObject land; | 6208 | ILandObject land; |
6209 | UUID id = UUID.Zero; | 6209 | UUID id = UUID.Zero; |
6210 | 6210 | ||
6211 | if (parcel || parcelOwned) | 6211 | if (parcel || parcelOwned) |
6212 | { | 6212 | { |
6213 | land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition()); | 6213 | land = World.LandChannel.GetLandObject(m_host.ParentGroup.RootPart.GetWorldPosition()); |
6214 | if (land == null) | 6214 | if (land == null) |
6215 | { | 6215 | { |
6216 | id = UUID.Zero; | 6216 | id = UUID.Zero; |
6217 | } | 6217 | } |
6218 | else | 6218 | else |
6219 | { | 6219 | { |
6220 | if (parcelOwned) | 6220 | if (parcelOwned) |
6221 | { | 6221 | { |
6222 | id = land.LandData.OwnerID; | 6222 | id = land.LandData.OwnerID; |
6223 | } | 6223 | } |
6224 | else | 6224 | else |
6225 | { | 6225 | { |
6226 | id = land.LandData.GlobalID; | 6226 | id = land.LandData.GlobalID; |
6227 | } | 6227 | } |
6228 | } | 6228 | } |
6229 | } | 6229 | } |
6230 | 6230 | ||
6231 | World.ForEachRootScenePresence( | 6231 | World.ForEachRootScenePresence( |
6232 | delegate (ScenePresence ssp) | 6232 | delegate (ScenePresence ssp) |
6233 | { | 6233 | { |
6234 | // Gods are not listed in SL | 6234 | // Gods are not listed in SL |
6235 | if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent) | 6235 | if (!ssp.IsDeleted && ssp.GodLevel == 0.0 && !ssp.IsChildAgent) |
6236 | { | 6236 | { |
6237 | if (!regionWide) | 6237 | if (!regionWide) |
6238 | { | 6238 | { |
6239 | land = World.LandChannel.GetLandObject(ssp.AbsolutePosition); | 6239 | land = World.LandChannel.GetLandObject(ssp.AbsolutePosition); |
6240 | if (land != null) | 6240 | if (land != null) |
6241 | { | 6241 | { |
6242 | if (parcelOwned && land.LandData.OwnerID == id || | 6242 | if (parcelOwned && land.LandData.OwnerID == id || |
6243 | parcel && land.LandData.GlobalID == id) | 6243 | parcel && land.LandData.GlobalID == id) |
6244 | { | 6244 | { |
6245 | result.Add(new LSL_Key(ssp.UUID.ToString())); | 6245 | result.Add(new LSL_Key(ssp.UUID.ToString())); |
6246 | } | 6246 | } |
6247 | } | 6247 | } |
6248 | } | 6248 | } |
6249 | else | 6249 | else |
6250 | { | 6250 | { |
6251 | result.Add(new LSL_Key(ssp.UUID.ToString())); | 6251 | result.Add(new LSL_Key(ssp.UUID.ToString())); |
6252 | } | 6252 | } |
6253 | } | 6253 | } |
6254 | // Maximum of 100 results | 6254 | // Maximum of 100 results |
6255 | if (result.Length > 99) | 6255 | if (result.Length > 99) |
6256 | { | 6256 | { |
6257 | return; | 6257 | return; |
6258 | } | 6258 | } |
6259 | } | 6259 | } |
6260 | ); | 6260 | ); |
6261 | return result; | 6261 | return result; |
6262 | } | 6262 | } |
6263 | 6263 | ||
6264 | public void llAdjustSoundVolume(double volume) | 6264 | public void llAdjustSoundVolume(double volume) |
6265 | { | 6265 | { |
6266 | m_host.AddScriptLPS(1); | 6266 | m_host.AddScriptLPS(1); |
6267 | m_host.AdjustSoundGain(volume); | 6267 | m_host.AdjustSoundGain(volume); |
6268 | ScriptSleep(m_sleepMsOnAdjustSoundVolume); | 6268 | ScriptSleep(m_sleepMsOnAdjustSoundVolume); |
6269 | } | 6269 | } |
6270 | 6270 | ||
6271 | public void llSetSoundRadius(double radius) | 6271 | public void llSetSoundRadius(double radius) |
6272 | { | 6272 | { |
6273 | m_host.AddScriptLPS(1); | 6273 | m_host.AddScriptLPS(1); |
6274 | m_host.SoundRadius = radius; | 6274 | m_host.SoundRadius = radius; |
6275 | } | 6275 | } |
6276 | 6276 | ||
6277 | public LSL_String llKey2Name(string id) | 6277 | public LSL_String llKey2Name(string id) |
6278 | { | 6278 | { |
6279 | m_host.AddScriptLPS(1); | 6279 | m_host.AddScriptLPS(1); |
6280 | UUID key = new UUID(); | 6280 | UUID key = new UUID(); |
6281 | if (UUID.TryParse(id,out key)) | 6281 | if (UUID.TryParse(id,out key)) |
6282 | { | 6282 | { |
6283 | ScenePresence presence = World.GetScenePresence(key); | 6283 | ScenePresence presence = World.GetScenePresence(key); |
6284 | 6284 | ||
6285 | if (presence != null) | 6285 | if (presence != null) |
6286 | { | 6286 | { |
6287 | return presence.ControllingClient.Name; | 6287 | return presence.ControllingClient.Name; |
6288 | //return presence.Name; | 6288 | //return presence.Name; |
6289 | } | 6289 | } |
6290 | 6290 | ||
6291 | if (World.GetSceneObjectPart(key) != null) | 6291 | if (World.GetSceneObjectPart(key) != null) |
6292 | { | 6292 | { |
6293 | return World.GetSceneObjectPart(key).Name; | 6293 | return World.GetSceneObjectPart(key).Name; |
6294 | } | 6294 | } |
6295 | } | 6295 | } |
6296 | return String.Empty; | 6296 | return String.Empty; |
6297 | } | 6297 | } |
6298 | 6298 | ||
6299 | 6299 | ||
6300 | 6300 | ||
6301 | public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) | 6301 | public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) |
6302 | { | 6302 | { |
6303 | m_host.AddScriptLPS(1); | 6303 | m_host.AddScriptLPS(1); |
6304 | 6304 | ||
6305 | SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate); | 6305 | SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate); |
6306 | } | 6306 | } |
6307 | 6307 | ||
6308 | public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate) | 6308 | public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate) |
6309 | { | 6309 | { |
6310 | m_host.AddScriptLPS(1); | 6310 | m_host.AddScriptLPS(1); |
6311 | 6311 | ||
6312 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 6312 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
6313 | 6313 | ||
6314 | foreach (SceneObjectPart part in parts) | 6314 | foreach (SceneObjectPart part in parts) |
6315 | { | 6315 | { |
6316 | SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); | 6316 | SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); |
6317 | } | 6317 | } |
6318 | } | 6318 | } |
6319 | 6319 | ||
6320 | private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) | 6320 | private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) |
6321 | { | 6321 | { |
6322 | 6322 | ||
6323 | Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); | 6323 | Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); |
6324 | pTexAnim.Flags = (Primitive.TextureAnimMode)mode; | 6324 | pTexAnim.Flags = (Primitive.TextureAnimMode)mode; |
6325 | 6325 | ||
6326 | //ALL_SIDES | 6326 | //ALL_SIDES |
6327 | if (face == ScriptBaseClass.ALL_SIDES) | 6327 | if (face == ScriptBaseClass.ALL_SIDES) |
6328 | face = 255; | 6328 | face = 255; |
6329 | 6329 | ||
6330 | pTexAnim.Face = (uint)face; | 6330 | pTexAnim.Face = (uint)face; |
6331 | pTexAnim.Length = (float)length; | 6331 | pTexAnim.Length = (float)length; |
6332 | pTexAnim.Rate = (float)rate; | 6332 | pTexAnim.Rate = (float)rate; |
6333 | pTexAnim.SizeX = (uint)sizex; | 6333 | pTexAnim.SizeX = (uint)sizex; |
6334 | pTexAnim.SizeY = (uint)sizey; | 6334 | pTexAnim.SizeY = (uint)sizey; |
6335 | pTexAnim.Start = (float)start; | 6335 | pTexAnim.Start = (float)start; |
6336 | 6336 | ||
6337 | part.AddTextureAnimation(pTexAnim); | 6337 | part.AddTextureAnimation(pTexAnim); |
6338 | part.SendFullUpdateToAllClients(); | 6338 | part.SendFullUpdateToAllClients(); |
6339 | part.ParentGroup.HasGroupChanged = true; | 6339 | part.ParentGroup.HasGroupChanged = true; |
6340 | } | 6340 | } |
6341 | 6341 | ||
6342 | public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, | 6342 | public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, |
6343 | LSL_Vector bottom_south_west) | 6343 | LSL_Vector bottom_south_west) |
6344 | { | 6344 | { |
6345 | m_host.AddScriptLPS(1); | 6345 | m_host.AddScriptLPS(1); |
6346 | if (m_SoundModule != null) | 6346 | if (m_SoundModule != null) |
6347 | { | 6347 | { |
6348 | m_SoundModule.TriggerSoundLimited(m_host.UUID, | 6348 | m_SoundModule.TriggerSoundLimited(m_host.UUID, |
6349 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, | 6349 | ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, sound, AssetType.Sound), volume, |
6350 | bottom_south_west, top_north_east); | 6350 | bottom_south_west, top_north_east); |
6351 | } | 6351 | } |
6352 | } | 6352 | } |
6353 | 6353 | ||
6354 | public void llEjectFromLand(string pest) | 6354 | public void llEjectFromLand(string pest) |
6355 | { | 6355 | { |
6356 | m_host.AddScriptLPS(1); | 6356 | m_host.AddScriptLPS(1); |
6357 | UUID agentID = new UUID(); | 6357 | UUID agentID = new UUID(); |
6358 | if (UUID.TryParse(pest, out agentID)) | 6358 | if (UUID.TryParse(pest, out agentID)) |
6359 | { | 6359 | { |
6360 | ScenePresence presence = World.GetScenePresence(agentID); | 6360 | ScenePresence presence = World.GetScenePresence(agentID); |
6361 | if (presence != null) | 6361 | if (presence != null) |
6362 | { | 6362 | { |
6363 | // agent must be over the owners land | 6363 | // agent must be over the owners land |
6364 | ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition); | 6364 | ILandObject land = World.LandChannel.GetLandObject(presence.AbsolutePosition); |
6365 | if (land == null) | 6365 | if (land == null) |
6366 | return; | 6366 | return; |
6367 | 6367 | ||
6368 | if (m_host.OwnerID == land.LandData.OwnerID) | 6368 | if (m_host.OwnerID == land.LandData.OwnerID) |
6369 | { | 6369 | { |
6370 | World.TeleportClientHome(agentID, presence.ControllingClient); | 6370 | World.TeleportClientHome(agentID, presence.ControllingClient); |
6371 | } | 6371 | } |
6372 | } | 6372 | } |
6373 | } | 6373 | } |
6374 | ScriptSleep(m_sleepMsOnEjectFromLand); | 6374 | ScriptSleep(m_sleepMsOnEjectFromLand); |
6375 | } | 6375 | } |
6376 | 6376 | ||
6377 | public LSL_Integer llOverMyLand(string id) | 6377 | public LSL_Integer llOverMyLand(string id) |
6378 | { | 6378 | { |
6379 | m_host.AddScriptLPS(1); | 6379 | m_host.AddScriptLPS(1); |
6380 | UUID key = new UUID(); | 6380 | UUID key = new UUID(); |
6381 | if (UUID.TryParse(id, out key)) | 6381 | if (UUID.TryParse(id, out key)) |
6382 | { | 6382 | { |
6383 | ScenePresence presence = World.GetScenePresence(key); | 6383 | ScenePresence presence = World.GetScenePresence(key); |
6384 | if (presence != null) // object is an avatar | 6384 | if (presence != null) // object is an avatar |
6385 | { | 6385 | { |
6386 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) | 6386 | if (m_host.OwnerID == World.LandChannel.GetLandObject(presence.AbsolutePosition).LandData.OwnerID) |
6387 | return 1; | 6387 | return 1; |
6388 | } | 6388 | } |
6389 | else // object is not an avatar | 6389 | else // object is not an avatar |
6390 | { | 6390 | { |
6391 | SceneObjectPart obj = World.GetSceneObjectPart(key); | 6391 | SceneObjectPart obj = World.GetSceneObjectPart(key); |
6392 | 6392 | ||
6393 | if (obj != null) | 6393 | if (obj != null) |
6394 | { | 6394 | { |
6395 | if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID) | 6395 | if (m_host.OwnerID == World.LandChannel.GetLandObject(obj.AbsolutePosition).LandData.OwnerID) |
6396 | return 1; | 6396 | return 1; |
6397 | } | 6397 | } |
6398 | } | 6398 | } |
6399 | } | 6399 | } |
6400 | 6400 | ||
6401 | return 0; | 6401 | return 0; |
6402 | } | 6402 | } |
6403 | 6403 | ||
6404 | public LSL_String llGetLandOwnerAt(LSL_Vector pos) | 6404 | public LSL_String llGetLandOwnerAt(LSL_Vector pos) |
6405 | { | 6405 | { |
6406 | m_host.AddScriptLPS(1); | 6406 | m_host.AddScriptLPS(1); |
6407 | ILandObject land = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); | 6407 | ILandObject land = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); |
6408 | if (land == null) | 6408 | if (land == null) |
6409 | return UUID.Zero.ToString(); | 6409 | return UUID.Zero.ToString(); |
6410 | return land.LandData.OwnerID.ToString(); | 6410 | return land.LandData.OwnerID.ToString(); |
6411 | } | 6411 | } |
6412 | 6412 | ||
6413 | /// <summary> | 6413 | /// <summary> |
6414 | /// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize | 6414 | /// According to http://lslwiki.net/lslwiki/wakka.php?wakka=llGetAgentSize |
6415 | /// only the height of avatars vary and that says: | 6415 | /// only the height of avatars vary and that says: |
6416 | /// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively). | 6416 | /// Width (x) and depth (y) are constant. (0.45m and 0.6m respectively). |
6417 | /// </summary> | 6417 | /// </summary> |
6418 | public LSL_Vector llGetAgentSize(string id) | 6418 | public LSL_Vector llGetAgentSize(string id) |
6419 | { | 6419 | { |
6420 | m_host.AddScriptLPS(1); | 6420 | m_host.AddScriptLPS(1); |
6421 | ScenePresence avatar = World.GetScenePresence((UUID)id); | 6421 | ScenePresence avatar = World.GetScenePresence((UUID)id); |
6422 | LSL_Vector agentSize; | 6422 | LSL_Vector agentSize; |
6423 | if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region | 6423 | if (avatar == null || avatar.IsChildAgent) // Fail if not in the same region |
6424 | { | 6424 | { |
6425 | agentSize = ScriptBaseClass.ZERO_VECTOR; | 6425 | agentSize = ScriptBaseClass.ZERO_VECTOR; |
6426 | } | 6426 | } |
6427 | else | 6427 | else |
6428 | { | 6428 | { |
6429 | agentSize = GetAgentSize(avatar); | 6429 | agentSize = GetAgentSize(avatar); |
6430 | } | 6430 | } |
6431 | 6431 | ||
6432 | return agentSize; | 6432 | return agentSize; |
6433 | } | 6433 | } |
6434 | 6434 | ||
6435 | public LSL_Integer llSameGroup(string agent) | 6435 | public LSL_Integer llSameGroup(string agent) |
6436 | { | 6436 | { |
6437 | m_host.AddScriptLPS(1); | 6437 | m_host.AddScriptLPS(1); |
6438 | UUID agentId = new UUID(); | 6438 | UUID agentId = new UUID(); |
6439 | if (!UUID.TryParse(agent, out agentId)) | 6439 | if (!UUID.TryParse(agent, out agentId)) |
6440 | return new LSL_Integer(0); | 6440 | return new LSL_Integer(0); |
6441 | ScenePresence presence = World.GetScenePresence(agentId); | 6441 | ScenePresence presence = World.GetScenePresence(agentId); |
6442 | if (presence == null || presence.IsChildAgent) // Return flase for child agents | 6442 | if (presence == null || presence.IsChildAgent) // Return flase for child agents |
6443 | return new LSL_Integer(0); | 6443 | return new LSL_Integer(0); |
6444 | IClientAPI client = presence.ControllingClient; | 6444 | IClientAPI client = presence.ControllingClient; |
6445 | if (m_host.GroupID == client.ActiveGroupId) | 6445 | if (m_host.GroupID == client.ActiveGroupId) |
6446 | return new LSL_Integer(1); | 6446 | return new LSL_Integer(1); |
6447 | else | 6447 | else |
6448 | return new LSL_Integer(0); | 6448 | return new LSL_Integer(0); |
6449 | } | 6449 | } |
6450 | 6450 | ||
6451 | public void llUnSit(string id) | 6451 | public void llUnSit(string id) |
6452 | { | 6452 | { |
6453 | m_host.AddScriptLPS(1); | 6453 | m_host.AddScriptLPS(1); |
6454 | 6454 | ||
6455 | UUID key = new UUID(); | 6455 | UUID key = new UUID(); |
6456 | if (UUID.TryParse(id, out key)) | 6456 | if (UUID.TryParse(id, out key)) |
6457 | { | 6457 | { |
6458 | ScenePresence av = World.GetScenePresence(key); | 6458 | ScenePresence av = World.GetScenePresence(key); |
6459 | List<ScenePresence> sittingAvatars = m_host.ParentGroup.GetSittingAvatars(); | 6459 | List<ScenePresence> sittingAvatars = m_host.ParentGroup.GetSittingAvatars(); |
6460 | 6460 | ||
6461 | if (av != null) | 6461 | if (av != null) |
6462 | { | 6462 | { |
6463 | if (sittingAvatars.Contains(av)) | 6463 | if (sittingAvatars.Contains(av)) |
6464 | { | 6464 | { |
6465 | // if the avatar is sitting on this object, then | 6465 | // if the avatar is sitting on this object, then |
6466 | // we can unsit them. We don't want random scripts unsitting random people | 6466 | // we can unsit them. We don't want random scripts unsitting random people |
6467 | // Lets avoid the popcorn avatar scenario. | 6467 | // Lets avoid the popcorn avatar scenario. |
6468 | av.StandUp(); | 6468 | av.StandUp(); |
6469 | } | 6469 | } |
6470 | else | 6470 | else |
6471 | { | 6471 | { |
6472 | // If the object owner also owns the parcel | 6472 | // If the object owner also owns the parcel |
6473 | // or | 6473 | // or |
6474 | // if the land is group owned and the object is group owned by the same group | 6474 | // if the land is group owned and the object is group owned by the same group |
6475 | // or | 6475 | // or |
6476 | // if the object is owned by a person with estate access. | 6476 | // if the object is owned by a person with estate access. |
6477 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition); | 6477 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition); |
6478 | if (parcel != null) | 6478 | if (parcel != null) |
6479 | { | 6479 | { |
6480 | if (m_host.OwnerID == parcel.LandData.OwnerID || | 6480 | if (m_host.OwnerID == parcel.LandData.OwnerID || |
6481 | (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID | 6481 | (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID |
6482 | && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID)) | 6482 | && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID)) |
6483 | { | 6483 | { |
6484 | av.StandUp(); | 6484 | av.StandUp(); |
6485 | } | 6485 | } |
6486 | } | 6486 | } |
6487 | } | 6487 | } |
6488 | } | 6488 | } |
6489 | } | 6489 | } |
6490 | } | 6490 | } |
6491 | 6491 | ||
6492 | public LSL_Vector llGroundSlope(LSL_Vector offset) | 6492 | public LSL_Vector llGroundSlope(LSL_Vector offset) |
6493 | { | 6493 | { |
6494 | m_host.AddScriptLPS(1); | 6494 | m_host.AddScriptLPS(1); |
6495 | 6495 | ||
6496 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. | 6496 | //Get the slope normal. This gives us the equation of the plane tangent to the slope. |
6497 | LSL_Vector vsn = llGroundNormal(offset); | 6497 | LSL_Vector vsn = llGroundNormal(offset); |
6498 | 6498 | ||
6499 | //Plug the x,y coordinates of the slope normal into the equation of the plane to get | 6499 | //Plug the x,y coordinates of the slope normal into the equation of the plane to get |
6500 | //the height of that point on the plane. The resulting vector gives the slope. | 6500 | //the height of that point on the plane. The resulting vector gives the slope. |
6501 | Vector3 vsl = vsn; | 6501 | Vector3 vsl = vsn; |
6502 | vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); | 6502 | vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); |
6503 | vsl.Normalize(); | 6503 | vsl.Normalize(); |
6504 | //Normalization might be overkill here | 6504 | //Normalization might be overkill here |
6505 | 6505 | ||
6506 | vsn.x = vsl.X; | 6506 | vsn.x = vsl.X; |
6507 | vsn.y = vsl.Y; | 6507 | vsn.y = vsl.Y; |
6508 | vsn.z = vsl.Z; | 6508 | vsn.z = vsl.Z; |
6509 | 6509 | ||
6510 | return vsn; | 6510 | return vsn; |
6511 | } | 6511 | } |
6512 | 6512 | ||
6513 | public LSL_Vector llGroundNormal(LSL_Vector offset) | 6513 | public LSL_Vector llGroundNormal(LSL_Vector offset) |
6514 | { | 6514 | { |
6515 | m_host.AddScriptLPS(1); | 6515 | m_host.AddScriptLPS(1); |
6516 | Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; | 6516 | Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; |
6517 | // Clamp to valid position | 6517 | // Clamp to valid position |
6518 | if (pos.X < 0) | 6518 | if (pos.X < 0) |
6519 | pos.X = 0; | 6519 | pos.X = 0; |
6520 | else if (pos.X >= World.Heightmap.Width) | 6520 | else if (pos.X >= World.Heightmap.Width) |
6521 | pos.X = World.Heightmap.Width - 1; | 6521 | pos.X = World.Heightmap.Width - 1; |
6522 | if (pos.Y < 0) | 6522 | if (pos.Y < 0) |
6523 | pos.Y = 0; | 6523 | pos.Y = 0; |
6524 | else if (pos.Y >= World.Heightmap.Height) | 6524 | else if (pos.Y >= World.Heightmap.Height) |
6525 | pos.Y = World.Heightmap.Height - 1; | 6525 | pos.Y = World.Heightmap.Height - 1; |
6526 | 6526 | ||
6527 | //Find two points in addition to the position to define a plane | 6527 | //Find two points in addition to the position to define a plane |
6528 | Vector3 p0 = new Vector3(pos.X, pos.Y, | 6528 | Vector3 p0 = new Vector3(pos.X, pos.Y, |
6529 | (float)World.Heightmap[(int)pos.X, (int)pos.Y]); | 6529 | (float)World.Heightmap[(int)pos.X, (int)pos.Y]); |
6530 | Vector3 p1 = new Vector3(); | 6530 | Vector3 p1 = new Vector3(); |
6531 | Vector3 p2 = new Vector3(); | 6531 | Vector3 p2 = new Vector3(); |
6532 | if ((pos.X + 1.0f) >= World.Heightmap.Width) | 6532 | if ((pos.X + 1.0f) >= World.Heightmap.Width) |
6533 | p1 = new Vector3(pos.X + 1.0f, pos.Y, | 6533 | p1 = new Vector3(pos.X + 1.0f, pos.Y, |
6534 | (float)World.Heightmap[(int)pos.X, (int)pos.Y]); | 6534 | (float)World.Heightmap[(int)pos.X, (int)pos.Y]); |
6535 | else | 6535 | else |
6536 | p1 = new Vector3(pos.X + 1.0f, pos.Y, | 6536 | p1 = new Vector3(pos.X + 1.0f, pos.Y, |
6537 | (float)World.Heightmap[(int)(pos.X + 1.0f), (int)pos.Y]); | 6537 | (float)World.Heightmap[(int)(pos.X + 1.0f), (int)pos.Y]); |
6538 | if ((pos.Y + 1.0f) >= World.Heightmap.Height) | 6538 | if ((pos.Y + 1.0f) >= World.Heightmap.Height) |
6539 | p2 = new Vector3(pos.X, pos.Y + 1.0f, | 6539 | p2 = new Vector3(pos.X, pos.Y + 1.0f, |
6540 | (float)World.Heightmap[(int)pos.X, (int)pos.Y]); | 6540 | (float)World.Heightmap[(int)pos.X, (int)pos.Y]); |
6541 | else | 6541 | else |
6542 | p2 = new Vector3(pos.X, pos.Y + 1.0f, | 6542 | p2 = new Vector3(pos.X, pos.Y + 1.0f, |
6543 | (float)World.Heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]); | 6543 | (float)World.Heightmap[(int)pos.X, (int)(pos.Y + 1.0f)]); |
6544 | 6544 | ||
6545 | //Find normalized vectors from p0 to p1 and p0 to p2 | 6545 | //Find normalized vectors from p0 to p1 and p0 to p2 |
6546 | Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); | 6546 | Vector3 v0 = new Vector3(p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); |
6547 | Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); | 6547 | Vector3 v1 = new Vector3(p2.X - p0.X, p2.Y - p0.Y, p2.Z - p0.Z); |
6548 | v0.Normalize(); | 6548 | v0.Normalize(); |
6549 | v1.Normalize(); | 6549 | v1.Normalize(); |
6550 | 6550 | ||
6551 | //Find the cross product of the vectors (the slope normal). | 6551 | //Find the cross product of the vectors (the slope normal). |
6552 | Vector3 vsn = new Vector3(); | 6552 | Vector3 vsn = new Vector3(); |
6553 | vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); | 6553 | vsn.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); |
6554 | vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z); | 6554 | vsn.Y = (v0.Z * v1.X) - (v0.X * v1.Z); |
6555 | vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X); | 6555 | vsn.Z = (v0.X * v1.Y) - (v0.Y * v1.X); |
6556 | vsn.Normalize(); | 6556 | vsn.Normalize(); |
6557 | //I believe the crossproduct of two normalized vectors is a normalized vector so | 6557 | //I believe the crossproduct of two normalized vectors is a normalized vector so |
6558 | //this normalization may be overkill | 6558 | //this normalization may be overkill |
6559 | 6559 | ||
6560 | return new LSL_Vector(vsn); | 6560 | return new LSL_Vector(vsn); |
6561 | } | 6561 | } |
6562 | 6562 | ||
6563 | public LSL_Vector llGroundContour(LSL_Vector offset) | 6563 | public LSL_Vector llGroundContour(LSL_Vector offset) |
6564 | { | 6564 | { |
6565 | m_host.AddScriptLPS(1); | 6565 | m_host.AddScriptLPS(1); |
6566 | LSL_Vector x = llGroundSlope(offset); | 6566 | LSL_Vector x = llGroundSlope(offset); |
6567 | return new LSL_Vector(-x.y, x.x, 0.0); | 6567 | return new LSL_Vector(-x.y, x.x, 0.0); |
6568 | } | 6568 | } |
6569 | 6569 | ||
6570 | public LSL_Integer llGetAttached() | 6570 | public LSL_Integer llGetAttached() |
6571 | { | 6571 | { |
6572 | m_host.AddScriptLPS(1); | 6572 | m_host.AddScriptLPS(1); |
6573 | return m_host.ParentGroup.AttachmentPoint; | 6573 | return m_host.ParentGroup.AttachmentPoint; |
6574 | } | 6574 | } |
6575 | 6575 | ||
6576 | public virtual LSL_Integer llGetFreeMemory() | 6576 | public virtual LSL_Integer llGetFreeMemory() |
6577 | { | 6577 | { |
6578 | m_host.AddScriptLPS(1); | 6578 | m_host.AddScriptLPS(1); |
6579 | // Make scripts designed for Mono happy | 6579 | // Make scripts designed for Mono happy |
6580 | return 65536; | 6580 | return 65536; |
6581 | } | 6581 | } |
6582 | 6582 | ||
6583 | public LSL_Integer llGetFreeURLs() | 6583 | public LSL_Integer llGetFreeURLs() |
6584 | { | 6584 | { |
6585 | m_host.AddScriptLPS(1); | 6585 | m_host.AddScriptLPS(1); |
6586 | if (m_UrlModule != null) | 6586 | if (m_UrlModule != null) |
6587 | return new LSL_Integer(m_UrlModule.GetFreeUrls()); | 6587 | return new LSL_Integer(m_UrlModule.GetFreeUrls()); |
6588 | return new LSL_Integer(0); | 6588 | return new LSL_Integer(0); |
6589 | } | 6589 | } |
6590 | 6590 | ||
6591 | 6591 | ||
6592 | public LSL_String llGetRegionName() | 6592 | public LSL_String llGetRegionName() |
6593 | { | 6593 | { |
6594 | m_host.AddScriptLPS(1); | 6594 | m_host.AddScriptLPS(1); |
6595 | return World.RegionInfo.RegionName; | 6595 | return World.RegionInfo.RegionName; |
6596 | } | 6596 | } |
6597 | 6597 | ||
6598 | public LSL_Float llGetRegionTimeDilation() | 6598 | public LSL_Float llGetRegionTimeDilation() |
6599 | { | 6599 | { |
6600 | m_host.AddScriptLPS(1); | 6600 | m_host.AddScriptLPS(1); |
6601 | return (double)World.TimeDilation; | 6601 | return (double)World.TimeDilation; |
6602 | } | 6602 | } |
6603 | 6603 | ||
6604 | /// <summary> | 6604 | /// <summary> |
6605 | /// Returns the value reported in the client Statistics window | 6605 | /// Returns the value reported in the client Statistics window |
6606 | /// </summary> | 6606 | /// </summary> |
6607 | public LSL_Float llGetRegionFPS() | 6607 | public LSL_Float llGetRegionFPS() |
6608 | { | 6608 | { |
6609 | m_host.AddScriptLPS(1); | 6609 | m_host.AddScriptLPS(1); |
6610 | return World.StatsReporter.LastReportedSimFPS; | 6610 | return World.StatsReporter.LastReportedSimFPS; |
6611 | } | 6611 | } |
6612 | 6612 | ||
6613 | 6613 | ||
6614 | /* particle system rules should be coming into this routine as doubles, that is | 6614 | /* particle system rules should be coming into this routine as doubles, that is |
6615 | rule[0] should be an integer from this list and rule[1] should be the arg | 6615 | rule[0] should be an integer from this list and rule[1] should be the arg |
6616 | for the same integer. wiki.secondlife.com has most of this mapping, but some | 6616 | for the same integer. wiki.secondlife.com has most of this mapping, but some |
6617 | came from http://www.caligari-designs.com/p4u2 | 6617 | came from http://www.caligari-designs.com/p4u2 |
6618 | 6618 | ||
6619 | We iterate through the list for 'Count' elements, incrementing by two for each | 6619 | We iterate through the list for 'Count' elements, incrementing by two for each |
6620 | iteration and set the members of Primitive.ParticleSystem, one at a time. | 6620 | iteration and set the members of Primitive.ParticleSystem, one at a time. |
6621 | */ | 6621 | */ |
6622 | 6622 | ||
6623 | public enum PrimitiveRule : int | 6623 | public enum PrimitiveRule : int |
6624 | { | 6624 | { |
6625 | PSYS_PART_FLAGS = 0, | 6625 | PSYS_PART_FLAGS = 0, |
6626 | PSYS_PART_START_COLOR = 1, | 6626 | PSYS_PART_START_COLOR = 1, |
6627 | PSYS_PART_START_ALPHA = 2, | 6627 | PSYS_PART_START_ALPHA = 2, |
6628 | PSYS_PART_END_COLOR = 3, | 6628 | PSYS_PART_END_COLOR = 3, |
6629 | PSYS_PART_END_ALPHA = 4, | 6629 | PSYS_PART_END_ALPHA = 4, |
6630 | PSYS_PART_START_SCALE = 5, | 6630 | PSYS_PART_START_SCALE = 5, |
6631 | PSYS_PART_END_SCALE = 6, | 6631 | PSYS_PART_END_SCALE = 6, |
6632 | PSYS_PART_MAX_AGE = 7, | 6632 | PSYS_PART_MAX_AGE = 7, |
6633 | PSYS_SRC_ACCEL = 8, | 6633 | PSYS_SRC_ACCEL = 8, |
6634 | PSYS_SRC_PATTERN = 9, | 6634 | PSYS_SRC_PATTERN = 9, |
6635 | PSYS_SRC_INNERANGLE = 10, | 6635 | PSYS_SRC_INNERANGLE = 10, |
6636 | PSYS_SRC_OUTERANGLE = 11, | 6636 | PSYS_SRC_OUTERANGLE = 11, |
6637 | PSYS_SRC_TEXTURE = 12, | 6637 | PSYS_SRC_TEXTURE = 12, |
6638 | PSYS_SRC_BURST_RATE = 13, | 6638 | PSYS_SRC_BURST_RATE = 13, |
6639 | PSYS_SRC_BURST_PART_COUNT = 15, | 6639 | PSYS_SRC_BURST_PART_COUNT = 15, |
6640 | PSYS_SRC_BURST_RADIUS = 16, | 6640 | PSYS_SRC_BURST_RADIUS = 16, |
6641 | PSYS_SRC_BURST_SPEED_MIN = 17, | 6641 | PSYS_SRC_BURST_SPEED_MIN = 17, |
6642 | PSYS_SRC_BURST_SPEED_MAX = 18, | 6642 | PSYS_SRC_BURST_SPEED_MAX = 18, |
6643 | PSYS_SRC_MAX_AGE = 19, | 6643 | PSYS_SRC_MAX_AGE = 19, |
6644 | PSYS_SRC_TARGET_KEY = 20, | 6644 | PSYS_SRC_TARGET_KEY = 20, |
6645 | PSYS_SRC_OMEGA = 21, | 6645 | PSYS_SRC_OMEGA = 21, |
6646 | PSYS_SRC_ANGLE_BEGIN = 22, | 6646 | PSYS_SRC_ANGLE_BEGIN = 22, |
6647 | PSYS_SRC_ANGLE_END = 23, | 6647 | PSYS_SRC_ANGLE_END = 23, |
6648 | PSYS_PART_BLEND_FUNC_SOURCE = 24, | 6648 | PSYS_PART_BLEND_FUNC_SOURCE = 24, |
6649 | PSYS_PART_BLEND_FUNC_DEST = 25, | 6649 | PSYS_PART_BLEND_FUNC_DEST = 25, |
6650 | PSYS_PART_START_GLOW = 26, | 6650 | PSYS_PART_START_GLOW = 26, |
6651 | PSYS_PART_END_GLOW = 27 | 6651 | PSYS_PART_END_GLOW = 27 |
6652 | } | 6652 | } |
6653 | 6653 | ||
6654 | internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) | 6654 | internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) |
6655 | { | 6655 | { |
6656 | Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None; | 6656 | Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None; |
6657 | 6657 | ||
6658 | return returnval; | 6658 | return returnval; |
6659 | } | 6659 | } |
6660 | 6660 | ||
6661 | protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues() | 6661 | protected Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues() |
6662 | { | 6662 | { |
6663 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(); | 6663 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(); |
6664 | 6664 | ||
6665 | // TODO find out about the other defaults and add them here | 6665 | // TODO find out about the other defaults and add them here |
6666 | ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); | 6666 | ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); |
6667 | ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); | 6667 | ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); |
6668 | ps.PartStartScaleX = 1.0f; | 6668 | ps.PartStartScaleX = 1.0f; |
6669 | ps.PartStartScaleY = 1.0f; | 6669 | ps.PartStartScaleY = 1.0f; |
6670 | ps.PartEndScaleX = 1.0f; | 6670 | ps.PartEndScaleX = 1.0f; |
6671 | ps.PartEndScaleY = 1.0f; | 6671 | ps.PartEndScaleY = 1.0f; |
6672 | ps.BurstSpeedMin = 1.0f; | 6672 | ps.BurstSpeedMin = 1.0f; |
6673 | ps.BurstSpeedMax = 1.0f; | 6673 | ps.BurstSpeedMax = 1.0f; |
6674 | ps.BurstRate = 0.1f; | 6674 | ps.BurstRate = 0.1f; |
6675 | ps.PartMaxAge = 10.0f; | 6675 | ps.PartMaxAge = 10.0f; |
6676 | ps.BurstPartCount = 1; | 6676 | ps.BurstPartCount = 1; |
6677 | ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA; | 6677 | ps.BlendFuncSource = ScriptBaseClass.PSYS_PART_BF_SOURCE_ALPHA; |
6678 | ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA; | 6678 | ps.BlendFuncDest = ScriptBaseClass.PSYS_PART_BF_ONE_MINUS_SOURCE_ALPHA; |
6679 | ps.PartStartGlow = 0.0f; | 6679 | ps.PartStartGlow = 0.0f; |
6680 | ps.PartEndGlow = 0.0f; | 6680 | ps.PartEndGlow = 0.0f; |
6681 | 6681 | ||
6682 | return ps; | 6682 | return ps; |
6683 | } | 6683 | } |
6684 | 6684 | ||
6685 | public void llLinkParticleSystem(int linknumber, LSL_List rules) | 6685 | public void llLinkParticleSystem(int linknumber, LSL_List rules) |
6686 | { | 6686 | { |
6687 | m_host.AddScriptLPS(1); | 6687 | m_host.AddScriptLPS(1); |
6688 | 6688 | ||
6689 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | 6689 | List<SceneObjectPart> parts = GetLinkParts(linknumber); |
6690 | 6690 | ||
6691 | foreach (SceneObjectPart part in parts) | 6691 | foreach (SceneObjectPart part in parts) |
6692 | { | 6692 | { |
6693 | SetParticleSystem(part, rules, "llLinkParticleSystem"); | 6693 | SetParticleSystem(part, rules, "llLinkParticleSystem"); |
6694 | } | 6694 | } |
6695 | } | 6695 | } |
6696 | 6696 | ||
6697 | public void llParticleSystem(LSL_List rules) | 6697 | public void llParticleSystem(LSL_List rules) |
6698 | { | 6698 | { |
6699 | m_host.AddScriptLPS(1); | 6699 | m_host.AddScriptLPS(1); |
6700 | SetParticleSystem(m_host, rules, "llParticleSystem"); | 6700 | SetParticleSystem(m_host, rules, "llParticleSystem"); |
6701 | } | 6701 | } |
6702 | 6702 | ||
6703 | private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc) | 6703 | private void SetParticleSystem(SceneObjectPart part, LSL_List rules, string originFunc) |
6704 | { | 6704 | { |
6705 | if (rules.Length == 0) | 6705 | if (rules.Length == 0) |
6706 | { | 6706 | { |
6707 | part.RemoveParticleSystem(); | 6707 | part.RemoveParticleSystem(); |
6708 | part.ParentGroup.HasGroupChanged = true; | 6708 | part.ParentGroup.HasGroupChanged = true; |
6709 | } | 6709 | } |
6710 | else | 6710 | else |
6711 | { | 6711 | { |
6712 | Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues(); | 6712 | Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues(); |
6713 | LSL_Vector tempv = new LSL_Vector(); | 6713 | LSL_Vector tempv = new LSL_Vector(); |
6714 | 6714 | ||
6715 | float tempf = 0; | 6715 | float tempf = 0; |
6716 | int tmpi = 0; | 6716 | int tmpi = 0; |
6717 | 6717 | ||
6718 | for (int i = 0; i < rules.Length; i += 2) | 6718 | for (int i = 0; i < rules.Length; i += 2) |
6719 | { | 6719 | { |
6720 | int psystype; | 6720 | int psystype; |
6721 | try | 6721 | try |
6722 | { | 6722 | { |
6723 | psystype = rules.GetLSLIntegerItem(i); | 6723 | psystype = rules.GetLSLIntegerItem(i); |
6724 | } | 6724 | } |
6725 | catch (InvalidCastException) | 6725 | catch (InvalidCastException) |
6726 | { | 6726 | { |
6727 | Error(originFunc, string.Format("Error running particle system params index #{0}: particle system parameter type must be integer", i)); | 6727 | Error(originFunc, string.Format("Error running particle system params index #{0}: particle system parameter type must be integer", i)); |
6728 | return; | 6728 | return; |
6729 | } | 6729 | } |
6730 | switch (psystype) | 6730 | switch (psystype) |
6731 | { | 6731 | { |
6732 | case (int)ScriptBaseClass.PSYS_PART_FLAGS: | 6732 | case (int)ScriptBaseClass.PSYS_PART_FLAGS: |
6733 | try | 6733 | try |
6734 | { | 6734 | { |
6735 | prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); | 6735 | prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); |
6736 | } | 6736 | } |
6737 | catch(InvalidCastException) | 6737 | catch(InvalidCastException) |
6738 | { | 6738 | { |
6739 | Error(originFunc, string.Format("Error running rule PSYS_PART_FLAGS: arg #{0} - parameter 1 must be integer", i + 1)); | 6739 | Error(originFunc, string.Format("Error running rule PSYS_PART_FLAGS: arg #{0} - parameter 1 must be integer", i + 1)); |
6740 | return; | 6740 | return; |
6741 | } | 6741 | } |
6742 | break; | 6742 | break; |
6743 | 6743 | ||
6744 | case (int)ScriptBaseClass.PSYS_PART_START_COLOR: | 6744 | case (int)ScriptBaseClass.PSYS_PART_START_COLOR: |
6745 | try | 6745 | try |
6746 | { | 6746 | { |
6747 | tempv = rules.GetVector3Item(i + 1); | 6747 | tempv = rules.GetVector3Item(i + 1); |
6748 | } | 6748 | } |
6749 | catch(InvalidCastException) | 6749 | catch(InvalidCastException) |
6750 | { | 6750 | { |
6751 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); | 6751 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); |
6752 | return; | 6752 | return; |
6753 | } | 6753 | } |
6754 | prules.PartStartColor.R = (float)tempv.x; | 6754 | prules.PartStartColor.R = (float)tempv.x; |
6755 | prules.PartStartColor.G = (float)tempv.y; | 6755 | prules.PartStartColor.G = (float)tempv.y; |
6756 | prules.PartStartColor.B = (float)tempv.z; | 6756 | prules.PartStartColor.B = (float)tempv.z; |
6757 | break; | 6757 | break; |
6758 | 6758 | ||
6759 | case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: | 6759 | case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: |
6760 | try | 6760 | try |
6761 | { | 6761 | { |
6762 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6762 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6763 | } | 6763 | } |
6764 | catch(InvalidCastException) | 6764 | catch(InvalidCastException) |
6765 | { | 6765 | { |
6766 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); | 6766 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); |
6767 | return; | 6767 | return; |
6768 | } | 6768 | } |
6769 | prules.PartStartColor.A = tempf; | 6769 | prules.PartStartColor.A = tempf; |
6770 | break; | 6770 | break; |
6771 | 6771 | ||
6772 | case (int)ScriptBaseClass.PSYS_PART_END_COLOR: | 6772 | case (int)ScriptBaseClass.PSYS_PART_END_COLOR: |
6773 | try | 6773 | try |
6774 | { | 6774 | { |
6775 | tempv = rules.GetVector3Item(i + 1); | 6775 | tempv = rules.GetVector3Item(i + 1); |
6776 | } | 6776 | } |
6777 | catch(InvalidCastException) | 6777 | catch(InvalidCastException) |
6778 | { | 6778 | { |
6779 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); | 6779 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_COLOR: arg #{0} - parameter 1 must be vector", i + 1)); |
6780 | return; | 6780 | return; |
6781 | } | 6781 | } |
6782 | prules.PartEndColor.R = (float)tempv.x; | 6782 | prules.PartEndColor.R = (float)tempv.x; |
6783 | prules.PartEndColor.G = (float)tempv.y; | 6783 | prules.PartEndColor.G = (float)tempv.y; |
6784 | prules.PartEndColor.B = (float)tempv.z; | 6784 | prules.PartEndColor.B = (float)tempv.z; |
6785 | break; | 6785 | break; |
6786 | 6786 | ||
6787 | case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: | 6787 | case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: |
6788 | try | 6788 | try |
6789 | { | 6789 | { |
6790 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6790 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6791 | } | 6791 | } |
6792 | catch(InvalidCastException) | 6792 | catch(InvalidCastException) |
6793 | { | 6793 | { |
6794 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); | 6794 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_ALPHA: arg #{0} - parameter 1 must be float", i + 1)); |
6795 | return; | 6795 | return; |
6796 | } | 6796 | } |
6797 | prules.PartEndColor.A = tempf; | 6797 | prules.PartEndColor.A = tempf; |
6798 | break; | 6798 | break; |
6799 | 6799 | ||
6800 | case (int)ScriptBaseClass.PSYS_PART_START_SCALE: | 6800 | case (int)ScriptBaseClass.PSYS_PART_START_SCALE: |
6801 | try | 6801 | try |
6802 | { | 6802 | { |
6803 | tempv = rules.GetVector3Item(i + 1); | 6803 | tempv = rules.GetVector3Item(i + 1); |
6804 | } | 6804 | } |
6805 | catch(InvalidCastException) | 6805 | catch(InvalidCastException) |
6806 | { | 6806 | { |
6807 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); | 6807 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); |
6808 | return; | 6808 | return; |
6809 | } | 6809 | } |
6810 | prules.PartStartScaleX = validParticleScale((float)tempv.x); | 6810 | prules.PartStartScaleX = validParticleScale((float)tempv.x); |
6811 | prules.PartStartScaleY = validParticleScale((float)tempv.y); | 6811 | prules.PartStartScaleY = validParticleScale((float)tempv.y); |
6812 | break; | 6812 | break; |
6813 | 6813 | ||
6814 | case (int)ScriptBaseClass.PSYS_PART_END_SCALE: | 6814 | case (int)ScriptBaseClass.PSYS_PART_END_SCALE: |
6815 | try | 6815 | try |
6816 | { | 6816 | { |
6817 | tempv = rules.GetVector3Item(i + 1); | 6817 | tempv = rules.GetVector3Item(i + 1); |
6818 | } | 6818 | } |
6819 | catch(InvalidCastException) | 6819 | catch(InvalidCastException) |
6820 | { | 6820 | { |
6821 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); | 6821 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_SCALE: arg #{0} - parameter 1 must be vector", i + 1)); |
6822 | return; | 6822 | return; |
6823 | } | 6823 | } |
6824 | prules.PartEndScaleX = validParticleScale((float)tempv.x); | 6824 | prules.PartEndScaleX = validParticleScale((float)tempv.x); |
6825 | prules.PartEndScaleY = validParticleScale((float)tempv.y); | 6825 | prules.PartEndScaleY = validParticleScale((float)tempv.y); |
6826 | break; | 6826 | break; |
6827 | 6827 | ||
6828 | case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: | 6828 | case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: |
6829 | try | 6829 | try |
6830 | { | 6830 | { |
6831 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6831 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6832 | } | 6832 | } |
6833 | catch(InvalidCastException) | 6833 | catch(InvalidCastException) |
6834 | { | 6834 | { |
6835 | Error(originFunc, string.Format("Error running rule PSYS_PART_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); | 6835 | Error(originFunc, string.Format("Error running rule PSYS_PART_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); |
6836 | return; | 6836 | return; |
6837 | } | 6837 | } |
6838 | prules.PartMaxAge = tempf; | 6838 | prules.PartMaxAge = tempf; |
6839 | break; | 6839 | break; |
6840 | 6840 | ||
6841 | case (int)ScriptBaseClass.PSYS_SRC_ACCEL: | 6841 | case (int)ScriptBaseClass.PSYS_SRC_ACCEL: |
6842 | try | 6842 | try |
6843 | { | 6843 | { |
6844 | tempv = rules.GetVector3Item(i + 1); | 6844 | tempv = rules.GetVector3Item(i + 1); |
6845 | } | 6845 | } |
6846 | catch(InvalidCastException) | 6846 | catch(InvalidCastException) |
6847 | { | 6847 | { |
6848 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ACCEL: arg #{0} - parameter 1 must be vector", i + 1)); | 6848 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ACCEL: arg #{0} - parameter 1 must be vector", i + 1)); |
6849 | return; | 6849 | return; |
6850 | } | 6850 | } |
6851 | prules.PartAcceleration.X = (float)tempv.x; | 6851 | prules.PartAcceleration.X = (float)tempv.x; |
6852 | prules.PartAcceleration.Y = (float)tempv.y; | 6852 | prules.PartAcceleration.Y = (float)tempv.y; |
6853 | prules.PartAcceleration.Z = (float)tempv.z; | 6853 | prules.PartAcceleration.Z = (float)tempv.z; |
6854 | break; | 6854 | break; |
6855 | 6855 | ||
6856 | case (int)ScriptBaseClass.PSYS_SRC_PATTERN: | 6856 | case (int)ScriptBaseClass.PSYS_SRC_PATTERN: |
6857 | try | 6857 | try |
6858 | { | 6858 | { |
6859 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); | 6859 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); |
6860 | } | 6860 | } |
6861 | catch(InvalidCastException) | 6861 | catch(InvalidCastException) |
6862 | { | 6862 | { |
6863 | Error(originFunc, string.Format("Error running rule PSYS_SRC_PATTERN: arg #{0} - parameter 1 must be integer", i + 1)); | 6863 | Error(originFunc, string.Format("Error running rule PSYS_SRC_PATTERN: arg #{0} - parameter 1 must be integer", i + 1)); |
6864 | return; | 6864 | return; |
6865 | } | 6865 | } |
6866 | prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; | 6866 | prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; |
6867 | break; | 6867 | break; |
6868 | 6868 | ||
6869 | // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The | 6869 | // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The |
6870 | // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The | 6870 | // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The |
6871 | // client tells the difference between the two by looking at the 0x02 bit in | 6871 | // client tells the difference between the two by looking at the 0x02 bit in |
6872 | // the PartFlags variable. | 6872 | // the PartFlags variable. |
6873 | case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: | 6873 | case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: |
6874 | try | 6874 | try |
6875 | { | 6875 | { |
6876 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6876 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6877 | } | 6877 | } |
6878 | catch(InvalidCastException) | 6878 | catch(InvalidCastException) |
6879 | { | 6879 | { |
6880 | Error(originFunc, string.Format("Error running rule PSYS_SRC_INNERANGLE: arg #{0} - parameter 1 must be float", i + 1)); | 6880 | Error(originFunc, string.Format("Error running rule PSYS_SRC_INNERANGLE: arg #{0} - parameter 1 must be float", i + 1)); |
6881 | return; | 6881 | return; |
6882 | } | 6882 | } |
6883 | prules.InnerAngle = (float)tempf; | 6883 | prules.InnerAngle = (float)tempf; |
6884 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. | 6884 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. |
6885 | break; | 6885 | break; |
6886 | 6886 | ||
6887 | case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: | 6887 | case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: |
6888 | try | 6888 | try |
6889 | { | 6889 | { |
6890 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6890 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6891 | } | 6891 | } |
6892 | catch(InvalidCastException) | 6892 | catch(InvalidCastException) |
6893 | { | 6893 | { |
6894 | Error(originFunc, string.Format("Error running rule PSYS_SRC_OUTERANGLE: arg #{0} - parameter 1 must be float", i + 1)); | 6894 | Error(originFunc, string.Format("Error running rule PSYS_SRC_OUTERANGLE: arg #{0} - parameter 1 must be float", i + 1)); |
6895 | return; | 6895 | return; |
6896 | } | 6896 | } |
6897 | prules.OuterAngle = (float)tempf; | 6897 | prules.OuterAngle = (float)tempf; |
6898 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. | 6898 | prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. |
6899 | break; | 6899 | break; |
6900 | 6900 | ||
6901 | case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE: | 6901 | case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_SOURCE: |
6902 | try | 6902 | try |
6903 | { | 6903 | { |
6904 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); | 6904 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); |
6905 | } | 6905 | } |
6906 | catch(InvalidCastException) | 6906 | catch(InvalidCastException) |
6907 | { | 6907 | { |
6908 | Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_SOURCE: arg #{0} - parameter 1 must be integer", i + 1)); | 6908 | Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_SOURCE: arg #{0} - parameter 1 must be integer", i + 1)); |
6909 | return; | 6909 | return; |
6910 | } | 6910 | } |
6911 | prules.BlendFuncSource = (byte)tmpi; | 6911 | prules.BlendFuncSource = (byte)tmpi; |
6912 | break; | 6912 | break; |
6913 | 6913 | ||
6914 | case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST: | 6914 | case (int)ScriptBaseClass.PSYS_PART_BLEND_FUNC_DEST: |
6915 | try | 6915 | try |
6916 | { | 6916 | { |
6917 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); | 6917 | tmpi = (int)rules.GetLSLIntegerItem(i + 1); |
6918 | } | 6918 | } |
6919 | catch(InvalidCastException) | 6919 | catch(InvalidCastException) |
6920 | { | 6920 | { |
6921 | Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_DEST: arg #{0} - parameter 1 must be integer", i + 1)); | 6921 | Error(originFunc, string.Format("Error running rule PSYS_PART_BLEND_FUNC_DEST: arg #{0} - parameter 1 must be integer", i + 1)); |
6922 | return; | 6922 | return; |
6923 | } | 6923 | } |
6924 | prules.BlendFuncDest = (byte)tmpi; | 6924 | prules.BlendFuncDest = (byte)tmpi; |
6925 | break; | 6925 | break; |
6926 | 6926 | ||
6927 | case (int)ScriptBaseClass.PSYS_PART_START_GLOW: | 6927 | case (int)ScriptBaseClass.PSYS_PART_START_GLOW: |
6928 | try | 6928 | try |
6929 | { | 6929 | { |
6930 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6930 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6931 | } | 6931 | } |
6932 | catch(InvalidCastException) | 6932 | catch(InvalidCastException) |
6933 | { | 6933 | { |
6934 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_GLOW: arg #{0} - parameter 1 must be float", i + 1)); | 6934 | Error(originFunc, string.Format("Error running rule PSYS_PART_START_GLOW: arg #{0} - parameter 1 must be float", i + 1)); |
6935 | return; | 6935 | return; |
6936 | } | 6936 | } |
6937 | prules.PartStartGlow = (float)tempf; | 6937 | prules.PartStartGlow = (float)tempf; |
6938 | break; | 6938 | break; |
6939 | 6939 | ||
6940 | case (int)ScriptBaseClass.PSYS_PART_END_GLOW: | 6940 | case (int)ScriptBaseClass.PSYS_PART_END_GLOW: |
6941 | try | 6941 | try |
6942 | { | 6942 | { |
6943 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6943 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6944 | } | 6944 | } |
6945 | catch(InvalidCastException) | 6945 | catch(InvalidCastException) |
6946 | { | 6946 | { |
6947 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_GLOW: arg #{0} - parameter 1 must be float", i + 1)); | 6947 | Error(originFunc, string.Format("Error running rule PSYS_PART_END_GLOW: arg #{0} - parameter 1 must be float", i + 1)); |
6948 | return; | 6948 | return; |
6949 | } | 6949 | } |
6950 | prules.PartEndGlow = (float)tempf; | 6950 | prules.PartEndGlow = (float)tempf; |
6951 | break; | 6951 | break; |
6952 | 6952 | ||
6953 | case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: | 6953 | case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: |
6954 | try | 6954 | try |
6955 | { | 6955 | { |
6956 | prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1)); | 6956 | prules.Texture = ScriptUtils.GetAssetIdFromKeyOrItemName(m_host, rules.GetLSLStringItem(i + 1)); |
6957 | } | 6957 | } |
6958 | catch(InvalidCastException) | 6958 | catch(InvalidCastException) |
6959 | { | 6959 | { |
6960 | Error(originFunc, string.Format("Error running rule PSYS_SRC_TEXTURE: arg #{0} - parameter 1 must be string or key", i + 1)); | 6960 | Error(originFunc, string.Format("Error running rule PSYS_SRC_TEXTURE: arg #{0} - parameter 1 must be string or key", i + 1)); |
6961 | return; | 6961 | return; |
6962 | } | 6962 | } |
6963 | break; | 6963 | break; |
6964 | 6964 | ||
6965 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: | 6965 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: |
6966 | try | 6966 | try |
6967 | { | 6967 | { |
6968 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6968 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6969 | } | 6969 | } |
6970 | catch(InvalidCastException) | 6970 | catch(InvalidCastException) |
6971 | { | 6971 | { |
6972 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RATE: arg #{0} - parameter 1 must be float", i + 1)); | 6972 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RATE: arg #{0} - parameter 1 must be float", i + 1)); |
6973 | return; | 6973 | return; |
6974 | } | 6974 | } |
6975 | prules.BurstRate = (float)tempf; | 6975 | prules.BurstRate = (float)tempf; |
6976 | break; | 6976 | break; |
6977 | 6977 | ||
6978 | case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: | 6978 | case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: |
6979 | try | 6979 | try |
6980 | { | 6980 | { |
6981 | prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); | 6981 | prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); |
6982 | } | 6982 | } |
6983 | catch(InvalidCastException) | 6983 | catch(InvalidCastException) |
6984 | { | 6984 | { |
6985 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_PART_COUNT: arg #{0} - parameter 1 must be integer", i + 1)); | 6985 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_PART_COUNT: arg #{0} - parameter 1 must be integer", i + 1)); |
6986 | return; | 6986 | return; |
6987 | } | 6987 | } |
6988 | break; | 6988 | break; |
6989 | 6989 | ||
6990 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: | 6990 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: |
6991 | try | 6991 | try |
6992 | { | 6992 | { |
6993 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 6993 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
6994 | } | 6994 | } |
6995 | catch(InvalidCastException) | 6995 | catch(InvalidCastException) |
6996 | { | 6996 | { |
6997 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RADIUS: arg #{0} - parameter 1 must be float", i + 1)); | 6997 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_RADIUS: arg #{0} - parameter 1 must be float", i + 1)); |
6998 | return; | 6998 | return; |
6999 | } | 6999 | } |
7000 | prules.BurstRadius = (float)tempf; | 7000 | prules.BurstRadius = (float)tempf; |
7001 | break; | 7001 | break; |
7002 | 7002 | ||
7003 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: | 7003 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: |
7004 | try | 7004 | try |
7005 | { | 7005 | { |
7006 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7006 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
7007 | } | 7007 | } |
7008 | catch(InvalidCastException) | 7008 | catch(InvalidCastException) |
7009 | { | 7009 | { |
7010 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MIN: arg #{0} - parameter 1 must be float", i + 1)); | 7010 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MIN: arg #{0} - parameter 1 must be float", i + 1)); |
7011 | return; | 7011 | return; |
7012 | } | 7012 | } |
7013 | prules.BurstSpeedMin = (float)tempf; | 7013 | prules.BurstSpeedMin = (float)tempf; |
7014 | break; | 7014 | break; |
7015 | 7015 | ||
7016 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: | 7016 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: |
7017 | try | 7017 | try |
7018 | { | 7018 | { |
7019 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7019 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
7020 | } | 7020 | } |
7021 | catch(InvalidCastException) | 7021 | catch(InvalidCastException) |
7022 | { | 7022 | { |
7023 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MAX: arg #{0} - parameter 1 must be float", i + 1)); | 7023 | Error(originFunc, string.Format("Error running rule PSYS_SRC_BURST_SPEED_MAX: arg #{0} - parameter 1 must be float", i + 1)); |
7024 | return; | 7024 | return; |
7025 | } | 7025 | } |
7026 | prules.BurstSpeedMax = (float)tempf; | 7026 | prules.BurstSpeedMax = (float)tempf; |
7027 | break; | 7027 | break; |
7028 | 7028 | ||
7029 | case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: | 7029 | case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: |
7030 | try | 7030 | try |
7031 | { | 7031 | { |
7032 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7032 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
7033 | } | 7033 | } |
7034 | catch(InvalidCastException) | 7034 | catch(InvalidCastException) |
7035 | { | 7035 | { |
7036 | Error(originFunc, string.Format("Error running rule PSYS_SRC_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); | 7036 | Error(originFunc, string.Format("Error running rule PSYS_SRC_MAX_AGE: arg #{0} - parameter 1 must be float", i + 1)); |
7037 | return; | 7037 | return; |
7038 | } | 7038 | } |
7039 | prules.MaxAge = (float)tempf; | 7039 | prules.MaxAge = (float)tempf; |
7040 | break; | 7040 | break; |
7041 | 7041 | ||
7042 | case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY: | 7042 | case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY: |
7043 | UUID key = UUID.Zero; | 7043 | UUID key = UUID.Zero; |
7044 | if (UUID.TryParse(rules.Data[i + 1].ToString(), out key)) | 7044 | if (UUID.TryParse(rules.Data[i + 1].ToString(), out key)) |
7045 | { | 7045 | { |
7046 | prules.Target = key; | 7046 | prules.Target = key; |
7047 | } | 7047 | } |
7048 | else | 7048 | else |
7049 | { | 7049 | { |
7050 | prules.Target = part.UUID; | 7050 | prules.Target = part.UUID; |
7051 | } | 7051 | } |
7052 | break; | 7052 | break; |
7053 | 7053 | ||
7054 | case (int)ScriptBaseClass.PSYS_SRC_OMEGA: | 7054 | case (int)ScriptBaseClass.PSYS_SRC_OMEGA: |
7055 | // AL: This is an assumption, since it is the only thing that would match. | 7055 | // AL: This is an assumption, since it is the only thing that would match. |
7056 | try | 7056 | try |
7057 | { | 7057 | { |
7058 | tempv = rules.GetVector3Item(i + 1); | 7058 | tempv = rules.GetVector3Item(i + 1); |
7059 | } | 7059 | } |
7060 | catch(InvalidCastException) | 7060 | catch(InvalidCastException) |
7061 | { | 7061 | { |
7062 | Error(originFunc, string.Format("Error running rule PSYS_SRC_OMEGA: arg #{0} - parameter 1 must be vector", i + 1)); | 7062 | Error(originFunc, string.Format("Error running rule PSYS_SRC_OMEGA: arg #{0} - parameter 1 must be vector", i + 1)); |
7063 | return; | 7063 | return; |
7064 | } | 7064 | } |
7065 | prules.AngularVelocity.X = (float)tempv.x; | 7065 | prules.AngularVelocity.X = (float)tempv.x; |
7066 | prules.AngularVelocity.Y = (float)tempv.y; | 7066 | prules.AngularVelocity.Y = (float)tempv.y; |
7067 | prules.AngularVelocity.Z = (float)tempv.z; | 7067 | prules.AngularVelocity.Z = (float)tempv.z; |
7068 | break; | 7068 | break; |
7069 | 7069 | ||
7070 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: | 7070 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: |
7071 | try | 7071 | try |
7072 | { | 7072 | { |
7073 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7073 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
7074 | } | 7074 | } |
7075 | catch(InvalidCastException) | 7075 | catch(InvalidCastException) |
7076 | { | 7076 | { |
7077 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_BEGIN: arg #{0} - parameter 1 must be float", i + 1)); | 7077 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_BEGIN: arg #{0} - parameter 1 must be float", i + 1)); |
7078 | return; | 7078 | return; |
7079 | } | 7079 | } |
7080 | prules.InnerAngle = (float)tempf; | 7080 | prules.InnerAngle = (float)tempf; |
7081 | prules.PartFlags |= 0x02; // Set new angle format. | 7081 | prules.PartFlags |= 0x02; // Set new angle format. |
7082 | break; | 7082 | break; |
7083 | 7083 | ||
7084 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: | 7084 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: |
7085 | try | 7085 | try |
7086 | { | 7086 | { |
7087 | tempf = (float)rules.GetLSLFloatItem(i + 1); | 7087 | tempf = (float)rules.GetLSLFloatItem(i + 1); |
7088 | } | 7088 | } |
7089 | catch (InvalidCastException) | 7089 | catch (InvalidCastException) |
7090 | { | 7090 | { |
7091 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_END: arg #{0} - parameter 1 must be float", i + 1)); | 7091 | Error(originFunc, string.Format("Error running rule PSYS_SRC_ANGLE_END: arg #{0} - parameter 1 must be float", i + 1)); |
7092 | return; | 7092 | return; |
7093 | } | 7093 | } |
7094 | prules.OuterAngle = (float)tempf; | 7094 | prules.OuterAngle = (float)tempf; |
7095 | prules.PartFlags |= 0x02; // Set new angle format. | 7095 | prules.PartFlags |= 0x02; // Set new angle format. |
7096 | break; | 7096 | break; |
7097 | } | 7097 | } |
7098 | 7098 | ||
7099 | } | 7099 | } |
7100 | prules.CRC = 1; | 7100 | prules.CRC = 1; |
7101 | 7101 | ||
7102 | part.AddNewParticleSystem(prules); | 7102 | part.AddNewParticleSystem(prules); |
7103 | part.ParentGroup.HasGroupChanged = true; | 7103 | part.ParentGroup.HasGroupChanged = true; |
7104 | } | 7104 | } |
7105 | part.SendFullUpdateToAllClients(); | 7105 | part.SendFullUpdateToAllClients(); |
7106 | } | 7106 | } |
7107 | 7107 | ||
7108 | private float validParticleScale(float value) | 7108 | private float validParticleScale(float value) |
7109 | { | 7109 | { |
7110 | if (value > 4.0f) return 4.0f; | 7110 | if (value > 4.0f) return 4.0f; |
7111 | return value; | 7111 | return value; |
7112 | } | 7112 | } |
7113 | 7113 | ||
7114 | public void llGroundRepel(double height, int water, double tau) | 7114 | public void llGroundRepel(double height, int water, double tau) |
7115 | { | 7115 | { |
7116 | m_host.AddScriptLPS(1); | 7116 | m_host.AddScriptLPS(1); |
7117 | if (m_host.PhysActor != null) | 7117 | if (m_host.PhysActor != null) |
7118 | { | 7118 | { |
7119 | float ground = (float)llGround(new LSL_Types.Vector3(0, 0, 0)); | 7119 | float ground = (float)llGround(new LSL_Types.Vector3(0, 0, 0)); |
7120 | float waterLevel = (float)llWater(new LSL_Types.Vector3(0, 0, 0)); | 7120 | float waterLevel = (float)llWater(new LSL_Types.Vector3(0, 0, 0)); |
7121 | PIDHoverType hoverType = PIDHoverType.Ground; | 7121 | PIDHoverType hoverType = PIDHoverType.Ground; |
7122 | if (water != 0) | 7122 | if (water != 0) |
7123 | { | 7123 | { |
7124 | hoverType = PIDHoverType.GroundAndWater; | 7124 | hoverType = PIDHoverType.GroundAndWater; |
7125 | if (ground < waterLevel) | 7125 | if (ground < waterLevel) |
7126 | height += waterLevel; | 7126 | height += waterLevel; |
7127 | else | 7127 | else |
7128 | height += ground; | 7128 | height += ground; |
7129 | } | 7129 | } |
7130 | else | 7130 | else |
7131 | { | 7131 | { |
7132 | height += ground; | 7132 | height += ground; |
7133 | } | 7133 | } |
7134 | 7134 | ||
7135 | m_host.SetHoverHeight((float)height, hoverType, (float)tau); | 7135 | m_host.SetHoverHeight((float)height, hoverType, (float)tau); |
7136 | } | 7136 | } |
7137 | } | 7137 | } |
7138 | 7138 | ||
7139 | public void llGiveInventoryList(string destination, string category, LSL_List inventory) | 7139 | public void llGiveInventoryList(string destination, string category, LSL_List inventory) |
7140 | { | 7140 | { |
7141 | m_host.AddScriptLPS(1); | 7141 | m_host.AddScriptLPS(1); |
7142 | 7142 | ||
7143 | UUID destID; | 7143 | UUID destID; |
7144 | if (!UUID.TryParse(destination, out destID)) | 7144 | if (!UUID.TryParse(destination, out destID)) |
7145 | return; | 7145 | return; |
7146 | 7146 | ||
7147 | List<UUID> itemList = new List<UUID>(); | 7147 | List<UUID> itemList = new List<UUID>(); |
7148 | 7148 | ||
7149 | foreach (Object item in inventory.Data) | 7149 | foreach (Object item in inventory.Data) |
7150 | { | 7150 | { |
7151 | string rawItemString = item.ToString(); | 7151 | string rawItemString = item.ToString(); |
7152 | 7152 | ||
7153 | UUID itemID; | 7153 | UUID itemID; |
7154 | if (UUID.TryParse(rawItemString, out itemID)) | 7154 | if (UUID.TryParse(rawItemString, out itemID)) |
7155 | { | 7155 | { |
7156 | itemList.Add(itemID); | 7156 | itemList.Add(itemID); |
7157 | } | 7157 | } |
7158 | else | 7158 | else |
7159 | { | 7159 | { |
7160 | TaskInventoryItem taskItem = m_host.Inventory.GetInventoryItem(rawItemString); | 7160 | TaskInventoryItem taskItem = m_host.Inventory.GetInventoryItem(rawItemString); |
7161 | 7161 | ||
7162 | if (taskItem != null) | 7162 | if (taskItem != null) |
7163 | itemList.Add(taskItem.ItemID); | 7163 | itemList.Add(taskItem.ItemID); |
7164 | } | 7164 | } |
7165 | } | 7165 | } |
7166 | 7166 | ||
7167 | if (itemList.Count == 0) | 7167 | if (itemList.Count == 0) |
7168 | return; | 7168 | return; |
7169 | 7169 | ||
7170 | UUID folderID = m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList); | 7170 | UUID folderID = m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList); |
7171 | 7171 | ||
7172 | if (folderID == UUID.Zero) | 7172 | if (folderID == UUID.Zero) |
7173 | return; | 7173 | return; |
7174 | 7174 | ||
7175 | if (m_TransferModule != null) | 7175 | if (m_TransferModule != null) |
7176 | { | 7176 | { |
7177 | byte[] bucket = new byte[] { (byte)AssetType.Folder }; | 7177 | byte[] bucket = new byte[] { (byte)AssetType.Folder }; |
7178 | 7178 | ||
7179 | Vector3 pos = m_host.AbsolutePosition; | 7179 | Vector3 pos = m_host.AbsolutePosition; |
7180 | 7180 | ||
7181 | GridInstantMessage msg = new GridInstantMessage(World, | 7181 | GridInstantMessage msg = new GridInstantMessage(World, |
7182 | m_host.OwnerID, m_host.Name, destID, | 7182 | m_host.OwnerID, m_host.Name, destID, |
7183 | (byte)InstantMessageDialog.TaskInventoryOffered, | 7183 | (byte)InstantMessageDialog.TaskInventoryOffered, |
7184 | false, string.Format("'{0}'", category), | 7184 | false, string.Format("'{0}'", category), |
7185 | // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 | 7185 | // We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 |
7186 | // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), | 7186 | // false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), |
7187 | folderID, false, pos, | 7187 | folderID, false, pos, |
7188 | bucket, false); | 7188 | bucket, false); |
7189 | 7189 | ||
7190 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); | 7190 | m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); |
7191 | } | 7191 | } |
7192 | } | 7192 | } |
7193 | 7193 | ||
7194 | public void llSetVehicleType(int type) | 7194 | public void llSetVehicleType(int type) |
7195 | { | 7195 | { |
7196 | m_host.AddScriptLPS(1); | 7196 | m_host.AddScriptLPS(1); |
7197 | 7197 | ||
7198 | if (!m_host.ParentGroup.IsDeleted) | 7198 | if (!m_host.ParentGroup.IsDeleted) |
7199 | { | 7199 | { |
7200 | m_host.ParentGroup.RootPart.SetVehicleType(type); | 7200 | m_host.ParentGroup.RootPart.SetVehicleType(type); |
7201 | } | 7201 | } |
7202 | } | 7202 | } |
7203 | 7203 | ||
7204 | //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in | 7204 | //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in |
7205 | //CFK 9/28: so these are not complete yet. | 7205 | //CFK 9/28: so these are not complete yet. |
7206 | public void llSetVehicleFloatParam(int param, LSL_Float value) | 7206 | public void llSetVehicleFloatParam(int param, LSL_Float value) |
7207 | { | 7207 | { |
7208 | m_host.AddScriptLPS(1); | 7208 | m_host.AddScriptLPS(1); |
7209 | 7209 | ||
7210 | if (!m_host.ParentGroup.IsDeleted) | 7210 | if (!m_host.ParentGroup.IsDeleted) |
7211 | { | 7211 | { |
7212 | m_host.ParentGroup.RootPart.SetVehicleFloatParam(param, (float)value); | 7212 | m_host.ParentGroup.RootPart.SetVehicleFloatParam(param, (float)value); |
7213 | } | 7213 | } |
7214 | } | 7214 | } |
7215 | 7215 | ||
7216 | //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in | 7216 | //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in |
7217 | //CFK 9/28: so these are not complete yet. | 7217 | //CFK 9/28: so these are not complete yet. |
7218 | public void llSetVehicleVectorParam(int param, LSL_Vector vec) | 7218 | public void llSetVehicleVectorParam(int param, LSL_Vector vec) |
7219 | { | 7219 | { |
7220 | m_host.AddScriptLPS(1); | 7220 | m_host.AddScriptLPS(1); |
7221 | 7221 | ||
7222 | if (!m_host.ParentGroup.IsDeleted) | 7222 | if (!m_host.ParentGroup.IsDeleted) |
7223 | { | 7223 | { |
7224 | m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); | 7224 | m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); |
7225 | } | 7225 | } |
7226 | } | 7226 | } |
7227 | 7227 | ||
7228 | //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in | 7228 | //CFK 9/28: Most, but not all of the underlying plumbing between here and the physics modules is in |
7229 | //CFK 9/28: so these are not complete yet. | 7229 | //CFK 9/28: so these are not complete yet. |
7230 | public void llSetVehicleRotationParam(int param, LSL_Rotation rot) | 7230 | public void llSetVehicleRotationParam(int param, LSL_Rotation rot) |
7231 | { | 7231 | { |
7232 | m_host.AddScriptLPS(1); | 7232 | m_host.AddScriptLPS(1); |
7233 | 7233 | ||
7234 | if (!m_host.ParentGroup.IsDeleted) | 7234 | if (!m_host.ParentGroup.IsDeleted) |
7235 | { | 7235 | { |
7236 | m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); | 7236 | m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); |
7237 | } | 7237 | } |
7238 | } | 7238 | } |
7239 | 7239 | ||
7240 | public void llSetVehicleFlags(int flags) | 7240 | public void llSetVehicleFlags(int flags) |
7241 | { | 7241 | { |
7242 | m_host.AddScriptLPS(1); | 7242 | m_host.AddScriptLPS(1); |
7243 | 7243 | ||
7244 | if (!m_host.ParentGroup.IsDeleted) | 7244 | if (!m_host.ParentGroup.IsDeleted) |
7245 | { | 7245 | { |
7246 | m_host.ParentGroup.RootPart.SetVehicleFlags(flags, false); | 7246 | m_host.ParentGroup.RootPart.SetVehicleFlags(flags, false); |
7247 | } | 7247 | } |
7248 | } | 7248 | } |
7249 | 7249 | ||
7250 | public void llRemoveVehicleFlags(int flags) | 7250 | public void llRemoveVehicleFlags(int flags) |
7251 | { | 7251 | { |
7252 | m_host.AddScriptLPS(1); | 7252 | m_host.AddScriptLPS(1); |
7253 | 7253 | ||
7254 | if (!m_host.ParentGroup.IsDeleted) | 7254 | if (!m_host.ParentGroup.IsDeleted) |
7255 | { | 7255 | { |
7256 | m_host.ParentGroup.RootPart.SetVehicleFlags(flags, true); | 7256 | m_host.ParentGroup.RootPart.SetVehicleFlags(flags, true); |
7257 | } | 7257 | } |
7258 | } | 7258 | } |
7259 | 7259 | ||
7260 | protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) | 7260 | protected void SitTarget(SceneObjectPart part, LSL_Vector offset, LSL_Rotation rot) |
7261 | { | 7261 | { |
7262 | part.SitTargetPosition = offset; | 7262 | part.SitTargetPosition = offset; |
7263 | part.SitTargetOrientation = rot; | 7263 | part.SitTargetOrientation = rot; |
7264 | part.ParentGroup.HasGroupChanged = true; | 7264 | part.ParentGroup.HasGroupChanged = true; |
7265 | } | 7265 | } |
7266 | 7266 | ||
7267 | public void llSitTarget(LSL_Vector offset, LSL_Rotation rot) | 7267 | public void llSitTarget(LSL_Vector offset, LSL_Rotation rot) |
7268 | { | 7268 | { |
7269 | m_host.AddScriptLPS(1); | 7269 | m_host.AddScriptLPS(1); |
7270 | SitTarget(m_host, offset, rot); | 7270 | SitTarget(m_host, offset, rot); |
7271 | } | 7271 | } |
7272 | 7272 | ||
7273 | public void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot) | 7273 | public void llLinkSitTarget(LSL_Integer link, LSL_Vector offset, LSL_Rotation rot) |
7274 | { | 7274 | { |
7275 | m_host.AddScriptLPS(1); | 7275 | m_host.AddScriptLPS(1); |
7276 | if (link == ScriptBaseClass.LINK_ROOT) | 7276 | if (link == ScriptBaseClass.LINK_ROOT) |
7277 | SitTarget(m_host.ParentGroup.RootPart, offset, rot); | 7277 | SitTarget(m_host.ParentGroup.RootPart, offset, rot); |
7278 | else if (link == ScriptBaseClass.LINK_THIS) | 7278 | else if (link == ScriptBaseClass.LINK_THIS) |
7279 | SitTarget(m_host, offset, rot); | 7279 | SitTarget(m_host, offset, rot); |
7280 | else | 7280 | else |
7281 | { | 7281 | { |
7282 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); | 7282 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); |
7283 | if (null != part) | 7283 | if (null != part) |
7284 | { | 7284 | { |
7285 | SitTarget(part, offset, rot); | 7285 | SitTarget(part, offset, rot); |
7286 | } | 7286 | } |
7287 | } | 7287 | } |
7288 | } | 7288 | } |
7289 | 7289 | ||
7290 | public LSL_String llAvatarOnSitTarget() | 7290 | public LSL_String llAvatarOnSitTarget() |
7291 | { | 7291 | { |
7292 | m_host.AddScriptLPS(1); | 7292 | m_host.AddScriptLPS(1); |
7293 | return m_host.SitTargetAvatar.ToString(); | 7293 | return m_host.SitTargetAvatar.ToString(); |
7294 | } | 7294 | } |
7295 | 7295 | ||
7296 | // http://wiki.secondlife.com/wiki/LlAvatarOnLinkSitTarget | 7296 | // http://wiki.secondlife.com/wiki/LlAvatarOnLinkSitTarget |
7297 | public LSL_String llAvatarOnLinkSitTarget(int linknum) | 7297 | public LSL_String llAvatarOnLinkSitTarget(int linknum) |
7298 | { | 7298 | { |
7299 | m_host.AddScriptLPS(1); | 7299 | m_host.AddScriptLPS(1); |
7300 | if(linknum == ScriptBaseClass.LINK_SET || | 7300 | if(linknum == ScriptBaseClass.LINK_SET || |
7301 | linknum == ScriptBaseClass.LINK_ALL_CHILDREN || | 7301 | linknum == ScriptBaseClass.LINK_ALL_CHILDREN || |
7302 | linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); | 7302 | linknum == ScriptBaseClass.LINK_ALL_OTHERS) return UUID.Zero.ToString(); |
7303 | 7303 | ||
7304 | List<SceneObjectPart> parts = GetLinkParts(linknum); | 7304 | List<SceneObjectPart> parts = GetLinkParts(linknum); |
7305 | if (parts.Count == 0) return UUID.Zero.ToString(); | 7305 | if (parts.Count == 0) return UUID.Zero.ToString(); |
7306 | return parts[0].SitTargetAvatar.ToString(); | 7306 | return parts[0].SitTargetAvatar.ToString(); |
7307 | } | 7307 | } |
7308 | 7308 | ||
7309 | 7309 | ||
7310 | public void llAddToLandPassList(string avatar, double hours) | 7310 | public void llAddToLandPassList(string avatar, double hours) |
7311 | { | 7311 | { |
7312 | m_host.AddScriptLPS(1); | 7312 | m_host.AddScriptLPS(1); |
7313 | UUID key; | 7313 | UUID key; |
7314 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); | 7314 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
7315 | 7315 | ||
7316 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 7316 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
7317 | { | 7317 | { |
7318 | int expires = 0; | 7318 | int expires = 0; |
7319 | if (hours != 0) | 7319 | if (hours != 0) |
7320 | expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours); | 7320 | expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours); |
7321 | 7321 | ||
7322 | if (UUID.TryParse(avatar, out key)) | 7322 | if (UUID.TryParse(avatar, out key)) |
7323 | { | 7323 | { |
7324 | int idx = land.LandData.ParcelAccessList.FindIndex( | 7324 | int idx = land.LandData.ParcelAccessList.FindIndex( |
7325 | delegate(LandAccessEntry e) | 7325 | delegate(LandAccessEntry e) |
7326 | { | 7326 | { |
7327 | if (e.AgentID == key && e.Flags == AccessList.Access) | 7327 | if (e.AgentID == key && e.Flags == AccessList.Access) |
7328 | return true; | 7328 | return true; |
7329 | return false; | 7329 | return false; |
7330 | }); | 7330 | }); |
7331 | 7331 | ||
7332 | if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires))) | 7332 | if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires))) |
7333 | return; | 7333 | return; |
7334 | 7334 | ||
7335 | if (idx != -1) | 7335 | if (idx != -1) |
7336 | land.LandData.ParcelAccessList.RemoveAt(idx); | 7336 | land.LandData.ParcelAccessList.RemoveAt(idx); |
7337 | 7337 | ||
7338 | LandAccessEntry entry = new LandAccessEntry(); | 7338 | LandAccessEntry entry = new LandAccessEntry(); |
7339 | 7339 | ||
7340 | entry.AgentID = key; | 7340 | entry.AgentID = key; |
7341 | entry.Flags = AccessList.Access; | 7341 | entry.Flags = AccessList.Access; |
7342 | entry.Expires = expires; | 7342 | entry.Expires = expires; |
7343 | 7343 | ||
7344 | land.LandData.ParcelAccessList.Add(entry); | 7344 | land.LandData.ParcelAccessList.Add(entry); |
7345 | 7345 | ||
7346 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | 7346 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); |
7347 | } | 7347 | } |
7348 | } | 7348 | } |
7349 | ScriptSleep(m_sleepMsOnAddToLandPassList); | 7349 | ScriptSleep(m_sleepMsOnAddToLandPassList); |
7350 | } | 7350 | } |
7351 | 7351 | ||
7352 | public void llSetTouchText(string text) | 7352 | public void llSetTouchText(string text) |
7353 | { | 7353 | { |
7354 | m_host.AddScriptLPS(1); | 7354 | m_host.AddScriptLPS(1); |
7355 | m_host.TouchName = text; | 7355 | m_host.TouchName = text; |
7356 | } | 7356 | } |
7357 | 7357 | ||
7358 | public void llSetSitText(string text) | 7358 | public void llSetSitText(string text) |
7359 | { | 7359 | { |
7360 | m_host.AddScriptLPS(1); | 7360 | m_host.AddScriptLPS(1); |
7361 | m_host.SitName = text; | 7361 | m_host.SitName = text; |
7362 | } | 7362 | } |
7363 | 7363 | ||
7364 | public void llSetCameraEyeOffset(LSL_Vector offset) | 7364 | public void llSetCameraEyeOffset(LSL_Vector offset) |
7365 | { | 7365 | { |
7366 | m_host.AddScriptLPS(1); | 7366 | m_host.AddScriptLPS(1); |
7367 | m_host.SetCameraEyeOffset(offset); | 7367 | m_host.SetCameraEyeOffset(offset); |
7368 | 7368 | ||
7369 | if (m_host.ParentGroup.RootPart.GetCameraEyeOffset() == Vector3.Zero) | 7369 | if (m_host.ParentGroup.RootPart.GetCameraEyeOffset() == Vector3.Zero) |
7370 | m_host.ParentGroup.RootPart.SetCameraEyeOffset(offset); | 7370 | m_host.ParentGroup.RootPart.SetCameraEyeOffset(offset); |
7371 | } | 7371 | } |
7372 | 7372 | ||
7373 | public void llSetCameraAtOffset(LSL_Vector offset) | 7373 | public void llSetCameraAtOffset(LSL_Vector offset) |
7374 | { | 7374 | { |
7375 | m_host.AddScriptLPS(1); | 7375 | m_host.AddScriptLPS(1); |
7376 | m_host.SetCameraAtOffset(offset); | 7376 | m_host.SetCameraAtOffset(offset); |
7377 | 7377 | ||
7378 | if (m_host.ParentGroup.RootPart.GetCameraAtOffset() == Vector3.Zero) | 7378 | if (m_host.ParentGroup.RootPart.GetCameraAtOffset() == Vector3.Zero) |
7379 | m_host.ParentGroup.RootPart.SetCameraAtOffset(offset); | 7379 | m_host.ParentGroup.RootPart.SetCameraAtOffset(offset); |
7380 | } | 7380 | } |
7381 | 7381 | ||
7382 | public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at) | 7382 | public void llSetLinkCamera(LSL_Integer link, LSL_Vector eye, LSL_Vector at) |
7383 | { | 7383 | { |
7384 | m_host.AddScriptLPS(1); | 7384 | m_host.AddScriptLPS(1); |
7385 | 7385 | ||
7386 | if (link == ScriptBaseClass.LINK_SET || | 7386 | if (link == ScriptBaseClass.LINK_SET || |
7387 | link == ScriptBaseClass.LINK_ALL_CHILDREN || | 7387 | link == ScriptBaseClass.LINK_ALL_CHILDREN || |
7388 | link == ScriptBaseClass.LINK_ALL_OTHERS) return; | 7388 | link == ScriptBaseClass.LINK_ALL_OTHERS) return; |
7389 | 7389 | ||
7390 | SceneObjectPart part = null; | 7390 | SceneObjectPart part = null; |
7391 | 7391 | ||
7392 | switch (link) | 7392 | switch (link) |
7393 | { | 7393 | { |
7394 | case ScriptBaseClass.LINK_ROOT: | 7394 | case ScriptBaseClass.LINK_ROOT: |
7395 | part = m_host.ParentGroup.RootPart; | 7395 | part = m_host.ParentGroup.RootPart; |
7396 | break; | 7396 | break; |
7397 | case ScriptBaseClass.LINK_THIS: | 7397 | case ScriptBaseClass.LINK_THIS: |
7398 | part = m_host; | 7398 | part = m_host; |
7399 | break; | 7399 | break; |
7400 | default: | 7400 | default: |
7401 | part = m_host.ParentGroup.GetLinkNumPart(link); | 7401 | part = m_host.ParentGroup.GetLinkNumPart(link); |
7402 | break; | 7402 | break; |
7403 | } | 7403 | } |
7404 | 7404 | ||
7405 | if (null != part) | 7405 | if (null != part) |
7406 | { | 7406 | { |
7407 | part.SetCameraEyeOffset(eye); | 7407 | part.SetCameraEyeOffset(eye); |
7408 | part.SetCameraAtOffset(at); | 7408 | part.SetCameraAtOffset(at); |
7409 | } | 7409 | } |
7410 | } | 7410 | } |
7411 | 7411 | ||
7412 | public LSL_String llDumpList2String(LSL_List src, string seperator) | 7412 | public LSL_String llDumpList2String(LSL_List src, string seperator) |
7413 | { | 7413 | { |
7414 | m_host.AddScriptLPS(1); | 7414 | m_host.AddScriptLPS(1); |
7415 | if (src.Length == 0) | 7415 | if (src.Length == 0) |
7416 | { | 7416 | { |
7417 | return String.Empty; | 7417 | return String.Empty; |
7418 | } | 7418 | } |
7419 | string ret = String.Empty; | 7419 | string ret = String.Empty; |
7420 | foreach (object o in src.Data) | 7420 | foreach (object o in src.Data) |
7421 | { | 7421 | { |
7422 | ret = ret + o.ToString() + seperator; | 7422 | ret = ret + o.ToString() + seperator; |
7423 | } | 7423 | } |
7424 | ret = ret.Substring(0, ret.Length - seperator.Length); | 7424 | ret = ret.Substring(0, ret.Length - seperator.Length); |
7425 | return ret; | 7425 | return ret; |
7426 | } | 7426 | } |
7427 | 7427 | ||
7428 | public LSL_Integer llScriptDanger(LSL_Vector pos) | 7428 | public LSL_Integer llScriptDanger(LSL_Vector pos) |
7429 | { | 7429 | { |
7430 | m_host.AddScriptLPS(1); | 7430 | m_host.AddScriptLPS(1); |
7431 | bool result = World.ScriptDanger(m_host.LocalId, pos); | 7431 | bool result = World.ScriptDanger(m_host.LocalId, pos); |
7432 | if (result) | 7432 | if (result) |
7433 | { | 7433 | { |
7434 | return 1; | 7434 | return 1; |
7435 | } | 7435 | } |
7436 | else | 7436 | else |
7437 | { | 7437 | { |
7438 | return 0; | 7438 | return 0; |
7439 | } | 7439 | } |
7440 | 7440 | ||
7441 | } | 7441 | } |
7442 | 7442 | ||
7443 | public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel) | 7443 | public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel) |
7444 | { | 7444 | { |
7445 | IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); | 7445 | IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); |
7446 | 7446 | ||
7447 | if (dm == null) | 7447 | if (dm == null) |
7448 | return; | 7448 | return; |
7449 | 7449 | ||
7450 | m_host.AddScriptLPS(1); | 7450 | m_host.AddScriptLPS(1); |
7451 | UUID av = new UUID(); | 7451 | UUID av = new UUID(); |
7452 | if (!UUID.TryParse(avatar,out av)) | 7452 | if (!UUID.TryParse(avatar,out av)) |
7453 | { | 7453 | { |
7454 | Error("llDialog", "First parameter must be a key"); | 7454 | Error("llDialog", "First parameter must be a key"); |
7455 | return; | 7455 | return; |
7456 | } | 7456 | } |
7457 | if (buttons.Length < 1) | 7457 | if (buttons.Length < 1) |
7458 | { | 7458 | { |
7459 | Error("llDialog", "At least 1 button must be shown"); | 7459 | Error("llDialog", "At least 1 button must be shown"); |
7460 | return; | 7460 | return; |
7461 | } | 7461 | } |
7462 | if (buttons.Length > 12) | 7462 | if (buttons.Length > 12) |
7463 | { | 7463 | { |
7464 | Error("llDialog", "No more than 12 buttons can be shown"); | 7464 | Error("llDialog", "No more than 12 buttons can be shown"); |
7465 | return; | 7465 | return; |
7466 | } | 7466 | } |
7467 | string[] buts = new string[buttons.Length]; | 7467 | string[] buts = new string[buttons.Length]; |
7468 | for (int i = 0; i < buttons.Length; i++) | 7468 | for (int i = 0; i < buttons.Length; i++) |
7469 | { | 7469 | { |
7470 | if (buttons.Data[i].ToString() == String.Empty) | 7470 | if (buttons.Data[i].ToString() == String.Empty) |
7471 | { | 7471 | { |
7472 | Error("llDialog", "Button label cannot be blank"); | 7472 | Error("llDialog", "Button label cannot be blank"); |
7473 | return; | 7473 | return; |
7474 | } | 7474 | } |
7475 | if (buttons.Data[i].ToString().Length > 24) | 7475 | if (buttons.Data[i].ToString().Length > 24) |
7476 | { | 7476 | { |
7477 | Error("llDialog", "Button label cannot be longer than 24 characters"); | 7477 | Error("llDialog", "Button label cannot be longer than 24 characters"); |
7478 | return; | 7478 | return; |
7479 | } | 7479 | } |
7480 | buts[i] = buttons.Data[i].ToString(); | 7480 | buts[i] = buttons.Data[i].ToString(); |
7481 | } | 7481 | } |
7482 | 7482 | ||
7483 | dm.SendDialogToUser( | 7483 | dm.SendDialogToUser( |
7484 | av, m_host.Name, m_host.UUID, m_host.OwnerID, | 7484 | av, m_host.Name, m_host.UUID, m_host.OwnerID, |
7485 | message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); | 7485 | message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); |
7486 | 7486 | ||
7487 | ScriptSleep(m_sleepMsOnDialog); | 7487 | ScriptSleep(m_sleepMsOnDialog); |
7488 | } | 7488 | } |
7489 | 7489 | ||
7490 | public void llVolumeDetect(int detect) | 7490 | public void llVolumeDetect(int detect) |
7491 | { | 7491 | { |
7492 | m_host.AddScriptLPS(1); | 7492 | m_host.AddScriptLPS(1); |
7493 | 7493 | ||
7494 | if (!m_host.ParentGroup.IsDeleted) | 7494 | if (!m_host.ParentGroup.IsDeleted) |
7495 | m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0); | 7495 | m_host.ParentGroup.ScriptSetVolumeDetect(detect != 0); |
7496 | } | 7496 | } |
7497 | 7497 | ||
7498 | public void llRemoteLoadScript(string target, string name, int running, int start_param) | 7498 | public void llRemoteLoadScript(string target, string name, int running, int start_param) |
7499 | { | 7499 | { |
7500 | m_host.AddScriptLPS(1); | 7500 | m_host.AddScriptLPS(1); |
7501 | Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead"); | 7501 | Deprecated("llRemoteLoadScript", "Use llRemoteLoadScriptPin instead"); |
7502 | ScriptSleep(m_sleepMsOnRemoteLoadScript); | 7502 | ScriptSleep(m_sleepMsOnRemoteLoadScript); |
7503 | } | 7503 | } |
7504 | 7504 | ||
7505 | public void llSetRemoteScriptAccessPin(int pin) | 7505 | public void llSetRemoteScriptAccessPin(int pin) |
7506 | { | 7506 | { |
7507 | m_host.AddScriptLPS(1); | 7507 | m_host.AddScriptLPS(1); |
7508 | m_host.ScriptAccessPin = pin; | 7508 | m_host.ScriptAccessPin = pin; |
7509 | } | 7509 | } |
7510 | 7510 | ||
7511 | public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) | 7511 | public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) |
7512 | { | 7512 | { |
7513 | m_host.AddScriptLPS(1); | 7513 | m_host.AddScriptLPS(1); |
7514 | 7514 | ||
7515 | UUID destId = UUID.Zero; | 7515 | UUID destId = UUID.Zero; |
7516 | 7516 | ||
7517 | if (!UUID.TryParse(target, out destId)) | 7517 | if (!UUID.TryParse(target, out destId)) |
7518 | { | 7518 | { |
7519 | Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'"); | 7519 | Error("llRemoteLoadScriptPin", "Can't parse key '" + target + "'"); |
7520 | return; | 7520 | return; |
7521 | } | 7521 | } |
7522 | 7522 | ||
7523 | // target must be a different prim than the one containing the script | 7523 | // target must be a different prim than the one containing the script |
7524 | if (m_host.UUID == destId) | 7524 | if (m_host.UUID == destId) |
7525 | { | 7525 | { |
7526 | return; | 7526 | return; |
7527 | } | 7527 | } |
7528 | 7528 | ||
7529 | // copy the first script found with this inventory name | 7529 | // copy the first script found with this inventory name |
7530 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 7530 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); |
7531 | 7531 | ||
7532 | // make sure the object is a script | 7532 | // make sure the object is a script |
7533 | if (item == null || item.Type != 10) | 7533 | if (item == null || item.Type != 10) |
7534 | { | 7534 | { |
7535 | Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'"); | 7535 | Error("llRemoteLoadScriptPin", "Can't find script '" + name + "'"); |
7536 | return; | 7536 | return; |
7537 | } | 7537 | } |
7538 | 7538 | ||
7539 | // the rest of the permission checks are done in RezScript, so check the pin there as well | 7539 | // the rest of the permission checks are done in RezScript, so check the pin there as well |
7540 | World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); | 7540 | World.RezScriptFromPrim(item.ItemID, m_host, destId, pin, running, start_param); |
7541 | 7541 | ||
7542 | // this will cause the delay even if the script pin or permissions were wrong - seems ok | 7542 | // this will cause the delay even if the script pin or permissions were wrong - seems ok |
7543 | ScriptSleep(m_sleepMsOnRemoteLoadScriptPin); | 7543 | ScriptSleep(m_sleepMsOnRemoteLoadScriptPin); |
7544 | } | 7544 | } |
7545 | 7545 | ||
7546 | public void llOpenRemoteDataChannel() | 7546 | public void llOpenRemoteDataChannel() |
7547 | { | 7547 | { |
7548 | m_host.AddScriptLPS(1); | 7548 | m_host.AddScriptLPS(1); |
7549 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7549 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
7550 | if (xmlrpcMod != null && xmlrpcMod.IsEnabled()) | 7550 | if (xmlrpcMod != null && xmlrpcMod.IsEnabled()) |
7551 | { | 7551 | { |
7552 | UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); | 7552 | UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_host.LocalId, m_item.ItemID, UUID.Zero); |
7553 | IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); | 7553 | IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); |
7554 | if (xmlRpcRouter != null) | 7554 | if (xmlRpcRouter != null) |
7555 | { | 7555 | { |
7556 | string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName; | 7556 | string ExternalHostName = m_ScriptEngine.World.RegionInfo.ExternalHostName; |
7557 | 7557 | ||
7558 | xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID, | 7558 | xmlRpcRouter.RegisterNewReceiver(m_ScriptEngine.ScriptModule, channelID, m_host.UUID, |
7559 | m_item.ItemID, String.Format("http://{0}:{1}/", ExternalHostName, | 7559 | m_item.ItemID, String.Format("http://{0}:{1}/", ExternalHostName, |
7560 | xmlrpcMod.Port.ToString())); | 7560 | xmlrpcMod.Port.ToString())); |
7561 | } | 7561 | } |
7562 | object[] resobj = new object[] | 7562 | object[] resobj = new object[] |
7563 | { | 7563 | { |
7564 | new LSL_Integer(1), | 7564 | new LSL_Integer(1), |
7565 | new LSL_String(channelID.ToString()), | 7565 | new LSL_String(channelID.ToString()), |
7566 | new LSL_String(UUID.Zero.ToString()), | 7566 | new LSL_String(UUID.Zero.ToString()), |
7567 | new LSL_String(String.Empty), | 7567 | new LSL_String(String.Empty), |
7568 | new LSL_Integer(0), | 7568 | new LSL_Integer(0), |
7569 | new LSL_String(String.Empty) | 7569 | new LSL_String(String.Empty) |
7570 | }; | 7570 | }; |
7571 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj, | 7571 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams("remote_data", resobj, |
7572 | new DetectParams[0])); | 7572 | new DetectParams[0])); |
7573 | } | 7573 | } |
7574 | ScriptSleep(m_sleepMsOnOpenRemoteDataChannel); | 7574 | ScriptSleep(m_sleepMsOnOpenRemoteDataChannel); |
7575 | } | 7575 | } |
7576 | 7576 | ||
7577 | public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) | 7577 | public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) |
7578 | { | 7578 | { |
7579 | m_host.AddScriptLPS(1); | 7579 | m_host.AddScriptLPS(1); |
7580 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7580 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
7581 | ScriptSleep(m_sleepMsOnSendRemoteData); | 7581 | ScriptSleep(m_sleepMsOnSendRemoteData); |
7582 | if (xmlrpcMod == null) | 7582 | if (xmlrpcMod == null) |
7583 | return ""; | 7583 | return ""; |
7584 | return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); | 7584 | return (xmlrpcMod.SendRemoteData(m_host.LocalId, m_item.ItemID, channel, dest, idata, sdata)).ToString(); |
7585 | } | 7585 | } |
7586 | 7586 | ||
7587 | public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) | 7587 | public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) |
7588 | { | 7588 | { |
7589 | m_host.AddScriptLPS(1); | 7589 | m_host.AddScriptLPS(1); |
7590 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7590 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
7591 | if (xmlrpcMod != null) | 7591 | if (xmlrpcMod != null) |
7592 | xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); | 7592 | xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); |
7593 | ScriptSleep(m_sleepMsOnRemoteDataReply); | 7593 | ScriptSleep(m_sleepMsOnRemoteDataReply); |
7594 | } | 7594 | } |
7595 | 7595 | ||
7596 | public void llCloseRemoteDataChannel(string channel) | 7596 | public void llCloseRemoteDataChannel(string channel) |
7597 | { | 7597 | { |
7598 | m_host.AddScriptLPS(1); | 7598 | m_host.AddScriptLPS(1); |
7599 | 7599 | ||
7600 | IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); | 7600 | IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>(); |
7601 | if (xmlRpcRouter != null) | 7601 | if (xmlRpcRouter != null) |
7602 | { | 7602 | { |
7603 | xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID); | 7603 | xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID); |
7604 | } | 7604 | } |
7605 | 7605 | ||
7606 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | 7606 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); |
7607 | if (xmlrpcMod != null) | 7607 | if (xmlrpcMod != null) |
7608 | xmlrpcMod.CloseXMLRPCChannel((UUID)channel); | 7608 | xmlrpcMod.CloseXMLRPCChannel((UUID)channel); |
7609 | ScriptSleep(m_sleepMsOnCloseRemoteDataChannel); | 7609 | ScriptSleep(m_sleepMsOnCloseRemoteDataChannel); |
7610 | } | 7610 | } |
7611 | 7611 | ||
7612 | public LSL_String llMD5String(string src, int nonce) | 7612 | public LSL_String llMD5String(string src, int nonce) |
7613 | { | 7613 | { |
7614 | m_host.AddScriptLPS(1); | 7614 | m_host.AddScriptLPS(1); |
7615 | return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); | 7615 | return Util.Md5Hash(String.Format("{0}:{1}", src, nonce.ToString())); |
7616 | } | 7616 | } |
7617 | 7617 | ||
7618 | public LSL_String llSHA1String(string src) | 7618 | public LSL_String llSHA1String(string src) |
7619 | { | 7619 | { |
7620 | m_host.AddScriptLPS(1); | 7620 | m_host.AddScriptLPS(1); |
7621 | return Util.SHA1Hash(src).ToLower(); | 7621 | return Util.SHA1Hash(src).ToLower(); |
7622 | } | 7622 | } |
7623 | 7623 | ||
7624 | protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) | 7624 | protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) |
7625 | { | 7625 | { |
7626 | float tempFloat; // Use in float expressions below to avoid byte cast precision issues. | 7626 | float tempFloat; // Use in float expressions below to avoid byte cast precision issues. |
7627 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); | 7627 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); |
7628 | 7628 | ||
7629 | if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && | 7629 | if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && |
7630 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && | 7630 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && |
7631 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE && | 7631 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE && |
7632 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE) | 7632 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE) |
7633 | { | 7633 | { |
7634 | holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT; | 7634 | holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT; |
7635 | } | 7635 | } |
7636 | shapeBlock.PathCurve = pathcurve; | 7636 | shapeBlock.PathCurve = pathcurve; |
7637 | shapeBlock.ProfileCurve = (byte)holeshape; // Set the hole shape. | 7637 | shapeBlock.ProfileCurve = (byte)holeshape; // Set the hole shape. |
7638 | shapeBlock.ProfileCurve += profileshape; // Add in the profile shape. | 7638 | shapeBlock.ProfileCurve += profileshape; // Add in the profile shape. |
7639 | if (cut.x < 0f) | 7639 | if (cut.x < 0f) |
7640 | { | 7640 | { |
7641 | cut.x = 0f; | 7641 | cut.x = 0f; |
7642 | } | 7642 | } |
7643 | if (cut.x > 1f) | 7643 | if (cut.x > 1f) |
7644 | { | 7644 | { |
7645 | cut.x = 1f; | 7645 | cut.x = 1f; |
7646 | } | 7646 | } |
7647 | if (cut.y < 0f) | 7647 | if (cut.y < 0f) |
7648 | { | 7648 | { |
7649 | cut.y = 0f; | 7649 | cut.y = 0f; |
7650 | } | 7650 | } |
7651 | if (cut.y > 1f) | 7651 | if (cut.y > 1f) |
7652 | { | 7652 | { |
7653 | cut.y = 1f; | 7653 | cut.y = 1f; |
7654 | } | 7654 | } |
7655 | if (cut.y - cut.x < 0.02f) | 7655 | if (cut.y - cut.x < 0.02f) |
7656 | { | 7656 | { |
7657 | cut.x = cut.y - 0.02f; | 7657 | cut.x = cut.y - 0.02f; |
7658 | if (cut.x < 0.0f) | 7658 | if (cut.x < 0.0f) |
7659 | { | 7659 | { |
7660 | cut.x = 0.0f; | 7660 | cut.x = 0.0f; |
7661 | cut.y = 0.02f; | 7661 | cut.y = 0.02f; |
7662 | } | 7662 | } |
7663 | } | 7663 | } |
7664 | shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); | 7664 | shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); |
7665 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y)); | 7665 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y)); |
7666 | if (hollow < 0f) | 7666 | if (hollow < 0f) |
7667 | { | 7667 | { |
7668 | hollow = 0f; | 7668 | hollow = 0f; |
7669 | } | 7669 | } |
7670 | // If the prim is a Cylinder, Prism, Sphere, Torus or Ring (or not a | 7670 | // If the prim is a Cylinder, Prism, Sphere, Torus or Ring (or not a |
7671 | // Box or Tube) and the hole shape is a square, hollow is limited to | 7671 | // Box or Tube) and the hole shape is a square, hollow is limited to |
7672 | // a max of 70%. The viewer performs its own check on this value but | 7672 | // a max of 70%. The viewer performs its own check on this value but |
7673 | // we need to do it here also so llGetPrimitiveParams can have access | 7673 | // we need to do it here also so llGetPrimitiveParams can have access |
7674 | // to the correct value. | 7674 | // to the correct value. |
7675 | if (profileshape != (byte)ProfileCurve.Square && | 7675 | if (profileshape != (byte)ProfileCurve.Square && |
7676 | holeshape == (int)ScriptBaseClass.PRIM_HOLE_SQUARE) | 7676 | holeshape == (int)ScriptBaseClass.PRIM_HOLE_SQUARE) |
7677 | { | 7677 | { |
7678 | if (hollow > 0.70f) | 7678 | if (hollow > 0.70f) |
7679 | { | 7679 | { |
7680 | hollow = 0.70f; | 7680 | hollow = 0.70f; |
7681 | } | 7681 | } |
7682 | } | 7682 | } |
7683 | // Otherwise, hollow is limited to 99%. | 7683 | // Otherwise, hollow is limited to 99%. |
7684 | else | 7684 | else |
7685 | { | 7685 | { |
7686 | if (hollow > 0.99f) | 7686 | if (hollow > 0.99f) |
7687 | { | 7687 | { |
7688 | hollow = 0.99f; | 7688 | hollow = 0.99f; |
7689 | } | 7689 | } |
7690 | } | 7690 | } |
7691 | shapeBlock.ProfileHollow = (ushort)(50000 * hollow); | 7691 | shapeBlock.ProfileHollow = (ushort)(50000 * hollow); |
7692 | if (twist.x < -1.0f) | 7692 | if (twist.x < -1.0f) |
7693 | { | 7693 | { |
7694 | twist.x = -1.0f; | 7694 | twist.x = -1.0f; |
7695 | } | 7695 | } |
7696 | if (twist.x > 1.0f) | 7696 | if (twist.x > 1.0f) |
7697 | { | 7697 | { |
7698 | twist.x = 1.0f; | 7698 | twist.x = 1.0f; |
7699 | } | 7699 | } |
7700 | if (twist.y < -1.0f) | 7700 | if (twist.y < -1.0f) |
7701 | { | 7701 | { |
7702 | twist.y = -1.0f; | 7702 | twist.y = -1.0f; |
7703 | } | 7703 | } |
7704 | if (twist.y > 1.0f) | 7704 | if (twist.y > 1.0f) |
7705 | { | 7705 | { |
7706 | twist.y = 1.0f; | 7706 | twist.y = 1.0f; |
7707 | } | 7707 | } |
7708 | // A fairly large precision error occurs for some calculations, | 7708 | // A fairly large precision error occurs for some calculations, |
7709 | // if a float or double is directly cast to a byte or sbyte | 7709 | // if a float or double is directly cast to a byte or sbyte |
7710 | // variable, in both .Net and Mono. In .Net, coding | 7710 | // variable, in both .Net and Mono. In .Net, coding |
7711 | // "(sbyte)(float)(some expression)" corrects the precision | 7711 | // "(sbyte)(float)(some expression)" corrects the precision |
7712 | // errors. But this does not work for Mono. This longer coding | 7712 | // errors. But this does not work for Mono. This longer coding |
7713 | // form of creating a tempoary float variable from the | 7713 | // form of creating a tempoary float variable from the |
7714 | // expression first, then casting that variable to a byte or | 7714 | // expression first, then casting that variable to a byte or |
7715 | // sbyte, works for both .Net and Mono. These types of | 7715 | // sbyte, works for both .Net and Mono. These types of |
7716 | // assignments occur in SetPrimtiveBlockShapeParams and | 7716 | // assignments occur in SetPrimtiveBlockShapeParams and |
7717 | // SetPrimitiveShapeParams in support of llSetPrimitiveParams. | 7717 | // SetPrimitiveShapeParams in support of llSetPrimitiveParams. |
7718 | tempFloat = (float)(100.0d * twist.x); | 7718 | tempFloat = (float)(100.0d * twist.x); |
7719 | shapeBlock.PathTwistBegin = (sbyte)tempFloat; | 7719 | shapeBlock.PathTwistBegin = (sbyte)tempFloat; |
7720 | tempFloat = (float)(100.0d * twist.y); | 7720 | tempFloat = (float)(100.0d * twist.y); |
7721 | shapeBlock.PathTwist = (sbyte)tempFloat; | 7721 | shapeBlock.PathTwist = (sbyte)tempFloat; |
7722 | 7722 | ||
7723 | shapeBlock.ObjectLocalID = part.LocalId; | 7723 | shapeBlock.ObjectLocalID = part.LocalId; |
7724 | 7724 | ||
7725 | part.Shape.SculptEntry = false; | 7725 | part.Shape.SculptEntry = false; |
7726 | return shapeBlock; | 7726 | return shapeBlock; |
7727 | } | 7727 | } |
7728 | 7728 | ||
7729 | // Prim type box, cylinder and prism. | 7729 | // Prim type box, cylinder and prism. |
7730 | protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) | 7730 | protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) |
7731 | { | 7731 | { |
7732 | float tempFloat; // Use in float expressions below to avoid byte cast precision issues. | 7732 | float tempFloat; // Use in float expressions below to avoid byte cast precision issues. |
7733 | ObjectShapePacket.ObjectDataBlock shapeBlock; | 7733 | ObjectShapePacket.ObjectDataBlock shapeBlock; |
7734 | 7734 | ||
7735 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); | 7735 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); |
7736 | 7736 | ||
7737 | if (taper_b.x < 0f) | 7737 | if (taper_b.x < 0f) |
7738 | { | 7738 | { |
7739 | taper_b.x = 0f; | 7739 | taper_b.x = 0f; |
7740 | } | 7740 | } |
7741 | if (taper_b.x > 2f) | 7741 | if (taper_b.x > 2f) |
7742 | { | 7742 | { |
7743 | taper_b.x = 2f; | 7743 | taper_b.x = 2f; |
7744 | } | 7744 | } |
7745 | if (taper_b.y < 0f) | 7745 | if (taper_b.y < 0f) |
7746 | { | 7746 | { |
7747 | taper_b.y = 0f; | 7747 | taper_b.y = 0f; |
7748 | } | 7748 | } |
7749 | if (taper_b.y > 2f) | 7749 | if (taper_b.y > 2f) |
7750 | { | 7750 | { |
7751 | taper_b.y = 2f; | 7751 | taper_b.y = 2f; |
7752 | } | 7752 | } |
7753 | tempFloat = (float)(100.0d * (2.0d - taper_b.x)); | 7753 | tempFloat = (float)(100.0d * (2.0d - taper_b.x)); |
7754 | shapeBlock.PathScaleX = (byte)tempFloat; | 7754 | shapeBlock.PathScaleX = (byte)tempFloat; |
7755 | tempFloat = (float)(100.0d * (2.0d - taper_b.y)); | 7755 | tempFloat = (float)(100.0d * (2.0d - taper_b.y)); |
7756 | shapeBlock.PathScaleY = (byte)tempFloat; | 7756 | shapeBlock.PathScaleY = (byte)tempFloat; |
7757 | if (topshear.x < -0.5f) | 7757 | if (topshear.x < -0.5f) |
7758 | { | 7758 | { |
7759 | topshear.x = -0.5f; | 7759 | topshear.x = -0.5f; |
7760 | } | 7760 | } |
7761 | if (topshear.x > 0.5f) | 7761 | if (topshear.x > 0.5f) |
7762 | { | 7762 | { |
7763 | topshear.x = 0.5f; | 7763 | topshear.x = 0.5f; |
7764 | } | 7764 | } |
7765 | if (topshear.y < -0.5f) | 7765 | if (topshear.y < -0.5f) |
7766 | { | 7766 | { |
7767 | topshear.y = -0.5f; | 7767 | topshear.y = -0.5f; |
7768 | } | 7768 | } |
7769 | if (topshear.y > 0.5f) | 7769 | if (topshear.y > 0.5f) |
7770 | { | 7770 | { |
7771 | topshear.y = 0.5f; | 7771 | topshear.y = 0.5f; |
7772 | } | 7772 | } |
7773 | tempFloat = (float)(100.0d * topshear.x); | 7773 | tempFloat = (float)(100.0d * topshear.x); |
7774 | shapeBlock.PathShearX = (byte)tempFloat; | 7774 | shapeBlock.PathShearX = (byte)tempFloat; |
7775 | tempFloat = (float)(100.0d * topshear.y); | 7775 | tempFloat = (float)(100.0d * topshear.y); |
7776 | shapeBlock.PathShearY = (byte)tempFloat; | 7776 | shapeBlock.PathShearY = (byte)tempFloat; |
7777 | 7777 | ||
7778 | part.Shape.SculptEntry = false; | 7778 | part.Shape.SculptEntry = false; |
7779 | part.UpdateShape(shapeBlock); | 7779 | part.UpdateShape(shapeBlock); |
7780 | } | 7780 | } |
7781 | 7781 | ||
7782 | // Prim type sphere. | 7782 | // Prim type sphere. |
7783 | protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) | 7783 | protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte profileshape, byte pathcurve) |
7784 | { | 7784 | { |
7785 | ObjectShapePacket.ObjectDataBlock shapeBlock; | 7785 | ObjectShapePacket.ObjectDataBlock shapeBlock; |
7786 | 7786 | ||
7787 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); | 7787 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); |
7788 | 7788 | ||
7789 | // profile/path swapped for a sphere | 7789 | // profile/path swapped for a sphere |
7790 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; | 7790 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; |
7791 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; | 7791 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; |
7792 | 7792 | ||
7793 | shapeBlock.PathScaleX = 100; | 7793 | shapeBlock.PathScaleX = 100; |
7794 | shapeBlock.PathScaleY = 100; | 7794 | shapeBlock.PathScaleY = 100; |
7795 | 7795 | ||
7796 | if (dimple.x < 0f) | 7796 | if (dimple.x < 0f) |
7797 | { | 7797 | { |
7798 | dimple.x = 0f; | 7798 | dimple.x = 0f; |
7799 | } | 7799 | } |
7800 | if (dimple.x > 1f) | 7800 | if (dimple.x > 1f) |
7801 | { | 7801 | { |
7802 | dimple.x = 1f; | 7802 | dimple.x = 1f; |
7803 | } | 7803 | } |
7804 | if (dimple.y < 0f) | 7804 | if (dimple.y < 0f) |
7805 | { | 7805 | { |
7806 | dimple.y = 0f; | 7806 | dimple.y = 0f; |
7807 | } | 7807 | } |
7808 | if (dimple.y > 1f) | 7808 | if (dimple.y > 1f) |
7809 | { | 7809 | { |
7810 | dimple.y = 1f; | 7810 | dimple.y = 1f; |
7811 | } | 7811 | } |
7812 | if (dimple.y - dimple.x < 0.02f) | 7812 | if (dimple.y - dimple.x < 0.02f) |
7813 | { | 7813 | { |
7814 | dimple.x = dimple.y - 0.02f; | 7814 | dimple.x = dimple.y - 0.02f; |
7815 | if (dimple.x < 0.0f) | 7815 | if (dimple.x < 0.0f) |
7816 | { | 7816 | { |
7817 | dimple.x = 0.0f; | 7817 | dimple.x = 0.0f; |
7818 | dimple.y = 0.02f; | 7818 | dimple.y = 0.02f; |
7819 | } | 7819 | } |
7820 | } | 7820 | } |
7821 | shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); | 7821 | shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); |
7822 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); | 7822 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); |
7823 | 7823 | ||
7824 | part.Shape.SculptEntry = false; | 7824 | part.Shape.SculptEntry = false; |
7825 | part.UpdateShape(shapeBlock); | 7825 | part.UpdateShape(shapeBlock); |
7826 | } | 7826 | } |
7827 | 7827 | ||
7828 | // Prim type torus, tube and ring. | 7828 | // Prim type torus, tube and ring. |
7829 | protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) | 7829 | protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) |
7830 | { | 7830 | { |
7831 | float tempFloat; // Use in float expressions below to avoid byte cast precision issues. | 7831 | float tempFloat; // Use in float expressions below to avoid byte cast precision issues. |
7832 | ObjectShapePacket.ObjectDataBlock shapeBlock; | 7832 | ObjectShapePacket.ObjectDataBlock shapeBlock; |
7833 | 7833 | ||
7834 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); | 7834 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); |
7835 | 7835 | ||
7836 | // profile/path swapped for a torrus, tube, ring | 7836 | // profile/path swapped for a torrus, tube, ring |
7837 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; | 7837 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; |
7838 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; | 7838 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; |
7839 | 7839 | ||
7840 | if (holesize.x < 0.01f) | 7840 | if (holesize.x < 0.01f) |
7841 | { | 7841 | { |
7842 | holesize.x = 0.01f; | 7842 | holesize.x = 0.01f; |
7843 | } | 7843 | } |
7844 | if (holesize.x > 1f) | 7844 | if (holesize.x > 1f) |
7845 | { | 7845 | { |
7846 | holesize.x = 1f; | 7846 | holesize.x = 1f; |
7847 | } | 7847 | } |
7848 | if (holesize.y < 0.01f) | 7848 | if (holesize.y < 0.01f) |
7849 | { | 7849 | { |
7850 | holesize.y = 0.01f; | 7850 | holesize.y = 0.01f; |
7851 | } | 7851 | } |
7852 | if (holesize.y > 0.5f) | 7852 | if (holesize.y > 0.5f) |
7853 | { | 7853 | { |
7854 | holesize.y = 0.5f; | 7854 | holesize.y = 0.5f; |
7855 | } | 7855 | } |
7856 | tempFloat = (float)(100.0d * (2.0d - holesize.x)); | 7856 | tempFloat = (float)(100.0d * (2.0d - holesize.x)); |
7857 | shapeBlock.PathScaleX = (byte)tempFloat; | 7857 | shapeBlock.PathScaleX = (byte)tempFloat; |
7858 | tempFloat = (float)(100.0d * (2.0d - holesize.y)); | 7858 | tempFloat = (float)(100.0d * (2.0d - holesize.y)); |
7859 | shapeBlock.PathScaleY = (byte)tempFloat; | 7859 | shapeBlock.PathScaleY = (byte)tempFloat; |
7860 | if (topshear.x < -0.5f) | 7860 | if (topshear.x < -0.5f) |
7861 | { | 7861 | { |
7862 | topshear.x = -0.5f; | 7862 | topshear.x = -0.5f; |
7863 | } | 7863 | } |
7864 | if (topshear.x > 0.5f) | 7864 | if (topshear.x > 0.5f) |
7865 | { | 7865 | { |
7866 | topshear.x = 0.5f; | 7866 | topshear.x = 0.5f; |
7867 | } | 7867 | } |
7868 | if (topshear.y < -0.5f) | 7868 | if (topshear.y < -0.5f) |
7869 | { | 7869 | { |
7870 | topshear.y = -0.5f; | 7870 | topshear.y = -0.5f; |
7871 | } | 7871 | } |
7872 | if (topshear.y > 0.5f) | 7872 | if (topshear.y > 0.5f) |
7873 | { | 7873 | { |
7874 | topshear.y = 0.5f; | 7874 | topshear.y = 0.5f; |
7875 | } | 7875 | } |
7876 | tempFloat = (float)(100.0d * topshear.x); | 7876 | tempFloat = (float)(100.0d * topshear.x); |
7877 | shapeBlock.PathShearX = (byte)tempFloat; | 7877 | shapeBlock.PathShearX = (byte)tempFloat; |
7878 | tempFloat = (float)(100.0d * topshear.y); | 7878 | tempFloat = (float)(100.0d * topshear.y); |
7879 | shapeBlock.PathShearY = (byte)tempFloat; | 7879 | shapeBlock.PathShearY = (byte)tempFloat; |
7880 | if (profilecut.x < 0f) | 7880 | if (profilecut.x < 0f) |
7881 | { | 7881 | { |
7882 | profilecut.x = 0f; | 7882 | profilecut.x = 0f; |
7883 | } | 7883 | } |
7884 | if (profilecut.x > 1f) | 7884 | if (profilecut.x > 1f) |
7885 | { | 7885 | { |
7886 | profilecut.x = 1f; | 7886 | profilecut.x = 1f; |
7887 | } | 7887 | } |
7888 | if (profilecut.y < 0f) | 7888 | if (profilecut.y < 0f) |
7889 | { | 7889 | { |
7890 | profilecut.y = 0f; | 7890 | profilecut.y = 0f; |
7891 | } | 7891 | } |
7892 | if (profilecut.y > 1f) | 7892 | if (profilecut.y > 1f) |
7893 | { | 7893 | { |
7894 | profilecut.y = 1f; | 7894 | profilecut.y = 1f; |
7895 | } | 7895 | } |
7896 | if (profilecut.y - profilecut.x < 0.02f) | 7896 | if (profilecut.y - profilecut.x < 0.02f) |
7897 | { | 7897 | { |
7898 | profilecut.x = profilecut.y - 0.02f; | 7898 | profilecut.x = profilecut.y - 0.02f; |
7899 | if (profilecut.x < 0.0f) | 7899 | if (profilecut.x < 0.0f) |
7900 | { | 7900 | { |
7901 | profilecut.x = 0.0f; | 7901 | profilecut.x = 0.0f; |
7902 | profilecut.y = 0.02f; | 7902 | profilecut.y = 0.02f; |
7903 | } | 7903 | } |
7904 | } | 7904 | } |
7905 | shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); | 7905 | shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); |
7906 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y)); | 7906 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y)); |
7907 | if (taper_a.x < -1f) | 7907 | if (taper_a.x < -1f) |
7908 | { | 7908 | { |
7909 | taper_a.x = -1f; | 7909 | taper_a.x = -1f; |
7910 | } | 7910 | } |
7911 | if (taper_a.x > 1f) | 7911 | if (taper_a.x > 1f) |
7912 | { | 7912 | { |
7913 | taper_a.x = 1f; | 7913 | taper_a.x = 1f; |
7914 | } | 7914 | } |
7915 | if (taper_a.y < -1f) | 7915 | if (taper_a.y < -1f) |
7916 | { | 7916 | { |
7917 | taper_a.y = -1f; | 7917 | taper_a.y = -1f; |
7918 | } | 7918 | } |
7919 | if (taper_a.y > 1f) | 7919 | if (taper_a.y > 1f) |
7920 | { | 7920 | { |
7921 | taper_a.y = 1f; | 7921 | taper_a.y = 1f; |
7922 | } | 7922 | } |
7923 | tempFloat = (float)(100.0d * taper_a.x); | 7923 | tempFloat = (float)(100.0d * taper_a.x); |
7924 | shapeBlock.PathTaperX = (sbyte)tempFloat; | 7924 | shapeBlock.PathTaperX = (sbyte)tempFloat; |
7925 | tempFloat = (float)(100.0d * taper_a.y); | 7925 | tempFloat = (float)(100.0d * taper_a.y); |
7926 | shapeBlock.PathTaperY = (sbyte)tempFloat; | 7926 | shapeBlock.PathTaperY = (sbyte)tempFloat; |
7927 | if (revolutions < 1f) | 7927 | if (revolutions < 1f) |
7928 | { | 7928 | { |
7929 | revolutions = 1f; | 7929 | revolutions = 1f; |
7930 | } | 7930 | } |
7931 | if (revolutions > 4f) | 7931 | if (revolutions > 4f) |
7932 | { | 7932 | { |
7933 | revolutions = 4f; | 7933 | revolutions = 4f; |
7934 | } | 7934 | } |
7935 | tempFloat = 66.66667f * (revolutions - 1.0f); | 7935 | tempFloat = 66.66667f * (revolutions - 1.0f); |
7936 | shapeBlock.PathRevolutions = (byte)tempFloat; | 7936 | shapeBlock.PathRevolutions = (byte)tempFloat; |
7937 | // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 | 7937 | // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 |
7938 | if (radiusoffset < 0f) | 7938 | if (radiusoffset < 0f) |
7939 | { | 7939 | { |
7940 | radiusoffset = 0f; | 7940 | radiusoffset = 0f; |
7941 | } | 7941 | } |
7942 | if (radiusoffset > 1f) | 7942 | if (radiusoffset > 1f) |
7943 | { | 7943 | { |
7944 | radiusoffset = 1f; | 7944 | radiusoffset = 1f; |
7945 | } | 7945 | } |
7946 | tempFloat = 100.0f * radiusoffset; | 7946 | tempFloat = 100.0f * radiusoffset; |
7947 | shapeBlock.PathRadiusOffset = (sbyte)tempFloat; | 7947 | shapeBlock.PathRadiusOffset = (sbyte)tempFloat; |
7948 | if (skew < -0.95f) | 7948 | if (skew < -0.95f) |
7949 | { | 7949 | { |
7950 | skew = -0.95f; | 7950 | skew = -0.95f; |
7951 | } | 7951 | } |
7952 | if (skew > 0.95f) | 7952 | if (skew > 0.95f) |
7953 | { | 7953 | { |
7954 | skew = 0.95f; | 7954 | skew = 0.95f; |
7955 | } | 7955 | } |
7956 | tempFloat = 100.0f * skew; | 7956 | tempFloat = 100.0f * skew; |
7957 | shapeBlock.PathSkew = (sbyte)tempFloat; | 7957 | shapeBlock.PathSkew = (sbyte)tempFloat; |
7958 | 7958 | ||
7959 | part.Shape.SculptEntry = false; | 7959 | part.Shape.SculptEntry = false; |
7960 | part.UpdateShape(shapeBlock); | 7960 | part.UpdateShape(shapeBlock); |
7961 | } | 7961 | } |
7962 | 7962 | ||
7963 | // Prim type sculpt. | 7963 | // Prim type sculpt. |
7964 | protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) | 7964 | protected void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type, byte pathcurve) |
7965 | { | 7965 | { |
7966 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); | 7966 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); |
7967 | UUID sculptId; | 7967 | UUID sculptId; |
7968 | 7968 | ||
7969 | if (!UUID.TryParse(map, out sculptId)) | 7969 | if (!UUID.TryParse(map, out sculptId)) |
7970 | sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture); | 7970 | sculptId = ScriptUtils.GetAssetIdFromItemName(m_host, map, (int)AssetType.Texture); |
7971 | 7971 | ||
7972 | if (sculptId == UUID.Zero) | 7972 | if (sculptId == UUID.Zero) |
7973 | return; | 7973 | return; |
7974 | 7974 | ||
7975 | shapeBlock.PathCurve = pathcurve; | 7975 | shapeBlock.PathCurve = pathcurve; |
7976 | shapeBlock.ObjectLocalID = part.LocalId; | 7976 | shapeBlock.ObjectLocalID = part.LocalId; |
7977 | shapeBlock.PathScaleX = 100; | 7977 | shapeBlock.PathScaleX = 100; |
7978 | shapeBlock.PathScaleY = 150; | 7978 | shapeBlock.PathScaleY = 150; |
7979 | 7979 | ||
7980 | int flag = type & (ScriptBaseClass.PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass.PRIM_SCULPT_FLAG_MIRROR); | 7980 | int flag = type & (ScriptBaseClass.PRIM_SCULPT_FLAG_INVERT | ScriptBaseClass.PRIM_SCULPT_FLAG_MIRROR); |
7981 | 7981 | ||
7982 | if (type != (ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER | flag) && | 7982 | if (type != (ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER | flag) && |
7983 | type != (ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE | flag) && | 7983 | type != (ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE | flag) && |
7984 | type != (ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE | flag) && | 7984 | type != (ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE | flag) && |
7985 | type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) | 7985 | type != (ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS | flag)) |
7986 | { | 7986 | { |
7987 | // default | 7987 | // default |
7988 | type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; | 7988 | type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; |
7989 | } | 7989 | } |
7990 | 7990 | ||
7991 | part.Shape.SetSculptProperties((byte)type, sculptId); | 7991 | part.Shape.SetSculptProperties((byte)type, sculptId); |
7992 | part.Shape.SculptEntry = true; | 7992 | part.Shape.SculptEntry = true; |
7993 | part.UpdateShape(shapeBlock); | 7993 | part.UpdateShape(shapeBlock); |
7994 | } | 7994 | } |
7995 | 7995 | ||
7996 | public void llSetPrimitiveParams(LSL_List rules) | 7996 | public void llSetPrimitiveParams(LSL_List rules) |
7997 | { | 7997 | { |
7998 | m_host.AddScriptLPS(1); | 7998 | m_host.AddScriptLPS(1); |
7999 | 7999 | ||
8000 | SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); | 8000 | SetLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); |
8001 | 8001 | ||
8002 | ScriptSleep(m_sleepMsOnSetPrimitiveParams); | 8002 | ScriptSleep(m_sleepMsOnSetPrimitiveParams); |
8003 | } | 8003 | } |
8004 | 8004 | ||
8005 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) | 8005 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) |
8006 | { | 8006 | { |
8007 | m_host.AddScriptLPS(1); | 8007 | m_host.AddScriptLPS(1); |
8008 | 8008 | ||
8009 | SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); | 8009 | SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); |
8010 | 8010 | ||
8011 | ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams); | 8011 | ScriptSleep(m_sleepMsOnSetLinkPrimitiveParams); |
8012 | } | 8012 | } |
8013 | 8013 | ||
8014 | public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) | 8014 | public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) |
8015 | { | 8015 | { |
8016 | m_host.AddScriptLPS(1); | 8016 | m_host.AddScriptLPS(1); |
8017 | 8017 | ||
8018 | SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); | 8018 | SetLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); |
8019 | } | 8019 | } |
8020 | 8020 | ||
8021 | protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc) | 8021 | protected void SetLinkPrimParams(int linknumber, LSL_List rules, string originFunc) |
8022 | { | 8022 | { |
8023 | SetEntityParams(GetLinkEntities(linknumber), rules, originFunc); | 8023 | SetEntityParams(GetLinkEntities(linknumber), rules, originFunc); |
8024 | } | 8024 | } |
8025 | 8025 | ||
8026 | protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc) | 8026 | protected void SetEntityParams(List<ISceneEntity> entities, LSL_List rules, string originFunc) |
8027 | { | 8027 | { |
8028 | LSL_List remaining = null; | 8028 | LSL_List remaining = null; |
8029 | uint rulesParsed = 0; | 8029 | uint rulesParsed = 0; |
8030 | 8030 | ||
8031 | foreach (ISceneEntity entity in entities) | 8031 | foreach (ISceneEntity entity in entities) |
8032 | { | 8032 | { |
8033 | if (entity is SceneObjectPart) | 8033 | if (entity is SceneObjectPart) |
8034 | remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); | 8034 | remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); |
8035 | else | 8035 | else |
8036 | remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); | 8036 | remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); |
8037 | } | 8037 | } |
8038 | 8038 | ||
8039 | while (remaining != null && remaining.Length > 2) | 8039 | while (remaining != null && remaining.Length > 2) |
8040 | { | 8040 | { |
8041 | int linknumber; | 8041 | int linknumber; |
8042 | try | 8042 | try |
8043 | { | 8043 | { |
8044 | linknumber = remaining.GetLSLIntegerItem(0); | 8044 | linknumber = remaining.GetLSLIntegerItem(0); |
8045 | } | 8045 | } |
8046 | catch(InvalidCastException) | 8046 | catch(InvalidCastException) |
8047 | { | 8047 | { |
8048 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_LINK_TARGET: parameter 2 must be integer", rulesParsed)); | 8048 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_LINK_TARGET: parameter 2 must be integer", rulesParsed)); |
8049 | return; | 8049 | return; |
8050 | } | 8050 | } |
8051 | 8051 | ||
8052 | rules = remaining.GetSublist(1, -1); | 8052 | rules = remaining.GetSublist(1, -1); |
8053 | entities = GetLinkEntities(linknumber); | 8053 | entities = GetLinkEntities(linknumber); |
8054 | 8054 | ||
8055 | foreach (ISceneEntity entity in entities) | 8055 | foreach (ISceneEntity entity in entities) |
8056 | { | 8056 | { |
8057 | if (entity is SceneObjectPart) | 8057 | if (entity is SceneObjectPart) |
8058 | remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); | 8058 | remaining = SetPrimParams((SceneObjectPart)entity, rules, originFunc, ref rulesParsed); |
8059 | else | 8059 | else |
8060 | remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); | 8060 | remaining = SetAgentParams((ScenePresence)entity, rules, originFunc, ref rulesParsed); |
8061 | } | 8061 | } |
8062 | } | 8062 | } |
8063 | } | 8063 | } |
8064 | 8064 | ||
8065 | public void llSetKeyframedMotion(LSL_List frames, LSL_List options) | 8065 | public void llSetKeyframedMotion(LSL_List frames, LSL_List options) |
8066 | { | 8066 | { |
8067 | SceneObjectGroup group = m_host.ParentGroup; | 8067 | SceneObjectGroup group = m_host.ParentGroup; |
8068 | 8068 | ||
8069 | if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical) | 8069 | if (group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical) |
8070 | return; | 8070 | return; |
8071 | if (group.IsAttachment) | 8071 | if (group.IsAttachment) |
8072 | return; | 8072 | return; |
8073 | 8073 | ||
8074 | if (frames.Data.Length > 0) // We are getting a new motion | 8074 | if (frames.Data.Length > 0) // We are getting a new motion |
8075 | { | 8075 | { |
8076 | if (group.RootPart.KeyframeMotion != null) | 8076 | if (group.RootPart.KeyframeMotion != null) |
8077 | group.RootPart.KeyframeMotion.Delete(); | 8077 | group.RootPart.KeyframeMotion.Delete(); |
8078 | group.RootPart.KeyframeMotion = null; | 8078 | group.RootPart.KeyframeMotion = null; |
8079 | 8079 | ||
8080 | int idx = 0; | 8080 | int idx = 0; |
8081 | 8081 | ||
8082 | KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward; | 8082 | KeyframeMotion.PlayMode mode = KeyframeMotion.PlayMode.Forward; |
8083 | KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation; | 8083 | KeyframeMotion.DataFormat data = KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation; |
8084 | 8084 | ||
8085 | while (idx < options.Data.Length) | 8085 | while (idx < options.Data.Length) |
8086 | { | 8086 | { |
8087 | int option = (int)options.GetLSLIntegerItem(idx++); | 8087 | int option = (int)options.GetLSLIntegerItem(idx++); |
8088 | int remain = options.Data.Length - idx; | 8088 | int remain = options.Data.Length - idx; |
8089 | 8089 | ||
8090 | switch (option) | 8090 | switch (option) |
8091 | { | 8091 | { |
8092 | case ScriptBaseClass.KFM_MODE: | 8092 | case ScriptBaseClass.KFM_MODE: |
8093 | if (remain < 1) | 8093 | if (remain < 1) |
8094 | break; | 8094 | break; |
8095 | int modeval = (int)options.GetLSLIntegerItem(idx++); | 8095 | int modeval = (int)options.GetLSLIntegerItem(idx++); |
8096 | switch(modeval) | 8096 | switch(modeval) |
8097 | { | 8097 | { |
8098 | case ScriptBaseClass.KFM_FORWARD: | 8098 | case ScriptBaseClass.KFM_FORWARD: |
8099 | mode = KeyframeMotion.PlayMode.Forward; | 8099 | mode = KeyframeMotion.PlayMode.Forward; |
8100 | break; | 8100 | break; |
8101 | case ScriptBaseClass.KFM_REVERSE: | 8101 | case ScriptBaseClass.KFM_REVERSE: |
8102 | mode = KeyframeMotion.PlayMode.Reverse; | 8102 | mode = KeyframeMotion.PlayMode.Reverse; |
8103 | break; | 8103 | break; |
8104 | case ScriptBaseClass.KFM_LOOP: | 8104 | case ScriptBaseClass.KFM_LOOP: |
8105 | mode = KeyframeMotion.PlayMode.Loop; | 8105 | mode = KeyframeMotion.PlayMode.Loop; |
8106 | break; | 8106 | break; |
8107 | case ScriptBaseClass.KFM_PING_PONG: | 8107 | case ScriptBaseClass.KFM_PING_PONG: |
8108 | mode = KeyframeMotion.PlayMode.PingPong; | 8108 | mode = KeyframeMotion.PlayMode.PingPong; |
8109 | break; | 8109 | break; |
8110 | } | 8110 | } |
8111 | break; | 8111 | break; |
8112 | case ScriptBaseClass.KFM_DATA: | 8112 | case ScriptBaseClass.KFM_DATA: |
8113 | if (remain < 1) | 8113 | if (remain < 1) |
8114 | break; | 8114 | break; |
8115 | int dataval = (int)options.GetLSLIntegerItem(idx++); | 8115 | int dataval = (int)options.GetLSLIntegerItem(idx++); |
8116 | data = (KeyframeMotion.DataFormat)dataval; | 8116 | data = (KeyframeMotion.DataFormat)dataval; |
8117 | break; | 8117 | break; |
8118 | } | 8118 | } |
8119 | } | 8119 | } |
8120 | 8120 | ||
8121 | group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data); | 8121 | group.RootPart.KeyframeMotion = new KeyframeMotion(group, mode, data); |
8122 | 8122 | ||
8123 | idx = 0; | 8123 | idx = 0; |
8124 | 8124 | ||
8125 | int elemLength = 2; | 8125 | int elemLength = 2; |
8126 | if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation)) | 8126 | if (data == (KeyframeMotion.DataFormat.Translation | KeyframeMotion.DataFormat.Rotation)) |
8127 | elemLength = 3; | 8127 | elemLength = 3; |
8128 | 8128 | ||
8129 | List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>(); | 8129 | List<KeyframeMotion.Keyframe> keyframes = new List<KeyframeMotion.Keyframe>(); |
8130 | while (idx < frames.Data.Length) | 8130 | while (idx < frames.Data.Length) |
8131 | { | 8131 | { |
8132 | int remain = frames.Data.Length - idx; | 8132 | int remain = frames.Data.Length - idx; |
8133 | 8133 | ||
8134 | if (remain < elemLength) | 8134 | if (remain < elemLength) |
8135 | break; | 8135 | break; |
8136 | 8136 | ||
8137 | KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe(); | 8137 | KeyframeMotion.Keyframe frame = new KeyframeMotion.Keyframe(); |
8138 | frame.Position = null; | 8138 | frame.Position = null; |
8139 | frame.Rotation = null; | 8139 | frame.Rotation = null; |
8140 | 8140 | ||
8141 | if ((data & KeyframeMotion.DataFormat.Translation) != 0) | 8141 | if ((data & KeyframeMotion.DataFormat.Translation) != 0) |
8142 | { | 8142 | { |
8143 | LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++); | 8143 | LSL_Types.Vector3 tempv = frames.GetVector3Item(idx++); |
8144 | frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z); | 8144 | frame.Position = new Vector3((float)tempv.x, (float)tempv.y, (float)tempv.z); |
8145 | } | 8145 | } |
8146 | if ((data & KeyframeMotion.DataFormat.Rotation) != 0) | 8146 | if ((data & KeyframeMotion.DataFormat.Rotation) != 0) |
8147 | { | 8147 | { |
8148 | LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++); | 8148 | LSL_Types.Quaternion tempq = frames.GetQuaternionItem(idx++); |
8149 | Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s); | 8149 | Quaternion q = new Quaternion((float)tempq.x, (float)tempq.y, (float)tempq.z, (float)tempq.s); |
8150 | q.Normalize(); | 8150 | q.Normalize(); |
8151 | frame.Rotation = q; | 8151 | frame.Rotation = q; |
8152 | } | 8152 | } |
8153 | 8153 | ||
8154 | float tempf = (float)frames.GetLSLFloatItem(idx++); | 8154 | float tempf = (float)frames.GetLSLFloatItem(idx++); |
8155 | frame.TimeMS = (int)(tempf * 1000.0f); | 8155 | frame.TimeMS = (int)(tempf * 1000.0f); |
8156 | 8156 | ||
8157 | keyframes.Add(frame); | 8157 | keyframes.Add(frame); |
8158 | } | 8158 | } |
8159 | 8159 | ||
8160 | group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray()); | 8160 | group.RootPart.KeyframeMotion.SetKeyframes(keyframes.ToArray()); |
8161 | group.RootPart.KeyframeMotion.Start(); | 8161 | group.RootPart.KeyframeMotion.Start(); |
8162 | } | 8162 | } |
8163 | else | 8163 | else |
8164 | { | 8164 | { |
8165 | if (group.RootPart.KeyframeMotion == null) | 8165 | if (group.RootPart.KeyframeMotion == null) |
8166 | return; | 8166 | return; |
8167 | 8167 | ||
8168 | if (options.Data.Length == 0) | 8168 | if (options.Data.Length == 0) |
8169 | { | 8169 | { |
8170 | group.RootPart.KeyframeMotion.Stop(); | 8170 | group.RootPart.KeyframeMotion.Stop(); |
8171 | return; | 8171 | return; |
8172 | } | 8172 | } |
8173 | 8173 | ||
8174 | int idx = 0; | 8174 | int idx = 0; |
8175 | 8175 | ||
8176 | while (idx < options.Data.Length) | 8176 | while (idx < options.Data.Length) |
8177 | { | 8177 | { |
8178 | int option = (int)options.GetLSLIntegerItem(idx++); | 8178 | int option = (int)options.GetLSLIntegerItem(idx++); |
8179 | 8179 | ||
8180 | switch (option) | 8180 | switch (option) |
8181 | { | 8181 | { |
8182 | case ScriptBaseClass.KFM_COMMAND: | 8182 | case ScriptBaseClass.KFM_COMMAND: |
8183 | int cmd = (int)options.GetLSLIntegerItem(idx++); | 8183 | int cmd = (int)options.GetLSLIntegerItem(idx++); |
8184 | switch (cmd) | 8184 | switch (cmd) |
8185 | { | 8185 | { |
8186 | case ScriptBaseClass.KFM_CMD_PLAY: | 8186 | case ScriptBaseClass.KFM_CMD_PLAY: |
8187 | group.RootPart.KeyframeMotion.Start(); | 8187 | group.RootPart.KeyframeMotion.Start(); |
8188 | break; | 8188 | break; |
8189 | case ScriptBaseClass.KFM_CMD_STOP: | 8189 | case ScriptBaseClass.KFM_CMD_STOP: |
8190 | group.RootPart.KeyframeMotion.Stop(); | 8190 | group.RootPart.KeyframeMotion.Stop(); |
8191 | break; | 8191 | break; |
8192 | case ScriptBaseClass.KFM_CMD_PAUSE: | 8192 | case ScriptBaseClass.KFM_CMD_PAUSE: |
8193 | group.RootPart.KeyframeMotion.Pause(); | 8193 | group.RootPart.KeyframeMotion.Pause(); |
8194 | break; | 8194 | break; |
8195 | } | 8195 | } |
8196 | break; | 8196 | break; |
8197 | } | 8197 | } |
8198 | } | 8198 | } |
8199 | } | 8199 | } |
8200 | } | 8200 | } |
8201 | 8201 | ||
8202 | protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) | 8202 | protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) |
8203 | { | 8203 | { |
8204 | int idx = 0; | 8204 | int idx = 0; |
8205 | int idxStart = 0; | 8205 | int idxStart = 0; |
8206 | 8206 | ||
8207 | bool positionChanged = false; | 8207 | bool positionChanged = false; |
8208 | LSL_Vector currentPosition = GetPartLocalPos(part); | 8208 | LSL_Vector currentPosition = GetPartLocalPos(part); |
8209 | 8209 | ||
8210 | try | 8210 | try |
8211 | { | 8211 | { |
8212 | while (idx < rules.Length) | 8212 | while (idx < rules.Length) |
8213 | { | 8213 | { |
8214 | ++rulesParsed; | 8214 | ++rulesParsed; |
8215 | int code = rules.GetLSLIntegerItem(idx++); | 8215 | int code = rules.GetLSLIntegerItem(idx++); |
8216 | 8216 | ||
8217 | int remain = rules.Length - idx; | 8217 | int remain = rules.Length - idx; |
8218 | idxStart = idx; | 8218 | idxStart = idx; |
8219 | 8219 | ||
8220 | int face; | 8220 | int face; |
8221 | LSL_Vector v; | 8221 | LSL_Vector v; |
8222 | 8222 | ||
8223 | switch (code) | 8223 | switch (code) |
8224 | { | 8224 | { |
8225 | case ScriptBaseClass.PRIM_POSITION: | 8225 | case ScriptBaseClass.PRIM_POSITION: |
8226 | case ScriptBaseClass.PRIM_POS_LOCAL: | 8226 | case ScriptBaseClass.PRIM_POS_LOCAL: |
8227 | if (remain < 1) | 8227 | if (remain < 1) |
8228 | return null; | 8228 | return null; |
8229 | 8229 | ||
8230 | try | 8230 | try |
8231 | { | 8231 | { |
8232 | v = rules.GetVector3Item(idx++); | 8232 | v = rules.GetVector3Item(idx++); |
8233 | } | 8233 | } |
8234 | catch(InvalidCastException) | 8234 | catch(InvalidCastException) |
8235 | { | 8235 | { |
8236 | if(code == ScriptBaseClass.PRIM_POSITION) | 8236 | if(code == ScriptBaseClass.PRIM_POSITION) |
8237 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); | 8237 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); |
8238 | else | 8238 | else |
8239 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); | 8239 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 1 must be vector", rulesParsed, idx - idxStart - 1)); |
8240 | return null; | 8240 | return null; |
8241 | } | 8241 | } |
8242 | positionChanged = true; | 8242 | positionChanged = true; |
8243 | currentPosition = GetSetPosTarget(part, v, currentPosition); | 8243 | currentPosition = GetSetPosTarget(part, v, currentPosition); |
8244 | 8244 | ||
8245 | break; | 8245 | break; |
8246 | case ScriptBaseClass.PRIM_SIZE: | 8246 | case ScriptBaseClass.PRIM_SIZE: |
8247 | if (remain < 1) | 8247 | if (remain < 1) |
8248 | return null; | 8248 | return null; |
8249 | 8249 | ||
8250 | v=rules.GetVector3Item(idx++); | 8250 | v=rules.GetVector3Item(idx++); |
8251 | SetScale(part, v); | 8251 | SetScale(part, v); |
8252 | 8252 | ||
8253 | break; | 8253 | break; |
8254 | case ScriptBaseClass.PRIM_ROTATION: | 8254 | case ScriptBaseClass.PRIM_ROTATION: |
8255 | if (remain < 1) | 8255 | if (remain < 1) |
8256 | return null; | 8256 | return null; |
8257 | LSL_Rotation q; | 8257 | LSL_Rotation q; |
8258 | try | 8258 | try |
8259 | { | 8259 | { |
8260 | q = rules.GetQuaternionItem(idx++); | 8260 | q = rules.GetQuaternionItem(idx++); |
8261 | } | 8261 | } |
8262 | catch(InvalidCastException) | 8262 | catch(InvalidCastException) |
8263 | { | 8263 | { |
8264 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 1 must be rotation", rulesParsed, idx - idxStart - 1)); | 8264 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 1 must be rotation", rulesParsed, idx - idxStart - 1)); |
8265 | return null; | 8265 | return null; |
8266 | } | 8266 | } |
8267 | // try to let this work as in SL... | 8267 | // try to let this work as in SL... |
8268 | if (part.ParentID == 0) | 8268 | if (part.ParentID == 0) |
8269 | { | 8269 | { |
8270 | // special case: If we are root, rotate complete SOG to new rotation | 8270 | // special case: If we are root, rotate complete SOG to new rotation |
8271 | SetRot(part, q); | 8271 | SetRot(part, q); |
8272 | } | 8272 | } |
8273 | else | 8273 | else |
8274 | { | 8274 | { |
8275 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. | 8275 | // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. |
8276 | SceneObjectPart rootPart = part.ParentGroup.RootPart; | 8276 | SceneObjectPart rootPart = part.ParentGroup.RootPart; |
8277 | SetRot(part, rootPart.RotationOffset * (Quaternion)q); | 8277 | SetRot(part, rootPart.RotationOffset * (Quaternion)q); |
8278 | } | 8278 | } |
8279 | 8279 | ||
8280 | break; | 8280 | break; |
8281 | 8281 | ||
8282 | case ScriptBaseClass.PRIM_TYPE: | 8282 | case ScriptBaseClass.PRIM_TYPE: |
8283 | if (remain < 3) | 8283 | if (remain < 3) |
8284 | return null; | 8284 | return null; |
8285 | 8285 | ||
8286 | try | 8286 | try |
8287 | { | 8287 | { |
8288 | code = (int)rules.GetLSLIntegerItem(idx++); | 8288 | code = (int)rules.GetLSLIntegerItem(idx++); |
8289 | } | 8289 | } |
8290 | catch(InvalidCastException) | 8290 | catch(InvalidCastException) |
8291 | { | 8291 | { |
8292 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1)); | 8292 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE: arg #{1} - parameter 1 must be integer", rulesParsed, idx - idxStart - 1)); |
8293 | return null; | 8293 | return null; |
8294 | } | 8294 | } |
8295 | 8295 | ||
8296 | remain = rules.Length - idx; | 8296 | remain = rules.Length - idx; |
8297 | float hollow; | 8297 | float hollow; |
8298 | LSL_Vector twist; | 8298 | LSL_Vector twist; |
8299 | LSL_Vector taper_b; | 8299 | LSL_Vector taper_b; |
8300 | LSL_Vector topshear; | 8300 | LSL_Vector topshear; |
8301 | float revolutions; | 8301 | float revolutions; |
8302 | float radiusoffset; | 8302 | float radiusoffset; |
8303 | float skew; | 8303 | float skew; |
8304 | LSL_Vector holesize; | 8304 | LSL_Vector holesize; |
8305 | LSL_Vector profilecut; | 8305 | LSL_Vector profilecut; |
8306 | 8306 | ||
8307 | switch (code) | 8307 | switch (code) |
8308 | { | 8308 | { |
8309 | case ScriptBaseClass.PRIM_TYPE_BOX: | 8309 | case ScriptBaseClass.PRIM_TYPE_BOX: |
8310 | if (remain < 6) | 8310 | if (remain < 6) |
8311 | return null; | 8311 | return null; |
8312 | 8312 | ||
8313 | try | 8313 | try |
8314 | { | 8314 | { |
8315 | face = (int)rules.GetLSLIntegerItem(idx++); | 8315 | face = (int)rules.GetLSLIntegerItem(idx++); |
8316 | } | 8316 | } |
8317 | catch(InvalidCastException) | 8317 | catch(InvalidCastException) |
8318 | { | 8318 | { |
8319 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 8319 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
8320 | return null; | 8320 | return null; |
8321 | } | 8321 | } |
8322 | try | 8322 | try |
8323 | { | 8323 | { |
8324 | v = rules.GetVector3Item(idx++); // cut | 8324 | v = rules.GetVector3Item(idx++); // cut |
8325 | } | 8325 | } |
8326 | catch(InvalidCastException) | 8326 | catch(InvalidCastException) |
8327 | { | 8327 | { |
8328 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | 8328 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); |
8329 | return null; | 8329 | return null; |
8330 | } | 8330 | } |
8331 | try | 8331 | try |
8332 | { | 8332 | { |
8333 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8333 | hollow = (float)rules.GetLSLFloatItem(idx++); |
8334 | } | 8334 | } |
8335 | catch(InvalidCastException) | 8335 | catch(InvalidCastException) |
8336 | { | 8336 | { |
8337 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | 8337 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); |
8338 | return null; | 8338 | return null; |
8339 | } | 8339 | } |
8340 | try | 8340 | try |
8341 | { | 8341 | { |
8342 | twist = rules.GetVector3Item(idx++); | 8342 | twist = rules.GetVector3Item(idx++); |
8343 | } | 8343 | } |
8344 | catch(InvalidCastException) | 8344 | catch(InvalidCastException) |
8345 | { | 8345 | { |
8346 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 5 must be vector", rulesParsed, idx - idxStart - 1)); | 8346 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 5 must be vector", rulesParsed, idx - idxStart - 1)); |
8347 | return null; | 8347 | return null; |
8348 | } | 8348 | } |
8349 | try | 8349 | try |
8350 | { | 8350 | { |
8351 | taper_b = rules.GetVector3Item(idx++); | 8351 | taper_b = rules.GetVector3Item(idx++); |
8352 | } | 8352 | } |
8353 | catch(InvalidCastException) | 8353 | catch(InvalidCastException) |
8354 | { | 8354 | { |
8355 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | 8355 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); |
8356 | return null; | 8356 | return null; |
8357 | } | 8357 | } |
8358 | try | 8358 | try |
8359 | { | 8359 | { |
8360 | topshear = rules.GetVector3Item(idx++); | 8360 | topshear = rules.GetVector3Item(idx++); |
8361 | } | 8361 | } |
8362 | catch(InvalidCastException) | 8362 | catch(InvalidCastException) |
8363 | { | 8363 | { |
8364 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | 8364 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_BOX: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); |
8365 | return null; | 8365 | return null; |
8366 | } | 8366 | } |
8367 | 8367 | ||
8368 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, | 8368 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, |
8369 | (byte)ProfileShape.Square, (byte)Extrusion.Straight); | 8369 | (byte)ProfileShape.Square, (byte)Extrusion.Straight); |
8370 | break; | 8370 | break; |
8371 | 8371 | ||
8372 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | 8372 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: |
8373 | if (remain < 6) | 8373 | if (remain < 6) |
8374 | return null; | 8374 | return null; |
8375 | 8375 | ||
8376 | try | 8376 | try |
8377 | { | 8377 | { |
8378 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8378 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
8379 | } | 8379 | } |
8380 | catch(InvalidCastException) | 8380 | catch(InvalidCastException) |
8381 | { | 8381 | { |
8382 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 8382 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
8383 | return null; | 8383 | return null; |
8384 | } | 8384 | } |
8385 | try | 8385 | try |
8386 | { | 8386 | { |
8387 | v = rules.GetVector3Item(idx++); // cut | 8387 | v = rules.GetVector3Item(idx++); // cut |
8388 | } | 8388 | } |
8389 | catch(InvalidCastException) | 8389 | catch(InvalidCastException) |
8390 | { | 8390 | { |
8391 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | 8391 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); |
8392 | return null; | 8392 | return null; |
8393 | } | 8393 | } |
8394 | try | 8394 | try |
8395 | { | 8395 | { |
8396 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8396 | hollow = (float)rules.GetLSLFloatItem(idx++); |
8397 | } | 8397 | } |
8398 | catch(InvalidCastException) | 8398 | catch(InvalidCastException) |
8399 | { | 8399 | { |
8400 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 8400 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
8401 | return null; | 8401 | return null; |
8402 | } | 8402 | } |
8403 | try | 8403 | try |
8404 | { | 8404 | { |
8405 | twist = rules.GetVector3Item(idx++); | 8405 | twist = rules.GetVector3Item(idx++); |
8406 | } | 8406 | } |
8407 | catch(InvalidCastException) | 8407 | catch(InvalidCastException) |
8408 | { | 8408 | { |
8409 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | 8409 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); |
8410 | return null; | 8410 | return null; |
8411 | } | 8411 | } |
8412 | try | 8412 | try |
8413 | { | 8413 | { |
8414 | taper_b = rules.GetVector3Item(idx++); | 8414 | taper_b = rules.GetVector3Item(idx++); |
8415 | } | 8415 | } |
8416 | catch(InvalidCastException) | 8416 | catch(InvalidCastException) |
8417 | { | 8417 | { |
8418 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | 8418 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); |
8419 | return null; | 8419 | return null; |
8420 | } | 8420 | } |
8421 | try | 8421 | try |
8422 | { | 8422 | { |
8423 | topshear = rules.GetVector3Item(idx++); | 8423 | topshear = rules.GetVector3Item(idx++); |
8424 | } | 8424 | } |
8425 | catch(InvalidCastException) | 8425 | catch(InvalidCastException) |
8426 | { | 8426 | { |
8427 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | 8427 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_CYLINDER: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); |
8428 | return null; | 8428 | return null; |
8429 | } | 8429 | } |
8430 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, | 8430 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, |
8431 | (byte)ProfileShape.Circle, (byte)Extrusion.Straight); | 8431 | (byte)ProfileShape.Circle, (byte)Extrusion.Straight); |
8432 | break; | 8432 | break; |
8433 | 8433 | ||
8434 | case ScriptBaseClass.PRIM_TYPE_PRISM: | 8434 | case ScriptBaseClass.PRIM_TYPE_PRISM: |
8435 | if (remain < 6) | 8435 | if (remain < 6) |
8436 | return null; | 8436 | return null; |
8437 | 8437 | ||
8438 | try | 8438 | try |
8439 | { | 8439 | { |
8440 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8440 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
8441 | } | 8441 | } |
8442 | catch(InvalidCastException) | 8442 | catch(InvalidCastException) |
8443 | { | 8443 | { |
8444 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 8444 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
8445 | return null; | 8445 | return null; |
8446 | } | 8446 | } |
8447 | try | 8447 | try |
8448 | { | 8448 | { |
8449 | v = rules.GetVector3Item(idx++); //cut | 8449 | v = rules.GetVector3Item(idx++); //cut |
8450 | } | 8450 | } |
8451 | catch(InvalidCastException) | 8451 | catch(InvalidCastException) |
8452 | { | 8452 | { |
8453 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | 8453 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); |
8454 | return null; | 8454 | return null; |
8455 | } | 8455 | } |
8456 | try | 8456 | try |
8457 | { | 8457 | { |
8458 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8458 | hollow = (float)rules.GetLSLFloatItem(idx++); |
8459 | } | 8459 | } |
8460 | catch(InvalidCastException) | 8460 | catch(InvalidCastException) |
8461 | { | 8461 | { |
8462 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 8462 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
8463 | return null; | 8463 | return null; |
8464 | } | 8464 | } |
8465 | try | 8465 | try |
8466 | { | 8466 | { |
8467 | twist = rules.GetVector3Item(idx++); | 8467 | twist = rules.GetVector3Item(idx++); |
8468 | } | 8468 | } |
8469 | catch(InvalidCastException) | 8469 | catch(InvalidCastException) |
8470 | { | 8470 | { |
8471 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | 8471 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); |
8472 | return null; | 8472 | return null; |
8473 | } | 8473 | } |
8474 | try | 8474 | try |
8475 | { | 8475 | { |
8476 | taper_b = rules.GetVector3Item(idx++); | 8476 | taper_b = rules.GetVector3Item(idx++); |
8477 | } | 8477 | } |
8478 | catch(InvalidCastException) | 8478 | catch(InvalidCastException) |
8479 | { | 8479 | { |
8480 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | 8480 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); |
8481 | return null; | 8481 | return null; |
8482 | } | 8482 | } |
8483 | try | 8483 | try |
8484 | { | 8484 | { |
8485 | topshear = rules.GetVector3Item(idx++); | 8485 | topshear = rules.GetVector3Item(idx++); |
8486 | } | 8486 | } |
8487 | catch(InvalidCastException) | 8487 | catch(InvalidCastException) |
8488 | { | 8488 | { |
8489 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | 8489 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_PRISM: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); |
8490 | return null; | 8490 | return null; |
8491 | } | 8491 | } |
8492 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, | 8492 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, |
8493 | (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight); | 8493 | (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Straight); |
8494 | break; | 8494 | break; |
8495 | 8495 | ||
8496 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | 8496 | case ScriptBaseClass.PRIM_TYPE_SPHERE: |
8497 | if (remain < 5) | 8497 | if (remain < 5) |
8498 | return null; | 8498 | return null; |
8499 | 8499 | ||
8500 | try | 8500 | try |
8501 | { | 8501 | { |
8502 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8502 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
8503 | } | 8503 | } |
8504 | catch(InvalidCastException) | 8504 | catch(InvalidCastException) |
8505 | { | 8505 | { |
8506 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 8506 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
8507 | return null; | 8507 | return null; |
8508 | } | 8508 | } |
8509 | try | 8509 | try |
8510 | { | 8510 | { |
8511 | v = rules.GetVector3Item(idx++); // cut | 8511 | v = rules.GetVector3Item(idx++); // cut |
8512 | } | 8512 | } |
8513 | catch(InvalidCastException) | 8513 | catch(InvalidCastException) |
8514 | { | 8514 | { |
8515 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | 8515 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); |
8516 | return null; | 8516 | return null; |
8517 | } | 8517 | } |
8518 | try | 8518 | try |
8519 | { | 8519 | { |
8520 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8520 | hollow = (float)rules.GetLSLFloatItem(idx++); |
8521 | } | 8521 | } |
8522 | catch(InvalidCastException) | 8522 | catch(InvalidCastException) |
8523 | { | 8523 | { |
8524 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 8524 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
8525 | return null; | 8525 | return null; |
8526 | } | 8526 | } |
8527 | try | 8527 | try |
8528 | { | 8528 | { |
8529 | twist = rules.GetVector3Item(idx++); | 8529 | twist = rules.GetVector3Item(idx++); |
8530 | } | 8530 | } |
8531 | catch(InvalidCastException) | 8531 | catch(InvalidCastException) |
8532 | { | 8532 | { |
8533 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | 8533 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); |
8534 | return null; | 8534 | return null; |
8535 | } | 8535 | } |
8536 | try | 8536 | try |
8537 | { | 8537 | { |
8538 | taper_b = rules.GetVector3Item(idx++); // dimple | 8538 | taper_b = rules.GetVector3Item(idx++); // dimple |
8539 | } | 8539 | } |
8540 | catch(InvalidCastException) | 8540 | catch(InvalidCastException) |
8541 | { | 8541 | { |
8542 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | 8542 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SPHERE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); |
8543 | return null; | 8543 | return null; |
8544 | } | 8544 | } |
8545 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, | 8545 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, |
8546 | (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1); | 8546 | (byte)ProfileShape.HalfCircle, (byte)Extrusion.Curve1); |
8547 | break; | 8547 | break; |
8548 | 8548 | ||
8549 | case ScriptBaseClass.PRIM_TYPE_TORUS: | 8549 | case ScriptBaseClass.PRIM_TYPE_TORUS: |
8550 | if (remain < 11) | 8550 | if (remain < 11) |
8551 | return null; | 8551 | return null; |
8552 | 8552 | ||
8553 | try | 8553 | try |
8554 | { | 8554 | { |
8555 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8555 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
8556 | } | 8556 | } |
8557 | catch(InvalidCastException) | 8557 | catch(InvalidCastException) |
8558 | { | 8558 | { |
8559 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 8559 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
8560 | return null; | 8560 | return null; |
8561 | } | 8561 | } |
8562 | try | 8562 | try |
8563 | { | 8563 | { |
8564 | v = rules.GetVector3Item(idx++); //cut | 8564 | v = rules.GetVector3Item(idx++); //cut |
8565 | } | 8565 | } |
8566 | catch(InvalidCastException) | 8566 | catch(InvalidCastException) |
8567 | { | 8567 | { |
8568 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | 8568 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); |
8569 | return null; | 8569 | return null; |
8570 | } | 8570 | } |
8571 | try | 8571 | try |
8572 | { | 8572 | { |
8573 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8573 | hollow = (float)rules.GetLSLFloatItem(idx++); |
8574 | } | 8574 | } |
8575 | catch(InvalidCastException) | 8575 | catch(InvalidCastException) |
8576 | { | 8576 | { |
8577 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 8577 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
8578 | return null; | 8578 | return null; |
8579 | } | 8579 | } |
8580 | try | 8580 | try |
8581 | { | 8581 | { |
8582 | twist = rules.GetVector3Item(idx++); | 8582 | twist = rules.GetVector3Item(idx++); |
8583 | } | 8583 | } |
8584 | catch(InvalidCastException) | 8584 | catch(InvalidCastException) |
8585 | { | 8585 | { |
8586 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | 8586 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); |
8587 | return null; | 8587 | return null; |
8588 | } | 8588 | } |
8589 | try | 8589 | try |
8590 | { | 8590 | { |
8591 | holesize = rules.GetVector3Item(idx++); | 8591 | holesize = rules.GetVector3Item(idx++); |
8592 | } | 8592 | } |
8593 | catch(InvalidCastException) | 8593 | catch(InvalidCastException) |
8594 | { | 8594 | { |
8595 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | 8595 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); |
8596 | return null; | 8596 | return null; |
8597 | } | 8597 | } |
8598 | try | 8598 | try |
8599 | { | 8599 | { |
8600 | topshear = rules.GetVector3Item(idx++); | 8600 | topshear = rules.GetVector3Item(idx++); |
8601 | } | 8601 | } |
8602 | catch(InvalidCastException) | 8602 | catch(InvalidCastException) |
8603 | { | 8603 | { |
8604 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | 8604 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); |
8605 | return null; | 8605 | return null; |
8606 | } | 8606 | } |
8607 | try | 8607 | try |
8608 | { | 8608 | { |
8609 | profilecut = rules.GetVector3Item(idx++); | 8609 | profilecut = rules.GetVector3Item(idx++); |
8610 | } | 8610 | } |
8611 | catch(InvalidCastException) | 8611 | catch(InvalidCastException) |
8612 | { | 8612 | { |
8613 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); | 8613 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); |
8614 | return null; | 8614 | return null; |
8615 | } | 8615 | } |
8616 | try | 8616 | try |
8617 | { | 8617 | { |
8618 | taper_b = rules.GetVector3Item(idx++); // taper_a | 8618 | taper_b = rules.GetVector3Item(idx++); // taper_a |
8619 | } | 8619 | } |
8620 | catch(InvalidCastException) | 8620 | catch(InvalidCastException) |
8621 | { | 8621 | { |
8622 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); | 8622 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); |
8623 | return null; | 8623 | return null; |
8624 | } | 8624 | } |
8625 | try | 8625 | try |
8626 | { | 8626 | { |
8627 | revolutions = (float)rules.GetLSLFloatItem(idx++); | 8627 | revolutions = (float)rules.GetLSLFloatItem(idx++); |
8628 | } | 8628 | } |
8629 | catch(InvalidCastException) | 8629 | catch(InvalidCastException) |
8630 | { | 8630 | { |
8631 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); | 8631 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); |
8632 | return null; | 8632 | return null; |
8633 | } | 8633 | } |
8634 | try | 8634 | try |
8635 | { | 8635 | { |
8636 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | 8636 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); |
8637 | } | 8637 | } |
8638 | catch(InvalidCastException) | 8638 | catch(InvalidCastException) |
8639 | { | 8639 | { |
8640 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); | 8640 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); |
8641 | return null; | 8641 | return null; |
8642 | } | 8642 | } |
8643 | try | 8643 | try |
8644 | { | 8644 | { |
8645 | skew = (float)rules.GetLSLFloatItem(idx++); | 8645 | skew = (float)rules.GetLSLFloatItem(idx++); |
8646 | } | 8646 | } |
8647 | catch(InvalidCastException) | 8647 | catch(InvalidCastException) |
8648 | { | 8648 | { |
8649 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 13 must be vector", rulesParsed, idx - idxStart - 1)); | 8649 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TORUS: arg #{1} - parameter 13 must be vector", rulesParsed, idx - idxStart - 1)); |
8650 | return null; | 8650 | return null; |
8651 | } | 8651 | } |
8652 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, | 8652 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, |
8653 | revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1); | 8653 | revolutions, radiusoffset, skew, (byte)ProfileShape.Circle, (byte)Extrusion.Curve1); |
8654 | break; | 8654 | break; |
8655 | 8655 | ||
8656 | case ScriptBaseClass.PRIM_TYPE_TUBE: | 8656 | case ScriptBaseClass.PRIM_TYPE_TUBE: |
8657 | if (remain < 11) | 8657 | if (remain < 11) |
8658 | return null; | 8658 | return null; |
8659 | 8659 | ||
8660 | try | 8660 | try |
8661 | { | 8661 | { |
8662 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8662 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
8663 | } | 8663 | } |
8664 | catch(InvalidCastException) | 8664 | catch(InvalidCastException) |
8665 | { | 8665 | { |
8666 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 8666 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
8667 | return null; | 8667 | return null; |
8668 | } | 8668 | } |
8669 | try | 8669 | try |
8670 | { | 8670 | { |
8671 | v = rules.GetVector3Item(idx++); //cut | 8671 | v = rules.GetVector3Item(idx++); //cut |
8672 | } | 8672 | } |
8673 | catch(InvalidCastException) | 8673 | catch(InvalidCastException) |
8674 | { | 8674 | { |
8675 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | 8675 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); |
8676 | return null; | 8676 | return null; |
8677 | } | 8677 | } |
8678 | try | 8678 | try |
8679 | { | 8679 | { |
8680 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8680 | hollow = (float)rules.GetLSLFloatItem(idx++); |
8681 | } | 8681 | } |
8682 | catch(InvalidCastException) | 8682 | catch(InvalidCastException) |
8683 | { | 8683 | { |
8684 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 8684 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
8685 | return null; | 8685 | return null; |
8686 | } | 8686 | } |
8687 | try | 8687 | try |
8688 | { | 8688 | { |
8689 | twist = rules.GetVector3Item(idx++); | 8689 | twist = rules.GetVector3Item(idx++); |
8690 | } | 8690 | } |
8691 | catch(InvalidCastException) | 8691 | catch(InvalidCastException) |
8692 | { | 8692 | { |
8693 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | 8693 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); |
8694 | return null; | 8694 | return null; |
8695 | } | 8695 | } |
8696 | try | 8696 | try |
8697 | { | 8697 | { |
8698 | holesize = rules.GetVector3Item(idx++); | 8698 | holesize = rules.GetVector3Item(idx++); |
8699 | } | 8699 | } |
8700 | catch(InvalidCastException) | 8700 | catch(InvalidCastException) |
8701 | { | 8701 | { |
8702 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | 8702 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); |
8703 | return null; | 8703 | return null; |
8704 | } | 8704 | } |
8705 | try | 8705 | try |
8706 | { | 8706 | { |
8707 | topshear = rules.GetVector3Item(idx++); | 8707 | topshear = rules.GetVector3Item(idx++); |
8708 | } | 8708 | } |
8709 | catch(InvalidCastException) | 8709 | catch(InvalidCastException) |
8710 | { | 8710 | { |
8711 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | 8711 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); |
8712 | return null; | 8712 | return null; |
8713 | } | 8713 | } |
8714 | try | 8714 | try |
8715 | { | 8715 | { |
8716 | profilecut = rules.GetVector3Item(idx++); | 8716 | profilecut = rules.GetVector3Item(idx++); |
8717 | } | 8717 | } |
8718 | catch(InvalidCastException) | 8718 | catch(InvalidCastException) |
8719 | { | 8719 | { |
8720 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); | 8720 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); |
8721 | return null; | 8721 | return null; |
8722 | } | 8722 | } |
8723 | try | 8723 | try |
8724 | { | 8724 | { |
8725 | taper_b = rules.GetVector3Item(idx++); // taper_a | 8725 | taper_b = rules.GetVector3Item(idx++); // taper_a |
8726 | } | 8726 | } |
8727 | catch(InvalidCastException) | 8727 | catch(InvalidCastException) |
8728 | { | 8728 | { |
8729 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); | 8729 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); |
8730 | return null; | 8730 | return null; |
8731 | } | 8731 | } |
8732 | try | 8732 | try |
8733 | { | 8733 | { |
8734 | revolutions = (float)rules.GetLSLFloatItem(idx++); | 8734 | revolutions = (float)rules.GetLSLFloatItem(idx++); |
8735 | } | 8735 | } |
8736 | catch(InvalidCastException) | 8736 | catch(InvalidCastException) |
8737 | { | 8737 | { |
8738 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); | 8738 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); |
8739 | return null; | 8739 | return null; |
8740 | } | 8740 | } |
8741 | try | 8741 | try |
8742 | { | 8742 | { |
8743 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | 8743 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); |
8744 | } | 8744 | } |
8745 | catch(InvalidCastException) | 8745 | catch(InvalidCastException) |
8746 | { | 8746 | { |
8747 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); | 8747 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); |
8748 | return null; | 8748 | return null; |
8749 | } | 8749 | } |
8750 | try | 8750 | try |
8751 | { | 8751 | { |
8752 | skew = (float)rules.GetLSLFloatItem(idx++); | 8752 | skew = (float)rules.GetLSLFloatItem(idx++); |
8753 | } | 8753 | } |
8754 | catch(InvalidCastException) | 8754 | catch(InvalidCastException) |
8755 | { | 8755 | { |
8756 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); | 8756 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_TUBE: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); |
8757 | return null; | 8757 | return null; |
8758 | } | 8758 | } |
8759 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, | 8759 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, |
8760 | revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1); | 8760 | revolutions, radiusoffset, skew, (byte)ProfileShape.Square, (byte)Extrusion.Curve1); |
8761 | break; | 8761 | break; |
8762 | 8762 | ||
8763 | case ScriptBaseClass.PRIM_TYPE_RING: | 8763 | case ScriptBaseClass.PRIM_TYPE_RING: |
8764 | if (remain < 11) | 8764 | if (remain < 11) |
8765 | return null; | 8765 | return null; |
8766 | 8766 | ||
8767 | try | 8767 | try |
8768 | { | 8768 | { |
8769 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | 8769 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape |
8770 | } | 8770 | } |
8771 | catch(InvalidCastException) | 8771 | catch(InvalidCastException) |
8772 | { | 8772 | { |
8773 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 8773 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
8774 | return null; | 8774 | return null; |
8775 | } | 8775 | } |
8776 | try | 8776 | try |
8777 | { | 8777 | { |
8778 | v = rules.GetVector3Item(idx++); //cut | 8778 | v = rules.GetVector3Item(idx++); //cut |
8779 | } | 8779 | } |
8780 | catch(InvalidCastException) | 8780 | catch(InvalidCastException) |
8781 | { | 8781 | { |
8782 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | 8782 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); |
8783 | return null; | 8783 | return null; |
8784 | } | 8784 | } |
8785 | try | 8785 | try |
8786 | { | 8786 | { |
8787 | hollow = (float)rules.GetLSLFloatItem(idx++); | 8787 | hollow = (float)rules.GetLSLFloatItem(idx++); |
8788 | } | 8788 | } |
8789 | catch(InvalidCastException) | 8789 | catch(InvalidCastException) |
8790 | { | 8790 | { |
8791 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 8791 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
8792 | return null; | 8792 | return null; |
8793 | } | 8793 | } |
8794 | try | 8794 | try |
8795 | { | 8795 | { |
8796 | twist = rules.GetVector3Item(idx++); | 8796 | twist = rules.GetVector3Item(idx++); |
8797 | } | 8797 | } |
8798 | catch(InvalidCastException) | 8798 | catch(InvalidCastException) |
8799 | { | 8799 | { |
8800 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); | 8800 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 6 must be vector", rulesParsed, idx - idxStart - 1)); |
8801 | return null; | 8801 | return null; |
8802 | } | 8802 | } |
8803 | try | 8803 | try |
8804 | { | 8804 | { |
8805 | holesize = rules.GetVector3Item(idx++); | 8805 | holesize = rules.GetVector3Item(idx++); |
8806 | } | 8806 | } |
8807 | catch(InvalidCastException) | 8807 | catch(InvalidCastException) |
8808 | { | 8808 | { |
8809 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); | 8809 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 7 must be vector", rulesParsed, idx - idxStart - 1)); |
8810 | return null; | 8810 | return null; |
8811 | } | 8811 | } |
8812 | try | 8812 | try |
8813 | { | 8813 | { |
8814 | topshear = rules.GetVector3Item(idx++); | 8814 | topshear = rules.GetVector3Item(idx++); |
8815 | } | 8815 | } |
8816 | catch(InvalidCastException) | 8816 | catch(InvalidCastException) |
8817 | { | 8817 | { |
8818 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | 8818 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); |
8819 | return null; | 8819 | return null; |
8820 | } | 8820 | } |
8821 | try | 8821 | try |
8822 | { | 8822 | { |
8823 | profilecut = rules.GetVector3Item(idx++); | 8823 | profilecut = rules.GetVector3Item(idx++); |
8824 | } | 8824 | } |
8825 | catch(InvalidCastException) | 8825 | catch(InvalidCastException) |
8826 | { | 8826 | { |
8827 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); | 8827 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 9 must be vector", rulesParsed, idx - idxStart - 1)); |
8828 | return null; | 8828 | return null; |
8829 | } | 8829 | } |
8830 | try | 8830 | try |
8831 | { | 8831 | { |
8832 | taper_b = rules.GetVector3Item(idx++); // taper_a | 8832 | taper_b = rules.GetVector3Item(idx++); // taper_a |
8833 | } | 8833 | } |
8834 | catch(InvalidCastException) | 8834 | catch(InvalidCastException) |
8835 | { | 8835 | { |
8836 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); | 8836 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 10 must be vector", rulesParsed, idx - idxStart - 1)); |
8837 | return null; | 8837 | return null; |
8838 | } | 8838 | } |
8839 | try | 8839 | try |
8840 | { | 8840 | { |
8841 | revolutions = (float)rules.GetLSLFloatItem(idx++); | 8841 | revolutions = (float)rules.GetLSLFloatItem(idx++); |
8842 | } | 8842 | } |
8843 | catch(InvalidCastException) | 8843 | catch(InvalidCastException) |
8844 | { | 8844 | { |
8845 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); | 8845 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 11 must be float", rulesParsed, idx - idxStart - 1)); |
8846 | return null; | 8846 | return null; |
8847 | } | 8847 | } |
8848 | try | 8848 | try |
8849 | { | 8849 | { |
8850 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | 8850 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); |
8851 | } | 8851 | } |
8852 | catch(InvalidCastException) | 8852 | catch(InvalidCastException) |
8853 | { | 8853 | { |
8854 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); | 8854 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 12 must be float", rulesParsed, idx - idxStart - 1)); |
8855 | return null; | 8855 | return null; |
8856 | } | 8856 | } |
8857 | try | 8857 | try |
8858 | { | 8858 | { |
8859 | skew = (float)rules.GetLSLFloatItem(idx++); | 8859 | skew = (float)rules.GetLSLFloatItem(idx++); |
8860 | } | 8860 | } |
8861 | catch(InvalidCastException) | 8861 | catch(InvalidCastException) |
8862 | { | 8862 | { |
8863 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); | 8863 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_RING: arg #{1} - parameter 13 must be float", rulesParsed, idx - idxStart - 1)); |
8864 | return null; | 8864 | return null; |
8865 | } | 8865 | } |
8866 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, | 8866 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, |
8867 | revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1); | 8867 | revolutions, radiusoffset, skew, (byte)ProfileShape.EquilateralTriangle, (byte)Extrusion.Curve1); |
8868 | break; | 8868 | break; |
8869 | 8869 | ||
8870 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | 8870 | case ScriptBaseClass.PRIM_TYPE_SCULPT: |
8871 | if (remain < 2) | 8871 | if (remain < 2) |
8872 | return null; | 8872 | return null; |
8873 | 8873 | ||
8874 | string map = rules.Data[idx++].ToString(); | 8874 | string map = rules.Data[idx++].ToString(); |
8875 | try | 8875 | try |
8876 | { | 8876 | { |
8877 | face = (int)rules.GetLSLIntegerItem(idx++); // type | 8877 | face = (int)rules.GetLSLIntegerItem(idx++); // type |
8878 | } | 8878 | } |
8879 | catch(InvalidCastException) | 8879 | catch(InvalidCastException) |
8880 | { | 8880 | { |
8881 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SCULPT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); | 8881 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TYPE, PRIM_TYPE_SCULPT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); |
8882 | return null; | 8882 | return null; |
8883 | } | 8883 | } |
8884 | SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1); | 8884 | SetPrimitiveShapeParams(part, map, face, (byte)Extrusion.Curve1); |
8885 | break; | 8885 | break; |
8886 | } | 8886 | } |
8887 | 8887 | ||
8888 | break; | 8888 | break; |
8889 | 8889 | ||
8890 | case ScriptBaseClass.PRIM_TEXTURE: | 8890 | case ScriptBaseClass.PRIM_TEXTURE: |
8891 | if (remain < 5) | 8891 | if (remain < 5) |
8892 | return null; | 8892 | return null; |
8893 | 8893 | ||
8894 | face=(int)rules.GetLSLIntegerItem(idx++); | 8894 | face=(int)rules.GetLSLIntegerItem(idx++); |
8895 | string tex; | 8895 | string tex; |
8896 | LSL_Vector repeats; | 8896 | LSL_Vector repeats; |
8897 | LSL_Vector offsets; | 8897 | LSL_Vector offsets; |
8898 | double rotation; | 8898 | double rotation; |
8899 | 8899 | ||
8900 | tex = rules.Data[idx++].ToString(); | 8900 | tex = rules.Data[idx++].ToString(); |
8901 | try | 8901 | try |
8902 | { | 8902 | { |
8903 | repeats = rules.GetVector3Item(idx++); | 8903 | repeats = rules.GetVector3Item(idx++); |
8904 | } | 8904 | } |
8905 | catch(InvalidCastException) | 8905 | catch(InvalidCastException) |
8906 | { | 8906 | { |
8907 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | 8907 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); |
8908 | return null; | 8908 | return null; |
8909 | } | 8909 | } |
8910 | try | 8910 | try |
8911 | { | 8911 | { |
8912 | offsets = rules.GetVector3Item(idx++); | 8912 | offsets = rules.GetVector3Item(idx++); |
8913 | } | 8913 | } |
8914 | catch(InvalidCastException) | 8914 | catch(InvalidCastException) |
8915 | { | 8915 | { |
8916 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); | 8916 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 4 must be vector", rulesParsed, idx - idxStart - 1)); |
8917 | return null; | 8917 | return null; |
8918 | } | 8918 | } |
8919 | try | 8919 | try |
8920 | { | 8920 | { |
8921 | rotation = (double)rules.GetLSLFloatItem(idx++); | 8921 | rotation = (double)rules.GetLSLFloatItem(idx++); |
8922 | } | 8922 | } |
8923 | catch(InvalidCastException) | 8923 | catch(InvalidCastException) |
8924 | { | 8924 | { |
8925 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 8925 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXTURE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
8926 | return null; | 8926 | return null; |
8927 | } | 8927 | } |
8928 | 8928 | ||
8929 | SetTexture(part, tex, face); | 8929 | SetTexture(part, tex, face); |
8930 | ScaleTexture(part, repeats.x, repeats.y, face); | 8930 | ScaleTexture(part, repeats.x, repeats.y, face); |
8931 | OffsetTexture(part, offsets.x, offsets.y, face); | 8931 | OffsetTexture(part, offsets.x, offsets.y, face); |
8932 | RotateTexture(part, rotation, face); | 8932 | RotateTexture(part, rotation, face); |
8933 | 8933 | ||
8934 | break; | 8934 | break; |
8935 | 8935 | ||
8936 | case ScriptBaseClass.PRIM_COLOR: | 8936 | case ScriptBaseClass.PRIM_COLOR: |
8937 | if (remain < 3) | 8937 | if (remain < 3) |
8938 | return null; | 8938 | return null; |
8939 | 8939 | ||
8940 | LSL_Vector color; | 8940 | LSL_Vector color; |
8941 | double alpha; | 8941 | double alpha; |
8942 | 8942 | ||
8943 | try | 8943 | try |
8944 | { | 8944 | { |
8945 | face = (int)rules.GetLSLIntegerItem(idx++); | 8945 | face = (int)rules.GetLSLIntegerItem(idx++); |
8946 | } | 8946 | } |
8947 | catch(InvalidCastException) | 8947 | catch(InvalidCastException) |
8948 | { | 8948 | { |
8949 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 8949 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
8950 | return null; | 8950 | return null; |
8951 | } | 8951 | } |
8952 | try | 8952 | try |
8953 | { | 8953 | { |
8954 | color = rules.GetVector3Item(idx++); | 8954 | color = rules.GetVector3Item(idx++); |
8955 | } | 8955 | } |
8956 | catch(InvalidCastException) | 8956 | catch(InvalidCastException) |
8957 | { | 8957 | { |
8958 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | 8958 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); |
8959 | return null; | 8959 | return null; |
8960 | } | 8960 | } |
8961 | try | 8961 | try |
8962 | { | 8962 | { |
8963 | alpha = (double)rules.GetLSLFloatItem(idx++); | 8963 | alpha = (double)rules.GetLSLFloatItem(idx++); |
8964 | } | 8964 | } |
8965 | catch(InvalidCastException) | 8965 | catch(InvalidCastException) |
8966 | { | 8966 | { |
8967 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | 8967 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_COLOR: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); |
8968 | return null; | 8968 | return null; |
8969 | } | 8969 | } |
8970 | 8970 | ||
8971 | part.SetFaceColorAlpha(face, color, alpha); | 8971 | part.SetFaceColorAlpha(face, color, alpha); |
8972 | 8972 | ||
8973 | break; | 8973 | break; |
8974 | 8974 | ||
8975 | case ScriptBaseClass.PRIM_FLEXIBLE: | 8975 | case ScriptBaseClass.PRIM_FLEXIBLE: |
8976 | if (remain < 7) | 8976 | if (remain < 7) |
8977 | return null; | 8977 | return null; |
8978 | bool flexi; | 8978 | bool flexi; |
8979 | int softness; | 8979 | int softness; |
8980 | float gravity; | 8980 | float gravity; |
8981 | float friction; | 8981 | float friction; |
8982 | float wind; | 8982 | float wind; |
8983 | float tension; | 8983 | float tension; |
8984 | LSL_Vector force; | 8984 | LSL_Vector force; |
8985 | 8985 | ||
8986 | try | 8986 | try |
8987 | { | 8987 | { |
8988 | flexi = rules.GetLSLIntegerItem(idx++); | 8988 | flexi = rules.GetLSLIntegerItem(idx++); |
8989 | } | 8989 | } |
8990 | catch(InvalidCastException) | 8990 | catch(InvalidCastException) |
8991 | { | 8991 | { |
8992 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 8992 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
8993 | return null; | 8993 | return null; |
8994 | } | 8994 | } |
8995 | try | 8995 | try |
8996 | { | 8996 | { |
8997 | softness = rules.GetLSLIntegerItem(idx++); | 8997 | softness = rules.GetLSLIntegerItem(idx++); |
8998 | } | 8998 | } |
8999 | catch(InvalidCastException) | 8999 | catch(InvalidCastException) |
9000 | { | 9000 | { |
9001 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 9001 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
9002 | return null; | 9002 | return null; |
9003 | } | 9003 | } |
9004 | try | 9004 | try |
9005 | { | 9005 | { |
9006 | gravity = (float)rules.GetLSLFloatItem(idx++); | 9006 | gravity = (float)rules.GetLSLFloatItem(idx++); |
9007 | } | 9007 | } |
9008 | catch(InvalidCastException) | 9008 | catch(InvalidCastException) |
9009 | { | 9009 | { |
9010 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | 9010 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); |
9011 | return null; | 9011 | return null; |
9012 | } | 9012 | } |
9013 | try | 9013 | try |
9014 | { | 9014 | { |
9015 | friction = (float)rules.GetLSLFloatItem(idx++); | 9015 | friction = (float)rules.GetLSLFloatItem(idx++); |
9016 | } | 9016 | } |
9017 | catch(InvalidCastException) | 9017 | catch(InvalidCastException) |
9018 | { | 9018 | { |
9019 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 9019 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
9020 | return null; | 9020 | return null; |
9021 | } | 9021 | } |
9022 | try | 9022 | try |
9023 | { | 9023 | { |
9024 | wind = (float)rules.GetLSLFloatItem(idx++); | 9024 | wind = (float)rules.GetLSLFloatItem(idx++); |
9025 | } | 9025 | } |
9026 | catch(InvalidCastException) | 9026 | catch(InvalidCastException) |
9027 | { | 9027 | { |
9028 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); | 9028 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); |
9029 | return null; | 9029 | return null; |
9030 | } | 9030 | } |
9031 | try | 9031 | try |
9032 | { | 9032 | { |
9033 | tension = (float)rules.GetLSLFloatItem(idx++); | 9033 | tension = (float)rules.GetLSLFloatItem(idx++); |
9034 | } | 9034 | } |
9035 | catch(InvalidCastException) | 9035 | catch(InvalidCastException) |
9036 | { | 9036 | { |
9037 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 7 must be float", rulesParsed, idx - idxStart - 1)); | 9037 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 7 must be float", rulesParsed, idx - idxStart - 1)); |
9038 | return null; | 9038 | return null; |
9039 | } | 9039 | } |
9040 | try | 9040 | try |
9041 | { | 9041 | { |
9042 | force = rules.GetVector3Item(idx++); | 9042 | force = rules.GetVector3Item(idx++); |
9043 | } | 9043 | } |
9044 | catch(InvalidCastException) | 9044 | catch(InvalidCastException) |
9045 | { | 9045 | { |
9046 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); | 9046 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FLEXIBLE: arg #{1} - parameter 8 must be vector", rulesParsed, idx - idxStart - 1)); |
9047 | return null; | 9047 | return null; |
9048 | } | 9048 | } |
9049 | 9049 | ||
9050 | SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); | 9050 | SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); |
9051 | 9051 | ||
9052 | break; | 9052 | break; |
9053 | 9053 | ||
9054 | case ScriptBaseClass.PRIM_POINT_LIGHT: | 9054 | case ScriptBaseClass.PRIM_POINT_LIGHT: |
9055 | if (remain < 5) | 9055 | if (remain < 5) |
9056 | return null; | 9056 | return null; |
9057 | bool light; | 9057 | bool light; |
9058 | LSL_Vector lightcolor; | 9058 | LSL_Vector lightcolor; |
9059 | float intensity; | 9059 | float intensity; |
9060 | float radius; | 9060 | float radius; |
9061 | float falloff; | 9061 | float falloff; |
9062 | 9062 | ||
9063 | try | 9063 | try |
9064 | { | 9064 | { |
9065 | light = rules.GetLSLIntegerItem(idx++); | 9065 | light = rules.GetLSLIntegerItem(idx++); |
9066 | } | 9066 | } |
9067 | catch(InvalidCastException) | 9067 | catch(InvalidCastException) |
9068 | { | 9068 | { |
9069 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 9069 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
9070 | return null; | 9070 | return null; |
9071 | } | 9071 | } |
9072 | try | 9072 | try |
9073 | { | 9073 | { |
9074 | lightcolor = rules.GetVector3Item(idx++); | 9074 | lightcolor = rules.GetVector3Item(idx++); |
9075 | } | 9075 | } |
9076 | catch(InvalidCastException) | 9076 | catch(InvalidCastException) |
9077 | { | 9077 | { |
9078 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | 9078 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); |
9079 | return null; | 9079 | return null; |
9080 | } | 9080 | } |
9081 | try | 9081 | try |
9082 | { | 9082 | { |
9083 | intensity = (float)rules.GetLSLFloatItem(idx++); | 9083 | intensity = (float)rules.GetLSLFloatItem(idx++); |
9084 | } | 9084 | } |
9085 | catch(InvalidCastException) | 9085 | catch(InvalidCastException) |
9086 | { | 9086 | { |
9087 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | 9087 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); |
9088 | return null; | 9088 | return null; |
9089 | } | 9089 | } |
9090 | try | 9090 | try |
9091 | { | 9091 | { |
9092 | radius = (float)rules.GetLSLFloatItem(idx++); | 9092 | radius = (float)rules.GetLSLFloatItem(idx++); |
9093 | } | 9093 | } |
9094 | catch(InvalidCastException) | 9094 | catch(InvalidCastException) |
9095 | { | 9095 | { |
9096 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); | 9096 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 5 must be float", rulesParsed, idx - idxStart - 1)); |
9097 | return null; | 9097 | return null; |
9098 | } | 9098 | } |
9099 | try | 9099 | try |
9100 | { | 9100 | { |
9101 | falloff = (float)rules.GetLSLFloatItem(idx++); | 9101 | falloff = (float)rules.GetLSLFloatItem(idx++); |
9102 | } | 9102 | } |
9103 | catch(InvalidCastException) | 9103 | catch(InvalidCastException) |
9104 | { | 9104 | { |
9105 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); | 9105 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POINT_LIGHT: arg #{1} - parameter 6 must be float", rulesParsed, idx - idxStart - 1)); |
9106 | return null; | 9106 | return null; |
9107 | } | 9107 | } |
9108 | 9108 | ||
9109 | SetPointLight(part, light, lightcolor, intensity, radius, falloff); | 9109 | SetPointLight(part, light, lightcolor, intensity, radius, falloff); |
9110 | 9110 | ||
9111 | break; | 9111 | break; |
9112 | 9112 | ||
9113 | case ScriptBaseClass.PRIM_GLOW: | 9113 | case ScriptBaseClass.PRIM_GLOW: |
9114 | if (remain < 2) | 9114 | if (remain < 2) |
9115 | return null; | 9115 | return null; |
9116 | 9116 | ||
9117 | float glow; | 9117 | float glow; |
9118 | 9118 | ||
9119 | try | 9119 | try |
9120 | { | 9120 | { |
9121 | face = rules.GetLSLIntegerItem(idx++); | 9121 | face = rules.GetLSLIntegerItem(idx++); |
9122 | } | 9122 | } |
9123 | catch(InvalidCastException) | 9123 | catch(InvalidCastException) |
9124 | { | 9124 | { |
9125 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 9125 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
9126 | return null; | 9126 | return null; |
9127 | } | 9127 | } |
9128 | try | 9128 | try |
9129 | { | 9129 | { |
9130 | glow = (float)rules.GetLSLFloatItem(idx++); | 9130 | glow = (float)rules.GetLSLFloatItem(idx++); |
9131 | } | 9131 | } |
9132 | catch(InvalidCastException) | 9132 | catch(InvalidCastException) |
9133 | { | 9133 | { |
9134 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); | 9134 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_GLOW: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); |
9135 | return null; | 9135 | return null; |
9136 | } | 9136 | } |
9137 | 9137 | ||
9138 | SetGlow(part, face, glow); | 9138 | SetGlow(part, face, glow); |
9139 | 9139 | ||
9140 | break; | 9140 | break; |
9141 | 9141 | ||
9142 | case ScriptBaseClass.PRIM_BUMP_SHINY: | 9142 | case ScriptBaseClass.PRIM_BUMP_SHINY: |
9143 | if (remain < 3) | 9143 | if (remain < 3) |
9144 | return null; | 9144 | return null; |
9145 | 9145 | ||
9146 | int shiny; | 9146 | int shiny; |
9147 | Bumpiness bump; | 9147 | Bumpiness bump; |
9148 | 9148 | ||
9149 | try | 9149 | try |
9150 | { | 9150 | { |
9151 | face = (int)rules.GetLSLIntegerItem(idx++); | 9151 | face = (int)rules.GetLSLIntegerItem(idx++); |
9152 | } | 9152 | } |
9153 | catch(InvalidCastException) | 9153 | catch(InvalidCastException) |
9154 | { | 9154 | { |
9155 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 9155 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
9156 | return null; | 9156 | return null; |
9157 | } | 9157 | } |
9158 | try | 9158 | try |
9159 | { | 9159 | { |
9160 | shiny = (int)rules.GetLSLIntegerItem(idx++); | 9160 | shiny = (int)rules.GetLSLIntegerItem(idx++); |
9161 | } | 9161 | } |
9162 | catch(InvalidCastException) | 9162 | catch(InvalidCastException) |
9163 | { | 9163 | { |
9164 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 9164 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
9165 | return null; | 9165 | return null; |
9166 | } | 9166 | } |
9167 | try | 9167 | try |
9168 | { | 9168 | { |
9169 | bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); | 9169 | bump = (Bumpiness)(int)rules.GetLSLIntegerItem(idx++); |
9170 | } | 9170 | } |
9171 | catch(InvalidCastException) | 9171 | catch(InvalidCastException) |
9172 | { | 9172 | { |
9173 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); | 9173 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_BUMP_SHINY: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); |
9174 | return null; | 9174 | return null; |
9175 | } | 9175 | } |
9176 | 9176 | ||
9177 | SetShiny(part, face, shiny, bump); | 9177 | SetShiny(part, face, shiny, bump); |
9178 | 9178 | ||
9179 | break; | 9179 | break; |
9180 | 9180 | ||
9181 | case ScriptBaseClass.PRIM_FULLBRIGHT: | 9181 | case ScriptBaseClass.PRIM_FULLBRIGHT: |
9182 | if (remain < 2) | 9182 | if (remain < 2) |
9183 | return null; | 9183 | return null; |
9184 | bool st; | 9184 | bool st; |
9185 | 9185 | ||
9186 | try | 9186 | try |
9187 | { | 9187 | { |
9188 | face = rules.GetLSLIntegerItem(idx++); | 9188 | face = rules.GetLSLIntegerItem(idx++); |
9189 | } | 9189 | } |
9190 | catch(InvalidCastException) | 9190 | catch(InvalidCastException) |
9191 | { | 9191 | { |
9192 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 9192 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
9193 | return null; | 9193 | return null; |
9194 | } | 9194 | } |
9195 | try | 9195 | try |
9196 | { | 9196 | { |
9197 | st = rules.GetLSLIntegerItem(idx++); | 9197 | st = rules.GetLSLIntegerItem(idx++); |
9198 | } | 9198 | } |
9199 | catch(InvalidCastException) | 9199 | catch(InvalidCastException) |
9200 | { | 9200 | { |
9201 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); | 9201 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_FULLBRIGHT: arg #{1} - parameter 4 must be integer", rulesParsed, idx - idxStart - 1)); |
9202 | return null; | 9202 | return null; |
9203 | } | 9203 | } |
9204 | SetFullBright(part, face , st); | 9204 | SetFullBright(part, face , st); |
9205 | break; | 9205 | break; |
9206 | 9206 | ||
9207 | case ScriptBaseClass.PRIM_MATERIAL: | 9207 | case ScriptBaseClass.PRIM_MATERIAL: |
9208 | if (remain < 1) | 9208 | if (remain < 1) |
9209 | return null; | 9209 | return null; |
9210 | int mat; | 9210 | int mat; |
9211 | 9211 | ||
9212 | try | 9212 | try |
9213 | { | 9213 | { |
9214 | mat = rules.GetLSLIntegerItem(idx++); | 9214 | mat = rules.GetLSLIntegerItem(idx++); |
9215 | } | 9215 | } |
9216 | catch(InvalidCastException) | 9216 | catch(InvalidCastException) |
9217 | { | 9217 | { |
9218 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_MATERIAL: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 9218 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_MATERIAL: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
9219 | return null; | 9219 | return null; |
9220 | } | 9220 | } |
9221 | if (mat < 0 || mat > 7) | 9221 | if (mat < 0 || mat > 7) |
9222 | return null; | 9222 | return null; |
9223 | 9223 | ||
9224 | part.Material = Convert.ToByte(mat); | 9224 | part.Material = Convert.ToByte(mat); |
9225 | break; | 9225 | break; |
9226 | 9226 | ||
9227 | case ScriptBaseClass.PRIM_PHANTOM: | 9227 | case ScriptBaseClass.PRIM_PHANTOM: |
9228 | if (remain < 1) | 9228 | if (remain < 1) |
9229 | return null; | 9229 | return null; |
9230 | 9230 | ||
9231 | string ph = rules.Data[idx++].ToString(); | 9231 | string ph = rules.Data[idx++].ToString(); |
9232 | part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); | 9232 | part.ParentGroup.ScriptSetPhantomStatus(ph.Equals("1")); |
9233 | 9233 | ||
9234 | break; | 9234 | break; |
9235 | 9235 | ||
9236 | case ScriptBaseClass.PRIM_PHYSICS: | 9236 | case ScriptBaseClass.PRIM_PHYSICS: |
9237 | if (remain < 1) | 9237 | if (remain < 1) |
9238 | return null; | 9238 | return null; |
9239 | string phy = rules.Data[idx++].ToString(); | 9239 | string phy = rules.Data[idx++].ToString(); |
9240 | part.ScriptSetPhysicsStatus(phy.Equals("1")); | 9240 | part.ScriptSetPhysicsStatus(phy.Equals("1")); |
9241 | break; | 9241 | break; |
9242 | 9242 | ||
9243 | case ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: | 9243 | case ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: |
9244 | if (remain < 1) | 9244 | if (remain < 1) |
9245 | return null; | 9245 | return null; |
9246 | 9246 | ||
9247 | int shape_type; | 9247 | int shape_type; |
9248 | 9248 | ||
9249 | try | 9249 | try |
9250 | { | 9250 | { |
9251 | shape_type = rules.GetLSLIntegerItem(idx++); | 9251 | shape_type = rules.GetLSLIntegerItem(idx++); |
9252 | } | 9252 | } |
9253 | catch(InvalidCastException) | 9253 | catch(InvalidCastException) |
9254 | { | 9254 | { |
9255 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_PHYSICS_SHAPE_TYPE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 9255 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_PHYSICS_SHAPE_TYPE: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
9256 | return null; | 9256 | return null; |
9257 | } | 9257 | } |
9258 | 9258 | ||
9259 | ExtraPhysicsData physdata = new ExtraPhysicsData(); | 9259 | ExtraPhysicsData physdata = new ExtraPhysicsData(); |
9260 | physdata.Density = part.Density; | 9260 | physdata.Density = part.Density; |
9261 | physdata.Bounce = part.Restitution; | 9261 | physdata.Bounce = part.Restitution; |
9262 | physdata.GravitationModifier = part.GravityModifier; | 9262 | physdata.GravitationModifier = part.GravityModifier; |
9263 | physdata.PhysShapeType = (PhysShapeType)shape_type; | 9263 | physdata.PhysShapeType = (PhysShapeType)shape_type; |
9264 | 9264 | ||
9265 | part.UpdateExtraPhysics(physdata); | 9265 | part.UpdateExtraPhysics(physdata); |
9266 | 9266 | ||
9267 | break; | 9267 | break; |
9268 | 9268 | ||
9269 | case ScriptBaseClass.PRIM_TEMP_ON_REZ: | 9269 | case ScriptBaseClass.PRIM_TEMP_ON_REZ: |
9270 | if (remain < 1) | 9270 | if (remain < 1) |
9271 | return null; | 9271 | return null; |
9272 | string temp = rules.Data[idx++].ToString(); | 9272 | string temp = rules.Data[idx++].ToString(); |
9273 | 9273 | ||
9274 | part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); | 9274 | part.ParentGroup.ScriptSetTemporaryStatus(temp.Equals("1")); |
9275 | 9275 | ||
9276 | break; | 9276 | break; |
9277 | 9277 | ||
9278 | case ScriptBaseClass.PRIM_TEXGEN: | 9278 | case ScriptBaseClass.PRIM_TEXGEN: |
9279 | if (remain < 2) | 9279 | if (remain < 2) |
9280 | return null; | 9280 | return null; |
9281 | //face,type | 9281 | //face,type |
9282 | int style; | 9282 | int style; |
9283 | 9283 | ||
9284 | try | 9284 | try |
9285 | { | 9285 | { |
9286 | face = rules.GetLSLIntegerItem(idx++); | 9286 | face = rules.GetLSLIntegerItem(idx++); |
9287 | } | 9287 | } |
9288 | catch(InvalidCastException) | 9288 | catch(InvalidCastException) |
9289 | { | 9289 | { |
9290 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); | 9290 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 2 must be integer", rulesParsed, idx - idxStart - 1)); |
9291 | return null; | 9291 | return null; |
9292 | } | 9292 | } |
9293 | try | 9293 | try |
9294 | { | 9294 | { |
9295 | style = rules.GetLSLIntegerItem(idx++); | 9295 | style = rules.GetLSLIntegerItem(idx++); |
9296 | } | 9296 | } |
9297 | catch(InvalidCastException) | 9297 | catch(InvalidCastException) |
9298 | { | 9298 | { |
9299 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); | 9299 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXGEN: arg #{1} - parameter 3 must be integer", rulesParsed, idx - idxStart - 1)); |
9300 | return null; | 9300 | return null; |
9301 | } | 9301 | } |
9302 | SetTexGen(part, face, style); | 9302 | SetTexGen(part, face, style); |
9303 | break; | 9303 | break; |
9304 | case ScriptBaseClass.PRIM_TEXT: | 9304 | case ScriptBaseClass.PRIM_TEXT: |
9305 | if (remain < 3) | 9305 | if (remain < 3) |
9306 | return null; | 9306 | return null; |
9307 | string primText; | 9307 | string primText; |
9308 | LSL_Vector primTextColor; | 9308 | LSL_Vector primTextColor; |
9309 | LSL_Float primTextAlpha; | 9309 | LSL_Float primTextAlpha; |
9310 | 9310 | ||
9311 | try | 9311 | try |
9312 | { | 9312 | { |
9313 | primText = rules.GetLSLStringItem(idx++); | 9313 | primText = rules.GetLSLStringItem(idx++); |
9314 | } | 9314 | } |
9315 | catch(InvalidCastException) | 9315 | catch(InvalidCastException) |
9316 | { | 9316 | { |
9317 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); | 9317 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); |
9318 | return null; | 9318 | return null; |
9319 | } | 9319 | } |
9320 | try | 9320 | try |
9321 | { | 9321 | { |
9322 | primTextColor = rules.GetVector3Item(idx++); | 9322 | primTextColor = rules.GetVector3Item(idx++); |
9323 | } | 9323 | } |
9324 | catch(InvalidCastException) | 9324 | catch(InvalidCastException) |
9325 | { | 9325 | { |
9326 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); | 9326 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 3 must be vector", rulesParsed, idx - idxStart - 1)); |
9327 | return null; | 9327 | return null; |
9328 | } | 9328 | } |
9329 | try | 9329 | try |
9330 | { | 9330 | { |
9331 | primTextAlpha = rules.GetLSLFloatItem(idx++); | 9331 | primTextAlpha = rules.GetLSLFloatItem(idx++); |
9332 | } | 9332 | } |
9333 | catch(InvalidCastException) | 9333 | catch(InvalidCastException) |
9334 | { | 9334 | { |
9335 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | 9335 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_TEXT: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); |
9336 | return null; | 9336 | return null; |
9337 | } | 9337 | } |
9338 | Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); | 9338 | Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); |
9339 | part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); | 9339 | part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); |
9340 | 9340 | ||
9341 | break; | 9341 | break; |
9342 | 9342 | ||
9343 | case ScriptBaseClass.PRIM_NAME: | 9343 | case ScriptBaseClass.PRIM_NAME: |
9344 | if (remain < 1) | 9344 | if (remain < 1) |
9345 | return null; | 9345 | return null; |
9346 | try | 9346 | try |
9347 | { | 9347 | { |
9348 | string primName = rules.GetLSLStringItem(idx++); | 9348 | string primName = rules.GetLSLStringItem(idx++); |
9349 | part.Name = primName; | 9349 | part.Name = primName; |
9350 | } | 9350 | } |
9351 | catch(InvalidCastException) | 9351 | catch(InvalidCastException) |
9352 | { | 9352 | { |
9353 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NAME: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); | 9353 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_NAME: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); |
9354 | return null; | 9354 | return null; |
9355 | } | 9355 | } |
9356 | break; | 9356 | break; |
9357 | case ScriptBaseClass.PRIM_DESC: | 9357 | case ScriptBaseClass.PRIM_DESC: |
9358 | if (remain < 1) | 9358 | if (remain < 1) |
9359 | return null; | 9359 | return null; |
9360 | try | 9360 | try |
9361 | { | 9361 | { |
9362 | string primDesc = rules.GetLSLStringItem(idx++); | 9362 | string primDesc = rules.GetLSLStringItem(idx++); |
9363 | part.Description = primDesc; | 9363 | part.Description = primDesc; |
9364 | } | 9364 | } |
9365 | catch(InvalidCastException) | 9365 | catch(InvalidCastException) |
9366 | { | 9366 | { |
9367 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_DESC: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); | 9367 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_DESC: arg #{1} - parameter 2 must be string", rulesParsed, idx - idxStart - 1)); |
9368 | return null; | 9368 | return null; |
9369 | } | 9369 | } |
9370 | break; | 9370 | break; |
9371 | case ScriptBaseClass.PRIM_ROT_LOCAL: | 9371 | case ScriptBaseClass.PRIM_ROT_LOCAL: |
9372 | if (remain < 1) | 9372 | if (remain < 1) |
9373 | return null; | 9373 | return null; |
9374 | LSL_Rotation rot; | 9374 | LSL_Rotation rot; |
9375 | try | 9375 | try |
9376 | { | 9376 | { |
9377 | rot = rules.GetQuaternionItem(idx++); | 9377 | rot = rules.GetQuaternionItem(idx++); |
9378 | } | 9378 | } |
9379 | catch(InvalidCastException) | 9379 | catch(InvalidCastException) |
9380 | { | 9380 | { |
9381 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); | 9381 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); |
9382 | return null; | 9382 | return null; |
9383 | } | 9383 | } |
9384 | SetRot(part, rot); | 9384 | SetRot(part, rot); |
9385 | break; | 9385 | break; |
9386 | 9386 | ||
9387 | case ScriptBaseClass.PRIM_OMEGA: | 9387 | case ScriptBaseClass.PRIM_OMEGA: |
9388 | if (remain < 3) | 9388 | if (remain < 3) |
9389 | return null; | 9389 | return null; |
9390 | LSL_Vector axis; | 9390 | LSL_Vector axis; |
9391 | LSL_Float spinrate; | 9391 | LSL_Float spinrate; |
9392 | LSL_Float gain; | 9392 | LSL_Float gain; |
9393 | 9393 | ||
9394 | try | 9394 | try |
9395 | { | 9395 | { |
9396 | axis = rules.GetVector3Item(idx++); | 9396 | axis = rules.GetVector3Item(idx++); |
9397 | } | 9397 | } |
9398 | catch(InvalidCastException) | 9398 | catch(InvalidCastException) |
9399 | { | 9399 | { |
9400 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | 9400 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); |
9401 | return null; | 9401 | return null; |
9402 | } | 9402 | } |
9403 | try | 9403 | try |
9404 | { | 9404 | { |
9405 | spinrate = rules.GetLSLFloatItem(idx++); | 9405 | spinrate = rules.GetLSLFloatItem(idx++); |
9406 | } | 9406 | } |
9407 | catch(InvalidCastException) | 9407 | catch(InvalidCastException) |
9408 | { | 9408 | { |
9409 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); | 9409 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 3 must be float", rulesParsed, idx - idxStart - 1)); |
9410 | return null; | 9410 | return null; |
9411 | } | 9411 | } |
9412 | try | 9412 | try |
9413 | { | 9413 | { |
9414 | gain = rules.GetLSLFloatItem(idx++); | 9414 | gain = rules.GetLSLFloatItem(idx++); |
9415 | } | 9415 | } |
9416 | catch(InvalidCastException) | 9416 | catch(InvalidCastException) |
9417 | { | 9417 | { |
9418 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); | 9418 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_OMEGA: arg #{1} - parameter 4 must be float", rulesParsed, idx - idxStart - 1)); |
9419 | return null; | 9419 | return null; |
9420 | } | 9420 | } |
9421 | TargetOmega(part, axis, (double)spinrate, (double)gain); | 9421 | TargetOmega(part, axis, (double)spinrate, (double)gain); |
9422 | break; | 9422 | break; |
9423 | 9423 | ||
9424 | case ScriptBaseClass.PRIM_SLICE: | 9424 | case ScriptBaseClass.PRIM_SLICE: |
9425 | if (remain < 1) | 9425 | if (remain < 1) |
9426 | return null; | 9426 | return null; |
9427 | LSL_Vector slice; | 9427 | LSL_Vector slice; |
9428 | try | 9428 | try |
9429 | { | 9429 | { |
9430 | slice = rules.GetVector3Item(idx++); | 9430 | slice = rules.GetVector3Item(idx++); |
9431 | } | 9431 | } |
9432 | catch(InvalidCastException) | 9432 | catch(InvalidCastException) |
9433 | { | 9433 | { |
9434 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SLICE: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | 9434 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_SLICE: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); |
9435 | return null; | 9435 | return null; |
9436 | } | 9436 | } |
9437 | part.UpdateSlice((float)slice.x, (float)slice.y); | 9437 | part.UpdateSlice((float)slice.x, (float)slice.y); |
9438 | break; | 9438 | break; |
9439 | 9439 | ||
9440 | case ScriptBaseClass.PRIM_LINK_TARGET: | 9440 | case ScriptBaseClass.PRIM_LINK_TARGET: |
9441 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | 9441 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. |
9442 | return null; | 9442 | return null; |
9443 | 9443 | ||
9444 | return rules.GetSublist(idx, -1); | 9444 | return rules.GetSublist(idx, -1); |
9445 | 9445 | ||
9446 | default: | 9446 | default: |
9447 | Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - unsupported parameter", rulesParsed, idx - idxStart)); | 9447 | Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - unsupported parameter", rulesParsed, idx - idxStart)); |
9448 | return null; | 9448 | return null; |
9449 | } | 9449 | } |
9450 | } | 9450 | } |
9451 | } | 9451 | } |
9452 | catch (InvalidCastException e) | 9452 | catch (InvalidCastException e) |
9453 | { | 9453 | { |
9454 | Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); | 9454 | Error(originFunc, string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); |
9455 | } | 9455 | } |
9456 | finally | 9456 | finally |
9457 | { | 9457 | { |
9458 | if (positionChanged) | 9458 | if (positionChanged) |
9459 | { | 9459 | { |
9460 | if (part.ParentGroup.RootPart == part) | 9460 | if (part.ParentGroup.RootPart == part) |
9461 | { | 9461 | { |
9462 | SceneObjectGroup parent = part.ParentGroup; | 9462 | SceneObjectGroup parent = part.ParentGroup; |
9463 | parent.UpdateGroupPosition(currentPosition); | 9463 | parent.UpdateGroupPosition(currentPosition); |
9464 | } | 9464 | } |
9465 | else | 9465 | else |
9466 | { | 9466 | { |
9467 | part.OffsetPosition = currentPosition; | 9467 | part.OffsetPosition = currentPosition; |
9468 | SceneObjectGroup parent = part.ParentGroup; | 9468 | SceneObjectGroup parent = part.ParentGroup; |
9469 | parent.HasGroupChanged = true; | 9469 | parent.HasGroupChanged = true; |
9470 | parent.ScheduleGroupForTerseUpdate(); | 9470 | parent.ScheduleGroupForTerseUpdate(); |
9471 | } | 9471 | } |
9472 | } | 9472 | } |
9473 | } | 9473 | } |
9474 | 9474 | ||
9475 | return null; | 9475 | return null; |
9476 | } | 9476 | } |
9477 | 9477 | ||
9478 | protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed) | 9478 | protected LSL_List SetAgentParams(ScenePresence sp, LSL_List rules, string originFunc, ref uint rulesParsed) |
9479 | { | 9479 | { |
9480 | int idx = 0; | 9480 | int idx = 0; |
9481 | int idxStart = 0; | 9481 | int idxStart = 0; |
9482 | 9482 | ||
9483 | try | 9483 | try |
9484 | { | 9484 | { |
9485 | while (idx < rules.Length) | 9485 | while (idx < rules.Length) |
9486 | { | 9486 | { |
9487 | ++rulesParsed; | 9487 | ++rulesParsed; |
9488 | int code = rules.GetLSLIntegerItem(idx++); | 9488 | int code = rules.GetLSLIntegerItem(idx++); |
9489 | 9489 | ||
9490 | int remain = rules.Length - idx; | 9490 | int remain = rules.Length - idx; |
9491 | idxStart = idx; | 9491 | idxStart = idx; |
9492 | 9492 | ||
9493 | switch (code) | 9493 | switch (code) |
9494 | { | 9494 | { |
9495 | case ScriptBaseClass.PRIM_POSITION: | 9495 | case ScriptBaseClass.PRIM_POSITION: |
9496 | case ScriptBaseClass.PRIM_POS_LOCAL: | 9496 | case ScriptBaseClass.PRIM_POS_LOCAL: |
9497 | if (remain < 1) | 9497 | if (remain < 1) |
9498 | return null; | 9498 | return null; |
9499 | 9499 | ||
9500 | try | 9500 | try |
9501 | { | 9501 | { |
9502 | sp.OffsetPosition = rules.GetVector3Item(idx++); | 9502 | sp.OffsetPosition = rules.GetVector3Item(idx++); |
9503 | } | 9503 | } |
9504 | catch(InvalidCastException) | 9504 | catch(InvalidCastException) |
9505 | { | 9505 | { |
9506 | if (code == ScriptBaseClass.PRIM_POSITION) | 9506 | if (code == ScriptBaseClass.PRIM_POSITION) |
9507 | { | 9507 | { |
9508 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | 9508 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POSITION: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); |
9509 | } | 9509 | } |
9510 | else | 9510 | else |
9511 | { | 9511 | { |
9512 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); | 9512 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_POS_LOCAL: arg #{1} - parameter 2 must be vector", rulesParsed, idx - idxStart - 1)); |
9513 | } | 9513 | } |
9514 | return null; | 9514 | return null; |
9515 | } | 9515 | } |
9516 | break; | 9516 | break; |
9517 | 9517 | ||
9518 | case ScriptBaseClass.PRIM_ROTATION: | 9518 | case ScriptBaseClass.PRIM_ROTATION: |
9519 | if (remain < 1) | 9519 | if (remain < 1) |
9520 | return null; | 9520 | return null; |
9521 | 9521 | ||
9522 | Quaternion inRot; | 9522 | Quaternion inRot; |
9523 | 9523 | ||
9524 | try | 9524 | try |
9525 | { | 9525 | { |
9526 | inRot = rules.GetQuaternionItem(idx++); | 9526 | inRot = rules.GetQuaternionItem(idx++); |
9527 | } | 9527 | } |
9528 | catch(InvalidCastException) | 9528 | catch(InvalidCastException) |
9529 | { | 9529 | { |
9530 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); | 9530 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROTATION: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); |
9531 | return null; | 9531 | return null; |
9532 | } | 9532 | } |
9533 | 9533 | ||
9534 | SceneObjectPart parentPart = sp.ParentPart; | 9534 | SceneObjectPart parentPart = sp.ParentPart; |
9535 | 9535 | ||
9536 | if (parentPart != null) | 9536 | if (parentPart != null) |
9537 | sp.Rotation = m_host.GetWorldRotation() * inRot; | 9537 | sp.Rotation = m_host.GetWorldRotation() * inRot; |
9538 | 9538 | ||
9539 | break; | 9539 | break; |
9540 | 9540 | ||
9541 | case ScriptBaseClass.PRIM_ROT_LOCAL: | 9541 | case ScriptBaseClass.PRIM_ROT_LOCAL: |
9542 | if (remain < 1) | 9542 | if (remain < 1) |
9543 | return null; | 9543 | return null; |
9544 | 9544 | ||
9545 | try | 9545 | try |
9546 | { | 9546 | { |
9547 | sp.Rotation = rules.GetQuaternionItem(idx++); | 9547 | sp.Rotation = rules.GetQuaternionItem(idx++); |
9548 | } | 9548 | } |
9549 | catch(InvalidCastException) | 9549 | catch(InvalidCastException) |
9550 | { | 9550 | { |
9551 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); | 9551 | Error(originFunc, string.Format("Error running rule #{0} -> PRIM_ROT_LOCAL: arg #{1} - parameter 2 must be rotation", rulesParsed, idx - idxStart - 1)); |
9552 | return null; | 9552 | return null; |
9553 | } | 9553 | } |
9554 | 9554 | ||
9555 | break; | 9555 | break; |
9556 | 9556 | ||
9557 | case ScriptBaseClass.PRIM_TYPE: | 9557 | case ScriptBaseClass.PRIM_TYPE: |
9558 | Error(originFunc, "PRIM_TYPE disallowed on agent"); | 9558 | Error(originFunc, "PRIM_TYPE disallowed on agent"); |
9559 | return null; | 9559 | return null; |
9560 | 9560 | ||
9561 | case ScriptBaseClass.PRIM_OMEGA: | 9561 | case ScriptBaseClass.PRIM_OMEGA: |
9562 | Error(originFunc, "PRIM_OMEGA disallowed on agent"); | 9562 | Error(originFunc, "PRIM_OMEGA disallowed on agent"); |
9563 | return null; | 9563 | return null; |
9564 | 9564 | ||
9565 | case ScriptBaseClass.PRIM_LINK_TARGET: | 9565 | case ScriptBaseClass.PRIM_LINK_TARGET: |
9566 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. | 9566 | if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. |
9567 | return null; | 9567 | return null; |
9568 | 9568 | ||
9569 | return rules.GetSublist(idx, -1); | 9569 | return rules.GetSublist(idx, -1); |
9570 | 9570 | ||
9571 | default: | 9571 | default: |
9572 | Error(originFunc, | 9572 | Error(originFunc, |
9573 | string.Format("Error running rule #{0} on agent: arg #{1} - disallowed on agent", rulesParsed, idx - idxStart)); | 9573 | string.Format("Error running rule #{0} on agent: arg #{1} - disallowed on agent", rulesParsed, idx - idxStart)); |
9574 | return null; | 9574 | return null; |
9575 | } | 9575 | } |
9576 | } | 9576 | } |
9577 | } | 9577 | } |
9578 | catch (InvalidCastException e) | 9578 | catch (InvalidCastException e) |
9579 | { | 9579 | { |
9580 | Error( | 9580 | Error( |
9581 | originFunc, | 9581 | originFunc, |
9582 | string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); | 9582 | string.Format("Error running rule #{0}: arg #{1} - ", rulesParsed, idx - idxStart) + e.Message); |
9583 | } | 9583 | } |
9584 | 9584 | ||
9585 | return null; | 9585 | return null; |
9586 | } | 9586 | } |
9587 | 9587 | ||
9588 | public LSL_String llStringToBase64(string str) | 9588 | public LSL_String llStringToBase64(string str) |
9589 | { | 9589 | { |
9590 | m_host.AddScriptLPS(1); | 9590 | m_host.AddScriptLPS(1); |
9591 | try | 9591 | try |
9592 | { | 9592 | { |
9593 | byte[] encData_byte; | 9593 | byte[] encData_byte; |
9594 | encData_byte = Util.UTF8.GetBytes(str); | 9594 | encData_byte = Util.UTF8.GetBytes(str); |
9595 | string encodedData = Convert.ToBase64String(encData_byte); | 9595 | string encodedData = Convert.ToBase64String(encData_byte); |
9596 | return encodedData; | 9596 | return encodedData; |
9597 | } | 9597 | } |
9598 | catch | 9598 | catch |
9599 | { | 9599 | { |
9600 | Error("llBase64ToString", "Error encoding string"); | 9600 | Error("llBase64ToString", "Error encoding string"); |
9601 | return String.Empty; | 9601 | return String.Empty; |
9602 | } | 9602 | } |
9603 | } | 9603 | } |
9604 | 9604 | ||
9605 | public LSL_String llBase64ToString(string str) | 9605 | public LSL_String llBase64ToString(string str) |
9606 | { | 9606 | { |
9607 | m_host.AddScriptLPS(1); | 9607 | m_host.AddScriptLPS(1); |
9608 | try | 9608 | try |
9609 | { | 9609 | { |
9610 | byte[] b = Convert.FromBase64String(str); | 9610 | byte[] b = Convert.FromBase64String(str); |
9611 | return Encoding.UTF8.GetString(b); | 9611 | return Encoding.UTF8.GetString(b); |
9612 | } | 9612 | } |
9613 | catch | 9613 | catch |
9614 | { | 9614 | { |
9615 | Error("llBase64ToString", "Error decoding string"); | 9615 | Error("llBase64ToString", "Error decoding string"); |
9616 | return String.Empty; | 9616 | return String.Empty; |
9617 | } | 9617 | } |
9618 | } | 9618 | } |
9619 | 9619 | ||
9620 | public LSL_String llXorBase64Strings(string str1, string str2) | 9620 | public LSL_String llXorBase64Strings(string str1, string str2) |
9621 | { | 9621 | { |
9622 | m_host.AddScriptLPS(1); | 9622 | m_host.AddScriptLPS(1); |
9623 | Deprecated("llXorBase64Strings", "Use llXorBase64 instead"); | 9623 | Deprecated("llXorBase64Strings", "Use llXorBase64 instead"); |
9624 | ScriptSleep(m_sleepMsOnXorBase64Strings); | 9624 | ScriptSleep(m_sleepMsOnXorBase64Strings); |
9625 | return String.Empty; | 9625 | return String.Empty; |
9626 | } | 9626 | } |
9627 | 9627 | ||
9628 | public void llRemoteDataSetRegion() | 9628 | public void llRemoteDataSetRegion() |
9629 | { | 9629 | { |
9630 | m_host.AddScriptLPS(1); | 9630 | m_host.AddScriptLPS(1); |
9631 | Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead"); | 9631 | Deprecated("llRemoteDataSetRegion", "Use llOpenRemoteDataChannel instead"); |
9632 | } | 9632 | } |
9633 | 9633 | ||
9634 | public LSL_Float llLog10(double val) | 9634 | public LSL_Float llLog10(double val) |
9635 | { | 9635 | { |
9636 | m_host.AddScriptLPS(1); | 9636 | m_host.AddScriptLPS(1); |
9637 | return (double)Math.Log10(val); | 9637 | return (double)Math.Log10(val); |
9638 | } | 9638 | } |
9639 | 9639 | ||
9640 | public LSL_Float llLog(double val) | 9640 | public LSL_Float llLog(double val) |
9641 | { | 9641 | { |
9642 | m_host.AddScriptLPS(1); | 9642 | m_host.AddScriptLPS(1); |
9643 | return (double)Math.Log(val); | 9643 | return (double)Math.Log(val); |
9644 | } | 9644 | } |
9645 | 9645 | ||
9646 | public LSL_List llGetAnimationList(string id) | 9646 | public LSL_List llGetAnimationList(string id) |
9647 | { | 9647 | { |
9648 | m_host.AddScriptLPS(1); | 9648 | m_host.AddScriptLPS(1); |
9649 | 9649 | ||
9650 | LSL_List l = new LSL_List(); | 9650 | LSL_List l = new LSL_List(); |
9651 | ScenePresence av = World.GetScenePresence((UUID)id); | 9651 | ScenePresence av = World.GetScenePresence((UUID)id); |
9652 | if (av == null || av.IsChildAgent) // only if in the region | 9652 | if (av == null || av.IsChildAgent) // only if in the region |
9653 | return l; | 9653 | return l; |
9654 | UUID[] anims; | 9654 | UUID[] anims; |
9655 | anims = av.Animator.GetAnimationArray(); | 9655 | anims = av.Animator.GetAnimationArray(); |
9656 | foreach (UUID foo in anims) | 9656 | foreach (UUID foo in anims) |
9657 | l.Add(new LSL_Key(foo.ToString())); | 9657 | l.Add(new LSL_Key(foo.ToString())); |
9658 | return l; | 9658 | return l; |
9659 | } | 9659 | } |
9660 | 9660 | ||
9661 | public void llSetParcelMusicURL(string url) | 9661 | public void llSetParcelMusicURL(string url) |
9662 | { | 9662 | { |
9663 | m_host.AddScriptLPS(1); | 9663 | m_host.AddScriptLPS(1); |
9664 | 9664 | ||
9665 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); | 9665 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
9666 | 9666 | ||
9667 | if (land.LandData.OwnerID != m_host.OwnerID) | 9667 | if (land.LandData.OwnerID != m_host.OwnerID) |
9668 | return; | 9668 | return; |
9669 | 9669 | ||
9670 | land.SetMusicUrl(url); | 9670 | land.SetMusicUrl(url); |
9671 | 9671 | ||
9672 | ScriptSleep(m_sleepMsOnSetParcelMusicURL); | 9672 | ScriptSleep(m_sleepMsOnSetParcelMusicURL); |
9673 | } | 9673 | } |
9674 | 9674 | ||
9675 | public LSL_String llGetParcelMusicURL() | 9675 | public LSL_String llGetParcelMusicURL() |
9676 | { | 9676 | { |
9677 | m_host.AddScriptLPS(1); | 9677 | m_host.AddScriptLPS(1); |
9678 | 9678 | ||
9679 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); | 9679 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
9680 | 9680 | ||
9681 | if (land.LandData.OwnerID != m_host.OwnerID) | 9681 | if (land.LandData.OwnerID != m_host.OwnerID) |
9682 | return String.Empty; | 9682 | return String.Empty; |
9683 | 9683 | ||
9684 | return land.GetMusicUrl(); | 9684 | return land.GetMusicUrl(); |
9685 | } | 9685 | } |
9686 | 9686 | ||
9687 | public LSL_Vector llGetRootPosition() | 9687 | public LSL_Vector llGetRootPosition() |
9688 | { | 9688 | { |
9689 | m_host.AddScriptLPS(1); | 9689 | m_host.AddScriptLPS(1); |
9690 | 9690 | ||
9691 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition); | 9691 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition); |
9692 | } | 9692 | } |
9693 | 9693 | ||
9694 | /// <summary> | 9694 | /// <summary> |
9695 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot | 9695 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetRot |
9696 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation | 9696 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=ChildRotation |
9697 | /// Also tested in sl in regards to the behaviour in attachments/mouselook | 9697 | /// Also tested in sl in regards to the behaviour in attachments/mouselook |
9698 | /// In the root prim:- | 9698 | /// In the root prim:- |
9699 | /// Returns the object rotation if not attached | 9699 | /// Returns the object rotation if not attached |
9700 | /// Returns the avatars rotation if attached | 9700 | /// Returns the avatars rotation if attached |
9701 | /// Returns the camera rotation if attached and the avatar is in mouselook | 9701 | /// Returns the camera rotation if attached and the avatar is in mouselook |
9702 | /// </summary> | 9702 | /// </summary> |
9703 | public LSL_Rotation llGetRootRotation() | 9703 | public LSL_Rotation llGetRootRotation() |
9704 | { | 9704 | { |
9705 | m_host.AddScriptLPS(1); | 9705 | m_host.AddScriptLPS(1); |
9706 | Quaternion q; | 9706 | Quaternion q; |
9707 | if (m_host.ParentGroup.AttachmentPoint != 0) | 9707 | if (m_host.ParentGroup.AttachmentPoint != 0) |
9708 | { | 9708 | { |
9709 | ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); | 9709 | ScenePresence avatar = World.GetScenePresence(m_host.ParentGroup.AttachedAvatar); |
9710 | if (avatar != null) | 9710 | if (avatar != null) |
9711 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) | 9711 | if ((avatar.AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0) |
9712 | q = avatar.CameraRotation; // Mouselook | 9712 | q = avatar.CameraRotation; // Mouselook |
9713 | else | 9713 | else |
9714 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate | 9714 | q = avatar.GetWorldRotation(); // Currently infrequently updated so may be inaccurate |
9715 | else | 9715 | else |
9716 | q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case | 9716 | q = m_host.ParentGroup.GroupRotation; // Likely never get here but just in case |
9717 | } | 9717 | } |
9718 | else | 9718 | else |
9719 | q = m_host.ParentGroup.GroupRotation; // just the group rotation | 9719 | q = m_host.ParentGroup.GroupRotation; // just the group rotation |
9720 | 9720 | ||
9721 | return new LSL_Rotation(q); | 9721 | return new LSL_Rotation(q); |
9722 | } | 9722 | } |
9723 | 9723 | ||
9724 | public LSL_String llGetObjectDesc() | 9724 | public LSL_String llGetObjectDesc() |
9725 | { | 9725 | { |
9726 | return m_host.Description!=null?m_host.Description:String.Empty; | 9726 | return m_host.Description!=null?m_host.Description:String.Empty; |
9727 | } | 9727 | } |
9728 | 9728 | ||
9729 | public void llSetObjectDesc(string desc) | 9729 | public void llSetObjectDesc(string desc) |
9730 | { | 9730 | { |
9731 | m_host.AddScriptLPS(1); | 9731 | m_host.AddScriptLPS(1); |
9732 | m_host.Description = desc!=null?desc:String.Empty; | 9732 | m_host.Description = desc!=null?desc:String.Empty; |
9733 | } | 9733 | } |
9734 | 9734 | ||
9735 | public LSL_String llGetCreator() | 9735 | public LSL_String llGetCreator() |
9736 | { | 9736 | { |
9737 | m_host.AddScriptLPS(1); | 9737 | m_host.AddScriptLPS(1); |
9738 | return m_host.CreatorID.ToString(); | 9738 | return m_host.CreatorID.ToString(); |
9739 | } | 9739 | } |
9740 | 9740 | ||
9741 | public LSL_String llGetTimestamp() | 9741 | public LSL_String llGetTimestamp() |
9742 | { | 9742 | { |
9743 | m_host.AddScriptLPS(1); | 9743 | m_host.AddScriptLPS(1); |
9744 | return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); | 9744 | return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); |
9745 | } | 9745 | } |
9746 | 9746 | ||
9747 | public LSL_Integer llGetNumberOfPrims() | 9747 | public LSL_Integer llGetNumberOfPrims() |
9748 | { | 9748 | { |
9749 | m_host.AddScriptLPS(1); | 9749 | m_host.AddScriptLPS(1); |
9750 | 9750 | ||
9751 | return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount(); | 9751 | return m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount(); |
9752 | } | 9752 | } |
9753 | 9753 | ||
9754 | /// <summary> | 9754 | /// <summary> |
9755 | /// Full implementation of llGetBoundingBox according to SL 2015-04-15. | 9755 | /// Full implementation of llGetBoundingBox according to SL 2015-04-15. |
9756 | /// http://wiki.secondlife.com/wiki/LlGetBoundingBox | 9756 | /// http://wiki.secondlife.com/wiki/LlGetBoundingBox |
9757 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox | 9757 | /// http://lslwiki.net/lslwiki/wakka.php?wakka=llGetBoundingBox |
9758 | /// Returns local bounding box of avatar without attachments | 9758 | /// Returns local bounding box of avatar without attachments |
9759 | /// if target is non-seated avatar or prim/mesh in avatar attachment. | 9759 | /// if target is non-seated avatar or prim/mesh in avatar attachment. |
9760 | /// Returns local bounding box of object including seated avatars | 9760 | /// Returns local bounding box of object including seated avatars |
9761 | /// if target is seated avatar or prim/mesh in object. | 9761 | /// if target is seated avatar or prim/mesh in object. |
9762 | /// Uses meshing of prims for high accuracy | 9762 | /// Uses meshing of prims for high accuracy |
9763 | /// or less accurate box models for speed. | 9763 | /// or less accurate box models for speed. |
9764 | /// </summary> | 9764 | /// </summary> |
9765 | public LSL_List llGetBoundingBox(string obj) | 9765 | public LSL_List llGetBoundingBox(string obj) |
9766 | { | 9766 | { |
9767 | m_host.AddScriptLPS(1); | 9767 | m_host.AddScriptLPS(1); |
9768 | 9768 | ||
9769 | // Get target avatar if non-seated avatar or attachment, or prim and object | 9769 | // Get target avatar if non-seated avatar or attachment, or prim and object |
9770 | UUID objID = UUID.Zero; | 9770 | UUID objID = UUID.Zero; |
9771 | UUID.TryParse(obj, out objID); | 9771 | UUID.TryParse(obj, out objID); |
9772 | ScenePresence agent = World.GetScenePresence(objID); | 9772 | ScenePresence agent = World.GetScenePresence(objID); |
9773 | if (agent != null) | 9773 | if (agent != null) |
9774 | { | 9774 | { |
9775 | if (agent.ParentPart != null) | 9775 | if (agent.ParentPart != null) |
9776 | { | 9776 | { |
9777 | objID = agent.ParentPart.UUID; | 9777 | objID = agent.ParentPart.UUID; |
9778 | agent = null; | 9778 | agent = null; |
9779 | } | 9779 | } |
9780 | } | 9780 | } |
9781 | SceneObjectGroup group = null; | 9781 | SceneObjectGroup group = null; |
9782 | SceneObjectPart target = World.GetSceneObjectPart(objID); | 9782 | SceneObjectPart target = World.GetSceneObjectPart(objID); |
9783 | if (target != null) | 9783 | if (target != null) |
9784 | { | 9784 | { |
9785 | group = target.ParentGroup; | 9785 | group = target.ParentGroup; |
9786 | if (group.IsAttachment) { | 9786 | if (group.IsAttachment) { |
9787 | objID = group.AttachedAvatar; | 9787 | objID = group.AttachedAvatar; |
9788 | agent = World.GetScenePresence(objID); | 9788 | agent = World.GetScenePresence(objID); |
9789 | group = null; | 9789 | group = null; |
9790 | target = null; | 9790 | target = null; |
9791 | } | 9791 | } |
9792 | } | 9792 | } |
9793 | 9793 | ||
9794 | // Initialize but break if no target | 9794 | // Initialize but break if no target |
9795 | LSL_List result = new LSL_List(); | 9795 | LSL_List result = new LSL_List(); |
9796 | int groupCount = 0; | 9796 | int groupCount = 0; |
9797 | int partCount = 0; | 9797 | int partCount = 0; |
9798 | int vertexCount = 0; | 9798 | int vertexCount = 0; |
9799 | if (target == null && agent == null) | 9799 | if (target == null && agent == null) |
9800 | { | 9800 | { |
9801 | result.Add(new LSL_Vector()); | 9801 | result.Add(new LSL_Vector()); |
9802 | result.Add(new LSL_Vector()); | 9802 | result.Add(new LSL_Vector()); |
9803 | if (m_addStatsInGetBoundingBox) | 9803 | if (m_addStatsInGetBoundingBox) |
9804 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | 9804 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); |
9805 | return result; | 9805 | return result; |
9806 | } | 9806 | } |
9807 | Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); | 9807 | Vector3 minPosition = new Vector3(float.MaxValue, float.MaxValue, float.MaxValue); |
9808 | Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue); | 9808 | Vector3 maxPosition = new Vector3(float.MinValue, float.MinValue, float.MinValue); |
9809 | 9809 | ||
9810 | // Try to get a mesher | 9810 | // Try to get a mesher |
9811 | IRendering primMesher = null; | 9811 | IRendering primMesher = null; |
9812 | List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); | 9812 | List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); |
9813 | if (renderers.Count > 0) | 9813 | if (renderers.Count > 0) |
9814 | primMesher = RenderingLoader.LoadRenderer(renderers[0]); | 9814 | primMesher = RenderingLoader.LoadRenderer(renderers[0]); |
9815 | 9815 | ||
9816 | // Get bounding box of just avatar, seated or not | 9816 | // Get bounding box of just avatar, seated or not |
9817 | if (agent != null) | 9817 | if (agent != null) |
9818 | { | 9818 | { |
9819 | bool hasParent = false; | 9819 | bool hasParent = false; |
9820 | Vector3 lower; | 9820 | Vector3 lower; |
9821 | Vector3 upper; | 9821 | Vector3 upper; |
9822 | BoundingBoxOfScenePresence(agent, out lower, out upper); | 9822 | BoundingBoxOfScenePresence(agent, out lower, out upper); |
9823 | Vector3 offset = Vector3.Zero; | 9823 | Vector3 offset = Vector3.Zero; |
9824 | 9824 | ||
9825 | // Since local bounding box unrotated and untilted, keep it simple | 9825 | // Since local bounding box unrotated and untilted, keep it simple |
9826 | AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9826 | AddBoundingBoxOfSimpleBox(lower, upper, offset, agent.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9827 | partCount++; | 9827 | partCount++; |
9828 | groupCount++; | 9828 | groupCount++; |
9829 | 9829 | ||
9830 | // Return lower and upper bounding box corners | 9830 | // Return lower and upper bounding box corners |
9831 | result.Add(new LSL_Vector(minPosition)); | 9831 | result.Add(new LSL_Vector(minPosition)); |
9832 | result.Add(new LSL_Vector(maxPosition)); | 9832 | result.Add(new LSL_Vector(maxPosition)); |
9833 | if (m_addStatsInGetBoundingBox) | 9833 | if (m_addStatsInGetBoundingBox) |
9834 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | 9834 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); |
9835 | return result; | 9835 | return result; |
9836 | } | 9836 | } |
9837 | // Get bounding box of object including seated avatars | 9837 | // Get bounding box of object including seated avatars |
9838 | else if (group != null) | 9838 | else if (group != null) |
9839 | { | 9839 | { |
9840 | // Merge bounding boxes of all parts (prims and mesh) | 9840 | // Merge bounding boxes of all parts (prims and mesh) |
9841 | foreach (SceneObjectPart part in group.Parts) | 9841 | foreach (SceneObjectPart part in group.Parts) |
9842 | { | 9842 | { |
9843 | bool hasParent = (!part.IsRoot); | 9843 | bool hasParent = (!part.IsRoot); |
9844 | // When requested or if no mesher, keep it simple | 9844 | // When requested or if no mesher, keep it simple |
9845 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) | 9845 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) |
9846 | { | 9846 | { |
9847 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9847 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9848 | } | 9848 | } |
9849 | // Do the full mounty | 9849 | // Do the full mounty |
9850 | else | 9850 | else |
9851 | { | 9851 | { |
9852 | Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset); | 9852 | Primitive omvPrim = part.Shape.ToOmvPrimitive(part.OffsetPosition, part.RotationOffset); |
9853 | byte[] sculptAsset = null; | 9853 | byte[] sculptAsset = null; |
9854 | if (omvPrim.Sculpt != null) | 9854 | if (omvPrim.Sculpt != null) |
9855 | sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); | 9855 | sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); |
9856 | 9856 | ||
9857 | // When part is mesh | 9857 | // When part is mesh |
9858 | // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler. | 9858 | // Quirk: Only imports as incompletely populated faceted mesh object, so needs an own handler. |
9859 | if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) | 9859 | if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) |
9860 | { | 9860 | { |
9861 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); | 9861 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); |
9862 | FacetedMesh mesh = null; | 9862 | FacetedMesh mesh = null; |
9863 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); | 9863 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, DetailLevel.Highest, out mesh); |
9864 | meshAsset = null; | 9864 | meshAsset = null; |
9865 | if (mesh != null) | 9865 | if (mesh != null) |
9866 | { | 9866 | { |
9867 | AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9867 | AddBoundingBoxOfFacetedMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9868 | mesh = null; | 9868 | mesh = null; |
9869 | } | 9869 | } |
9870 | } | 9870 | } |
9871 | 9871 | ||
9872 | // When part is sculpt | 9872 | // When part is sculpt |
9873 | // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. | 9873 | // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. |
9874 | else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) | 9874 | else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) |
9875 | { | 9875 | { |
9876 | IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); | 9876 | IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); |
9877 | if (imgDecoder != null) | 9877 | if (imgDecoder != null) |
9878 | { | 9878 | { |
9879 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); | 9879 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); |
9880 | if (sculpt != null) | 9880 | if (sculpt != null) |
9881 | { | 9881 | { |
9882 | SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); | 9882 | SimpleMesh mesh = primMesher.GenerateSimpleSculptMesh(omvPrim, (Bitmap)sculpt, DetailLevel.Medium); |
9883 | sculpt.Dispose(); | 9883 | sculpt.Dispose(); |
9884 | if (mesh != null) | 9884 | if (mesh != null) |
9885 | { | 9885 | { |
9886 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9886 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9887 | mesh = null; | 9887 | mesh = null; |
9888 | } | 9888 | } |
9889 | } | 9889 | } |
9890 | } | 9890 | } |
9891 | } | 9891 | } |
9892 | 9892 | ||
9893 | // When part is prim | 9893 | // When part is prim |
9894 | else if (omvPrim.Sculpt == null) | 9894 | else if (omvPrim.Sculpt == null) |
9895 | { | 9895 | { |
9896 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); | 9896 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); |
9897 | if (mesh != null) | 9897 | if (mesh != null) |
9898 | { | 9898 | { |
9899 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9899 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9900 | mesh = null; | 9900 | mesh = null; |
9901 | } | 9901 | } |
9902 | } | 9902 | } |
9903 | 9903 | ||
9904 | // When all else fails, try fallback to simple box | 9904 | // When all else fails, try fallback to simple box |
9905 | else | 9905 | else |
9906 | { | 9906 | { |
9907 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9907 | AddBoundingBoxOfSimpleBox(part.Scale * -0.5f, part.Scale * 0.5f, part.OffsetPosition, part.RotationOffset, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9908 | } | 9908 | } |
9909 | } | 9909 | } |
9910 | partCount++; | 9910 | partCount++; |
9911 | } | 9911 | } |
9912 | } | 9912 | } |
9913 | 9913 | ||
9914 | // Merge bounding boxes of seated avatars | 9914 | // Merge bounding boxes of seated avatars |
9915 | foreach (ScenePresence sp in group.GetSittingAvatars()) | 9915 | foreach (ScenePresence sp in group.GetSittingAvatars()) |
9916 | { | 9916 | { |
9917 | Vector3 lower; | 9917 | Vector3 lower; |
9918 | Vector3 upper; | 9918 | Vector3 upper; |
9919 | BoundingBoxOfScenePresence(sp, out lower, out upper); | 9919 | BoundingBoxOfScenePresence(sp, out lower, out upper); |
9920 | Vector3 offset = sp.OffsetPosition; | 9920 | Vector3 offset = sp.OffsetPosition; |
9921 | 9921 | ||
9922 | bool hasParent = true; | 9922 | bool hasParent = true; |
9923 | // When requested or if no mesher, keep it simple | 9923 | // When requested or if no mesher, keep it simple |
9924 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) | 9924 | if (m_useSimpleBoxesInGetBoundingBox || primMesher == null) |
9925 | { | 9925 | { |
9926 | AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9926 | AddBoundingBoxOfSimpleBox(lower, upper, offset, sp.Rotation, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9927 | } | 9927 | } |
9928 | // Do the full mounty | 9928 | // Do the full mounty |
9929 | else | 9929 | else |
9930 | { | 9930 | { |
9931 | // Prim shapes don't do center offsets, so add it here. | 9931 | // Prim shapes don't do center offsets, so add it here. |
9932 | offset = offset + (lower + upper) * 0.5f * sp.Rotation; | 9932 | offset = offset + (lower + upper) * 0.5f * sp.Rotation; |
9933 | Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); | 9933 | Primitive omvPrim = MakeOpenMetaversePrim(upper - lower, offset, sp.Rotation, ScriptBaseClass.PRIM_TYPE_SPHERE); |
9934 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); | 9934 | SimpleMesh mesh = primMesher.GenerateSimpleMesh(omvPrim, DetailLevel.Medium); |
9935 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); | 9935 | AddBoundingBoxOfSimpleMesh(mesh, omvPrim, hasParent, ref minPosition, ref maxPosition, ref vertexCount); |
9936 | mesh = null; | 9936 | mesh = null; |
9937 | } | 9937 | } |
9938 | partCount++; | 9938 | partCount++; |
9939 | } | 9939 | } |
9940 | 9940 | ||
9941 | groupCount++; | 9941 | groupCount++; |
9942 | 9942 | ||
9943 | // Return lower and upper bounding box corners | 9943 | // Return lower and upper bounding box corners |
9944 | result.Add(new LSL_Vector(minPosition)); | 9944 | result.Add(new LSL_Vector(minPosition)); |
9945 | result.Add(new LSL_Vector(maxPosition)); | 9945 | result.Add(new LSL_Vector(maxPosition)); |
9946 | if (m_addStatsInGetBoundingBox) | 9946 | if (m_addStatsInGetBoundingBox) |
9947 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); | 9947 | result.Add(new LSL_Vector((float)groupCount, (float)partCount, (float)vertexCount)); |
9948 | 9948 | ||
9949 | primMesher = null; | 9949 | primMesher = null; |
9950 | return result; | 9950 | return result; |
9951 | } | 9951 | } |
9952 | 9952 | ||
9953 | /// <summary> | 9953 | /// <summary> |
9954 | /// Helper to calculate bounding box of an avatar. | 9954 | /// Helper to calculate bounding box of an avatar. |
9955 | /// </summary> | 9955 | /// </summary> |
9956 | private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) | 9956 | private void BoundingBoxOfScenePresence(ScenePresence sp, out Vector3 lower, out Vector3 upper) |
9957 | { | 9957 | { |
9958 | // Adjust from OS model | 9958 | // Adjust from OS model |
9959 | // avatar height = visual height - 0.2, bounding box height = visual height | 9959 | // avatar height = visual height - 0.2, bounding box height = visual height |
9960 | // to SL model | 9960 | // to SL model |
9961 | // avatar height = visual height, bounding box height = visual height + 0.2 | 9961 | // avatar height = visual height, bounding box height = visual height + 0.2 |
9962 | float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; | 9962 | float height = sp.Appearance.AvatarHeight + m_avatarHeightCorrection; |
9963 | 9963 | ||
9964 | // According to avatar bounding box in SL 2015-04-18: | 9964 | // According to avatar bounding box in SL 2015-04-18: |
9965 | // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> | 9965 | // standing = <-0.275,-0.35,-0.1-0.5*h> : <0.275,0.35,0.1+0.5*h> |
9966 | // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> | 9966 | // groundsitting = <-0.3875,-0.5,-0.05-0.375*h> : <0.3875,0.5,0.5> |
9967 | // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> | 9967 | // sitting = <-0.5875,-0.35,-0.35-0.375*h> : <0.1875,0.35,-0.25+0.25*h> |
9968 | 9968 | ||
9969 | // When avatar is sitting | 9969 | // When avatar is sitting |
9970 | if (sp.ParentPart != null) | 9970 | if (sp.ParentPart != null) |
9971 | { | 9971 | { |
9972 | lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); | 9972 | lower = new Vector3(m_lABB1SitX0, m_lABB1SitY0, m_lABB1SitZ0 + m_lABB1SitZ1 * height); |
9973 | upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); | 9973 | upper = new Vector3(m_lABB2SitX0, m_lABB2SitY0, m_lABB2SitZ0 + m_lABB2SitZ1 * height); |
9974 | } | 9974 | } |
9975 | // When avatar is groundsitting | 9975 | // When avatar is groundsitting |
9976 | else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) | 9976 | else if (sp.Animator.Animations.ImplicitDefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) |
9977 | { | 9977 | { |
9978 | lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); | 9978 | lower = new Vector3(m_lABB1GrsX0, m_lABB1GrsY0, m_lABB1GrsZ0 + m_lABB1GrsZ1 * height); |
9979 | upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); | 9979 | upper = new Vector3(m_lABB2GrsX0, m_lABB2GrsY0, m_lABB2GrsZ0 + m_lABB2GrsZ1 * height); |
9980 | } | 9980 | } |
9981 | // When avatar is standing or flying | 9981 | // When avatar is standing or flying |
9982 | else | 9982 | else |
9983 | { | 9983 | { |
9984 | lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); | 9984 | lower = new Vector3(m_lABB1StdX0, m_lABB1StdY0, m_lABB1StdZ0 + m_lABB1StdZ1 * height); |
9985 | upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); | 9985 | upper = new Vector3(m_lABB2StdX0, m_lABB2StdY0, m_lABB2StdZ0 + m_lABB2StdZ1 * height); |
9986 | } | 9986 | } |
9987 | } | 9987 | } |
9988 | 9988 | ||
9989 | /// <summary> | 9989 | /// <summary> |
9990 | /// Helper to approximate a part with a simple box. | 9990 | /// Helper to approximate a part with a simple box. |
9991 | /// </summary> | 9991 | /// </summary> |
9992 | private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | 9992 | private void AddBoundingBoxOfSimpleBox(Vector3 corner1, Vector3 corner2, Vector3 offset, Quaternion rotation, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) |
9993 | { | 9993 | { |
9994 | // Parse the 8 box corners | 9994 | // Parse the 8 box corners |
9995 | for (int i = 0; i < 8; i++) | 9995 | for (int i = 0; i < 8; i++) |
9996 | { | 9996 | { |
9997 | // Calculate each box corner | 9997 | // Calculate each box corner |
9998 | Vector3 position = corner1; | 9998 | Vector3 position = corner1; |
9999 | if ((i & 1) != 0) | 9999 | if ((i & 1) != 0) |
10000 | position.X = corner2.X; | 10000 | position.X = corner2.X; |
10001 | if ((i & 2) != 0) | 10001 | if ((i & 2) != 0) |
10002 | position.Y = corner2.Y; | 10002 | position.Y = corner2.Y; |
10003 | if ((i & 4) != 0) | 10003 | if ((i & 4) != 0) |
10004 | position.Z = corner2.Z; | 10004 | position.Z = corner2.Z; |
10005 | // Rotate part unless part is root | 10005 | // Rotate part unless part is root |
10006 | if (hasParent) | 10006 | if (hasParent) |
10007 | position = position * rotation; | 10007 | position = position * rotation; |
10008 | position = position + offset; | 10008 | position = position + offset; |
10009 | // Adjust lower and upper bounding box corners if needed | 10009 | // Adjust lower and upper bounding box corners if needed |
10010 | lower = Vector3.Min(lower, position); | 10010 | lower = Vector3.Min(lower, position); |
10011 | upper = Vector3.Max(upper, position); | 10011 | upper = Vector3.Max(upper, position); |
10012 | count++; | 10012 | count++; |
10013 | } | 10013 | } |
10014 | } | 10014 | } |
10015 | 10015 | ||
10016 | /// <summary> | 10016 | /// <summary> |
10017 | /// Helper to parse a meshed prim and needed especially | 10017 | /// Helper to parse a meshed prim and needed especially |
10018 | /// for accuracy with tortured prims and sculpts. | 10018 | /// for accuracy with tortured prims and sculpts. |
10019 | /// </summary> | 10019 | /// </summary> |
10020 | private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | 10020 | private void AddBoundingBoxOfSimpleMesh(SimpleMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) |
10021 | { | 10021 | { |
10022 | // Quirk: A meshed box contains 10 instead of the 8 necessary vertices. | 10022 | // Quirk: A meshed box contains 10 instead of the 8 necessary vertices. |
10023 | if (mesh != null) | 10023 | if (mesh != null) |
10024 | { | 10024 | { |
10025 | // Parse each vertex in mesh | 10025 | // Parse each vertex in mesh |
10026 | foreach (Vertex vertex in mesh.Vertices) | 10026 | foreach (Vertex vertex in mesh.Vertices) |
10027 | { | 10027 | { |
10028 | Vector3 position = vertex.Position; | 10028 | Vector3 position = vertex.Position; |
10029 | position = position * prim.Scale; | 10029 | position = position * prim.Scale; |
10030 | // Rotate part unless part is root | 10030 | // Rotate part unless part is root |
10031 | if (hasParent) | 10031 | if (hasParent) |
10032 | position = position * prim.Rotation; | 10032 | position = position * prim.Rotation; |
10033 | position = position + prim.Position; | 10033 | position = position + prim.Position; |
10034 | // Adjust lower and upper bounding box corners if needed | 10034 | // Adjust lower and upper bounding box corners if needed |
10035 | lower = Vector3.Min(lower, position); | 10035 | lower = Vector3.Min(lower, position); |
10036 | upper = Vector3.Max(upper, position); | 10036 | upper = Vector3.Max(upper, position); |
10037 | count++; | 10037 | count++; |
10038 | } | 10038 | } |
10039 | } | 10039 | } |
10040 | } | 10040 | } |
10041 | 10041 | ||
10042 | /// <summary> | 10042 | /// <summary> |
10043 | /// Helper to parse mesh because no method exists | 10043 | /// Helper to parse mesh because no method exists |
10044 | /// to parse mesh assets to SimpleMesh. | 10044 | /// to parse mesh assets to SimpleMesh. |
10045 | /// </summary> | 10045 | /// </summary> |
10046 | private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) | 10046 | private void AddBoundingBoxOfFacetedMesh(FacetedMesh mesh, Primitive prim, bool hasParent, ref Vector3 lower, ref Vector3 upper, ref int count) |
10047 | { | 10047 | { |
10048 | if (mesh != null) | 10048 | if (mesh != null) |
10049 | { | 10049 | { |
10050 | // Parse each face in mesh | 10050 | // Parse each face in mesh |
10051 | // since vertex array isn't populated. | 10051 | // since vertex array isn't populated. |
10052 | // This parses each unique vertex 3-6 times. | 10052 | // This parses each unique vertex 3-6 times. |
10053 | foreach (Face face in mesh.Faces) | 10053 | foreach (Face face in mesh.Faces) |
10054 | { | 10054 | { |
10055 | // Parse each vertex in face | 10055 | // Parse each vertex in face |
10056 | foreach (Vertex vertex in face.Vertices) | 10056 | foreach (Vertex vertex in face.Vertices) |
10057 | { | 10057 | { |
10058 | Vector3 position = vertex.Position; | 10058 | Vector3 position = vertex.Position; |
10059 | position = position * prim.Scale; | 10059 | position = position * prim.Scale; |
10060 | // Rotate part unless part is root | 10060 | // Rotate part unless part is root |
10061 | if (hasParent) | 10061 | if (hasParent) |
10062 | position = position * prim.Rotation; | 10062 | position = position * prim.Rotation; |
10063 | position = position + prim.Position; | 10063 | position = position + prim.Position; |
10064 | // Adjust lower and upper bounding box corners if needed | 10064 | // Adjust lower and upper bounding box corners if needed |
10065 | lower = Vector3.Min(lower, position); | 10065 | lower = Vector3.Min(lower, position); |
10066 | upper = Vector3.Max(upper, position); | 10066 | upper = Vector3.Max(upper, position); |
10067 | count++; | 10067 | count++; |
10068 | } | 10068 | } |
10069 | } | 10069 | } |
10070 | } | 10070 | } |
10071 | } | 10071 | } |
10072 | 10072 | ||
10073 | /// <summary> | 10073 | /// <summary> |
10074 | /// Helper to make up an OpenMetaverse prim | 10074 | /// Helper to make up an OpenMetaverse prim |
10075 | /// needed to create mesh from parts. | 10075 | /// needed to create mesh from parts. |
10076 | /// </summary> | 10076 | /// </summary> |
10077 | private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType) | 10077 | private Primitive MakeOpenMetaversePrim(Vector3 scale, Vector3 position, Quaternion rotation, int primType) |
10078 | { | 10078 | { |
10079 | // Initialize and set common parameters | 10079 | // Initialize and set common parameters |
10080 | Primitive prim = new OpenMetaverse.Primitive(); | 10080 | Primitive prim = new OpenMetaverse.Primitive(); |
10081 | prim.Scale = scale; | 10081 | prim.Scale = scale; |
10082 | prim.Position = position; | 10082 | prim.Position = position; |
10083 | prim.Rotation = rotation; | 10083 | prim.Rotation = rotation; |
10084 | prim.PrimData.PathShearX = 0.0f; | 10084 | prim.PrimData.PathShearX = 0.0f; |
10085 | prim.PrimData.PathShearY = 0.0f; | 10085 | prim.PrimData.PathShearY = 0.0f; |
10086 | prim.PrimData.PathBegin = 0.0f; | 10086 | prim.PrimData.PathBegin = 0.0f; |
10087 | prim.PrimData.PathEnd = 1.0f; | 10087 | prim.PrimData.PathEnd = 1.0f; |
10088 | prim.PrimData.PathScaleX = 1.0f; | 10088 | prim.PrimData.PathScaleX = 1.0f; |
10089 | prim.PrimData.PathScaleY = 1.0f; | 10089 | prim.PrimData.PathScaleY = 1.0f; |
10090 | prim.PrimData.PathTaperX = 0.0f; | 10090 | prim.PrimData.PathTaperX = 0.0f; |
10091 | prim.PrimData.PathTaperY = 0.0f; | 10091 | prim.PrimData.PathTaperY = 0.0f; |
10092 | prim.PrimData.PathTwistBegin = 0.0f; | 10092 | prim.PrimData.PathTwistBegin = 0.0f; |
10093 | prim.PrimData.PathTwist = 0.0f; | 10093 | prim.PrimData.PathTwist = 0.0f; |
10094 | prim.PrimData.ProfileBegin = 0.0f; | 10094 | prim.PrimData.ProfileBegin = 0.0f; |
10095 | prim.PrimData.ProfileEnd = 1.0f; | 10095 | prim.PrimData.ProfileEnd = 1.0f; |
10096 | prim.PrimData.ProfileHollow = 0.0f; | 10096 | prim.PrimData.ProfileHollow = 0.0f; |
10097 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | 10097 | prim.PrimData.ProfileCurve = (ProfileCurve)1; |
10098 | prim.PrimData.ProfileHole = (HoleType)0; | 10098 | prim.PrimData.ProfileHole = (HoleType)0; |
10099 | prim.PrimData.PathCurve = (PathCurve)16; | 10099 | prim.PrimData.PathCurve = (PathCurve)16; |
10100 | prim.PrimData.PathRadiusOffset = 0.0f; | 10100 | prim.PrimData.PathRadiusOffset = 0.0f; |
10101 | prim.PrimData.PathRevolutions = 1.0f; | 10101 | prim.PrimData.PathRevolutions = 1.0f; |
10102 | prim.PrimData.PathSkew = 0.0f; | 10102 | prim.PrimData.PathSkew = 0.0f; |
10103 | prim.PrimData.PCode = OpenMetaverse.PCode.Prim; | 10103 | prim.PrimData.PCode = OpenMetaverse.PCode.Prim; |
10104 | prim.PrimData.State = (byte)0; | 10104 | prim.PrimData.State = (byte)0; |
10105 | 10105 | ||
10106 | // Set type specific parameters | 10106 | // Set type specific parameters |
10107 | switch (primType) | 10107 | switch (primType) |
10108 | { | 10108 | { |
10109 | // Set specific parameters for box | 10109 | // Set specific parameters for box |
10110 | case ScriptBaseClass.PRIM_TYPE_BOX: | 10110 | case ScriptBaseClass.PRIM_TYPE_BOX: |
10111 | prim.PrimData.PathScaleY = 1.0f; | 10111 | prim.PrimData.PathScaleY = 1.0f; |
10112 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | 10112 | prim.PrimData.ProfileCurve = (ProfileCurve)1; |
10113 | prim.PrimData.PathCurve = (PathCurve)16; | 10113 | prim.PrimData.PathCurve = (PathCurve)16; |
10114 | break; | 10114 | break; |
10115 | // Set specific parameters for cylinder | 10115 | // Set specific parameters for cylinder |
10116 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | 10116 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: |
10117 | prim.PrimData.PathScaleY = 1.0f; | 10117 | prim.PrimData.PathScaleY = 1.0f; |
10118 | prim.PrimData.ProfileCurve = (ProfileCurve)0; | 10118 | prim.PrimData.ProfileCurve = (ProfileCurve)0; |
10119 | prim.PrimData.PathCurve = (PathCurve)16; | 10119 | prim.PrimData.PathCurve = (PathCurve)16; |
10120 | break; | 10120 | break; |
10121 | // Set specific parameters for prism | 10121 | // Set specific parameters for prism |
10122 | case ScriptBaseClass.PRIM_TYPE_PRISM: | 10122 | case ScriptBaseClass.PRIM_TYPE_PRISM: |
10123 | prim.PrimData.PathScaleY = 1.0f; | 10123 | prim.PrimData.PathScaleY = 1.0f; |
10124 | prim.PrimData.ProfileCurve = (ProfileCurve)3; | 10124 | prim.PrimData.ProfileCurve = (ProfileCurve)3; |
10125 | prim.PrimData.PathCurve = (PathCurve)16; | 10125 | prim.PrimData.PathCurve = (PathCurve)16; |
10126 | break; | 10126 | break; |
10127 | // Set specific parameters for sphere | 10127 | // Set specific parameters for sphere |
10128 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | 10128 | case ScriptBaseClass.PRIM_TYPE_SPHERE: |
10129 | prim.PrimData.PathScaleY = 1.0f; | 10129 | prim.PrimData.PathScaleY = 1.0f; |
10130 | prim.PrimData.ProfileCurve = (ProfileCurve)5; | 10130 | prim.PrimData.ProfileCurve = (ProfileCurve)5; |
10131 | prim.PrimData.PathCurve = (PathCurve)32; | 10131 | prim.PrimData.PathCurve = (PathCurve)32; |
10132 | break; | 10132 | break; |
10133 | // Set specific parameters for torus | 10133 | // Set specific parameters for torus |
10134 | case ScriptBaseClass.PRIM_TYPE_TORUS: | 10134 | case ScriptBaseClass.PRIM_TYPE_TORUS: |
10135 | prim.PrimData.PathScaleY = 0.5f; | 10135 | prim.PrimData.PathScaleY = 0.5f; |
10136 | prim.PrimData.ProfileCurve = (ProfileCurve)0; | 10136 | prim.PrimData.ProfileCurve = (ProfileCurve)0; |
10137 | prim.PrimData.PathCurve = (PathCurve)32; | 10137 | prim.PrimData.PathCurve = (PathCurve)32; |
10138 | break; | 10138 | break; |
10139 | // Set specific parameters for tube | 10139 | // Set specific parameters for tube |
10140 | case ScriptBaseClass.PRIM_TYPE_TUBE: | 10140 | case ScriptBaseClass.PRIM_TYPE_TUBE: |
10141 | prim.PrimData.PathScaleY = 0.5f; | 10141 | prim.PrimData.PathScaleY = 0.5f; |
10142 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | 10142 | prim.PrimData.ProfileCurve = (ProfileCurve)1; |
10143 | prim.PrimData.PathCurve = (PathCurve)32; | 10143 | prim.PrimData.PathCurve = (PathCurve)32; |
10144 | break; | 10144 | break; |
10145 | // Set specific parameters for ring | 10145 | // Set specific parameters for ring |
10146 | case ScriptBaseClass.PRIM_TYPE_RING: | 10146 | case ScriptBaseClass.PRIM_TYPE_RING: |
10147 | prim.PrimData.PathScaleY = 0.5f; | 10147 | prim.PrimData.PathScaleY = 0.5f; |
10148 | prim.PrimData.ProfileCurve = (ProfileCurve)3; | 10148 | prim.PrimData.ProfileCurve = (ProfileCurve)3; |
10149 | prim.PrimData.PathCurve = (PathCurve)32; | 10149 | prim.PrimData.PathCurve = (PathCurve)32; |
10150 | break; | 10150 | break; |
10151 | // Set specific parameters for sculpt | 10151 | // Set specific parameters for sculpt |
10152 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | 10152 | case ScriptBaseClass.PRIM_TYPE_SCULPT: |
10153 | prim.PrimData.PathScaleY = 1.0f; | 10153 | prim.PrimData.PathScaleY = 1.0f; |
10154 | prim.PrimData.ProfileCurve = (ProfileCurve)5; | 10154 | prim.PrimData.ProfileCurve = (ProfileCurve)5; |
10155 | prim.PrimData.PathCurve = (PathCurve)32; | 10155 | prim.PrimData.PathCurve = (PathCurve)32; |
10156 | break; | 10156 | break; |
10157 | // Default to specific parameters for box | 10157 | // Default to specific parameters for box |
10158 | default: | 10158 | default: |
10159 | prim.PrimData.PathScaleY = 1.0f; | 10159 | prim.PrimData.PathScaleY = 1.0f; |
10160 | prim.PrimData.ProfileCurve = (ProfileCurve)1; | 10160 | prim.PrimData.ProfileCurve = (ProfileCurve)1; |
10161 | prim.PrimData.PathCurve = (PathCurve)16; | 10161 | prim.PrimData.PathCurve = (PathCurve)16; |
10162 | break; | 10162 | break; |
10163 | } | 10163 | } |
10164 | 10164 | ||
10165 | return prim; | 10165 | return prim; |
10166 | } | 10166 | } |
10167 | 10167 | ||
10168 | /// <summary> | 10168 | /// <summary> |
10169 | /// Implementation of llGetGeometricCenter according to SL 2015-04-30. | 10169 | /// Implementation of llGetGeometricCenter according to SL 2015-04-30. |
10170 | /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter | 10170 | /// http://wiki.secondlife.com/wiki/LlGetGeometricCenter |
10171 | /// Returns the average position offset of all linked parts, | 10171 | /// Returns the average position offset of all linked parts, |
10172 | /// including the root prim and seated avatars, | 10172 | /// including the root prim and seated avatars, |
10173 | /// relative to the root prim in local coordinates. | 10173 | /// relative to the root prim in local coordinates. |
10174 | /// </summary> | 10174 | /// </summary> |
10175 | public LSL_Vector llGetGeometricCenter() | 10175 | public LSL_Vector llGetGeometricCenter() |
10176 | { | 10176 | { |
10177 | // Subtract whatever position the root prim has to make it zero | 10177 | // Subtract whatever position the root prim has to make it zero |
10178 | Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f; | 10178 | Vector3 offset = m_host.ParentGroup.RootPart.OffsetPosition * -1.0f; |
10179 | 10179 | ||
10180 | // Add all prim/part position offsets | 10180 | // Add all prim/part position offsets |
10181 | foreach (SceneObjectPart part in m_host.ParentGroup.Parts) | 10181 | foreach (SceneObjectPart part in m_host.ParentGroup.Parts) |
10182 | offset = offset + part.OffsetPosition; | 10182 | offset = offset + part.OffsetPosition; |
10183 | // Add all avatar/scene presence position offsets | 10183 | // Add all avatar/scene presence position offsets |
10184 | foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars()) | 10184 | foreach (ScenePresence sp in m_host.ParentGroup.GetSittingAvatars()) |
10185 | offset = offset + sp.OffsetPosition; | 10185 | offset = offset + sp.OffsetPosition; |
10186 | 10186 | ||
10187 | // Calculate and return the average offset | 10187 | // Calculate and return the average offset |
10188 | offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount()); | 10188 | offset = offset / (float)(m_host.ParentGroup.PrimCount + m_host.ParentGroup.GetSittingAvatarsCount()); |
10189 | return new LSL_Vector(offset); | 10189 | return new LSL_Vector(offset); |
10190 | } | 10190 | } |
10191 | 10191 | ||
10192 | public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) | 10192 | public LSL_List GetEntityParams(ISceneEntity entity, LSL_List rules) |
10193 | { | 10193 | { |
10194 | LSL_List result = new LSL_List(); | 10194 | LSL_List result = new LSL_List(); |
10195 | LSL_List remaining = null; | 10195 | LSL_List remaining = null; |
10196 | 10196 | ||
10197 | while (true) | 10197 | while (true) |
10198 | { | 10198 | { |
10199 | // m_log.DebugFormat( | 10199 | // m_log.DebugFormat( |
10200 | // "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}", | 10200 | // "[LSL API]: GetEntityParams has {0} rules with scene entity named {1}", |
10201 | // rules.Length, entity != null ? entity.Name : "NULL"); | 10201 | // rules.Length, entity != null ? entity.Name : "NULL"); |
10202 | 10202 | ||
10203 | if (entity == null) | 10203 | if (entity == null) |
10204 | return result; | 10204 | return result; |
10205 | 10205 | ||
10206 | if (entity is SceneObjectPart) | 10206 | if (entity is SceneObjectPart) |
10207 | remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result); | 10207 | remaining = GetPrimParams((SceneObjectPart)entity, rules, ref result); |
10208 | else | 10208 | else |
10209 | remaining = GetAgentParams((ScenePresence)entity, rules, ref result); | 10209 | remaining = GetAgentParams((ScenePresence)entity, rules, ref result); |
10210 | 10210 | ||
10211 | if (remaining == null || remaining.Length < 2) | 10211 | if (remaining == null || remaining.Length < 2) |
10212 | return result; | 10212 | return result; |
10213 | 10213 | ||
10214 | int linknumber = remaining.GetLSLIntegerItem(0); | 10214 | int linknumber = remaining.GetLSLIntegerItem(0); |
10215 | rules = remaining.GetSublist(1, -1); | 10215 | rules = remaining.GetSublist(1, -1); |
10216 | entity = GetLinkEntity(m_host, linknumber); | 10216 | entity = GetLinkEntity(m_host, linknumber); |
10217 | } | 10217 | } |
10218 | } | 10218 | } |
10219 | 10219 | ||
10220 | public LSL_List llGetPrimitiveParams(LSL_List rules) | 10220 | public LSL_List llGetPrimitiveParams(LSL_List rules) |
10221 | { | 10221 | { |
10222 | m_host.AddScriptLPS(1); | 10222 | m_host.AddScriptLPS(1); |
10223 | 10223 | ||
10224 | return GetEntityParams(m_host, rules); | 10224 | return GetEntityParams(m_host, rules); |
10225 | } | 10225 | } |
10226 | 10226 | ||
10227 | public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) | 10227 | public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) |
10228 | { | 10228 | { |
10229 | m_host.AddScriptLPS(1); | 10229 | m_host.AddScriptLPS(1); |
10230 | 10230 | ||
10231 | return GetEntityParams(GetLinkEntity(m_host, linknumber), rules); | 10231 | return GetEntityParams(GetLinkEntity(m_host, linknumber), rules); |
10232 | } | 10232 | } |
10233 | 10233 | ||
10234 | public LSL_Vector GetAgentSize(ScenePresence sp) | 10234 | public LSL_Vector GetAgentSize(ScenePresence sp) |
10235 | { | 10235 | { |
10236 | return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight); | 10236 | return new LSL_Vector(0.45, 0.6, sp.Appearance.AvatarHeight); |
10237 | } | 10237 | } |
10238 | 10238 | ||
10239 | /// <summary> | 10239 | /// <summary> |
10240 | /// Gets params for a seated avatar in a linkset. | 10240 | /// Gets params for a seated avatar in a linkset. |
10241 | /// </summary> | 10241 | /// </summary> |
10242 | /// <returns></returns> | 10242 | /// <returns></returns> |
10243 | /// <param name='sp'></param> | 10243 | /// <param name='sp'></param> |
10244 | /// <param name='rules'></param> | 10244 | /// <param name='rules'></param> |
10245 | /// <param name='res'></param> | 10245 | /// <param name='res'></param> |
10246 | public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res) | 10246 | public LSL_List GetAgentParams(ScenePresence sp, LSL_List rules, ref LSL_List res) |
10247 | { | 10247 | { |
10248 | int idx = 0; | 10248 | int idx = 0; |
10249 | while (idx < rules.Length) | 10249 | while (idx < rules.Length) |
10250 | { | 10250 | { |
10251 | int code = (int)rules.GetLSLIntegerItem(idx++); | 10251 | int code = (int)rules.GetLSLIntegerItem(idx++); |
10252 | int remain = rules.Length-idx; | 10252 | int remain = rules.Length-idx; |
10253 | 10253 | ||
10254 | switch (code) | 10254 | switch (code) |
10255 | { | 10255 | { |
10256 | case (int)ScriptBaseClass.PRIM_MATERIAL: | 10256 | case (int)ScriptBaseClass.PRIM_MATERIAL: |
10257 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH)); | 10257 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MATERIAL_FLESH)); |
10258 | break; | 10258 | break; |
10259 | 10259 | ||
10260 | case (int)ScriptBaseClass.PRIM_PHYSICS: | 10260 | case (int)ScriptBaseClass.PRIM_PHYSICS: |
10261 | res.Add(ScriptBaseClass.FALSE); | 10261 | res.Add(ScriptBaseClass.FALSE); |
10262 | break; | 10262 | break; |
10263 | 10263 | ||
10264 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | 10264 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: |
10265 | res.Add(ScriptBaseClass.FALSE); | 10265 | res.Add(ScriptBaseClass.FALSE); |
10266 | break; | 10266 | break; |
10267 | 10267 | ||
10268 | case (int)ScriptBaseClass.PRIM_PHANTOM: | 10268 | case (int)ScriptBaseClass.PRIM_PHANTOM: |
10269 | res.Add(ScriptBaseClass.FALSE); | 10269 | res.Add(ScriptBaseClass.FALSE); |
10270 | break; | 10270 | break; |
10271 | 10271 | ||
10272 | case (int)ScriptBaseClass.PRIM_POSITION: | 10272 | case (int)ScriptBaseClass.PRIM_POSITION: |
10273 | res.Add(new LSL_Vector(sp.AbsolutePosition)); | 10273 | res.Add(new LSL_Vector(sp.AbsolutePosition)); |
10274 | break; | 10274 | break; |
10275 | 10275 | ||
10276 | case (int)ScriptBaseClass.PRIM_SIZE: | 10276 | case (int)ScriptBaseClass.PRIM_SIZE: |
10277 | res.Add(GetAgentSize(sp)); | 10277 | res.Add(GetAgentSize(sp)); |
10278 | break; | 10278 | break; |
10279 | 10279 | ||
10280 | case (int)ScriptBaseClass.PRIM_ROTATION: | 10280 | case (int)ScriptBaseClass.PRIM_ROTATION: |
10281 | res.Add(sp.GetWorldRotation()); | 10281 | res.Add(sp.GetWorldRotation()); |
10282 | break; | 10282 | break; |
10283 | 10283 | ||
10284 | case (int)ScriptBaseClass.PRIM_TYPE: | 10284 | case (int)ScriptBaseClass.PRIM_TYPE: |
10285 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); | 10285 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); |
10286 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); | 10286 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); |
10287 | res.Add(new LSL_Vector(0, 1, 0)); | 10287 | res.Add(new LSL_Vector(0, 1, 0)); |
10288 | res.Add(new LSL_Float(0)); | 10288 | res.Add(new LSL_Float(0)); |
10289 | res.Add(new LSL_Vector(0, 0, 0)); | 10289 | res.Add(new LSL_Vector(0, 0, 0)); |
10290 | res.Add(new LSL_Vector(1, 1, 0)); | 10290 | res.Add(new LSL_Vector(1, 1, 0)); |
10291 | res.Add(new LSL_Vector(0, 0, 0)); | 10291 | res.Add(new LSL_Vector(0, 0, 0)); |
10292 | break; | 10292 | break; |
10293 | 10293 | ||
10294 | case (int)ScriptBaseClass.PRIM_TEXTURE: | 10294 | case (int)ScriptBaseClass.PRIM_TEXTURE: |
10295 | if (remain < 1) | 10295 | if (remain < 1) |
10296 | return null; | 10296 | return null; |
10297 | 10297 | ||
10298 | int face = (int)rules.GetLSLIntegerItem(idx++); | 10298 | int face = (int)rules.GetLSLIntegerItem(idx++); |
10299 | if (face > 21) | 10299 | if (face > 21) |
10300 | break; | 10300 | break; |
10301 | 10301 | ||
10302 | res.Add(new LSL_String("")); | 10302 | res.Add(new LSL_String("")); |
10303 | res.Add(ScriptBaseClass.ZERO_VECTOR); | 10303 | res.Add(ScriptBaseClass.ZERO_VECTOR); |
10304 | res.Add(ScriptBaseClass.ZERO_VECTOR); | 10304 | res.Add(ScriptBaseClass.ZERO_VECTOR); |
10305 | res.Add(new LSL_Float(0)); | 10305 | res.Add(new LSL_Float(0)); |
10306 | break; | 10306 | break; |
10307 | 10307 | ||
10308 | case (int)ScriptBaseClass.PRIM_COLOR: | 10308 | case (int)ScriptBaseClass.PRIM_COLOR: |
10309 | if (remain < 1) | 10309 | if (remain < 1) |
10310 | return null; | 10310 | return null; |
10311 | 10311 | ||
10312 | face = (int)rules.GetLSLIntegerItem(idx++); | 10312 | face = (int)rules.GetLSLIntegerItem(idx++); |
10313 | if (face > 21) | 10313 | if (face > 21) |
10314 | break; | 10314 | break; |
10315 | 10315 | ||
10316 | res.Add(ScriptBaseClass.ZERO_VECTOR); | 10316 | res.Add(ScriptBaseClass.ZERO_VECTOR); |
10317 | res.Add(new LSL_Float(0)); | 10317 | res.Add(new LSL_Float(0)); |
10318 | break; | 10318 | break; |
10319 | 10319 | ||
10320 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | 10320 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: |
10321 | if (remain < 1) | 10321 | if (remain < 1) |
10322 | return null; | 10322 | return null; |
10323 | 10323 | ||
10324 | face = (int)rules.GetLSLIntegerItem(idx++); | 10324 | face = (int)rules.GetLSLIntegerItem(idx++); |
10325 | if (face > 21) | 10325 | if (face > 21) |
10326 | break; | 10326 | break; |
10327 | 10327 | ||
10328 | res.Add(ScriptBaseClass.PRIM_SHINY_NONE); | 10328 | res.Add(ScriptBaseClass.PRIM_SHINY_NONE); |
10329 | res.Add(ScriptBaseClass.PRIM_BUMP_NONE); | 10329 | res.Add(ScriptBaseClass.PRIM_BUMP_NONE); |
10330 | break; | 10330 | break; |
10331 | 10331 | ||
10332 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | 10332 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: |
10333 | if (remain < 1) | 10333 | if (remain < 1) |
10334 | return null; | 10334 | return null; |
10335 | 10335 | ||
10336 | face = (int)rules.GetLSLIntegerItem(idx++); | 10336 | face = (int)rules.GetLSLIntegerItem(idx++); |
10337 | if (face > 21) | 10337 | if (face > 21) |
10338 | break; | 10338 | break; |
10339 | 10339 | ||
10340 | res.Add(ScriptBaseClass.FALSE); | 10340 | res.Add(ScriptBaseClass.FALSE); |
10341 | break; | 10341 | break; |
10342 | 10342 | ||
10343 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | 10343 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: |
10344 | res.Add(ScriptBaseClass.FALSE); | 10344 | res.Add(ScriptBaseClass.FALSE); |
10345 | res.Add(new LSL_Integer(0)); | 10345 | res.Add(new LSL_Integer(0)); |
10346 | res.Add(new LSL_Float(0)); | 10346 | res.Add(new LSL_Float(0)); |
10347 | res.Add(new LSL_Float(0)); | 10347 | res.Add(new LSL_Float(0)); |
10348 | res.Add(new LSL_Float(0)); | 10348 | res.Add(new LSL_Float(0)); |
10349 | res.Add(new LSL_Float(0)); | 10349 | res.Add(new LSL_Float(0)); |
10350 | res.Add(ScriptBaseClass.ZERO_VECTOR); | 10350 | res.Add(ScriptBaseClass.ZERO_VECTOR); |
10351 | break; | 10351 | break; |
10352 | 10352 | ||
10353 | case (int)ScriptBaseClass.PRIM_TEXGEN: | 10353 | case (int)ScriptBaseClass.PRIM_TEXGEN: |
10354 | if (remain < 1) | 10354 | if (remain < 1) |
10355 | return null; | 10355 | return null; |
10356 | 10356 | ||
10357 | face = (int)rules.GetLSLIntegerItem(idx++); | 10357 | face = (int)rules.GetLSLIntegerItem(idx++); |
10358 | if (face > 21) | 10358 | if (face > 21) |
10359 | break; | 10359 | break; |
10360 | 10360 | ||
10361 | res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT); | 10361 | res.Add(ScriptBaseClass.PRIM_TEXGEN_DEFAULT); |
10362 | break; | 10362 | break; |
10363 | 10363 | ||
10364 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | 10364 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: |
10365 | res.Add(ScriptBaseClass.FALSE); | 10365 | res.Add(ScriptBaseClass.FALSE); |
10366 | res.Add(ScriptBaseClass.ZERO_VECTOR); | 10366 | res.Add(ScriptBaseClass.ZERO_VECTOR); |
10367 | res.Add(ScriptBaseClass.ZERO_VECTOR); | 10367 | res.Add(ScriptBaseClass.ZERO_VECTOR); |
10368 | break; | 10368 | break; |
10369 | 10369 | ||
10370 | case (int)ScriptBaseClass.PRIM_GLOW: | 10370 | case (int)ScriptBaseClass.PRIM_GLOW: |
10371 | if (remain < 1) | 10371 | if (remain < 1) |
10372 | return null; | 10372 | return null; |
10373 | 10373 | ||
10374 | face = (int)rules.GetLSLIntegerItem(idx++); | 10374 | face = (int)rules.GetLSLIntegerItem(idx++); |
10375 | if (face > 21) | 10375 | if (face > 21) |
10376 | break; | 10376 | break; |
10377 | 10377 | ||
10378 | res.Add(new LSL_Float(0)); | 10378 | res.Add(new LSL_Float(0)); |
10379 | break; | 10379 | break; |
10380 | 10380 | ||
10381 | case (int)ScriptBaseClass.PRIM_TEXT: | 10381 | case (int)ScriptBaseClass.PRIM_TEXT: |
10382 | res.Add(new LSL_String("")); | 10382 | res.Add(new LSL_String("")); |
10383 | res.Add(ScriptBaseClass.ZERO_VECTOR); | 10383 | res.Add(ScriptBaseClass.ZERO_VECTOR); |
10384 | res.Add(new LSL_Float(1)); | 10384 | res.Add(new LSL_Float(1)); |
10385 | break; | 10385 | break; |
10386 | 10386 | ||
10387 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | 10387 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: |
10388 | res.Add(new LSL_Rotation(sp.Rotation)); | 10388 | res.Add(new LSL_Rotation(sp.Rotation)); |
10389 | break; | 10389 | break; |
10390 | 10390 | ||
10391 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | 10391 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: |
10392 | res.Add(new LSL_Vector(sp.OffsetPosition)); | 10392 | res.Add(new LSL_Vector(sp.OffsetPosition)); |
10393 | break; | 10393 | break; |
10394 | 10394 | ||
10395 | case (int)ScriptBaseClass.PRIM_SLICE: | 10395 | case (int)ScriptBaseClass.PRIM_SLICE: |
10396 | res.Add(new LSL_Vector(0, 1, 0)); | 10396 | res.Add(new LSL_Vector(0, 1, 0)); |
10397 | break; | 10397 | break; |
10398 | 10398 | ||
10399 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | 10399 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: |
10400 | if(remain < 3) | 10400 | if(remain < 3) |
10401 | return null; | 10401 | return null; |
10402 | 10402 | ||
10403 | return rules.GetSublist(idx, -1); | 10403 | return rules.GetSublist(idx, -1); |
10404 | } | 10404 | } |
10405 | } | 10405 | } |
10406 | 10406 | ||
10407 | return null; | 10407 | return null; |
10408 | } | 10408 | } |
10409 | 10409 | ||
10410 | public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) | 10410 | public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) |
10411 | { | 10411 | { |
10412 | int idx = 0; | 10412 | int idx = 0; |
10413 | while (idx < rules.Length) | 10413 | while (idx < rules.Length) |
10414 | { | 10414 | { |
10415 | int code = (int)rules.GetLSLIntegerItem(idx++); | 10415 | int code = (int)rules.GetLSLIntegerItem(idx++); |
10416 | int remain = rules.Length - idx; | 10416 | int remain = rules.Length - idx; |
10417 | 10417 | ||
10418 | switch (code) | 10418 | switch (code) |
10419 | { | 10419 | { |
10420 | case (int)ScriptBaseClass.PRIM_MATERIAL: | 10420 | case (int)ScriptBaseClass.PRIM_MATERIAL: |
10421 | res.Add(new LSL_Integer(part.Material)); | 10421 | res.Add(new LSL_Integer(part.Material)); |
10422 | break; | 10422 | break; |
10423 | 10423 | ||
10424 | case (int)ScriptBaseClass.PRIM_PHYSICS: | 10424 | case (int)ScriptBaseClass.PRIM_PHYSICS: |
10425 | if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) | 10425 | if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) |
10426 | res.Add(new LSL_Integer(1)); | 10426 | res.Add(new LSL_Integer(1)); |
10427 | else | 10427 | else |
10428 | res.Add(new LSL_Integer(0)); | 10428 | res.Add(new LSL_Integer(0)); |
10429 | break; | 10429 | break; |
10430 | 10430 | ||
10431 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | 10431 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: |
10432 | if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) | 10432 | if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) |
10433 | res.Add(new LSL_Integer(1)); | 10433 | res.Add(new LSL_Integer(1)); |
10434 | else | 10434 | else |
10435 | res.Add(new LSL_Integer(0)); | 10435 | res.Add(new LSL_Integer(0)); |
10436 | break; | 10436 | break; |
10437 | 10437 | ||
10438 | case (int)ScriptBaseClass.PRIM_PHANTOM: | 10438 | case (int)ScriptBaseClass.PRIM_PHANTOM: |
10439 | if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) | 10439 | if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) |
10440 | res.Add(new LSL_Integer(1)); | 10440 | res.Add(new LSL_Integer(1)); |
10441 | else | 10441 | else |
10442 | res.Add(new LSL_Integer(0)); | 10442 | res.Add(new LSL_Integer(0)); |
10443 | break; | 10443 | break; |
10444 | 10444 | ||
10445 | case (int)ScriptBaseClass.PRIM_POSITION: | 10445 | case (int)ScriptBaseClass.PRIM_POSITION: |
10446 | LSL_Vector v = new LSL_Vector(part.AbsolutePosition); | 10446 | LSL_Vector v = new LSL_Vector(part.AbsolutePosition); |
10447 | 10447 | ||
10448 | // For some reason, the part.AbsolutePosition.* values do not change if the | 10448 | // For some reason, the part.AbsolutePosition.* values do not change if the |
10449 | // linkset is rotated; they always reflect the child prim's world position | 10449 | // linkset is rotated; they always reflect the child prim's world position |
10450 | // as though the linkset is unrotated. This is incompatible behavior with SL's | 10450 | // as though the linkset is unrotated. This is incompatible behavior with SL's |
10451 | // implementation, so will break scripts imported from there (not to mention it | 10451 | // implementation, so will break scripts imported from there (not to mention it |
10452 | // makes it more difficult to determine a child prim's actual inworld position). | 10452 | // makes it more difficult to determine a child prim's actual inworld position). |
10453 | if (!part.IsRoot) | 10453 | if (!part.IsRoot) |
10454 | { | 10454 | { |
10455 | LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition); | 10455 | LSL_Vector rootPos = new LSL_Vector(m_host.ParentGroup.AbsolutePosition); |
10456 | v = ((v - rootPos) * llGetRootRotation()) + rootPos; | 10456 | v = ((v - rootPos) * llGetRootRotation()) + rootPos; |
10457 | } | 10457 | } |
10458 | 10458 | ||
10459 | res.Add(v); | 10459 | res.Add(v); |
10460 | break; | 10460 | break; |
10461 | 10461 | ||
10462 | case (int)ScriptBaseClass.PRIM_SIZE: | 10462 | case (int)ScriptBaseClass.PRIM_SIZE: |
10463 | res.Add(new LSL_Vector(part.Scale)); | 10463 | res.Add(new LSL_Vector(part.Scale)); |
10464 | break; | 10464 | break; |
10465 | 10465 | ||
10466 | case (int)ScriptBaseClass.PRIM_ROTATION: | 10466 | case (int)ScriptBaseClass.PRIM_ROTATION: |
10467 | res.Add(GetPartRot(part)); | 10467 | res.Add(GetPartRot(part)); |
10468 | break; | 10468 | break; |
10469 | 10469 | ||
10470 | case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: | 10470 | case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: |
10471 | res.Add(new LSL_Integer((int)part.PhysicsShapeType)); | 10471 | res.Add(new LSL_Integer((int)part.PhysicsShapeType)); |
10472 | break; | 10472 | break; |
10473 | 10473 | ||
10474 | case (int)ScriptBaseClass.PRIM_TYPE: | 10474 | case (int)ScriptBaseClass.PRIM_TYPE: |
10475 | // implementing box | 10475 | // implementing box |
10476 | PrimitiveBaseShape Shape = part.Shape; | 10476 | PrimitiveBaseShape Shape = part.Shape; |
10477 | int primType = (int)part.GetPrimType(); | 10477 | int primType = (int)part.GetPrimType(); |
10478 | res.Add(new LSL_Integer(primType)); | 10478 | res.Add(new LSL_Integer(primType)); |
10479 | double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX | 10479 | double topshearx = (double)(sbyte)Shape.PathShearX / 100.0; // Fix negative values for PathShearX |
10480 | double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. | 10480 | double topsheary = (double)(sbyte)Shape.PathShearY / 100.0; // and PathShearY. |
10481 | switch (primType) | 10481 | switch (primType) |
10482 | { | 10482 | { |
10483 | case ScriptBaseClass.PRIM_TYPE_BOX: | 10483 | case ScriptBaseClass.PRIM_TYPE_BOX: |
10484 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | 10484 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: |
10485 | case ScriptBaseClass.PRIM_TYPE_PRISM: | 10485 | case ScriptBaseClass.PRIM_TYPE_PRISM: |
10486 | res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. | 10486 | res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. |
10487 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | 10487 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); |
10488 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | 10488 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); |
10489 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | 10489 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); |
10490 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); | 10490 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); |
10491 | res.Add(new LSL_Vector(topshearx, topsheary, 0)); | 10491 | res.Add(new LSL_Vector(topshearx, topsheary, 0)); |
10492 | break; | 10492 | break; |
10493 | 10493 | ||
10494 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | 10494 | case ScriptBaseClass.PRIM_TYPE_SPHERE: |
10495 | res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. | 10495 | res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. |
10496 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); | 10496 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); |
10497 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | 10497 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); |
10498 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | 10498 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); |
10499 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | 10499 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); |
10500 | break; | 10500 | break; |
10501 | 10501 | ||
10502 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | 10502 | case ScriptBaseClass.PRIM_TYPE_SCULPT: |
10503 | res.Add(new LSL_String(Shape.SculptTexture.ToString())); | 10503 | res.Add(new LSL_String(Shape.SculptTexture.ToString())); |
10504 | res.Add(new LSL_Integer(Shape.SculptType)); | 10504 | res.Add(new LSL_Integer(Shape.SculptType)); |
10505 | break; | 10505 | break; |
10506 | 10506 | ||
10507 | case ScriptBaseClass.PRIM_TYPE_RING: | 10507 | case ScriptBaseClass.PRIM_TYPE_RING: |
10508 | case ScriptBaseClass.PRIM_TYPE_TUBE: | 10508 | case ScriptBaseClass.PRIM_TYPE_TUBE: |
10509 | case ScriptBaseClass.PRIM_TYPE_TORUS: | 10509 | case ScriptBaseClass.PRIM_TYPE_TORUS: |
10510 | // holeshape | 10510 | // holeshape |
10511 | res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. | 10511 | res.Add(new LSL_Integer(Shape.ProfileCurve) & 0xf0); // Isolate hole shape nibble. |
10512 | 10512 | ||
10513 | // cut | 10513 | // cut |
10514 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); | 10514 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); |
10515 | 10515 | ||
10516 | // hollow | 10516 | // hollow |
10517 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | 10517 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); |
10518 | 10518 | ||
10519 | // twist | 10519 | // twist |
10520 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | 10520 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); |
10521 | 10521 | ||
10522 | // vector holesize | 10522 | // vector holesize |
10523 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); | 10523 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); |
10524 | 10524 | ||
10525 | // vector topshear | 10525 | // vector topshear |
10526 | res.Add(new LSL_Vector(topshearx, topsheary, 0)); | 10526 | res.Add(new LSL_Vector(topshearx, topsheary, 0)); |
10527 | 10527 | ||
10528 | // vector profilecut | 10528 | // vector profilecut |
10529 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | 10529 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); |
10530 | 10530 | ||
10531 | // vector tapera | 10531 | // vector tapera |
10532 | res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); | 10532 | res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); |
10533 | 10533 | ||
10534 | // float revolutions | 10534 | // float revolutions |
10535 | res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); | 10535 | res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); |
10536 | // Slightly inaccurate, because an unsigned byte is being used to represent | 10536 | // Slightly inaccurate, because an unsigned byte is being used to represent |
10537 | // the entire range of floating-point values from 1.0 through 4.0 (which is how | 10537 | // the entire range of floating-point values from 1.0 through 4.0 (which is how |
10538 | // SL does it). | 10538 | // SL does it). |
10539 | // | 10539 | // |
10540 | // Using these formulas to store and retrieve PathRevolutions, it is not | 10540 | // Using these formulas to store and retrieve PathRevolutions, it is not |
10541 | // possible to use all values between 1.00 and 4.00. For instance, you can't | 10541 | // possible to use all values between 1.00 and 4.00. For instance, you can't |
10542 | // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you | 10542 | // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you |
10543 | // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them | 10543 | // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them |
10544 | // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar | 10544 | // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar |
10545 | // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. | 10545 | // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. |
10546 | // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value | 10546 | // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value |
10547 | // such as 1.10. So, SL must store and retreive the actual user input rather | 10547 | // such as 1.10. So, SL must store and retreive the actual user input rather |
10548 | // than only storing the encoded value. | 10548 | // than only storing the encoded value. |
10549 | 10549 | ||
10550 | // float radiusoffset | 10550 | // float radiusoffset |
10551 | res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); | 10551 | res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); |
10552 | 10552 | ||
10553 | // float skew | 10553 | // float skew |
10554 | res.Add(new LSL_Float(Shape.PathSkew / 100.0)); | 10554 | res.Add(new LSL_Float(Shape.PathSkew / 100.0)); |
10555 | break; | 10555 | break; |
10556 | } | 10556 | } |
10557 | break; | 10557 | break; |
10558 | 10558 | ||
10559 | case (int)ScriptBaseClass.PRIM_TEXTURE: | 10559 | case (int)ScriptBaseClass.PRIM_TEXTURE: |
10560 | if (remain < 1) | 10560 | if (remain < 1) |
10561 | return null; | 10561 | return null; |
10562 | 10562 | ||
10563 | int face = (int)rules.GetLSLIntegerItem(idx++); | 10563 | int face = (int)rules.GetLSLIntegerItem(idx++); |
10564 | Primitive.TextureEntry tex = part.Shape.Textures; | 10564 | Primitive.TextureEntry tex = part.Shape.Textures; |
10565 | if (face == ScriptBaseClass.ALL_SIDES) | 10565 | if (face == ScriptBaseClass.ALL_SIDES) |
10566 | { | 10566 | { |
10567 | for (face = 0 ; face < GetNumberOfSides(part); face++) | 10567 | for (face = 0 ; face < GetNumberOfSides(part); face++) |
10568 | { | 10568 | { |
10569 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10569 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10570 | 10570 | ||
10571 | res.Add(new LSL_String(texface.TextureID.ToString())); | 10571 | res.Add(new LSL_String(texface.TextureID.ToString())); |
10572 | res.Add(new LSL_Vector(texface.RepeatU, | 10572 | res.Add(new LSL_Vector(texface.RepeatU, |
10573 | texface.RepeatV, | 10573 | texface.RepeatV, |
10574 | 0)); | 10574 | 0)); |
10575 | res.Add(new LSL_Vector(texface.OffsetU, | 10575 | res.Add(new LSL_Vector(texface.OffsetU, |
10576 | texface.OffsetV, | 10576 | texface.OffsetV, |
10577 | 0)); | 10577 | 0)); |
10578 | res.Add(new LSL_Float(texface.Rotation)); | 10578 | res.Add(new LSL_Float(texface.Rotation)); |
10579 | } | 10579 | } |
10580 | } | 10580 | } |
10581 | else | 10581 | else |
10582 | { | 10582 | { |
10583 | if (face >= 0 && face < GetNumberOfSides(part)) | 10583 | if (face >= 0 && face < GetNumberOfSides(part)) |
10584 | { | 10584 | { |
10585 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10585 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10586 | 10586 | ||
10587 | res.Add(new LSL_String(texface.TextureID.ToString())); | 10587 | res.Add(new LSL_String(texface.TextureID.ToString())); |
10588 | res.Add(new LSL_Vector(texface.RepeatU, | 10588 | res.Add(new LSL_Vector(texface.RepeatU, |
10589 | texface.RepeatV, | 10589 | texface.RepeatV, |
10590 | 0)); | 10590 | 0)); |
10591 | res.Add(new LSL_Vector(texface.OffsetU, | 10591 | res.Add(new LSL_Vector(texface.OffsetU, |
10592 | texface.OffsetV, | 10592 | texface.OffsetV, |
10593 | 0)); | 10593 | 0)); |
10594 | res.Add(new LSL_Float(texface.Rotation)); | 10594 | res.Add(new LSL_Float(texface.Rotation)); |
10595 | } | 10595 | } |
10596 | } | 10596 | } |
10597 | break; | 10597 | break; |
10598 | 10598 | ||
10599 | case (int)ScriptBaseClass.PRIM_COLOR: | 10599 | case (int)ScriptBaseClass.PRIM_COLOR: |
10600 | if (remain < 1) | 10600 | if (remain < 1) |
10601 | return null; | 10601 | return null; |
10602 | 10602 | ||
10603 | face=(int)rules.GetLSLIntegerItem(idx++); | 10603 | face=(int)rules.GetLSLIntegerItem(idx++); |
10604 | 10604 | ||
10605 | tex = part.Shape.Textures; | 10605 | tex = part.Shape.Textures; |
10606 | Color4 texcolor; | 10606 | Color4 texcolor; |
10607 | if (face == ScriptBaseClass.ALL_SIDES) | 10607 | if (face == ScriptBaseClass.ALL_SIDES) |
10608 | { | 10608 | { |
10609 | for (face = 0 ; face < GetNumberOfSides(part); face++) | 10609 | for (face = 0 ; face < GetNumberOfSides(part); face++) |
10610 | { | 10610 | { |
10611 | texcolor = tex.GetFace((uint)face).RGBA; | 10611 | texcolor = tex.GetFace((uint)face).RGBA; |
10612 | res.Add(new LSL_Vector(texcolor.R, | 10612 | res.Add(new LSL_Vector(texcolor.R, |
10613 | texcolor.G, | 10613 | texcolor.G, |
10614 | texcolor.B)); | 10614 | texcolor.B)); |
10615 | res.Add(new LSL_Float(texcolor.A)); | 10615 | res.Add(new LSL_Float(texcolor.A)); |
10616 | } | 10616 | } |
10617 | } | 10617 | } |
10618 | else | 10618 | else |
10619 | { | 10619 | { |
10620 | texcolor = tex.GetFace((uint)face).RGBA; | 10620 | texcolor = tex.GetFace((uint)face).RGBA; |
10621 | res.Add(new LSL_Vector(texcolor.R, | 10621 | res.Add(new LSL_Vector(texcolor.R, |
10622 | texcolor.G, | 10622 | texcolor.G, |
10623 | texcolor.B)); | 10623 | texcolor.B)); |
10624 | res.Add(new LSL_Float(texcolor.A)); | 10624 | res.Add(new LSL_Float(texcolor.A)); |
10625 | } | 10625 | } |
10626 | break; | 10626 | break; |
10627 | 10627 | ||
10628 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | 10628 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: |
10629 | if (remain < 1) | 10629 | if (remain < 1) |
10630 | return null; | 10630 | return null; |
10631 | 10631 | ||
10632 | face=(int)rules.GetLSLIntegerItem(idx++); | 10632 | face=(int)rules.GetLSLIntegerItem(idx++); |
10633 | 10633 | ||
10634 | tex = part.Shape.Textures; | 10634 | tex = part.Shape.Textures; |
10635 | if (face == ScriptBaseClass.ALL_SIDES) | 10635 | if (face == ScriptBaseClass.ALL_SIDES) |
10636 | { | 10636 | { |
10637 | for (face = 0; face < GetNumberOfSides(part); face++) | 10637 | for (face = 0; face < GetNumberOfSides(part); face++) |
10638 | { | 10638 | { |
10639 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10639 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10640 | // Convert Shininess to PRIM_SHINY_* | 10640 | // Convert Shininess to PRIM_SHINY_* |
10641 | res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); | 10641 | res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); |
10642 | // PRIM_BUMP_* | 10642 | // PRIM_BUMP_* |
10643 | res.Add(new LSL_Integer((int)texface.Bump)); | 10643 | res.Add(new LSL_Integer((int)texface.Bump)); |
10644 | } | 10644 | } |
10645 | } | 10645 | } |
10646 | else | 10646 | else |
10647 | { | 10647 | { |
10648 | if (face >= 0 && face < GetNumberOfSides(part)) | 10648 | if (face >= 0 && face < GetNumberOfSides(part)) |
10649 | { | 10649 | { |
10650 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10650 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10651 | // Convert Shininess to PRIM_SHINY_* | 10651 | // Convert Shininess to PRIM_SHINY_* |
10652 | res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); | 10652 | res.Add(new LSL_Integer((uint)texface.Shiny >> 6)); |
10653 | // PRIM_BUMP_* | 10653 | // PRIM_BUMP_* |
10654 | res.Add(new LSL_Integer((int)texface.Bump)); | 10654 | res.Add(new LSL_Integer((int)texface.Bump)); |
10655 | } | 10655 | } |
10656 | } | 10656 | } |
10657 | break; | 10657 | break; |
10658 | 10658 | ||
10659 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | 10659 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: |
10660 | if (remain < 1) | 10660 | if (remain < 1) |
10661 | return null; | 10661 | return null; |
10662 | 10662 | ||
10663 | face = (int)rules.GetLSLIntegerItem(idx++); | 10663 | face = (int)rules.GetLSLIntegerItem(idx++); |
10664 | 10664 | ||
10665 | tex = part.Shape.Textures; | 10665 | tex = part.Shape.Textures; |
10666 | if (face == ScriptBaseClass.ALL_SIDES) | 10666 | if (face == ScriptBaseClass.ALL_SIDES) |
10667 | { | 10667 | { |
10668 | for (face = 0; face < GetNumberOfSides(part); face++) | 10668 | for (face = 0; face < GetNumberOfSides(part); face++) |
10669 | { | 10669 | { |
10670 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10670 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10671 | res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); | 10671 | res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); |
10672 | } | 10672 | } |
10673 | } | 10673 | } |
10674 | else | 10674 | else |
10675 | { | 10675 | { |
10676 | if (face >= 0 && face < GetNumberOfSides(part)) | 10676 | if (face >= 0 && face < GetNumberOfSides(part)) |
10677 | { | 10677 | { |
10678 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10678 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10679 | res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); | 10679 | res.Add(new LSL_Integer(texface.Fullbright ? 1 : 0)); |
10680 | } | 10680 | } |
10681 | } | 10681 | } |
10682 | break; | 10682 | break; |
10683 | 10683 | ||
10684 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | 10684 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: |
10685 | PrimitiveBaseShape shape = part.Shape; | 10685 | PrimitiveBaseShape shape = part.Shape; |
10686 | 10686 | ||
10687 | if (shape.FlexiEntry) | 10687 | if (shape.FlexiEntry) |
10688 | res.Add(new LSL_Integer(1)); // active | 10688 | res.Add(new LSL_Integer(1)); // active |
10689 | else | 10689 | else |
10690 | res.Add(new LSL_Integer(0)); | 10690 | res.Add(new LSL_Integer(0)); |
10691 | res.Add(new LSL_Integer(shape.FlexiSoftness));// softness | 10691 | res.Add(new LSL_Integer(shape.FlexiSoftness));// softness |
10692 | res.Add(new LSL_Float(shape.FlexiGravity)); // gravity | 10692 | res.Add(new LSL_Float(shape.FlexiGravity)); // gravity |
10693 | res.Add(new LSL_Float(shape.FlexiDrag)); // friction | 10693 | res.Add(new LSL_Float(shape.FlexiDrag)); // friction |
10694 | res.Add(new LSL_Float(shape.FlexiWind)); // wind | 10694 | res.Add(new LSL_Float(shape.FlexiWind)); // wind |
10695 | res.Add(new LSL_Float(shape.FlexiTension)); // tension | 10695 | res.Add(new LSL_Float(shape.FlexiTension)); // tension |
10696 | res.Add(new LSL_Vector(shape.FlexiForceX, // force | 10696 | res.Add(new LSL_Vector(shape.FlexiForceX, // force |
10697 | shape.FlexiForceY, | 10697 | shape.FlexiForceY, |
10698 | shape.FlexiForceZ)); | 10698 | shape.FlexiForceZ)); |
10699 | break; | 10699 | break; |
10700 | 10700 | ||
10701 | case (int)ScriptBaseClass.PRIM_TEXGEN: | 10701 | case (int)ScriptBaseClass.PRIM_TEXGEN: |
10702 | if (remain < 1) | 10702 | if (remain < 1) |
10703 | return null; | 10703 | return null; |
10704 | 10704 | ||
10705 | face=(int)rules.GetLSLIntegerItem(idx++); | 10705 | face=(int)rules.GetLSLIntegerItem(idx++); |
10706 | 10706 | ||
10707 | tex = part.Shape.Textures; | 10707 | tex = part.Shape.Textures; |
10708 | if (face == ScriptBaseClass.ALL_SIDES) | 10708 | if (face == ScriptBaseClass.ALL_SIDES) |
10709 | { | 10709 | { |
10710 | for (face = 0; face < GetNumberOfSides(part); face++) | 10710 | for (face = 0; face < GetNumberOfSides(part); face++) |
10711 | { | 10711 | { |
10712 | MappingType texgen = tex.GetFace((uint)face).TexMapType; | 10712 | MappingType texgen = tex.GetFace((uint)face).TexMapType; |
10713 | // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. | 10713 | // Convert MappingType to PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR etc. |
10714 | res.Add(new LSL_Integer((uint)texgen >> 1)); | 10714 | res.Add(new LSL_Integer((uint)texgen >> 1)); |
10715 | } | 10715 | } |
10716 | } | 10716 | } |
10717 | else | 10717 | else |
10718 | { | 10718 | { |
10719 | if (face >= 0 && face < GetNumberOfSides(part)) | 10719 | if (face >= 0 && face < GetNumberOfSides(part)) |
10720 | { | 10720 | { |
10721 | MappingType texgen = tex.GetFace((uint)face).TexMapType; | 10721 | MappingType texgen = tex.GetFace((uint)face).TexMapType; |
10722 | res.Add(new LSL_Integer((uint)texgen >> 1)); | 10722 | res.Add(new LSL_Integer((uint)texgen >> 1)); |
10723 | } | 10723 | } |
10724 | } | 10724 | } |
10725 | break; | 10725 | break; |
10726 | 10726 | ||
10727 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | 10727 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: |
10728 | shape = part.Shape; | 10728 | shape = part.Shape; |
10729 | 10729 | ||
10730 | if (shape.LightEntry) | 10730 | if (shape.LightEntry) |
10731 | res.Add(new LSL_Integer(1)); // active | 10731 | res.Add(new LSL_Integer(1)); // active |
10732 | else | 10732 | else |
10733 | res.Add(new LSL_Integer(0)); | 10733 | res.Add(new LSL_Integer(0)); |
10734 | res.Add(new LSL_Vector(shape.LightColorR, // color | 10734 | res.Add(new LSL_Vector(shape.LightColorR, // color |
10735 | shape.LightColorG, | 10735 | shape.LightColorG, |
10736 | shape.LightColorB)); | 10736 | shape.LightColorB)); |
10737 | res.Add(new LSL_Float(shape.LightIntensity)); // intensity | 10737 | res.Add(new LSL_Float(shape.LightIntensity)); // intensity |
10738 | res.Add(new LSL_Float(shape.LightRadius)); // radius | 10738 | res.Add(new LSL_Float(shape.LightRadius)); // radius |
10739 | res.Add(new LSL_Float(shape.LightFalloff)); // falloff | 10739 | res.Add(new LSL_Float(shape.LightFalloff)); // falloff |
10740 | break; | 10740 | break; |
10741 | 10741 | ||
10742 | case (int)ScriptBaseClass.PRIM_GLOW: | 10742 | case (int)ScriptBaseClass.PRIM_GLOW: |
10743 | if (remain < 1) | 10743 | if (remain < 1) |
10744 | return null; | 10744 | return null; |
10745 | 10745 | ||
10746 | face=(int)rules.GetLSLIntegerItem(idx++); | 10746 | face=(int)rules.GetLSLIntegerItem(idx++); |
10747 | 10747 | ||
10748 | tex = part.Shape.Textures; | 10748 | tex = part.Shape.Textures; |
10749 | if (face == ScriptBaseClass.ALL_SIDES) | 10749 | if (face == ScriptBaseClass.ALL_SIDES) |
10750 | { | 10750 | { |
10751 | for (face = 0; face < GetNumberOfSides(part); face++) | 10751 | for (face = 0; face < GetNumberOfSides(part); face++) |
10752 | { | 10752 | { |
10753 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10753 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10754 | res.Add(new LSL_Float(texface.Glow)); | 10754 | res.Add(new LSL_Float(texface.Glow)); |
10755 | } | 10755 | } |
10756 | } | 10756 | } |
10757 | else | 10757 | else |
10758 | { | 10758 | { |
10759 | if (face >= 0 && face < GetNumberOfSides(part)) | 10759 | if (face >= 0 && face < GetNumberOfSides(part)) |
10760 | { | 10760 | { |
10761 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | 10761 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); |
10762 | res.Add(new LSL_Float(texface.Glow)); | 10762 | res.Add(new LSL_Float(texface.Glow)); |
10763 | } | 10763 | } |
10764 | } | 10764 | } |
10765 | break; | 10765 | break; |
10766 | 10766 | ||
10767 | case (int)ScriptBaseClass.PRIM_TEXT: | 10767 | case (int)ScriptBaseClass.PRIM_TEXT: |
10768 | Color4 textColor = part.GetTextColor(); | 10768 | Color4 textColor = part.GetTextColor(); |
10769 | res.Add(new LSL_String(part.Text)); | 10769 | res.Add(new LSL_String(part.Text)); |
10770 | res.Add(new LSL_Vector(textColor.R, | 10770 | res.Add(new LSL_Vector(textColor.R, |
10771 | textColor.G, | 10771 | textColor.G, |
10772 | textColor.B)); | 10772 | textColor.B)); |
10773 | res.Add(new LSL_Float(1.0 - textColor.A)); | 10773 | res.Add(new LSL_Float(1.0 - textColor.A)); |
10774 | break; | 10774 | break; |
10775 | case (int)ScriptBaseClass.PRIM_NAME: | 10775 | case (int)ScriptBaseClass.PRIM_NAME: |
10776 | res.Add(new LSL_String(part.Name)); | 10776 | res.Add(new LSL_String(part.Name)); |
10777 | break; | 10777 | break; |
10778 | case (int)ScriptBaseClass.PRIM_DESC: | 10778 | case (int)ScriptBaseClass.PRIM_DESC: |
10779 | res.Add(new LSL_String(part.Description)); | 10779 | res.Add(new LSL_String(part.Description)); |
10780 | break; | 10780 | break; |
10781 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: | 10781 | case (int)ScriptBaseClass.PRIM_ROT_LOCAL: |
10782 | res.Add(new LSL_Rotation(part.RotationOffset)); | 10782 | res.Add(new LSL_Rotation(part.RotationOffset)); |
10783 | break; | 10783 | break; |
10784 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: | 10784 | case (int)ScriptBaseClass.PRIM_POS_LOCAL: |
10785 | res.Add(new LSL_Vector(GetPartLocalPos(part))); | 10785 | res.Add(new LSL_Vector(GetPartLocalPos(part))); |
10786 | break; | 10786 | break; |
10787 | case (int)ScriptBaseClass.PRIM_SLICE: | 10787 | case (int)ScriptBaseClass.PRIM_SLICE: |
10788 | PrimType prim_type = part.GetPrimType(); | 10788 | PrimType prim_type = part.GetPrimType(); |
10789 | bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); | 10789 | bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); |
10790 | res.Add(new LSL_Vector( | 10790 | res.Add(new LSL_Vector( |
10791 | (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, | 10791 | (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, |
10792 | 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, | 10792 | 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, |
10793 | 0 | 10793 | 0 |
10794 | )); | 10794 | )); |
10795 | break; | 10795 | break; |
10796 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: | 10796 | case (int)ScriptBaseClass.PRIM_LINK_TARGET: |
10797 | 10797 | ||
10798 | // TODO: Should be issuing a runtime script warning in this case. | 10798 | // TODO: Should be issuing a runtime script warning in this case. |
10799 | if (remain < 2) | 10799 | if (remain < 2) |
10800 | return null; | 10800 | return null; |
10801 | 10801 | ||
10802 | return rules.GetSublist(idx, -1); | 10802 | return rules.GetSublist(idx, -1); |
10803 | } | 10803 | } |
10804 | } | 10804 | } |
10805 | 10805 | ||
10806 | return null; | 10806 | return null; |
10807 | } | 10807 | } |
10808 | 10808 | ||
10809 | public LSL_List llGetPrimMediaParams(int face, LSL_List rules) | 10809 | public LSL_List llGetPrimMediaParams(int face, LSL_List rules) |
10810 | { | 10810 | { |
10811 | m_host.AddScriptLPS(1); | 10811 | m_host.AddScriptLPS(1); |
10812 | ScriptSleep(m_sleepMsOnGetPrimMediaParams); | 10812 | ScriptSleep(m_sleepMsOnGetPrimMediaParams); |
10813 | return GetPrimMediaParams(m_host, face, rules); | 10813 | return GetPrimMediaParams(m_host, face, rules); |
10814 | } | 10814 | } |
10815 | 10815 | ||
10816 | public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) | 10816 | public LSL_List llGetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) |
10817 | { | 10817 | { |
10818 | m_host.AddScriptLPS(1); | 10818 | m_host.AddScriptLPS(1); |
10819 | ScriptSleep(m_sleepMsOnGetLinkMedia); | 10819 | ScriptSleep(m_sleepMsOnGetLinkMedia); |
10820 | if (link == ScriptBaseClass.LINK_ROOT) | 10820 | if (link == ScriptBaseClass.LINK_ROOT) |
10821 | return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); | 10821 | return GetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); |
10822 | else if (link == ScriptBaseClass.LINK_THIS) | 10822 | else if (link == ScriptBaseClass.LINK_THIS) |
10823 | return GetPrimMediaParams(m_host, face, rules); | 10823 | return GetPrimMediaParams(m_host, face, rules); |
10824 | else | 10824 | else |
10825 | { | 10825 | { |
10826 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); | 10826 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); |
10827 | if (null != part) | 10827 | if (null != part) |
10828 | return GetPrimMediaParams(part, face, rules); | 10828 | return GetPrimMediaParams(part, face, rules); |
10829 | } | 10829 | } |
10830 | 10830 | ||
10831 | return new LSL_List(); | 10831 | return new LSL_List(); |
10832 | } | 10832 | } |
10833 | 10833 | ||
10834 | private LSL_List GetPrimMediaParams(SceneObjectPart part, int face, LSL_List rules) | 10834 | private LSL_List GetPrimMediaParams(SceneObjectPart part, int face, LSL_List rules) |
10835 | { | 10835 | { |
10836 | // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid | 10836 | // LSL Spec http://wiki.secondlife.com/wiki/LlGetPrimMediaParams says to fail silently if face is invalid |
10837 | // TODO: Need to correctly handle case where a face has no media (which gives back an empty list). | 10837 | // TODO: Need to correctly handle case where a face has no media (which gives back an empty list). |
10838 | // Assuming silently fail means give back an empty list. Ideally, need to check this. | 10838 | // Assuming silently fail means give back an empty list. Ideally, need to check this. |
10839 | if (face < 0 || face > part.GetNumberOfSides() - 1) | 10839 | if (face < 0 || face > part.GetNumberOfSides() - 1) |
10840 | return new LSL_List(); | 10840 | return new LSL_List(); |
10841 | 10841 | ||
10842 | IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); | 10842 | IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); |
10843 | if (null == module) | 10843 | if (null == module) |
10844 | return new LSL_List(); | 10844 | return new LSL_List(); |
10845 | 10845 | ||
10846 | MediaEntry me = module.GetMediaEntry(part, face); | 10846 | MediaEntry me = module.GetMediaEntry(part, face); |
10847 | 10847 | ||
10848 | // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams | 10848 | // As per http://wiki.secondlife.com/wiki/LlGetPrimMediaParams |
10849 | if (null == me) | 10849 | if (null == me) |
10850 | return new LSL_List(); | 10850 | return new LSL_List(); |
10851 | 10851 | ||
10852 | LSL_List res = new LSL_List(); | 10852 | LSL_List res = new LSL_List(); |
10853 | 10853 | ||
10854 | for (int i = 0; i < rules.Length; i++) | 10854 | for (int i = 0; i < rules.Length; i++) |
10855 | { | 10855 | { |
10856 | int code = (int)rules.GetLSLIntegerItem(i); | 10856 | int code = (int)rules.GetLSLIntegerItem(i); |
10857 | 10857 | ||
10858 | switch (code) | 10858 | switch (code) |
10859 | { | 10859 | { |
10860 | case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: | 10860 | case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: |
10861 | // Not implemented | 10861 | // Not implemented |
10862 | res.Add(new LSL_Integer(0)); | 10862 | res.Add(new LSL_Integer(0)); |
10863 | break; | 10863 | break; |
10864 | 10864 | ||
10865 | case ScriptBaseClass.PRIM_MEDIA_CONTROLS: | 10865 | case ScriptBaseClass.PRIM_MEDIA_CONTROLS: |
10866 | if (me.Controls == MediaControls.Standard) | 10866 | if (me.Controls == MediaControls.Standard) |
10867 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD)); | 10867 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD)); |
10868 | else | 10868 | else |
10869 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI)); | 10869 | res.Add(new LSL_Integer(ScriptBaseClass.PRIM_MEDIA_CONTROLS_MINI)); |
10870 | break; | 10870 | break; |
10871 | 10871 | ||
10872 | case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: | 10872 | case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: |
10873 | res.Add(new LSL_String(me.CurrentURL)); | 10873 | res.Add(new LSL_String(me.CurrentURL)); |
10874 | break; | 10874 | break; |
10875 | 10875 | ||
10876 | case ScriptBaseClass.PRIM_MEDIA_HOME_URL: | 10876 | case ScriptBaseClass.PRIM_MEDIA_HOME_URL: |
10877 | res.Add(new LSL_String(me.HomeURL)); | 10877 | res.Add(new LSL_String(me.HomeURL)); |
10878 | break; | 10878 | break; |
10879 | 10879 | ||
10880 | case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: | 10880 | case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: |
10881 | res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); | 10881 | res.Add(me.AutoLoop ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); |
10882 | break; | 10882 | break; |
10883 | 10883 | ||
10884 | case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: | 10884 | case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: |
10885 | res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); | 10885 | res.Add(me.AutoPlay ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); |
10886 | break; | 10886 | break; |
10887 | 10887 | ||
10888 | case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: | 10888 | case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: |
10889 | res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); | 10889 | res.Add(me.AutoScale ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); |
10890 | break; | 10890 | break; |
10891 | 10891 | ||
10892 | case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: | 10892 | case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: |
10893 | res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); | 10893 | res.Add(me.AutoZoom ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); |
10894 | break; | 10894 | break; |
10895 | 10895 | ||
10896 | case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: | 10896 | case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: |
10897 | res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); | 10897 | res.Add(me.InteractOnFirstClick ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); |
10898 | break; | 10898 | break; |
10899 | 10899 | ||
10900 | case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS: | 10900 | case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS: |
10901 | res.Add(new LSL_Integer(me.Width)); | 10901 | res.Add(new LSL_Integer(me.Width)); |
10902 | break; | 10902 | break; |
10903 | 10903 | ||
10904 | case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS: | 10904 | case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS: |
10905 | res.Add(new LSL_Integer(me.Height)); | 10905 | res.Add(new LSL_Integer(me.Height)); |
10906 | break; | 10906 | break; |
10907 | 10907 | ||
10908 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE: | 10908 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE: |
10909 | res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); | 10909 | res.Add(me.EnableWhiteList ? ScriptBaseClass.TRUE : ScriptBaseClass.FALSE); |
10910 | break; | 10910 | break; |
10911 | 10911 | ||
10912 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST: | 10912 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST: |
10913 | string[] urls = (string[])me.WhiteList.Clone(); | 10913 | string[] urls = (string[])me.WhiteList.Clone(); |
10914 | 10914 | ||
10915 | for (int j = 0; j < urls.Length; j++) | 10915 | for (int j = 0; j < urls.Length; j++) |
10916 | urls[j] = Uri.EscapeDataString(urls[j]); | 10916 | urls[j] = Uri.EscapeDataString(urls[j]); |
10917 | 10917 | ||
10918 | res.Add(new LSL_String(string.Join(", ", urls))); | 10918 | res.Add(new LSL_String(string.Join(", ", urls))); |
10919 | break; | 10919 | break; |
10920 | 10920 | ||
10921 | case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT: | 10921 | case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT: |
10922 | res.Add(new LSL_Integer((int)me.InteractPermissions)); | 10922 | res.Add(new LSL_Integer((int)me.InteractPermissions)); |
10923 | break; | 10923 | break; |
10924 | 10924 | ||
10925 | case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL: | 10925 | case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL: |
10926 | res.Add(new LSL_Integer((int)me.ControlPermissions)); | 10926 | res.Add(new LSL_Integer((int)me.ControlPermissions)); |
10927 | break; | 10927 | break; |
10928 | 10928 | ||
10929 | default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS; | 10929 | default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS; |
10930 | } | 10930 | } |
10931 | } | 10931 | } |
10932 | 10932 | ||
10933 | return res; | 10933 | return res; |
10934 | } | 10934 | } |
10935 | 10935 | ||
10936 | public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules) | 10936 | public LSL_Integer llSetPrimMediaParams(LSL_Integer face, LSL_List rules) |
10937 | { | 10937 | { |
10938 | m_host.AddScriptLPS(1); | 10938 | m_host.AddScriptLPS(1); |
10939 | ScriptSleep(m_sleepMsOnSetPrimMediaParams); | 10939 | ScriptSleep(m_sleepMsOnSetPrimMediaParams); |
10940 | return SetPrimMediaParams(m_host, face, rules); | 10940 | return SetPrimMediaParams(m_host, face, rules); |
10941 | } | 10941 | } |
10942 | 10942 | ||
10943 | public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) | 10943 | public LSL_Integer llSetLinkMedia(LSL_Integer link, LSL_Integer face, LSL_List rules) |
10944 | { | 10944 | { |
10945 | m_host.AddScriptLPS(1); | 10945 | m_host.AddScriptLPS(1); |
10946 | ScriptSleep(m_sleepMsOnSetLinkMedia); | 10946 | ScriptSleep(m_sleepMsOnSetLinkMedia); |
10947 | if (link == ScriptBaseClass.LINK_ROOT) | 10947 | if (link == ScriptBaseClass.LINK_ROOT) |
10948 | return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); | 10948 | return SetPrimMediaParams(m_host.ParentGroup.RootPart, face, rules); |
10949 | else if (link == ScriptBaseClass.LINK_THIS) | 10949 | else if (link == ScriptBaseClass.LINK_THIS) |
10950 | return SetPrimMediaParams(m_host, face, rules); | 10950 | return SetPrimMediaParams(m_host, face, rules); |
10951 | else | 10951 | else |
10952 | { | 10952 | { |
10953 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); | 10953 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); |
10954 | if (null != part) | 10954 | if (null != part) |
10955 | return SetPrimMediaParams(part, face, rules); | 10955 | return SetPrimMediaParams(part, face, rules); |
10956 | } | 10956 | } |
10957 | 10957 | ||
10958 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; | 10958 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; |
10959 | } | 10959 | } |
10960 | 10960 | ||
10961 | private LSL_Integer SetPrimMediaParams(SceneObjectPart part, LSL_Integer face, LSL_List rules) | 10961 | private LSL_Integer SetPrimMediaParams(SceneObjectPart part, LSL_Integer face, LSL_List rules) |
10962 | { | 10962 | { |
10963 | // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid | 10963 | // LSL Spec http://wiki.secondlife.com/wiki/LlSetPrimMediaParams says to fail silently if face is invalid |
10964 | // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this. | 10964 | // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this. |
10965 | // Don't perform the media check directly | 10965 | // Don't perform the media check directly |
10966 | if (face < 0 || face > part.GetNumberOfSides() - 1) | 10966 | if (face < 0 || face > part.GetNumberOfSides() - 1) |
10967 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; | 10967 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; |
10968 | 10968 | ||
10969 | IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); | 10969 | IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); |
10970 | if (null == module) | 10970 | if (null == module) |
10971 | return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED; | 10971 | return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED; |
10972 | 10972 | ||
10973 | MediaEntry me = module.GetMediaEntry(part, face); | 10973 | MediaEntry me = module.GetMediaEntry(part, face); |
10974 | if (null == me) | 10974 | if (null == me) |
10975 | me = new MediaEntry(); | 10975 | me = new MediaEntry(); |
10976 | 10976 | ||
10977 | int i = 0; | 10977 | int i = 0; |
10978 | 10978 | ||
10979 | while (i < rules.Length - 1) | 10979 | while (i < rules.Length - 1) |
10980 | { | 10980 | { |
10981 | int code = rules.GetLSLIntegerItem(i++); | 10981 | int code = rules.GetLSLIntegerItem(i++); |
10982 | 10982 | ||
10983 | switch (code) | 10983 | switch (code) |
10984 | { | 10984 | { |
10985 | case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: | 10985 | case ScriptBaseClass.PRIM_MEDIA_ALT_IMAGE_ENABLE: |
10986 | me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false); | 10986 | me.EnableAlterntiveImage = (rules.GetLSLIntegerItem(i++) != 0 ? true : false); |
10987 | break; | 10987 | break; |
10988 | 10988 | ||
10989 | case ScriptBaseClass.PRIM_MEDIA_CONTROLS: | 10989 | case ScriptBaseClass.PRIM_MEDIA_CONTROLS: |
10990 | int v = rules.GetLSLIntegerItem(i++); | 10990 | int v = rules.GetLSLIntegerItem(i++); |
10991 | if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v) | 10991 | if (ScriptBaseClass.PRIM_MEDIA_CONTROLS_STANDARD == v) |
10992 | me.Controls = MediaControls.Standard; | 10992 | me.Controls = MediaControls.Standard; |
10993 | else | 10993 | else |
10994 | me.Controls = MediaControls.Mini; | 10994 | me.Controls = MediaControls.Mini; |
10995 | break; | 10995 | break; |
10996 | 10996 | ||
10997 | case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: | 10997 | case ScriptBaseClass.PRIM_MEDIA_CURRENT_URL: |
10998 | me.CurrentURL = rules.GetLSLStringItem(i++); | 10998 | me.CurrentURL = rules.GetLSLStringItem(i++); |
10999 | break; | 10999 | break; |
11000 | 11000 | ||
11001 | case ScriptBaseClass.PRIM_MEDIA_HOME_URL: | 11001 | case ScriptBaseClass.PRIM_MEDIA_HOME_URL: |
11002 | me.HomeURL = rules.GetLSLStringItem(i++); | 11002 | me.HomeURL = rules.GetLSLStringItem(i++); |
11003 | break; | 11003 | break; |
11004 | 11004 | ||
11005 | case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: | 11005 | case ScriptBaseClass.PRIM_MEDIA_AUTO_LOOP: |
11006 | me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); | 11006 | me.AutoLoop = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); |
11007 | break; | 11007 | break; |
11008 | 11008 | ||
11009 | case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: | 11009 | case ScriptBaseClass.PRIM_MEDIA_AUTO_PLAY: |
11010 | me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); | 11010 | me.AutoPlay = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); |
11011 | break; | 11011 | break; |
11012 | 11012 | ||
11013 | case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: | 11013 | case ScriptBaseClass.PRIM_MEDIA_AUTO_SCALE: |
11014 | me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); | 11014 | me.AutoScale = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); |
11015 | break; | 11015 | break; |
11016 | 11016 | ||
11017 | case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: | 11017 | case ScriptBaseClass.PRIM_MEDIA_AUTO_ZOOM: |
11018 | me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); | 11018 | me.AutoZoom = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); |
11019 | break; | 11019 | break; |
11020 | 11020 | ||
11021 | case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: | 11021 | case ScriptBaseClass.PRIM_MEDIA_FIRST_CLICK_INTERACT: |
11022 | me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); | 11022 | me.InteractOnFirstClick = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); |
11023 | break; | 11023 | break; |
11024 | 11024 | ||
11025 | case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS: | 11025 | case ScriptBaseClass.PRIM_MEDIA_WIDTH_PIXELS: |
11026 | me.Width = (int)rules.GetLSLIntegerItem(i++); | 11026 | me.Width = (int)rules.GetLSLIntegerItem(i++); |
11027 | break; | 11027 | break; |
11028 | 11028 | ||
11029 | case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS: | 11029 | case ScriptBaseClass.PRIM_MEDIA_HEIGHT_PIXELS: |
11030 | me.Height = (int)rules.GetLSLIntegerItem(i++); | 11030 | me.Height = (int)rules.GetLSLIntegerItem(i++); |
11031 | break; | 11031 | break; |
11032 | 11032 | ||
11033 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE: | 11033 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST_ENABLE: |
11034 | me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); | 11034 | me.EnableWhiteList = (ScriptBaseClass.TRUE == rules.GetLSLIntegerItem(i++) ? true : false); |
11035 | break; | 11035 | break; |
11036 | 11036 | ||
11037 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST: | 11037 | case ScriptBaseClass.PRIM_MEDIA_WHITELIST: |
11038 | string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' }); | 11038 | string[] rawWhiteListUrls = rules.GetLSLStringItem(i++).ToString().Split(new char[] { ',' }); |
11039 | List<string> whiteListUrls = new List<string>(); | 11039 | List<string> whiteListUrls = new List<string>(); |
11040 | Array.ForEach( | 11040 | Array.ForEach( |
11041 | rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); }); | 11041 | rawWhiteListUrls, delegate(string rawUrl) { whiteListUrls.Add(rawUrl.Trim()); }); |
11042 | me.WhiteList = whiteListUrls.ToArray(); | 11042 | me.WhiteList = whiteListUrls.ToArray(); |
11043 | break; | 11043 | break; |
11044 | 11044 | ||
11045 | case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT: | 11045 | case ScriptBaseClass.PRIM_MEDIA_PERMS_INTERACT: |
11046 | me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++); | 11046 | me.InteractPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++); |
11047 | break; | 11047 | break; |
11048 | 11048 | ||
11049 | case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL: | 11049 | case ScriptBaseClass.PRIM_MEDIA_PERMS_CONTROL: |
11050 | me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++); | 11050 | me.ControlPermissions = (MediaPermission)(byte)(int)rules.GetLSLIntegerItem(i++); |
11051 | break; | 11051 | break; |
11052 | 11052 | ||
11053 | default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS; | 11053 | default: return ScriptBaseClass.LSL_STATUS_MALFORMED_PARAMS; |
11054 | } | 11054 | } |
11055 | } | 11055 | } |
11056 | 11056 | ||
11057 | module.SetMediaEntry(part, face, me); | 11057 | module.SetMediaEntry(part, face, me); |
11058 | 11058 | ||
11059 | return ScriptBaseClass.LSL_STATUS_OK; | 11059 | return ScriptBaseClass.LSL_STATUS_OK; |
11060 | } | 11060 | } |
11061 | 11061 | ||
11062 | public LSL_Integer llClearPrimMedia(LSL_Integer face) | 11062 | public LSL_Integer llClearPrimMedia(LSL_Integer face) |
11063 | { | 11063 | { |
11064 | m_host.AddScriptLPS(1); | 11064 | m_host.AddScriptLPS(1); |
11065 | ScriptSleep(m_sleepMsOnClearPrimMedia); | 11065 | ScriptSleep(m_sleepMsOnClearPrimMedia); |
11066 | return ClearPrimMedia(m_host, face); | 11066 | return ClearPrimMedia(m_host, face); |
11067 | } | 11067 | } |
11068 | 11068 | ||
11069 | public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face) | 11069 | public LSL_Integer llClearLinkMedia(LSL_Integer link, LSL_Integer face) |
11070 | { | 11070 | { |
11071 | m_host.AddScriptLPS(1); | 11071 | m_host.AddScriptLPS(1); |
11072 | ScriptSleep(m_sleepMsOnClearLinkMedia); | 11072 | ScriptSleep(m_sleepMsOnClearLinkMedia); |
11073 | if (link == ScriptBaseClass.LINK_ROOT) | 11073 | if (link == ScriptBaseClass.LINK_ROOT) |
11074 | return ClearPrimMedia(m_host.ParentGroup.RootPart, face); | 11074 | return ClearPrimMedia(m_host.ParentGroup.RootPart, face); |
11075 | else if (link == ScriptBaseClass.LINK_THIS) | 11075 | else if (link == ScriptBaseClass.LINK_THIS) |
11076 | return ClearPrimMedia(m_host, face); | 11076 | return ClearPrimMedia(m_host, face); |
11077 | else | 11077 | else |
11078 | { | 11078 | { |
11079 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); | 11079 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(link); |
11080 | if (null != part) | 11080 | if (null != part) |
11081 | return ClearPrimMedia(part, face); | 11081 | return ClearPrimMedia(part, face); |
11082 | } | 11082 | } |
11083 | 11083 | ||
11084 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; | 11084 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; |
11085 | } | 11085 | } |
11086 | 11086 | ||
11087 | private LSL_Integer ClearPrimMedia(SceneObjectPart part, LSL_Integer face) | 11087 | private LSL_Integer ClearPrimMedia(SceneObjectPart part, LSL_Integer face) |
11088 | { | 11088 | { |
11089 | // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid | 11089 | // LSL Spec http://wiki.secondlife.com/wiki/LlClearPrimMedia says to fail silently if face is invalid |
11090 | // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this. | 11090 | // Assuming silently fail means sending back LSL_STATUS_OK. Ideally, need to check this. |
11091 | // FIXME: Don't perform the media check directly | 11091 | // FIXME: Don't perform the media check directly |
11092 | if (face < 0 || face > part.GetNumberOfSides() - 1) | 11092 | if (face < 0 || face > part.GetNumberOfSides() - 1) |
11093 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; | 11093 | return ScriptBaseClass.LSL_STATUS_NOT_FOUND; |
11094 | 11094 | ||
11095 | IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); | 11095 | IMoapModule module = m_ScriptEngine.World.RequestModuleInterface<IMoapModule>(); |
11096 | if (null == module) | 11096 | if (null == module) |
11097 | return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED; | 11097 | return ScriptBaseClass.LSL_STATUS_NOT_SUPPORTED; |
11098 | 11098 | ||
11099 | module.ClearMediaEntry(part, face); | 11099 | module.ClearMediaEntry(part, face); |
11100 | 11100 | ||
11101 | return ScriptBaseClass.LSL_STATUS_OK; | 11101 | return ScriptBaseClass.LSL_STATUS_OK; |
11102 | } | 11102 | } |
11103 | 11103 | ||
11104 | // <remarks> | 11104 | // <remarks> |
11105 | // <para> | 11105 | // <para> |
11106 | // The .NET definition of base 64 is: | 11106 | // The .NET definition of base 64 is: |
11107 | // <list> | 11107 | // <list> |
11108 | // <item> | 11108 | // <item> |
11109 | // Significant: A-Z a-z 0-9 + - | 11109 | // Significant: A-Z a-z 0-9 + - |
11110 | // </item> | 11110 | // </item> |
11111 | // <item> | 11111 | // <item> |
11112 | // Whitespace: \t \n \r ' ' | 11112 | // Whitespace: \t \n \r ' ' |
11113 | // </item> | 11113 | // </item> |
11114 | // <item> | 11114 | // <item> |
11115 | // Valueless: = | 11115 | // Valueless: = |
11116 | // </item> | 11116 | // </item> |
11117 | // <item> | 11117 | // <item> |
11118 | // End-of-string: \0 or '==' | 11118 | // End-of-string: \0 or '==' |
11119 | // </item> | 11119 | // </item> |
11120 | // </list> | 11120 | // </list> |
11121 | // </para> | 11121 | // </para> |
11122 | // <para> | 11122 | // <para> |
11123 | // Each point in a base-64 string represents | 11123 | // Each point in a base-64 string represents |
11124 | // a 6 bit value. A 32-bit integer can be | 11124 | // a 6 bit value. A 32-bit integer can be |
11125 | // represented using 6 characters (with some | 11125 | // represented using 6 characters (with some |
11126 | // redundancy). | 11126 | // redundancy). |
11127 | // </para> | 11127 | // </para> |
11128 | // <para> | 11128 | // <para> |
11129 | // LSL requires a base64 string to be 8 | 11129 | // LSL requires a base64 string to be 8 |
11130 | // characters in length. LSL also uses '/' | 11130 | // characters in length. LSL also uses '/' |
11131 | // rather than '-' (MIME compliant). | 11131 | // rather than '-' (MIME compliant). |
11132 | // </para> | 11132 | // </para> |
11133 | // <para> | 11133 | // <para> |
11134 | // RFC 1341 used as a reference (as specified | 11134 | // RFC 1341 used as a reference (as specified |
11135 | // by the SecondLife Wiki). | 11135 | // by the SecondLife Wiki). |
11136 | // </para> | 11136 | // </para> |
11137 | // <para> | 11137 | // <para> |
11138 | // SL do not record any kind of exception for | 11138 | // SL do not record any kind of exception for |
11139 | // these functions, so the string to integer | 11139 | // these functions, so the string to integer |
11140 | // conversion returns '0' if an invalid | 11140 | // conversion returns '0' if an invalid |
11141 | // character is encountered during conversion. | 11141 | // character is encountered during conversion. |
11142 | // </para> | 11142 | // </para> |
11143 | // <para> | 11143 | // <para> |
11144 | // References | 11144 | // References |
11145 | // <list> | 11145 | // <list> |
11146 | // <item> | 11146 | // <item> |
11147 | // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64 | 11147 | // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64 |
11148 | // </item> | 11148 | // </item> |
11149 | // <item> | 11149 | // <item> |
11150 | // </item> | 11150 | // </item> |
11151 | // </list> | 11151 | // </list> |
11152 | // </para> | 11152 | // </para> |
11153 | // </remarks> | 11153 | // </remarks> |
11154 | 11154 | ||
11155 | // <summary> | 11155 | // <summary> |
11156 | // Table for converting 6-bit integers into | 11156 | // Table for converting 6-bit integers into |
11157 | // base-64 characters | 11157 | // base-64 characters |
11158 | // </summary> | 11158 | // </summary> |
11159 | 11159 | ||
11160 | protected static readonly char[] i2ctable = | 11160 | protected static readonly char[] i2ctable = |
11161 | { | 11161 | { |
11162 | 'A','B','C','D','E','F','G','H', | 11162 | 'A','B','C','D','E','F','G','H', |
11163 | 'I','J','K','L','M','N','O','P', | 11163 | 'I','J','K','L','M','N','O','P', |
11164 | 'Q','R','S','T','U','V','W','X', | 11164 | 'Q','R','S','T','U','V','W','X', |
11165 | 'Y','Z', | 11165 | 'Y','Z', |
11166 | 'a','b','c','d','e','f','g','h', | 11166 | 'a','b','c','d','e','f','g','h', |
11167 | 'i','j','k','l','m','n','o','p', | 11167 | 'i','j','k','l','m','n','o','p', |
11168 | 'q','r','s','t','u','v','w','x', | 11168 | 'q','r','s','t','u','v','w','x', |
11169 | 'y','z', | 11169 | 'y','z', |
11170 | '0','1','2','3','4','5','6','7', | 11170 | '0','1','2','3','4','5','6','7', |
11171 | '8','9', | 11171 | '8','9', |
11172 | '+','/' | 11172 | '+','/' |
11173 | }; | 11173 | }; |
11174 | 11174 | ||
11175 | // <summary> | 11175 | // <summary> |
11176 | // Table for converting base-64 characters | 11176 | // Table for converting base-64 characters |
11177 | // into 6-bit integers. | 11177 | // into 6-bit integers. |
11178 | // </summary> | 11178 | // </summary> |
11179 | 11179 | ||
11180 | protected static readonly int[] c2itable = | 11180 | protected static readonly int[] c2itable = |
11181 | { | 11181 | { |
11182 | -1,-1,-1,-1,-1,-1,-1,-1, // 0x | 11182 | -1,-1,-1,-1,-1,-1,-1,-1, // 0x |
11183 | -1,-1,-1,-1,-1,-1,-1,-1, | 11183 | -1,-1,-1,-1,-1,-1,-1,-1, |
11184 | -1,-1,-1,-1,-1,-1,-1,-1, // 1x | 11184 | -1,-1,-1,-1,-1,-1,-1,-1, // 1x |
11185 | -1,-1,-1,-1,-1,-1,-1,-1, | 11185 | -1,-1,-1,-1,-1,-1,-1,-1, |
11186 | -1,-1,-1,-1,-1,-1,-1,-1, // 2x | 11186 | -1,-1,-1,-1,-1,-1,-1,-1, // 2x |
11187 | -1,-1,-1,63,-1,-1,-1,64, | 11187 | -1,-1,-1,63,-1,-1,-1,64, |
11188 | 53,54,55,56,57,58,59,60, // 3x | 11188 | 53,54,55,56,57,58,59,60, // 3x |
11189 | 61,62,-1,-1,-1,0,-1,-1, | 11189 | 61,62,-1,-1,-1,0,-1,-1, |
11190 | -1,1,2,3,4,5,6,7, // 4x | 11190 | -1,1,2,3,4,5,6,7, // 4x |
11191 | 8,9,10,11,12,13,14,15, | 11191 | 8,9,10,11,12,13,14,15, |
11192 | 16,17,18,19,20,21,22,23, // 5x | 11192 | 16,17,18,19,20,21,22,23, // 5x |
11193 | 24,25,26,-1,-1,-1,-1,-1, | 11193 | 24,25,26,-1,-1,-1,-1,-1, |
11194 | -1,27,28,29,30,31,32,33, // 6x | 11194 | -1,27,28,29,30,31,32,33, // 6x |
11195 | 34,35,36,37,38,39,40,41, | 11195 | 34,35,36,37,38,39,40,41, |
11196 | 42,43,44,45,46,47,48,49, // 7x | 11196 | 42,43,44,45,46,47,48,49, // 7x |
11197 | 50,51,52,-1,-1,-1,-1,-1, | 11197 | 50,51,52,-1,-1,-1,-1,-1, |
11198 | -1,-1,-1,-1,-1,-1,-1,-1, // 8x | 11198 | -1,-1,-1,-1,-1,-1,-1,-1, // 8x |
11199 | -1,-1,-1,-1,-1,-1,-1,-1, | 11199 | -1,-1,-1,-1,-1,-1,-1,-1, |
11200 | -1,-1,-1,-1,-1,-1,-1,-1, // 9x | 11200 | -1,-1,-1,-1,-1,-1,-1,-1, // 9x |
11201 | -1,-1,-1,-1,-1,-1,-1,-1, | 11201 | -1,-1,-1,-1,-1,-1,-1,-1, |
11202 | -1,-1,-1,-1,-1,-1,-1,-1, // Ax | 11202 | -1,-1,-1,-1,-1,-1,-1,-1, // Ax |
11203 | -1,-1,-1,-1,-1,-1,-1,-1, | 11203 | -1,-1,-1,-1,-1,-1,-1,-1, |
11204 | -1,-1,-1,-1,-1,-1,-1,-1, // Bx | 11204 | -1,-1,-1,-1,-1,-1,-1,-1, // Bx |
11205 | -1,-1,-1,-1,-1,-1,-1,-1, | 11205 | -1,-1,-1,-1,-1,-1,-1,-1, |
11206 | -1,-1,-1,-1,-1,-1,-1,-1, // Cx | 11206 | -1,-1,-1,-1,-1,-1,-1,-1, // Cx |
11207 | -1,-1,-1,-1,-1,-1,-1,-1, | 11207 | -1,-1,-1,-1,-1,-1,-1,-1, |
11208 | -1,-1,-1,-1,-1,-1,-1,-1, // Dx | 11208 | -1,-1,-1,-1,-1,-1,-1,-1, // Dx |
11209 | -1,-1,-1,-1,-1,-1,-1,-1, | 11209 | -1,-1,-1,-1,-1,-1,-1,-1, |
11210 | -1,-1,-1,-1,-1,-1,-1,-1, // Ex | 11210 | -1,-1,-1,-1,-1,-1,-1,-1, // Ex |
11211 | -1,-1,-1,-1,-1,-1,-1,-1, | 11211 | -1,-1,-1,-1,-1,-1,-1,-1, |
11212 | -1,-1,-1,-1,-1,-1,-1,-1, // Fx | 11212 | -1,-1,-1,-1,-1,-1,-1,-1, // Fx |
11213 | -1,-1,-1,-1,-1,-1,-1,-1 | 11213 | -1,-1,-1,-1,-1,-1,-1,-1 |
11214 | }; | 11214 | }; |
11215 | 11215 | ||
11216 | // <summary> | 11216 | // <summary> |
11217 | // Converts a 32-bit integer into a Base64 | 11217 | // Converts a 32-bit integer into a Base64 |
11218 | // character string. Base64 character strings | 11218 | // character string. Base64 character strings |
11219 | // are always 8 characters long. All iinteger | 11219 | // are always 8 characters long. All iinteger |
11220 | // values are acceptable. | 11220 | // values are acceptable. |
11221 | // </summary> | 11221 | // </summary> |
11222 | // <param name="number"> | 11222 | // <param name="number"> |
11223 | // 32-bit integer to be converted. | 11223 | // 32-bit integer to be converted. |
11224 | // </param> | 11224 | // </param> |
11225 | // <returns> | 11225 | // <returns> |
11226 | // 8 character string. The 1st six characters | 11226 | // 8 character string. The 1st six characters |
11227 | // contain the encoded number, the last two | 11227 | // contain the encoded number, the last two |
11228 | // characters are padded with "=". | 11228 | // characters are padded with "=". |
11229 | // </returns> | 11229 | // </returns> |
11230 | 11230 | ||
11231 | public LSL_String llIntegerToBase64(int number) | 11231 | public LSL_String llIntegerToBase64(int number) |
11232 | { | 11232 | { |
11233 | // uninitialized string | 11233 | // uninitialized string |
11234 | 11234 | ||
11235 | char[] imdt = new char[8]; | 11235 | char[] imdt = new char[8]; |
11236 | 11236 | ||
11237 | m_host.AddScriptLPS(1); | 11237 | m_host.AddScriptLPS(1); |
11238 | 11238 | ||
11239 | // Manually unroll the loop | 11239 | // Manually unroll the loop |
11240 | 11240 | ||
11241 | imdt[7] = '='; | 11241 | imdt[7] = '='; |
11242 | imdt[6] = '='; | 11242 | imdt[6] = '='; |
11243 | imdt[5] = i2ctable[number<<4 & 0x3F]; | 11243 | imdt[5] = i2ctable[number<<4 & 0x3F]; |
11244 | imdt[4] = i2ctable[number>>2 & 0x3F]; | 11244 | imdt[4] = i2ctable[number>>2 & 0x3F]; |
11245 | imdt[3] = i2ctable[number>>8 & 0x3F]; | 11245 | imdt[3] = i2ctable[number>>8 & 0x3F]; |
11246 | imdt[2] = i2ctable[number>>14 & 0x3F]; | 11246 | imdt[2] = i2ctable[number>>14 & 0x3F]; |
11247 | imdt[1] = i2ctable[number>>20 & 0x3F]; | 11247 | imdt[1] = i2ctable[number>>20 & 0x3F]; |
11248 | imdt[0] = i2ctable[number>>26 & 0x3F]; | 11248 | imdt[0] = i2ctable[number>>26 & 0x3F]; |
11249 | 11249 | ||
11250 | return new string(imdt); | 11250 | return new string(imdt); |
11251 | } | 11251 | } |
11252 | 11252 | ||
11253 | // <summary> | 11253 | // <summary> |
11254 | // Converts an eight character base-64 string | 11254 | // Converts an eight character base-64 string |
11255 | // into a 32-bit integer. | 11255 | // into a 32-bit integer. |
11256 | // </summary> | 11256 | // </summary> |
11257 | // <param name="str"> | 11257 | // <param name="str"> |
11258 | // 8 characters string to be converted. Other | 11258 | // 8 characters string to be converted. Other |
11259 | // length strings return zero. | 11259 | // length strings return zero. |
11260 | // </param> | 11260 | // </param> |
11261 | // <returns> | 11261 | // <returns> |
11262 | // Returns an integer representing the | 11262 | // Returns an integer representing the |
11263 | // encoded value providedint he 1st 6 | 11263 | // encoded value providedint he 1st 6 |
11264 | // characters of the string. | 11264 | // characters of the string. |
11265 | // </returns> | 11265 | // </returns> |
11266 | // <remarks> | 11266 | // <remarks> |
11267 | // This is coded to behave like LSL's | 11267 | // This is coded to behave like LSL's |
11268 | // implementation (I think), based upon the | 11268 | // implementation (I think), based upon the |
11269 | // information available at the Wiki. | 11269 | // information available at the Wiki. |
11270 | // If more than 8 characters are supplied, | 11270 | // If more than 8 characters are supplied, |
11271 | // zero is returned. | 11271 | // zero is returned. |
11272 | // If a NULL string is supplied, zero will | 11272 | // If a NULL string is supplied, zero will |
11273 | // be returned. | 11273 | // be returned. |
11274 | // If fewer than 6 characters are supplied, then | 11274 | // If fewer than 6 characters are supplied, then |
11275 | // the answer will reflect a partial | 11275 | // the answer will reflect a partial |
11276 | // accumulation. | 11276 | // accumulation. |
11277 | // <para> | 11277 | // <para> |
11278 | // The 6-bit segments are | 11278 | // The 6-bit segments are |
11279 | // extracted left-to-right in big-endian mode, | 11279 | // extracted left-to-right in big-endian mode, |
11280 | // which means that segment 6 only contains the | 11280 | // which means that segment 6 only contains the |
11281 | // two low-order bits of the 32 bit integer as | 11281 | // two low-order bits of the 32 bit integer as |
11282 | // its high order 2 bits. A short string therefore | 11282 | // its high order 2 bits. A short string therefore |
11283 | // means loss of low-order information. E.g. | 11283 | // means loss of low-order information. E.g. |
11284 | // | 11284 | // |
11285 | // |<---------------------- 32-bit integer ----------------------->|<-Pad->| | 11285 | // |<---------------------- 32-bit integer ----------------------->|<-Pad->| |
11286 | // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->| | 11286 | // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->| |
11287 | // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P| | 11287 | // |3|3|2|2|2|2|2|2|2|2|2|2|1|1|1|1|1|1|1|1|1|1| | | | | | | | | | |P|P|P|P| |
11288 | // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P| | 11288 | // |1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|9|8|7|6|5|4|3|2|1|0|P|P|P|P| |
11289 | // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] | | 11289 | // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] | |
11290 | // | 11290 | // |
11291 | // </para> | 11291 | // </para> |
11292 | // </remarks> | 11292 | // </remarks> |
11293 | 11293 | ||
11294 | public LSL_Integer llBase64ToInteger(string str) | 11294 | public LSL_Integer llBase64ToInteger(string str) |
11295 | { | 11295 | { |
11296 | int number = 0; | 11296 | int number = 0; |
11297 | int digit; | 11297 | int digit; |
11298 | 11298 | ||
11299 | m_host.AddScriptLPS(1); | 11299 | m_host.AddScriptLPS(1); |
11300 | 11300 | ||
11301 | // Require a well-fromed base64 string | 11301 | // Require a well-fromed base64 string |
11302 | 11302 | ||
11303 | if (str.Length > 8) | 11303 | if (str.Length > 8) |
11304 | return 0; | 11304 | return 0; |
11305 | 11305 | ||
11306 | // The loop is unrolled in the interests | 11306 | // The loop is unrolled in the interests |
11307 | // of performance and simple necessity. | 11307 | // of performance and simple necessity. |
11308 | // | 11308 | // |
11309 | // MUST find 6 digits to be well formed | 11309 | // MUST find 6 digits to be well formed |
11310 | // -1 == invalid | 11310 | // -1 == invalid |
11311 | // 0 == padding | 11311 | // 0 == padding |
11312 | 11312 | ||
11313 | if ((digit = c2itable[str[0]]) <= 0) | 11313 | if ((digit = c2itable[str[0]]) <= 0) |
11314 | { | 11314 | { |
11315 | return digit < 0 ? (int)0 : number; | 11315 | return digit < 0 ? (int)0 : number; |
11316 | } | 11316 | } |
11317 | number += --digit<<26; | 11317 | number += --digit<<26; |
11318 | 11318 | ||
11319 | if ((digit = c2itable[str[1]]) <= 0) | 11319 | if ((digit = c2itable[str[1]]) <= 0) |
11320 | { | 11320 | { |
11321 | return digit < 0 ? (int)0 : number; | 11321 | return digit < 0 ? (int)0 : number; |
11322 | } | 11322 | } |
11323 | number += --digit<<20; | 11323 | number += --digit<<20; |
11324 | 11324 | ||
11325 | if ((digit = c2itable[str[2]]) <= 0) | 11325 | if ((digit = c2itable[str[2]]) <= 0) |
11326 | { | 11326 | { |
11327 | return digit < 0 ? (int)0 : number; | 11327 | return digit < 0 ? (int)0 : number; |
11328 | } | 11328 | } |
11329 | number += --digit<<14; | 11329 | number += --digit<<14; |
11330 | 11330 | ||
11331 | if ((digit = c2itable[str[3]]) <= 0) | 11331 | if ((digit = c2itable[str[3]]) <= 0) |
11332 | { | 11332 | { |
11333 | return digit < 0 ? (int)0 : number; | 11333 | return digit < 0 ? (int)0 : number; |
11334 | } | 11334 | } |
11335 | number += --digit<<8; | 11335 | number += --digit<<8; |
11336 | 11336 | ||
11337 | if ((digit = c2itable[str[4]]) <= 0) | 11337 | if ((digit = c2itable[str[4]]) <= 0) |
11338 | { | 11338 | { |
11339 | return digit < 0 ? (int)0 : number; | 11339 | return digit < 0 ? (int)0 : number; |
11340 | } | 11340 | } |
11341 | number += --digit<<2; | 11341 | number += --digit<<2; |
11342 | 11342 | ||
11343 | if ((digit = c2itable[str[5]]) <= 0) | 11343 | if ((digit = c2itable[str[5]]) <= 0) |
11344 | { | 11344 | { |
11345 | return digit < 0 ? (int)0 : number; | 11345 | return digit < 0 ? (int)0 : number; |
11346 | } | 11346 | } |
11347 | number += --digit>>4; | 11347 | number += --digit>>4; |
11348 | 11348 | ||
11349 | // ignore trailing padding | 11349 | // ignore trailing padding |
11350 | 11350 | ||
11351 | return number; | 11351 | return number; |
11352 | } | 11352 | } |
11353 | 11353 | ||
11354 | public LSL_Float llGetGMTclock() | 11354 | public LSL_Float llGetGMTclock() |
11355 | { | 11355 | { |
11356 | m_host.AddScriptLPS(1); | 11356 | m_host.AddScriptLPS(1); |
11357 | return DateTime.UtcNow.TimeOfDay.TotalSeconds; | 11357 | return DateTime.UtcNow.TimeOfDay.TotalSeconds; |
11358 | } | 11358 | } |
11359 | 11359 | ||
11360 | public LSL_String llGetHTTPHeader(LSL_Key request_id, string header) | 11360 | public LSL_String llGetHTTPHeader(LSL_Key request_id, string header) |
11361 | { | 11361 | { |
11362 | m_host.AddScriptLPS(1); | 11362 | m_host.AddScriptLPS(1); |
11363 | 11363 | ||
11364 | if (m_UrlModule != null) | 11364 | if (m_UrlModule != null) |
11365 | return m_UrlModule.GetHttpHeader(new UUID(request_id), header); | 11365 | return m_UrlModule.GetHttpHeader(new UUID(request_id), header); |
11366 | return String.Empty; | 11366 | return String.Empty; |
11367 | } | 11367 | } |
11368 | 11368 | ||
11369 | 11369 | ||
11370 | public LSL_String llGetSimulatorHostname() | 11370 | public LSL_String llGetSimulatorHostname() |
11371 | { | 11371 | { |
11372 | m_host.AddScriptLPS(1); | 11372 | m_host.AddScriptLPS(1); |
11373 | IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); | 11373 | IUrlModule UrlModule = World.RequestModuleInterface<IUrlModule>(); |
11374 | return UrlModule.ExternalHostNameForLSL; | 11374 | return UrlModule.ExternalHostNameForLSL; |
11375 | } | 11375 | } |
11376 | 11376 | ||
11377 | // <summary> | 11377 | // <summary> |
11378 | // Scan the string supplied in 'src' and | 11378 | // Scan the string supplied in 'src' and |
11379 | // tokenize it based upon two sets of | 11379 | // tokenize it based upon two sets of |
11380 | // tokenizers provided in two lists, | 11380 | // tokenizers provided in two lists, |
11381 | // separators and spacers. | 11381 | // separators and spacers. |
11382 | // </summary> | 11382 | // </summary> |
11383 | // | 11383 | // |
11384 | // <remarks> | 11384 | // <remarks> |
11385 | // Separators demarcate tokens and are | 11385 | // Separators demarcate tokens and are |
11386 | // elided as they are encountered. Spacers | 11386 | // elided as they are encountered. Spacers |
11387 | // also demarcate tokens, but are themselves | 11387 | // also demarcate tokens, but are themselves |
11388 | // retained as tokens. | 11388 | // retained as tokens. |
11389 | // | 11389 | // |
11390 | // Both separators and spacers may be arbitrarily | 11390 | // Both separators and spacers may be arbitrarily |
11391 | // long strings. i.e. ":::". | 11391 | // long strings. i.e. ":::". |
11392 | // | 11392 | // |
11393 | // The function returns an ordered list | 11393 | // The function returns an ordered list |
11394 | // representing the tokens found in the supplied | 11394 | // representing the tokens found in the supplied |
11395 | // sources string. If two successive tokenizers | 11395 | // sources string. If two successive tokenizers |
11396 | // are encountered, then a NULL entry is added | 11396 | // are encountered, then a NULL entry is added |
11397 | // to the list. | 11397 | // to the list. |
11398 | // | 11398 | // |
11399 | // It is a precondition that the source and | 11399 | // It is a precondition that the source and |
11400 | // toekizer lisst are non-null. If they are null, | 11400 | // toekizer lisst are non-null. If they are null, |
11401 | // then a null pointer exception will be thrown | 11401 | // then a null pointer exception will be thrown |
11402 | // while their lengths are being determined. | 11402 | // while their lengths are being determined. |
11403 | // | 11403 | // |
11404 | // A small amount of working memoryis required | 11404 | // A small amount of working memoryis required |
11405 | // of approximately 8*#tokenizers. | 11405 | // of approximately 8*#tokenizers. |
11406 | // | 11406 | // |
11407 | // There are many ways in which this function | 11407 | // There are many ways in which this function |
11408 | // can be implemented, this implementation is | 11408 | // can be implemented, this implementation is |
11409 | // fairly naive and assumes that when the | 11409 | // fairly naive and assumes that when the |
11410 | // function is invooked with a short source | 11410 | // function is invooked with a short source |
11411 | // string and/or short lists of tokenizers, then | 11411 | // string and/or short lists of tokenizers, then |
11412 | // performance will not be an issue. | 11412 | // performance will not be an issue. |
11413 | // | 11413 | // |
11414 | // In order to minimize the perofrmance | 11414 | // In order to minimize the perofrmance |
11415 | // effects of long strings, or large numbers | 11415 | // effects of long strings, or large numbers |
11416 | // of tokeizers, the function skips as far as | 11416 | // of tokeizers, the function skips as far as |
11417 | // possible whenever a toekenizer is found, | 11417 | // possible whenever a toekenizer is found, |
11418 | // and eliminates redundant tokenizers as soon | 11418 | // and eliminates redundant tokenizers as soon |
11419 | // as is possible. | 11419 | // as is possible. |
11420 | // | 11420 | // |
11421 | // The implementation tries to avoid any copying | 11421 | // The implementation tries to avoid any copying |
11422 | // of arrays or other objects. | 11422 | // of arrays or other objects. |
11423 | // </remarks> | 11423 | // </remarks> |
11424 | 11424 | ||
11425 | private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) | 11425 | private LSL_List ParseString(string src, LSL_List separators, LSL_List spacers, bool keepNulls) |
11426 | { | 11426 | { |
11427 | int beginning = 0; | 11427 | int beginning = 0; |
11428 | int srclen = src.Length; | 11428 | int srclen = src.Length; |
11429 | int seplen = separators.Length; | 11429 | int seplen = separators.Length; |
11430 | object[] separray = separators.Data; | 11430 | object[] separray = separators.Data; |
11431 | int spclen = spacers.Length; | 11431 | int spclen = spacers.Length; |
11432 | object[] spcarray = spacers.Data; | 11432 | object[] spcarray = spacers.Data; |
11433 | int mlen = seplen+spclen; | 11433 | int mlen = seplen+spclen; |
11434 | 11434 | ||
11435 | int[] offset = new int[mlen+1]; | 11435 | int[] offset = new int[mlen+1]; |
11436 | bool[] active = new bool[mlen]; | 11436 | bool[] active = new bool[mlen]; |
11437 | 11437 | ||
11438 | int best; | 11438 | int best; |
11439 | int j; | 11439 | int j; |
11440 | 11440 | ||
11441 | // Initial capacity reduces resize cost | 11441 | // Initial capacity reduces resize cost |
11442 | 11442 | ||
11443 | LSL_List tokens = new LSL_List(); | 11443 | LSL_List tokens = new LSL_List(); |
11444 | 11444 | ||
11445 | // All entries are initially valid | 11445 | // All entries are initially valid |
11446 | 11446 | ||
11447 | for (int i = 0; i < mlen; i++) | 11447 | for (int i = 0; i < mlen; i++) |
11448 | active[i] = true; | 11448 | active[i] = true; |
11449 | 11449 | ||
11450 | offset[mlen] = srclen; | 11450 | offset[mlen] = srclen; |
11451 | 11451 | ||
11452 | while (beginning < srclen) | 11452 | while (beginning < srclen) |
11453 | { | 11453 | { |
11454 | 11454 | ||
11455 | best = mlen; // as bad as it gets | 11455 | best = mlen; // as bad as it gets |
11456 | 11456 | ||
11457 | // Scan for separators | 11457 | // Scan for separators |
11458 | 11458 | ||
11459 | for (j = 0; j < seplen; j++) | 11459 | for (j = 0; j < seplen; j++) |
11460 | { | 11460 | { |
11461 | if (separray[j].ToString() == String.Empty) | 11461 | if (separray[j].ToString() == String.Empty) |
11462 | active[j] = false; | 11462 | active[j] = false; |
11463 | 11463 | ||
11464 | if (active[j]) | 11464 | if (active[j]) |
11465 | { | 11465 | { |
11466 | // scan all of the markers | 11466 | // scan all of the markers |
11467 | if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) | 11467 | if ((offset[j] = src.IndexOf(separray[j].ToString(), beginning)) == -1) |
11468 | { | 11468 | { |
11469 | // not present at all | 11469 | // not present at all |
11470 | active[j] = false; | 11470 | active[j] = false; |
11471 | } | 11471 | } |
11472 | else | 11472 | else |
11473 | { | 11473 | { |
11474 | // present and correct | 11474 | // present and correct |
11475 | if (offset[j] < offset[best]) | 11475 | if (offset[j] < offset[best]) |
11476 | { | 11476 | { |
11477 | // closest so far | 11477 | // closest so far |
11478 | best = j; | 11478 | best = j; |
11479 | if (offset[best] == beginning) | 11479 | if (offset[best] == beginning) |
11480 | break; | 11480 | break; |
11481 | } | 11481 | } |
11482 | } | 11482 | } |
11483 | } | 11483 | } |
11484 | } | 11484 | } |
11485 | 11485 | ||
11486 | // Scan for spacers | 11486 | // Scan for spacers |
11487 | 11487 | ||
11488 | if (offset[best] != beginning) | 11488 | if (offset[best] != beginning) |
11489 | { | 11489 | { |
11490 | for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) | 11490 | for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) |
11491 | { | 11491 | { |
11492 | if (spcarray[j-seplen].ToString() == String.Empty) | 11492 | if (spcarray[j-seplen].ToString() == String.Empty) |
11493 | active[j] = false; | 11493 | active[j] = false; |
11494 | 11494 | ||
11495 | if (active[j]) | 11495 | if (active[j]) |
11496 | { | 11496 | { |
11497 | // scan all of the markers | 11497 | // scan all of the markers |
11498 | if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1) | 11498 | if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1) |
11499 | { | 11499 | { |
11500 | // not present at all | 11500 | // not present at all |
11501 | active[j] = false; | 11501 | active[j] = false; |
11502 | } | 11502 | } |
11503 | else | 11503 | else |
11504 | { | 11504 | { |
11505 | // present and correct | 11505 | // present and correct |
11506 | if (offset[j] < offset[best]) | 11506 | if (offset[j] < offset[best]) |
11507 | { | 11507 | { |
11508 | // closest so far | 11508 | // closest so far |
11509 | best = j; | 11509 | best = j; |
11510 | } | 11510 | } |
11511 | } | 11511 | } |
11512 | } | 11512 | } |
11513 | } | 11513 | } |
11514 | } | 11514 | } |
11515 | 11515 | ||
11516 | // This is the normal exit from the scanning loop | 11516 | // This is the normal exit from the scanning loop |
11517 | 11517 | ||
11518 | if (best == mlen) | 11518 | if (best == mlen) |
11519 | { | 11519 | { |
11520 | // no markers were found on this pass | 11520 | // no markers were found on this pass |
11521 | // so we're pretty much done | 11521 | // so we're pretty much done |
11522 | if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0)) | 11522 | if ((keepNulls) || ((!keepNulls) && (srclen - beginning) > 0)) |
11523 | tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning))); | 11523 | tokens.Add(new LSL_String(src.Substring(beginning, srclen - beginning))); |
11524 | break; | 11524 | break; |
11525 | } | 11525 | } |
11526 | 11526 | ||
11527 | // Otherwise we just add the newly delimited token | 11527 | // Otherwise we just add the newly delimited token |
11528 | // and recalculate where the search should continue. | 11528 | // and recalculate where the search should continue. |
11529 | if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) | 11529 | if ((keepNulls) || ((!keepNulls) && (offset[best] - beginning) > 0)) |
11530 | tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); | 11530 | tokens.Add(new LSL_String(src.Substring(beginning,offset[best]-beginning))); |
11531 | 11531 | ||
11532 | if (best < seplen) | 11532 | if (best < seplen) |
11533 | { | 11533 | { |
11534 | beginning = offset[best] + (separray[best].ToString()).Length; | 11534 | beginning = offset[best] + (separray[best].ToString()).Length; |
11535 | } | 11535 | } |
11536 | else | 11536 | else |
11537 | { | 11537 | { |
11538 | beginning = offset[best] + (spcarray[best - seplen].ToString()).Length; | 11538 | beginning = offset[best] + (spcarray[best - seplen].ToString()).Length; |
11539 | string str = spcarray[best - seplen].ToString(); | 11539 | string str = spcarray[best - seplen].ToString(); |
11540 | if ((keepNulls) || ((!keepNulls) && (str.Length > 0))) | 11540 | if ((keepNulls) || ((!keepNulls) && (str.Length > 0))) |
11541 | tokens.Add(new LSL_String(str)); | 11541 | tokens.Add(new LSL_String(str)); |
11542 | } | 11542 | } |
11543 | } | 11543 | } |
11544 | 11544 | ||
11545 | // This an awkward an not very intuitive boundary case. If the | 11545 | // This an awkward an not very intuitive boundary case. If the |
11546 | // last substring is a tokenizer, then there is an implied trailing | 11546 | // last substring is a tokenizer, then there is an implied trailing |
11547 | // null list entry. Hopefully the single comparison will not be too | 11547 | // null list entry. Hopefully the single comparison will not be too |
11548 | // arduous. Alternatively the 'break' could be replced with a return | 11548 | // arduous. Alternatively the 'break' could be replced with a return |
11549 | // but that's shabby programming. | 11549 | // but that's shabby programming. |
11550 | 11550 | ||
11551 | if ((beginning == srclen) && (keepNulls)) | 11551 | if ((beginning == srclen) && (keepNulls)) |
11552 | { | 11552 | { |
11553 | if (srclen != 0) | 11553 | if (srclen != 0) |
11554 | tokens.Add(new LSL_String("")); | 11554 | tokens.Add(new LSL_String("")); |
11555 | } | 11555 | } |
11556 | 11556 | ||
11557 | return tokens; | 11557 | return tokens; |
11558 | } | 11558 | } |
11559 | 11559 | ||
11560 | public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers) | 11560 | public LSL_List llParseString2List(string src, LSL_List separators, LSL_List spacers) |
11561 | { | 11561 | { |
11562 | m_host.AddScriptLPS(1); | 11562 | m_host.AddScriptLPS(1); |
11563 | return this.ParseString(src, separators, spacers, false); | 11563 | return this.ParseString(src, separators, spacers, false); |
11564 | } | 11564 | } |
11565 | 11565 | ||
11566 | public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) | 11566 | public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) |
11567 | { | 11567 | { |
11568 | m_host.AddScriptLPS(1); | 11568 | m_host.AddScriptLPS(1); |
11569 | return this.ParseString(src, separators, spacers, true); | 11569 | return this.ParseString(src, separators, spacers, true); |
11570 | } | 11570 | } |
11571 | 11571 | ||
11572 | public LSL_Integer llGetObjectPermMask(int mask) | 11572 | public LSL_Integer llGetObjectPermMask(int mask) |
11573 | { | 11573 | { |
11574 | m_host.AddScriptLPS(1); | 11574 | m_host.AddScriptLPS(1); |
11575 | 11575 | ||
11576 | int permmask = 0; | 11576 | int permmask = 0; |
11577 | 11577 | ||
11578 | if (mask == ScriptBaseClass.MASK_BASE)//0 | 11578 | if (mask == ScriptBaseClass.MASK_BASE)//0 |
11579 | { | 11579 | { |
11580 | permmask = (int)m_host.BaseMask; | 11580 | permmask = (int)m_host.BaseMask; |
11581 | } | 11581 | } |
11582 | 11582 | ||
11583 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 | 11583 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 |
11584 | { | 11584 | { |
11585 | permmask = (int)m_host.OwnerMask; | 11585 | permmask = (int)m_host.OwnerMask; |
11586 | } | 11586 | } |
11587 | 11587 | ||
11588 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 | 11588 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 |
11589 | { | 11589 | { |
11590 | permmask = (int)m_host.GroupMask; | 11590 | permmask = (int)m_host.GroupMask; |
11591 | } | 11591 | } |
11592 | 11592 | ||
11593 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 | 11593 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 |
11594 | { | 11594 | { |
11595 | permmask = (int)m_host.EveryoneMask; | 11595 | permmask = (int)m_host.EveryoneMask; |
11596 | } | 11596 | } |
11597 | 11597 | ||
11598 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 | 11598 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 |
11599 | { | 11599 | { |
11600 | permmask = (int)m_host.NextOwnerMask; | 11600 | permmask = (int)m_host.NextOwnerMask; |
11601 | } | 11601 | } |
11602 | 11602 | ||
11603 | return permmask; | 11603 | return permmask; |
11604 | } | 11604 | } |
11605 | 11605 | ||
11606 | public void llSetObjectPermMask(int mask, int value) | 11606 | public void llSetObjectPermMask(int mask, int value) |
11607 | { | 11607 | { |
11608 | m_host.AddScriptLPS(1); | 11608 | m_host.AddScriptLPS(1); |
11609 | 11609 | ||
11610 | if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) | 11610 | if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) |
11611 | { | 11611 | { |
11612 | if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) | 11612 | if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) |
11613 | { | 11613 | { |
11614 | if (mask == ScriptBaseClass.MASK_BASE)//0 | 11614 | if (mask == ScriptBaseClass.MASK_BASE)//0 |
11615 | { | 11615 | { |
11616 | m_host.BaseMask = (uint)value; | 11616 | m_host.BaseMask = (uint)value; |
11617 | } | 11617 | } |
11618 | 11618 | ||
11619 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 | 11619 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 |
11620 | { | 11620 | { |
11621 | m_host.OwnerMask = (uint)value; | 11621 | m_host.OwnerMask = (uint)value; |
11622 | } | 11622 | } |
11623 | 11623 | ||
11624 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 | 11624 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 |
11625 | { | 11625 | { |
11626 | m_host.GroupMask = (uint)value; | 11626 | m_host.GroupMask = (uint)value; |
11627 | } | 11627 | } |
11628 | 11628 | ||
11629 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 | 11629 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 |
11630 | { | 11630 | { |
11631 | m_host.EveryoneMask = (uint)value; | 11631 | m_host.EveryoneMask = (uint)value; |
11632 | } | 11632 | } |
11633 | 11633 | ||
11634 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 | 11634 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 |
11635 | { | 11635 | { |
11636 | m_host.NextOwnerMask = (uint)value; | 11636 | m_host.NextOwnerMask = (uint)value; |
11637 | } | 11637 | } |
11638 | } | 11638 | } |
11639 | } | 11639 | } |
11640 | } | 11640 | } |
11641 | 11641 | ||
11642 | public LSL_Integer llGetInventoryPermMask(string itemName, int mask) | 11642 | public LSL_Integer llGetInventoryPermMask(string itemName, int mask) |
11643 | { | 11643 | { |
11644 | m_host.AddScriptLPS(1); | 11644 | m_host.AddScriptLPS(1); |
11645 | 11645 | ||
11646 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); | 11646 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); |
11647 | 11647 | ||
11648 | if (item == null) | 11648 | if (item == null) |
11649 | return -1; | 11649 | return -1; |
11650 | 11650 | ||
11651 | switch (mask) | 11651 | switch (mask) |
11652 | { | 11652 | { |
11653 | case 0: | 11653 | case 0: |
11654 | return (int)item.BasePermissions; | 11654 | return (int)item.BasePermissions; |
11655 | case 1: | 11655 | case 1: |
11656 | return (int)item.CurrentPermissions; | 11656 | return (int)item.CurrentPermissions; |
11657 | case 2: | 11657 | case 2: |
11658 | return (int)item.GroupPermissions; | 11658 | return (int)item.GroupPermissions; |
11659 | case 3: | 11659 | case 3: |
11660 | return (int)item.EveryonePermissions; | 11660 | return (int)item.EveryonePermissions; |
11661 | case 4: | 11661 | case 4: |
11662 | return (int)item.NextPermissions; | 11662 | return (int)item.NextPermissions; |
11663 | } | 11663 | } |
11664 | 11664 | ||
11665 | return -1; | 11665 | return -1; |
11666 | } | 11666 | } |
11667 | 11667 | ||
11668 | public void llSetInventoryPermMask(string itemName, int mask, int value) | 11668 | public void llSetInventoryPermMask(string itemName, int mask, int value) |
11669 | { | 11669 | { |
11670 | m_host.AddScriptLPS(1); | 11670 | m_host.AddScriptLPS(1); |
11671 | 11671 | ||
11672 | if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) | 11672 | if (m_ScriptEngine.Config.GetBoolean("AllowGodFunctions", false)) |
11673 | { | 11673 | { |
11674 | if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) | 11674 | if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) |
11675 | { | 11675 | { |
11676 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); | 11676 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); |
11677 | 11677 | ||
11678 | if (item != null) | 11678 | if (item != null) |
11679 | { | 11679 | { |
11680 | switch (mask) | 11680 | switch (mask) |
11681 | { | 11681 | { |
11682 | case 0: | 11682 | case 0: |
11683 | item.BasePermissions = (uint)value; | 11683 | item.BasePermissions = (uint)value; |
11684 | break; | 11684 | break; |
11685 | case 1: | 11685 | case 1: |
11686 | item.CurrentPermissions = (uint)value; | 11686 | item.CurrentPermissions = (uint)value; |
11687 | break; | 11687 | break; |
11688 | case 2: | 11688 | case 2: |
11689 | item.GroupPermissions = (uint)value; | 11689 | item.GroupPermissions = (uint)value; |
11690 | break; | 11690 | break; |
11691 | case 3: | 11691 | case 3: |
11692 | item.EveryonePermissions = (uint)value; | 11692 | item.EveryonePermissions = (uint)value; |
11693 | break; | 11693 | break; |
11694 | case 4: | 11694 | case 4: |
11695 | item.NextPermissions = (uint)value; | 11695 | item.NextPermissions = (uint)value; |
11696 | break; | 11696 | break; |
11697 | } | 11697 | } |
11698 | } | 11698 | } |
11699 | } | 11699 | } |
11700 | } | 11700 | } |
11701 | } | 11701 | } |
11702 | 11702 | ||
11703 | public LSL_String llGetInventoryCreator(string itemName) | 11703 | public LSL_String llGetInventoryCreator(string itemName) |
11704 | { | 11704 | { |
11705 | m_host.AddScriptLPS(1); | 11705 | m_host.AddScriptLPS(1); |
11706 | 11706 | ||
11707 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); | 11707 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(itemName); |
11708 | 11708 | ||
11709 | if (item == null) | 11709 | if (item == null) |
11710 | { | 11710 | { |
11711 | Error("llGetInventoryCreator", "Can't find item '" + item + "'"); | 11711 | Error("llGetInventoryCreator", "Can't find item '" + item + "'"); |
11712 | 11712 | ||
11713 | return String.Empty; | 11713 | return String.Empty; |
11714 | } | 11714 | } |
11715 | 11715 | ||
11716 | return item.CreatorID.ToString(); | 11716 | return item.CreatorID.ToString(); |
11717 | } | 11717 | } |
11718 | 11718 | ||
11719 | public void llOwnerSay(string msg) | 11719 | public void llOwnerSay(string msg) |
11720 | { | 11720 | { |
11721 | m_host.AddScriptLPS(1); | 11721 | m_host.AddScriptLPS(1); |
11722 | 11722 | ||
11723 | World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, | 11723 | World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, |
11724 | m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); | 11724 | m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); |
11725 | // IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 11725 | // IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
11726 | // wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg); | 11726 | // wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg); |
11727 | } | 11727 | } |
11728 | 11728 | ||
11729 | public LSL_String llRequestSecureURL() | 11729 | public LSL_String llRequestSecureURL() |
11730 | { | 11730 | { |
11731 | m_host.AddScriptLPS(1); | 11731 | m_host.AddScriptLPS(1); |
11732 | if (m_UrlModule != null) | 11732 | if (m_UrlModule != null) |
11733 | return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); | 11733 | return m_UrlModule.RequestSecureURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); |
11734 | return UUID.Zero.ToString(); | 11734 | return UUID.Zero.ToString(); |
11735 | } | 11735 | } |
11736 | 11736 | ||
11737 | public LSL_String llRequestSimulatorData(string simulator, int data) | 11737 | public LSL_String llRequestSimulatorData(string simulator, int data) |
11738 | { | 11738 | { |
11739 | IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); | 11739 | IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); |
11740 | 11740 | ||
11741 | try | 11741 | try |
11742 | { | 11742 | { |
11743 | m_host.AddScriptLPS(1); | 11743 | m_host.AddScriptLPS(1); |
11744 | 11744 | ||
11745 | string reply = String.Empty; | 11745 | string reply = String.Empty; |
11746 | 11746 | ||
11747 | GridRegion info; | 11747 | GridRegion info; |
11748 | 11748 | ||
11749 | if (World.RegionInfo.RegionName == simulator) | 11749 | if (World.RegionInfo.RegionName == simulator) |
11750 | info = new GridRegion(World.RegionInfo); | 11750 | info = new GridRegion(World.RegionInfo); |
11751 | else | 11751 | else |
11752 | info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); | 11752 | info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); |
11753 | 11753 | ||
11754 | switch (data) | 11754 | switch (data) |
11755 | { | 11755 | { |
11756 | case ScriptBaseClass.DATA_SIM_POS: | 11756 | case ScriptBaseClass.DATA_SIM_POS: |
11757 | if (info == null) | 11757 | if (info == null) |
11758 | { | 11758 | { |
11759 | ScriptSleep(m_sleepMsOnRequestSimulatorData); | 11759 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
11760 | return UUID.Zero.ToString(); | 11760 | return UUID.Zero.ToString(); |
11761 | } | 11761 | } |
11762 | 11762 | ||
11763 | bool isHypergridRegion = false; | 11763 | bool isHypergridRegion = false; |
11764 | 11764 | ||
11765 | if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") | 11765 | if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") |
11766 | { | 11766 | { |
11767 | // Hypergrid is currently placing real destination region co-ords into RegionSecret. | 11767 | // Hypergrid is currently placing real destination region co-ords into RegionSecret. |
11768 | // But other code can also use this field for a genuine RegionSecret! Therefore, if | 11768 | // But other code can also use this field for a genuine RegionSecret! Therefore, if |
11769 | // anything is present we need to disambiguate. | 11769 | // anything is present we need to disambiguate. |
11770 | // | 11770 | // |
11771 | // FIXME: Hypergrid should be storing this data in a different field. | 11771 | // FIXME: Hypergrid should be storing this data in a different field. |
11772 | RegionFlags regionFlags | 11772 | RegionFlags regionFlags |
11773 | = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( | 11773 | = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( |
11774 | info.ScopeID, info.RegionID); | 11774 | info.ScopeID, info.RegionID); |
11775 | isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; | 11775 | isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; |
11776 | } | 11776 | } |
11777 | 11777 | ||
11778 | if (isHypergridRegion) | 11778 | if (isHypergridRegion) |
11779 | { | 11779 | { |
11780 | uint rx = 0, ry = 0; | 11780 | uint rx = 0, ry = 0; |
11781 | Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); | 11781 | Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); |
11782 | 11782 | ||
11783 | reply = new LSL_Vector( | 11783 | reply = new LSL_Vector( |
11784 | rx, | 11784 | rx, |
11785 | ry, | 11785 | ry, |
11786 | 0).ToString(); | 11786 | 0).ToString(); |
11787 | } | 11787 | } |
11788 | else | 11788 | else |
11789 | { | 11789 | { |
11790 | // Local grid co-oridnates | 11790 | // Local grid co-oridnates |
11791 | reply = new LSL_Vector( | 11791 | reply = new LSL_Vector( |
11792 | info.RegionLocX, | 11792 | info.RegionLocX, |
11793 | info.RegionLocY, | 11793 | info.RegionLocY, |
11794 | 0).ToString(); | 11794 | 0).ToString(); |
11795 | } | 11795 | } |
11796 | break; | 11796 | break; |
11797 | case ScriptBaseClass.DATA_SIM_STATUS: | 11797 | case ScriptBaseClass.DATA_SIM_STATUS: |
11798 | if (info != null) | 11798 | if (info != null) |
11799 | reply = "up"; // Duh! | 11799 | reply = "up"; // Duh! |
11800 | else | 11800 | else |
11801 | reply = "unknown"; | 11801 | reply = "unknown"; |
11802 | break; | 11802 | break; |
11803 | case ScriptBaseClass.DATA_SIM_RATING: | 11803 | case ScriptBaseClass.DATA_SIM_RATING: |
11804 | if (info == null) | 11804 | if (info == null) |
11805 | { | 11805 | { |
11806 | ScriptSleep(m_sleepMsOnRequestSimulatorData); | 11806 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
11807 | return UUID.Zero.ToString(); | 11807 | return UUID.Zero.ToString(); |
11808 | } | 11808 | } |
11809 | int access = info.Maturity; | 11809 | int access = info.Maturity; |
11810 | if (access == 0) | 11810 | if (access == 0) |
11811 | reply = "PG"; | 11811 | reply = "PG"; |
11812 | else if (access == 1) | 11812 | else if (access == 1) |
11813 | reply = "MATURE"; | 11813 | reply = "MATURE"; |
11814 | else if (access == 2) | 11814 | else if (access == 2) |
11815 | reply = "ADULT"; | 11815 | reply = "ADULT"; |
11816 | else | 11816 | else |
11817 | reply = "UNKNOWN"; | 11817 | reply = "UNKNOWN"; |
11818 | break; | 11818 | break; |
11819 | case ScriptBaseClass.DATA_SIM_RELEASE: | 11819 | case ScriptBaseClass.DATA_SIM_RELEASE: |
11820 | if (ossl != null) | 11820 | if (ossl != null) |
11821 | ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData"); | 11821 | ossl.CheckThreatLevel(ThreatLevel.High, "llRequestSimulatorData"); |
11822 | reply = "OpenSim"; | 11822 | reply = "OpenSim"; |
11823 | break; | 11823 | break; |
11824 | default: | 11824 | default: |
11825 | ScriptSleep(m_sleepMsOnRequestSimulatorData); | 11825 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
11826 | return UUID.Zero.ToString(); // Raise no event | 11826 | return UUID.Zero.ToString(); // Raise no event |
11827 | } | 11827 | } |
11828 | UUID rq = UUID.Random(); | 11828 | UUID rq = UUID.Random(); |
11829 | 11829 | ||
11830 | UUID tid = AsyncCommands. | 11830 | UUID tid = AsyncCommands. |
11831 | DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); | 11831 | DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); |
11832 | 11832 | ||
11833 | AsyncCommands. | 11833 | AsyncCommands. |
11834 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | 11834 | DataserverPlugin.DataserverReply(rq.ToString(), reply); |
11835 | 11835 | ||
11836 | ScriptSleep(m_sleepMsOnRequestSimulatorData); | 11836 | ScriptSleep(m_sleepMsOnRequestSimulatorData); |
11837 | return tid.ToString(); | 11837 | return tid.ToString(); |
11838 | } | 11838 | } |
11839 | catch(Exception) | 11839 | catch(Exception) |
11840 | { | 11840 | { |
11841 | //m_log.Error("[LSL_API]: llRequestSimulatorData" + e.ToString()); | 11841 | //m_log.Error("[LSL_API]: llRequestSimulatorData" + e.ToString()); |
11842 | return UUID.Zero.ToString(); | 11842 | return UUID.Zero.ToString(); |
11843 | } | 11843 | } |
11844 | } | 11844 | } |
11845 | 11845 | ||
11846 | public LSL_String llRequestURL() | 11846 | public LSL_String llRequestURL() |
11847 | { | 11847 | { |
11848 | m_host.AddScriptLPS(1); | 11848 | m_host.AddScriptLPS(1); |
11849 | 11849 | ||
11850 | if (m_UrlModule != null) | 11850 | if (m_UrlModule != null) |
11851 | return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); | 11851 | return m_UrlModule.RequestURL(m_ScriptEngine.ScriptModule, m_host, m_item.ItemID).ToString(); |
11852 | return UUID.Zero.ToString(); | 11852 | return UUID.Zero.ToString(); |
11853 | } | 11853 | } |
11854 | 11854 | ||
11855 | public void llForceMouselook(int mouselook) | 11855 | public void llForceMouselook(int mouselook) |
11856 | { | 11856 | { |
11857 | m_host.AddScriptLPS(1); | 11857 | m_host.AddScriptLPS(1); |
11858 | m_host.SetForceMouselook(mouselook != 0); | 11858 | m_host.SetForceMouselook(mouselook != 0); |
11859 | } | 11859 | } |
11860 | 11860 | ||
11861 | public LSL_Float llGetObjectMass(string id) | 11861 | public LSL_Float llGetObjectMass(string id) |
11862 | { | 11862 | { |
11863 | m_host.AddScriptLPS(1); | 11863 | m_host.AddScriptLPS(1); |
11864 | UUID key = new UUID(); | 11864 | UUID key = new UUID(); |
11865 | if (UUID.TryParse(id, out key)) | 11865 | if (UUID.TryParse(id, out key)) |
11866 | { | 11866 | { |
11867 | try | 11867 | try |
11868 | { | 11868 | { |
11869 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); | 11869 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); |
11870 | if (obj != null) | 11870 | if (obj != null) |
11871 | return (double)obj.GetMass(); | 11871 | return (double)obj.GetMass(); |
11872 | // the object is null so the key is for an avatar | 11872 | // the object is null so the key is for an avatar |
11873 | ScenePresence avatar = World.GetScenePresence(key); | 11873 | ScenePresence avatar = World.GetScenePresence(key); |
11874 | if (avatar != null) | 11874 | if (avatar != null) |
11875 | if (avatar.IsChildAgent) | 11875 | if (avatar.IsChildAgent) |
11876 | // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass | 11876 | // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass |
11877 | // child agents have a mass of 1.0 | 11877 | // child agents have a mass of 1.0 |
11878 | return 1; | 11878 | return 1; |
11879 | else | 11879 | else |
11880 | return (double)avatar.GetMass(); | 11880 | return (double)avatar.GetMass(); |
11881 | } | 11881 | } |
11882 | catch (KeyNotFoundException) | 11882 | catch (KeyNotFoundException) |
11883 | { | 11883 | { |
11884 | return 0; // The Object/Agent not in the region so just return zero | 11884 | return 0; // The Object/Agent not in the region so just return zero |
11885 | } | 11885 | } |
11886 | } | 11886 | } |
11887 | return 0; | 11887 | return 0; |
11888 | } | 11888 | } |
11889 | 11889 | ||
11890 | /// <summary> | 11890 | /// <summary> |
11891 | /// illListReplaceList removes the sub-list defined by the inclusive indices | 11891 | /// illListReplaceList removes the sub-list defined by the inclusive indices |
11892 | /// start and end and inserts the src list in its place. The inclusive | 11892 | /// start and end and inserts the src list in its place. The inclusive |
11893 | /// nature of the indices means that at least one element must be deleted | 11893 | /// nature of the indices means that at least one element must be deleted |
11894 | /// if the indices are within the bounds of the existing list. I.e. 2,2 | 11894 | /// if the indices are within the bounds of the existing list. I.e. 2,2 |
11895 | /// will remove the element at index 2 and replace it with the source | 11895 | /// will remove the element at index 2 and replace it with the source |
11896 | /// list. Both indices may be negative, with the usual interpretation. An | 11896 | /// list. Both indices may be negative, with the usual interpretation. An |
11897 | /// interesting case is where end is lower than start. As these indices | 11897 | /// interesting case is where end is lower than start. As these indices |
11898 | /// bound the list to be removed, then 0->end, and start->lim are removed | 11898 | /// bound the list to be removed, then 0->end, and start->lim are removed |
11899 | /// and the source list is added as a suffix. | 11899 | /// and the source list is added as a suffix. |
11900 | /// </summary> | 11900 | /// </summary> |
11901 | 11901 | ||
11902 | public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) | 11902 | public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) |
11903 | { | 11903 | { |
11904 | LSL_List pref = null; | 11904 | LSL_List pref = null; |
11905 | 11905 | ||
11906 | m_host.AddScriptLPS(1); | 11906 | m_host.AddScriptLPS(1); |
11907 | 11907 | ||
11908 | // Note that although we have normalized, both | 11908 | // Note that although we have normalized, both |
11909 | // indices could still be negative. | 11909 | // indices could still be negative. |
11910 | if (start < 0) | 11910 | if (start < 0) |
11911 | { | 11911 | { |
11912 | start = start+dest.Length; | 11912 | start = start+dest.Length; |
11913 | } | 11913 | } |
11914 | 11914 | ||
11915 | if (end < 0) | 11915 | if (end < 0) |
11916 | { | 11916 | { |
11917 | end = end+dest.Length; | 11917 | end = end+dest.Length; |
11918 | } | 11918 | } |
11919 | // The comventional case, remove a sequence starting with | 11919 | // The comventional case, remove a sequence starting with |
11920 | // start and ending with end. And then insert the source | 11920 | // start and ending with end. And then insert the source |
11921 | // list. | 11921 | // list. |
11922 | if (start <= end) | 11922 | if (start <= end) |
11923 | { | 11923 | { |
11924 | // If greater than zero, then there is going to be a | 11924 | // If greater than zero, then there is going to be a |
11925 | // surviving prefix. Otherwise the inclusive nature | 11925 | // surviving prefix. Otherwise the inclusive nature |
11926 | // of the indices mean that we're going to add the | 11926 | // of the indices mean that we're going to add the |
11927 | // source list as a prefix. | 11927 | // source list as a prefix. |
11928 | if (start > 0) | 11928 | if (start > 0) |
11929 | { | 11929 | { |
11930 | pref = dest.GetSublist(0,start-1); | 11930 | pref = dest.GetSublist(0,start-1); |
11931 | // Only add a suffix if there is something | 11931 | // Only add a suffix if there is something |
11932 | // beyond the end index (it's inclusive too). | 11932 | // beyond the end index (it's inclusive too). |
11933 | if (end + 1 < dest.Length) | 11933 | if (end + 1 < dest.Length) |
11934 | { | 11934 | { |
11935 | return pref + src + dest.GetSublist(end + 1, -1); | 11935 | return pref + src + dest.GetSublist(end + 1, -1); |
11936 | } | 11936 | } |
11937 | else | 11937 | else |
11938 | { | 11938 | { |
11939 | return pref + src; | 11939 | return pref + src; |
11940 | } | 11940 | } |
11941 | } | 11941 | } |
11942 | // If start is less than or equal to zero, then | 11942 | // If start is less than or equal to zero, then |
11943 | // the new list is simply a prefix. We still need to | 11943 | // the new list is simply a prefix. We still need to |
11944 | // figure out any necessary surgery to the destination | 11944 | // figure out any necessary surgery to the destination |
11945 | // based upon end. Note that if end exceeds the upper | 11945 | // based upon end. Note that if end exceeds the upper |
11946 | // bound in this case, the entire destination list | 11946 | // bound in this case, the entire destination list |
11947 | // is removed. | 11947 | // is removed. |
11948 | else | 11948 | else |
11949 | { | 11949 | { |
11950 | if (end + 1 < dest.Length) | 11950 | if (end + 1 < dest.Length) |
11951 | { | 11951 | { |
11952 | return src + dest.GetSublist(end + 1, -1); | 11952 | return src + dest.GetSublist(end + 1, -1); |
11953 | } | 11953 | } |
11954 | else | 11954 | else |
11955 | { | 11955 | { |
11956 | return src; | 11956 | return src; |
11957 | } | 11957 | } |
11958 | } | 11958 | } |
11959 | } | 11959 | } |
11960 | // Finally, if start > end, we strip away a prefix and | 11960 | // Finally, if start > end, we strip away a prefix and |
11961 | // a suffix, to leave the list that sits <between> ens | 11961 | // a suffix, to leave the list that sits <between> ens |
11962 | // and start, and then tag on the src list. AT least | 11962 | // and start, and then tag on the src list. AT least |
11963 | // that's my interpretation. We can get sublist to do | 11963 | // that's my interpretation. We can get sublist to do |
11964 | // this for us. Note that one, or both of the indices | 11964 | // this for us. Note that one, or both of the indices |
11965 | // might have been negative. | 11965 | // might have been negative. |
11966 | else | 11966 | else |
11967 | { | 11967 | { |
11968 | return dest.GetSublist(end + 1, start - 1) + src; | 11968 | return dest.GetSublist(end + 1, start - 1) + src; |
11969 | } | 11969 | } |
11970 | } | 11970 | } |
11971 | 11971 | ||
11972 | public void llLoadURL(string avatar_id, string message, string url) | 11972 | public void llLoadURL(string avatar_id, string message, string url) |
11973 | { | 11973 | { |
11974 | m_host.AddScriptLPS(1); | 11974 | m_host.AddScriptLPS(1); |
11975 | 11975 | ||
11976 | IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); | 11976 | IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); |
11977 | if (null != dm) | 11977 | if (null != dm) |
11978 | dm.SendUrlToUser( | 11978 | dm.SendUrlToUser( |
11979 | new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url); | 11979 | new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url); |
11980 | 11980 | ||
11981 | ScriptSleep(m_sleepMsOnLoadURL); | 11981 | ScriptSleep(m_sleepMsOnLoadURL); |
11982 | } | 11982 | } |
11983 | 11983 | ||
11984 | public void llParcelMediaCommandList(LSL_List commandList) | 11984 | public void llParcelMediaCommandList(LSL_List commandList) |
11985 | { | 11985 | { |
11986 | // TODO: Not implemented yet (missing in libomv?): | 11986 | // TODO: Not implemented yet (missing in libomv?): |
11987 | // PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) | 11987 | // PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) |
11988 | 11988 | ||
11989 | m_host.AddScriptLPS(1); | 11989 | m_host.AddScriptLPS(1); |
11990 | 11990 | ||
11991 | // according to the docs, this command only works if script owner and land owner are the same | 11991 | // according to the docs, this command only works if script owner and land owner are the same |
11992 | // lets add estate owners and gods, too, and use the generic permission check. | 11992 | // lets add estate owners and gods, too, and use the generic permission check. |
11993 | ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition); | 11993 | ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
11994 | if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; | 11994 | if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, landObject, GroupPowers.ChangeMedia)) return; |
11995 | 11995 | ||
11996 | bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? | 11996 | bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? |
11997 | byte loop = 0; | 11997 | byte loop = 0; |
11998 | 11998 | ||
11999 | LandData landData = landObject.LandData; | 11999 | LandData landData = landObject.LandData; |
12000 | string url = landData.MediaURL; | 12000 | string url = landData.MediaURL; |
12001 | string texture = landData.MediaID.ToString(); | 12001 | string texture = landData.MediaID.ToString(); |
12002 | bool autoAlign = landData.MediaAutoScale != 0; | 12002 | bool autoAlign = landData.MediaAutoScale != 0; |
12003 | string mediaType = ""; // TODO these have to be added as soon as LandData supports it | 12003 | string mediaType = ""; // TODO these have to be added as soon as LandData supports it |
12004 | string description = ""; | 12004 | string description = ""; |
12005 | int width = 0; | 12005 | int width = 0; |
12006 | int height = 0; | 12006 | int height = 0; |
12007 | 12007 | ||
12008 | ParcelMediaCommandEnum? commandToSend = null; | 12008 | ParcelMediaCommandEnum? commandToSend = null; |
12009 | float time = 0.0f; // default is from start | 12009 | float time = 0.0f; // default is from start |
12010 | 12010 | ||
12011 | ScenePresence presence = null; | 12011 | ScenePresence presence = null; |
12012 | 12012 | ||
12013 | for (int i = 0; i < commandList.Data.Length; i++) | 12013 | for (int i = 0; i < commandList.Data.Length; i++) |
12014 | { | 12014 | { |
12015 | ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; | 12015 | ParcelMediaCommandEnum command = (ParcelMediaCommandEnum)commandList.Data[i]; |
12016 | switch (command) | 12016 | switch (command) |
12017 | { | 12017 | { |
12018 | case ParcelMediaCommandEnum.Agent: | 12018 | case ParcelMediaCommandEnum.Agent: |
12019 | // we send only to one agent | 12019 | // we send only to one agent |
12020 | if ((i + 1) < commandList.Length) | 12020 | if ((i + 1) < commandList.Length) |
12021 | { | 12021 | { |
12022 | if (commandList.Data[i + 1] is LSL_String) | 12022 | if (commandList.Data[i + 1] is LSL_String) |
12023 | { | 12023 | { |
12024 | UUID agentID; | 12024 | UUID agentID; |
12025 | if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID)) | 12025 | if (UUID.TryParse((LSL_String)commandList.Data[i + 1], out agentID)) |
12026 | { | 12026 | { |
12027 | presence = World.GetScenePresence(agentID); | 12027 | presence = World.GetScenePresence(agentID); |
12028 | } | 12028 | } |
12029 | } | 12029 | } |
12030 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); | 12030 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AGENT must be a key"); |
12031 | ++i; | 12031 | ++i; |
12032 | } | 12032 | } |
12033 | break; | 12033 | break; |
12034 | 12034 | ||
12035 | case ParcelMediaCommandEnum.Loop: | 12035 | case ParcelMediaCommandEnum.Loop: |
12036 | loop = 1; | 12036 | loop = 1; |
12037 | commandToSend = command; | 12037 | commandToSend = command; |
12038 | update = true; //need to send the media update packet to set looping | 12038 | update = true; //need to send the media update packet to set looping |
12039 | break; | 12039 | break; |
12040 | 12040 | ||
12041 | case ParcelMediaCommandEnum.Play: | 12041 | case ParcelMediaCommandEnum.Play: |
12042 | loop = 0; | 12042 | loop = 0; |
12043 | commandToSend = command; | 12043 | commandToSend = command; |
12044 | update = true; //need to send the media update packet to make sure it doesn't loop | 12044 | update = true; //need to send the media update packet to make sure it doesn't loop |
12045 | break; | 12045 | break; |
12046 | 12046 | ||
12047 | case ParcelMediaCommandEnum.Pause: | 12047 | case ParcelMediaCommandEnum.Pause: |
12048 | case ParcelMediaCommandEnum.Stop: | 12048 | case ParcelMediaCommandEnum.Stop: |
12049 | case ParcelMediaCommandEnum.Unload: | 12049 | case ParcelMediaCommandEnum.Unload: |
12050 | commandToSend = command; | 12050 | commandToSend = command; |
12051 | break; | 12051 | break; |
12052 | 12052 | ||
12053 | case ParcelMediaCommandEnum.Url: | 12053 | case ParcelMediaCommandEnum.Url: |
12054 | if ((i + 1) < commandList.Length) | 12054 | if ((i + 1) < commandList.Length) |
12055 | { | 12055 | { |
12056 | if (commandList.Data[i + 1] is LSL_String) | 12056 | if (commandList.Data[i + 1] is LSL_String) |
12057 | { | 12057 | { |
12058 | url = (LSL_String)commandList.Data[i + 1]; | 12058 | url = (LSL_String)commandList.Data[i + 1]; |
12059 | update = true; | 12059 | update = true; |
12060 | } | 12060 | } |
12061 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string"); | 12061 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_URL must be a string"); |
12062 | ++i; | 12062 | ++i; |
12063 | } | 12063 | } |
12064 | break; | 12064 | break; |
12065 | 12065 | ||
12066 | case ParcelMediaCommandEnum.Texture: | 12066 | case ParcelMediaCommandEnum.Texture: |
12067 | if ((i + 1) < commandList.Length) | 12067 | if ((i + 1) < commandList.Length) |
12068 | { | 12068 | { |
12069 | if (commandList.Data[i + 1] is LSL_String) | 12069 | if (commandList.Data[i + 1] is LSL_String) |
12070 | { | 12070 | { |
12071 | texture = (LSL_String)commandList.Data[i + 1]; | 12071 | texture = (LSL_String)commandList.Data[i + 1]; |
12072 | update = true; | 12072 | update = true; |
12073 | } | 12073 | } |
12074 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key"); | 12074 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TEXTURE must be a string or a key"); |
12075 | ++i; | 12075 | ++i; |
12076 | } | 12076 | } |
12077 | break; | 12077 | break; |
12078 | 12078 | ||
12079 | case ParcelMediaCommandEnum.Time: | 12079 | case ParcelMediaCommandEnum.Time: |
12080 | if ((i + 1) < commandList.Length) | 12080 | if ((i + 1) < commandList.Length) |
12081 | { | 12081 | { |
12082 | if (commandList.Data[i + 1] is LSL_Float) | 12082 | if (commandList.Data[i + 1] is LSL_Float) |
12083 | { | 12083 | { |
12084 | time = (float)(LSL_Float)commandList.Data[i + 1]; | 12084 | time = (float)(LSL_Float)commandList.Data[i + 1]; |
12085 | } | 12085 | } |
12086 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float"); | 12086 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TIME must be a float"); |
12087 | ++i; | 12087 | ++i; |
12088 | } | 12088 | } |
12089 | break; | 12089 | break; |
12090 | 12090 | ||
12091 | case ParcelMediaCommandEnum.AutoAlign: | 12091 | case ParcelMediaCommandEnum.AutoAlign: |
12092 | if ((i + 1) < commandList.Length) | 12092 | if ((i + 1) < commandList.Length) |
12093 | { | 12093 | { |
12094 | if (commandList.Data[i + 1] is LSL_Integer) | 12094 | if (commandList.Data[i + 1] is LSL_Integer) |
12095 | { | 12095 | { |
12096 | autoAlign = (LSL_Integer)commandList.Data[i + 1]; | 12096 | autoAlign = (LSL_Integer)commandList.Data[i + 1]; |
12097 | update = true; | 12097 | update = true; |
12098 | } | 12098 | } |
12099 | 12099 | ||
12100 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer"); | 12100 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_AUTO_ALIGN must be an integer"); |
12101 | ++i; | 12101 | ++i; |
12102 | } | 12102 | } |
12103 | break; | 12103 | break; |
12104 | 12104 | ||
12105 | case ParcelMediaCommandEnum.Type: | 12105 | case ParcelMediaCommandEnum.Type: |
12106 | if ((i + 1) < commandList.Length) | 12106 | if ((i + 1) < commandList.Length) |
12107 | { | 12107 | { |
12108 | if (commandList.Data[i + 1] is LSL_String) | 12108 | if (commandList.Data[i + 1] is LSL_String) |
12109 | { | 12109 | { |
12110 | mediaType = (LSL_String)commandList.Data[i + 1]; | 12110 | mediaType = (LSL_String)commandList.Data[i + 1]; |
12111 | update = true; | 12111 | update = true; |
12112 | } | 12112 | } |
12113 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string"); | 12113 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_TYPE must be a string"); |
12114 | ++i; | 12114 | ++i; |
12115 | } | 12115 | } |
12116 | break; | 12116 | break; |
12117 | 12117 | ||
12118 | case ParcelMediaCommandEnum.Desc: | 12118 | case ParcelMediaCommandEnum.Desc: |
12119 | if ((i + 1) < commandList.Length) | 12119 | if ((i + 1) < commandList.Length) |
12120 | { | 12120 | { |
12121 | if (commandList.Data[i + 1] is LSL_String) | 12121 | if (commandList.Data[i + 1] is LSL_String) |
12122 | { | 12122 | { |
12123 | description = (LSL_String)commandList.Data[i + 1]; | 12123 | description = (LSL_String)commandList.Data[i + 1]; |
12124 | update = true; | 12124 | update = true; |
12125 | } | 12125 | } |
12126 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string"); | 12126 | else Error("llParcelMediaCommandList", "The argument of PARCEL_MEDIA_COMMAND_DESC must be a string"); |
12127 | ++i; | 12127 | ++i; |
12128 | } | 12128 | } |
12129 | break; | 12129 | break; |
12130 | 12130 | ||
12131 | case ParcelMediaCommandEnum.Size: | 12131 | case ParcelMediaCommandEnum.Size: |
12132 | if ((i + 2) < commandList.Length) | 12132 | if ((i + 2) < commandList.Length) |
12133 | { | 12133 | { |
12134 | if (commandList.Data[i + 1] is LSL_Integer) | 12134 | if (commandList.Data[i + 1] is LSL_Integer) |
12135 | { | 12135 | { |
12136 | if (commandList.Data[i + 2] is LSL_Integer) | 12136 | if (commandList.Data[i + 2] is LSL_Integer) |
12137 | { | 12137 | { |
12138 | width = (LSL_Integer)commandList.Data[i + 1]; | 12138 | width = (LSL_Integer)commandList.Data[i + 1]; |
12139 | height = (LSL_Integer)commandList.Data[i + 2]; | 12139 | height = (LSL_Integer)commandList.Data[i + 2]; |
12140 | update = true; | 12140 | update = true; |
12141 | } | 12141 | } |
12142 | else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); | 12142 | else Error("llParcelMediaCommandList", "The second argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); |
12143 | } | 12143 | } |
12144 | else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); | 12144 | else Error("llParcelMediaCommandList", "The first argument of PARCEL_MEDIA_COMMAND_SIZE must be an integer"); |
12145 | i += 2; | 12145 | i += 2; |
12146 | } | 12146 | } |
12147 | break; | 12147 | break; |
12148 | 12148 | ||
12149 | default: | 12149 | default: |
12150 | NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString()); | 12150 | NotImplemented("llParcelMediaCommandList", "Parameter not supported yet: " + Enum.Parse(typeof(ParcelMediaCommandEnum), commandList.Data[i].ToString()).ToString()); |
12151 | break; | 12151 | break; |
12152 | }//end switch | 12152 | }//end switch |
12153 | }//end for | 12153 | }//end for |
12154 | 12154 | ||
12155 | // if we didn't get a presence, we send to all and change the url | 12155 | // if we didn't get a presence, we send to all and change the url |
12156 | // if we did get a presence, we only send to the agent specified, and *don't change the land settings*! | 12156 | // if we did get a presence, we only send to the agent specified, and *don't change the land settings*! |
12157 | 12157 | ||
12158 | // did something important change or do we only start/stop/pause? | 12158 | // did something important change or do we only start/stop/pause? |
12159 | if (update) | 12159 | if (update) |
12160 | { | 12160 | { |
12161 | if (presence == null) | 12161 | if (presence == null) |
12162 | { | 12162 | { |
12163 | // we send to all | 12163 | // we send to all |
12164 | landData.MediaID = new UUID(texture); | 12164 | landData.MediaID = new UUID(texture); |
12165 | landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0; | 12165 | landData.MediaAutoScale = autoAlign ? (byte)1 : (byte)0; |
12166 | landData.MediaWidth = width; | 12166 | landData.MediaWidth = width; |
12167 | landData.MediaHeight = height; | 12167 | landData.MediaHeight = height; |
12168 | landData.MediaType = mediaType; | 12168 | landData.MediaType = mediaType; |
12169 | 12169 | ||
12170 | // do that one last, it will cause a ParcelPropertiesUpdate | 12170 | // do that one last, it will cause a ParcelPropertiesUpdate |
12171 | landObject.SetMediaUrl(url); | 12171 | landObject.SetMediaUrl(url); |
12172 | 12172 | ||
12173 | // now send to all (non-child) agents in the parcel | 12173 | // now send to all (non-child) agents in the parcel |
12174 | World.ForEachRootScenePresence(delegate(ScenePresence sp) | 12174 | World.ForEachRootScenePresence(delegate(ScenePresence sp) |
12175 | { | 12175 | { |
12176 | if (sp.currentParcelUUID == landData.GlobalID) | 12176 | if (sp.currentParcelUUID == landData.GlobalID) |
12177 | { | 12177 | { |
12178 | sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, | 12178 | sp.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, |
12179 | landData.MediaID, | 12179 | landData.MediaID, |
12180 | landData.MediaAutoScale, | 12180 | landData.MediaAutoScale, |
12181 | mediaType, | 12181 | mediaType, |
12182 | description, | 12182 | description, |
12183 | width, height, | 12183 | width, height, |
12184 | loop); | 12184 | loop); |
12185 | } | 12185 | } |
12186 | }); | 12186 | }); |
12187 | } | 12187 | } |
12188 | else if (!presence.IsChildAgent) | 12188 | else if (!presence.IsChildAgent) |
12189 | { | 12189 | { |
12190 | // we only send to one (root) agent | 12190 | // we only send to one (root) agent |
12191 | presence.ControllingClient.SendParcelMediaUpdate(url, | 12191 | presence.ControllingClient.SendParcelMediaUpdate(url, |
12192 | new UUID(texture), | 12192 | new UUID(texture), |
12193 | autoAlign ? (byte)1 : (byte)0, | 12193 | autoAlign ? (byte)1 : (byte)0, |
12194 | mediaType, | 12194 | mediaType, |
12195 | description, | 12195 | description, |
12196 | width, height, | 12196 | width, height, |
12197 | loop); | 12197 | loop); |
12198 | } | 12198 | } |
12199 | } | 12199 | } |
12200 | 12200 | ||
12201 | if (commandToSend != null) | 12201 | if (commandToSend != null) |
12202 | { | 12202 | { |
12203 | // the commandList contained a start/stop/... command, too | 12203 | // the commandList contained a start/stop/... command, too |
12204 | if (presence == null) | 12204 | if (presence == null) |
12205 | { | 12205 | { |
12206 | // send to all (non-child) agents in the parcel | 12206 | // send to all (non-child) agents in the parcel |
12207 | World.ForEachRootScenePresence(delegate(ScenePresence sp) | 12207 | World.ForEachRootScenePresence(delegate(ScenePresence sp) |
12208 | { | 12208 | { |
12209 | if (sp.currentParcelUUID == landData.GlobalID) | 12209 | if (sp.currentParcelUUID == landData.GlobalID) |
12210 | { | 12210 | { |
12211 | sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? | 12211 | sp.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? |
12212 | (ParcelMediaCommandEnum)commandToSend, | 12212 | (ParcelMediaCommandEnum)commandToSend, |
12213 | time); | 12213 | time); |
12214 | } | 12214 | } |
12215 | }); | 12215 | }); |
12216 | } | 12216 | } |
12217 | else if (!presence.IsChildAgent) | 12217 | else if (!presence.IsChildAgent) |
12218 | { | 12218 | { |
12219 | presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? | 12219 | presence.ControllingClient.SendParcelMediaCommand(0x4, // TODO what is this? |
12220 | (ParcelMediaCommandEnum)commandToSend, | 12220 | (ParcelMediaCommandEnum)commandToSend, |
12221 | time); | 12221 | time); |
12222 | } | 12222 | } |
12223 | } | 12223 | } |
12224 | ScriptSleep(m_sleepMsOnParcelMediaCommandList); | 12224 | ScriptSleep(m_sleepMsOnParcelMediaCommandList); |
12225 | } | 12225 | } |
12226 | 12226 | ||
12227 | public LSL_List llParcelMediaQuery(LSL_List aList) | 12227 | public LSL_List llParcelMediaQuery(LSL_List aList) |
12228 | { | 12228 | { |
12229 | m_host.AddScriptLPS(1); | 12229 | m_host.AddScriptLPS(1); |
12230 | LSL_List list = new LSL_List(); | 12230 | LSL_List list = new LSL_List(); |
12231 | //TO DO: make the implementation for the missing commands | 12231 | //TO DO: make the implementation for the missing commands |
12232 | //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) | 12232 | //PARCEL_MEDIA_COMMAND_LOOP_SET float loop Use this to get or set the parcel's media loop duration. (1.19.1 RC0 or later) |
12233 | for (int i = 0; i < aList.Data.Length; i++) | 12233 | for (int i = 0; i < aList.Data.Length; i++) |
12234 | { | 12234 | { |
12235 | 12235 | ||
12236 | if (aList.Data[i] != null) | 12236 | if (aList.Data[i] != null) |
12237 | { | 12237 | { |
12238 | switch ((ParcelMediaCommandEnum) aList.Data[i]) | 12238 | switch ((ParcelMediaCommandEnum) aList.Data[i]) |
12239 | { | 12239 | { |
12240 | case ParcelMediaCommandEnum.Url: | 12240 | case ParcelMediaCommandEnum.Url: |
12241 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); | 12241 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); |
12242 | break; | 12242 | break; |
12243 | case ParcelMediaCommandEnum.Desc: | 12243 | case ParcelMediaCommandEnum.Desc: |
12244 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); | 12244 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); |
12245 | break; | 12245 | break; |
12246 | case ParcelMediaCommandEnum.Texture: | 12246 | case ParcelMediaCommandEnum.Texture: |
12247 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); | 12247 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); |
12248 | break; | 12248 | break; |
12249 | case ParcelMediaCommandEnum.Type: | 12249 | case ParcelMediaCommandEnum.Type: |
12250 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); | 12250 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); |
12251 | break; | 12251 | break; |
12252 | case ParcelMediaCommandEnum.Size: | 12252 | case ParcelMediaCommandEnum.Size: |
12253 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); | 12253 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); |
12254 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); | 12254 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); |
12255 | break; | 12255 | break; |
12256 | default: | 12256 | default: |
12257 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; | 12257 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; |
12258 | NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); | 12258 | NotImplemented("llParcelMediaQuery", "Parameter not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); |
12259 | break; | 12259 | break; |
12260 | } | 12260 | } |
12261 | 12261 | ||
12262 | } | 12262 | } |
12263 | } | 12263 | } |
12264 | ScriptSleep(m_sleepMsOnParcelMediaQuery); | 12264 | ScriptSleep(m_sleepMsOnParcelMediaQuery); |
12265 | return list; | 12265 | return list; |
12266 | } | 12266 | } |
12267 | 12267 | ||
12268 | public LSL_Integer llModPow(int a, int b, int c) | 12268 | public LSL_Integer llModPow(int a, int b, int c) |
12269 | { | 12269 | { |
12270 | m_host.AddScriptLPS(1); | 12270 | m_host.AddScriptLPS(1); |
12271 | Int64 tmp = 0; | 12271 | Int64 tmp = 0; |
12272 | Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); | 12272 | Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); |
12273 | ScriptSleep(m_sleepMsOnModPow); | 12273 | ScriptSleep(m_sleepMsOnModPow); |
12274 | return Convert.ToInt32(tmp); | 12274 | return Convert.ToInt32(tmp); |
12275 | } | 12275 | } |
12276 | 12276 | ||
12277 | public LSL_Integer llGetInventoryType(string name) | 12277 | public LSL_Integer llGetInventoryType(string name) |
12278 | { | 12278 | { |
12279 | m_host.AddScriptLPS(1); | 12279 | m_host.AddScriptLPS(1); |
12280 | 12280 | ||
12281 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 12281 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); |
12282 | 12282 | ||
12283 | if (item == null) | 12283 | if (item == null) |
12284 | return -1; | 12284 | return -1; |
12285 | 12285 | ||
12286 | return item.Type; | 12286 | return item.Type; |
12287 | } | 12287 | } |
12288 | 12288 | ||
12289 | public void llSetPayPrice(int price, LSL_List quick_pay_buttons) | 12289 | public void llSetPayPrice(int price, LSL_List quick_pay_buttons) |
12290 | { | 12290 | { |
12291 | m_host.AddScriptLPS(1); | 12291 | m_host.AddScriptLPS(1); |
12292 | 12292 | ||
12293 | if (quick_pay_buttons.Data.Length < 4) | 12293 | if (quick_pay_buttons.Data.Length < 4) |
12294 | { | 12294 | { |
12295 | Error("llSetPayPrice", "List must have at least 4 elements"); | 12295 | Error("llSetPayPrice", "List must have at least 4 elements"); |
12296 | return; | 12296 | return; |
12297 | } | 12297 | } |
12298 | m_host.ParentGroup.RootPart.PayPrice[0]=price; | 12298 | m_host.ParentGroup.RootPart.PayPrice[0]=price; |
12299 | 12299 | ||
12300 | m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; | 12300 | m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; |
12301 | m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; | 12301 | m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; |
12302 | m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; | 12302 | m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; |
12303 | m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; | 12303 | m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; |
12304 | m_host.ParentGroup.HasGroupChanged = true; | 12304 | m_host.ParentGroup.HasGroupChanged = true; |
12305 | } | 12305 | } |
12306 | 12306 | ||
12307 | public LSL_Vector llGetCameraPos() | 12307 | public LSL_Vector llGetCameraPos() |
12308 | { | 12308 | { |
12309 | m_host.AddScriptLPS(1); | 12309 | m_host.AddScriptLPS(1); |
12310 | 12310 | ||
12311 | if (m_item.PermsGranter == UUID.Zero) | 12311 | if (m_item.PermsGranter == UUID.Zero) |
12312 | return Vector3.Zero; | 12312 | return Vector3.Zero; |
12313 | 12313 | ||
12314 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | 12314 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) |
12315 | { | 12315 | { |
12316 | Error("llGetCameraPos", "No permissions to track the camera"); | 12316 | Error("llGetCameraPos", "No permissions to track the camera"); |
12317 | return Vector3.Zero; | 12317 | return Vector3.Zero; |
12318 | } | 12318 | } |
12319 | 12319 | ||
12320 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | 12320 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); |
12321 | if (presence != null) | 12321 | if (presence != null) |
12322 | { | 12322 | { |
12323 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition); | 12323 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition); |
12324 | return pos; | 12324 | return pos; |
12325 | } | 12325 | } |
12326 | 12326 | ||
12327 | return Vector3.Zero; | 12327 | return Vector3.Zero; |
12328 | } | 12328 | } |
12329 | 12329 | ||
12330 | public LSL_Rotation llGetCameraRot() | 12330 | public LSL_Rotation llGetCameraRot() |
12331 | { | 12331 | { |
12332 | m_host.AddScriptLPS(1); | 12332 | m_host.AddScriptLPS(1); |
12333 | 12333 | ||
12334 | if (m_item.PermsGranter == UUID.Zero) | 12334 | if (m_item.PermsGranter == UUID.Zero) |
12335 | return Quaternion.Identity; | 12335 | return Quaternion.Identity; |
12336 | 12336 | ||
12337 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | 12337 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) |
12338 | { | 12338 | { |
12339 | Error("llGetCameraRot", "No permissions to track the camera"); | 12339 | Error("llGetCameraRot", "No permissions to track the camera"); |
12340 | return Quaternion.Identity; | 12340 | return Quaternion.Identity; |
12341 | } | 12341 | } |
12342 | 12342 | ||
12343 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | 12343 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); |
12344 | if (presence != null) | 12344 | if (presence != null) |
12345 | { | 12345 | { |
12346 | return new LSL_Rotation(presence.CameraRotation); | 12346 | return new LSL_Rotation(presence.CameraRotation); |
12347 | } | 12347 | } |
12348 | 12348 | ||
12349 | return Quaternion.Identity; | 12349 | return Quaternion.Identity; |
12350 | } | 12350 | } |
12351 | 12351 | ||
12352 | public void llSetPrimURL(string url) | 12352 | public void llSetPrimURL(string url) |
12353 | { | 12353 | { |
12354 | m_host.AddScriptLPS(1); | 12354 | m_host.AddScriptLPS(1); |
12355 | Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead"); | 12355 | Deprecated("llSetPrimURL", "Use llSetPrimMediaParams instead"); |
12356 | ScriptSleep(m_sleepMsOnSetPrimURL); | 12356 | ScriptSleep(m_sleepMsOnSetPrimURL); |
12357 | } | 12357 | } |
12358 | 12358 | ||
12359 | public void llRefreshPrimURL() | 12359 | public void llRefreshPrimURL() |
12360 | { | 12360 | { |
12361 | m_host.AddScriptLPS(1); | 12361 | m_host.AddScriptLPS(1); |
12362 | Deprecated("llRefreshPrimURL"); | 12362 | Deprecated("llRefreshPrimURL"); |
12363 | ScriptSleep(m_sleepMsOnRefreshPrimURL); | 12363 | ScriptSleep(m_sleepMsOnRefreshPrimURL); |
12364 | } | 12364 | } |
12365 | 12365 | ||
12366 | public LSL_String llEscapeURL(string url) | 12366 | public LSL_String llEscapeURL(string url) |
12367 | { | 12367 | { |
12368 | m_host.AddScriptLPS(1); | 12368 | m_host.AddScriptLPS(1); |
12369 | try | 12369 | try |
12370 | { | 12370 | { |
12371 | return Uri.EscapeDataString(url); | 12371 | return Uri.EscapeDataString(url); |
12372 | } | 12372 | } |
12373 | catch (Exception ex) | 12373 | catch (Exception ex) |
12374 | { | 12374 | { |
12375 | return "llEscapeURL: " + ex.ToString(); | 12375 | return "llEscapeURL: " + ex.ToString(); |
12376 | } | 12376 | } |
12377 | } | 12377 | } |
12378 | 12378 | ||
12379 | public LSL_String llUnescapeURL(string url) | 12379 | public LSL_String llUnescapeURL(string url) |
12380 | { | 12380 | { |
12381 | m_host.AddScriptLPS(1); | 12381 | m_host.AddScriptLPS(1); |
12382 | try | 12382 | try |
12383 | { | 12383 | { |
12384 | return Uri.UnescapeDataString(url); | 12384 | return Uri.UnescapeDataString(url); |
12385 | } | 12385 | } |
12386 | catch (Exception ex) | 12386 | catch (Exception ex) |
12387 | { | 12387 | { |
12388 | return "llUnescapeURL: " + ex.ToString(); | 12388 | return "llUnescapeURL: " + ex.ToString(); |
12389 | } | 12389 | } |
12390 | } | 12390 | } |
12391 | 12391 | ||
12392 | public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt) | 12392 | public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector lookAt) |
12393 | { | 12393 | { |
12394 | m_host.AddScriptLPS(1); | 12394 | m_host.AddScriptLPS(1); |
12395 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); | 12395 | DetectParams detectedParams = m_ScriptEngine.GetDetectParams(m_item.ItemID, 0); |
12396 | if (detectedParams == null) return; // only works on the first detected avatar | 12396 | if (detectedParams == null) return; // only works on the first detected avatar |
12397 | 12397 | ||
12398 | ScenePresence avatar = World.GetScenePresence(detectedParams.Key); | 12398 | ScenePresence avatar = World.GetScenePresence(detectedParams.Key); |
12399 | if (avatar != null) | 12399 | if (avatar != null) |
12400 | { | 12400 | { |
12401 | avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, | 12401 | avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, |
12402 | simname, pos, lookAt); | 12402 | simname, pos, lookAt); |
12403 | } | 12403 | } |
12404 | ScriptSleep(m_sleepMsOnMapDestination); | 12404 | ScriptSleep(m_sleepMsOnMapDestination); |
12405 | } | 12405 | } |
12406 | 12406 | ||
12407 | public void llAddToLandBanList(string avatar, double hours) | 12407 | public void llAddToLandBanList(string avatar, double hours) |
12408 | { | 12408 | { |
12409 | m_host.AddScriptLPS(1); | 12409 | m_host.AddScriptLPS(1); |
12410 | UUID key; | 12410 | UUID key; |
12411 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); | 12411 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
12412 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 12412 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
12413 | { | 12413 | { |
12414 | int expires = 0; | 12414 | int expires = 0; |
12415 | if (hours != 0) | 12415 | if (hours != 0) |
12416 | expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours); | 12416 | expires = Util.UnixTimeSinceEpoch() + (int)(3600.0 * hours); |
12417 | 12417 | ||
12418 | if (UUID.TryParse(avatar, out key)) | 12418 | if (UUID.TryParse(avatar, out key)) |
12419 | { | 12419 | { |
12420 | int idx = land.LandData.ParcelAccessList.FindIndex( | 12420 | int idx = land.LandData.ParcelAccessList.FindIndex( |
12421 | delegate(LandAccessEntry e) | 12421 | delegate(LandAccessEntry e) |
12422 | { | 12422 | { |
12423 | if (e.AgentID == key && e.Flags == AccessList.Ban) | 12423 | if (e.AgentID == key && e.Flags == AccessList.Ban) |
12424 | return true; | 12424 | return true; |
12425 | return false; | 12425 | return false; |
12426 | }); | 12426 | }); |
12427 | 12427 | ||
12428 | if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires))) | 12428 | if (idx != -1 && (land.LandData.ParcelAccessList[idx].Expires == 0 || (expires != 0 && expires < land.LandData.ParcelAccessList[idx].Expires))) |
12429 | return; | 12429 | return; |
12430 | 12430 | ||
12431 | if (idx != -1) | 12431 | if (idx != -1) |
12432 | land.LandData.ParcelAccessList.RemoveAt(idx); | 12432 | land.LandData.ParcelAccessList.RemoveAt(idx); |
12433 | 12433 | ||
12434 | LandAccessEntry entry = new LandAccessEntry(); | 12434 | LandAccessEntry entry = new LandAccessEntry(); |
12435 | 12435 | ||
12436 | entry.AgentID = key; | 12436 | entry.AgentID = key; |
12437 | entry.Flags = AccessList.Ban; | 12437 | entry.Flags = AccessList.Ban; |
12438 | entry.Expires = expires; | 12438 | entry.Expires = expires; |
12439 | 12439 | ||
12440 | land.LandData.ParcelAccessList.Add(entry); | 12440 | land.LandData.ParcelAccessList.Add(entry); |
12441 | 12441 | ||
12442 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | 12442 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); |
12443 | } | 12443 | } |
12444 | } | 12444 | } |
12445 | ScriptSleep(m_sleepMsOnAddToLandBanList); | 12445 | ScriptSleep(m_sleepMsOnAddToLandBanList); |
12446 | } | 12446 | } |
12447 | 12447 | ||
12448 | public void llRemoveFromLandPassList(string avatar) | 12448 | public void llRemoveFromLandPassList(string avatar) |
12449 | { | 12449 | { |
12450 | m_host.AddScriptLPS(1); | 12450 | m_host.AddScriptLPS(1); |
12451 | UUID key; | 12451 | UUID key; |
12452 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); | 12452 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
12453 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) | 12453 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed)) |
12454 | { | 12454 | { |
12455 | if (UUID.TryParse(avatar, out key)) | 12455 | if (UUID.TryParse(avatar, out key)) |
12456 | { | 12456 | { |
12457 | int idx = land.LandData.ParcelAccessList.FindIndex( | 12457 | int idx = land.LandData.ParcelAccessList.FindIndex( |
12458 | delegate(LandAccessEntry e) | 12458 | delegate(LandAccessEntry e) |
12459 | { | 12459 | { |
12460 | if (e.AgentID == key && e.Flags == AccessList.Access) | 12460 | if (e.AgentID == key && e.Flags == AccessList.Access) |
12461 | return true; | 12461 | return true; |
12462 | return false; | 12462 | return false; |
12463 | }); | 12463 | }); |
12464 | 12464 | ||
12465 | if (idx != -1) | 12465 | if (idx != -1) |
12466 | { | 12466 | { |
12467 | land.LandData.ParcelAccessList.RemoveAt(idx); | 12467 | land.LandData.ParcelAccessList.RemoveAt(idx); |
12468 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | 12468 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); |
12469 | } | 12469 | } |
12470 | } | 12470 | } |
12471 | } | 12471 | } |
12472 | ScriptSleep(m_sleepMsOnRemoveFromLandPassList); | 12472 | ScriptSleep(m_sleepMsOnRemoveFromLandPassList); |
12473 | } | 12473 | } |
12474 | 12474 | ||
12475 | public void llRemoveFromLandBanList(string avatar) | 12475 | public void llRemoveFromLandBanList(string avatar) |
12476 | { | 12476 | { |
12477 | m_host.AddScriptLPS(1); | 12477 | m_host.AddScriptLPS(1); |
12478 | UUID key; | 12478 | UUID key; |
12479 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); | 12479 | ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); |
12480 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) | 12480 | if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned)) |
12481 | { | 12481 | { |
12482 | if (UUID.TryParse(avatar, out key)) | 12482 | if (UUID.TryParse(avatar, out key)) |
12483 | { | 12483 | { |
12484 | int idx = land.LandData.ParcelAccessList.FindIndex( | 12484 | int idx = land.LandData.ParcelAccessList.FindIndex( |
12485 | delegate(LandAccessEntry e) | 12485 | delegate(LandAccessEntry e) |
12486 | { | 12486 | { |
12487 | if (e.AgentID == key && e.Flags == AccessList.Ban) | 12487 | if (e.AgentID == key && e.Flags == AccessList.Ban) |
12488 | return true; | 12488 | return true; |
12489 | return false; | 12489 | return false; |
12490 | }); | 12490 | }); |
12491 | 12491 | ||
12492 | if (idx != -1) | 12492 | if (idx != -1) |
12493 | { | 12493 | { |
12494 | land.LandData.ParcelAccessList.RemoveAt(idx); | 12494 | land.LandData.ParcelAccessList.RemoveAt(idx); |
12495 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); | 12495 | World.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); |
12496 | } | 12496 | } |
12497 | } | 12497 | } |
12498 | } | 12498 | } |
12499 | ScriptSleep(m_sleepMsOnRemoveFromLandBanList); | 12499 | ScriptSleep(m_sleepMsOnRemoveFromLandBanList); |
12500 | } | 12500 | } |
12501 | 12501 | ||
12502 | public void llSetCameraParams(LSL_List rules) | 12502 | public void llSetCameraParams(LSL_List rules) |
12503 | { | 12503 | { |
12504 | m_host.AddScriptLPS(1); | 12504 | m_host.AddScriptLPS(1); |
12505 | 12505 | ||
12506 | // the object we are in | 12506 | // the object we are in |
12507 | UUID objectID = m_host.ParentUUID; | 12507 | UUID objectID = m_host.ParentUUID; |
12508 | if (objectID == UUID.Zero) | 12508 | if (objectID == UUID.Zero) |
12509 | return; | 12509 | return; |
12510 | 12510 | ||
12511 | // we need the permission first, to know which avatar we want to set the camera for | 12511 | // we need the permission first, to know which avatar we want to set the camera for |
12512 | UUID agentID = m_item.PermsGranter; | 12512 | UUID agentID = m_item.PermsGranter; |
12513 | 12513 | ||
12514 | if (agentID == UUID.Zero) | 12514 | if (agentID == UUID.Zero) |
12515 | return; | 12515 | return; |
12516 | 12516 | ||
12517 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) | 12517 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) |
12518 | return; | 12518 | return; |
12519 | 12519 | ||
12520 | ScenePresence presence = World.GetScenePresence(agentID); | 12520 | ScenePresence presence = World.GetScenePresence(agentID); |
12521 | 12521 | ||
12522 | // we are not interested in child-agents | 12522 | // we are not interested in child-agents |
12523 | if (presence.IsChildAgent) return; | 12523 | if (presence.IsChildAgent) return; |
12524 | 12524 | ||
12525 | SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); | 12525 | SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); |
12526 | object[] data = rules.Data; | 12526 | object[] data = rules.Data; |
12527 | for (int i = 0; i < data.Length; ++i) | 12527 | for (int i = 0; i < data.Length; ++i) |
12528 | { | 12528 | { |
12529 | int type; | 12529 | int type; |
12530 | try | 12530 | try |
12531 | { | 12531 | { |
12532 | type = Convert.ToInt32(data[i++].ToString()); | 12532 | type = Convert.ToInt32(data[i++].ToString()); |
12533 | } | 12533 | } |
12534 | catch | 12534 | catch |
12535 | { | 12535 | { |
12536 | Error("llSetCameraParams", string.Format("Invalid camera param type {0}", data[i - 1])); | 12536 | Error("llSetCameraParams", string.Format("Invalid camera param type {0}", data[i - 1])); |
12537 | return; | 12537 | return; |
12538 | } | 12538 | } |
12539 | if (i >= data.Length) break; // odd number of entries => ignore the last | 12539 | if (i >= data.Length) break; // odd number of entries => ignore the last |
12540 | 12540 | ||
12541 | // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) | 12541 | // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) |
12542 | switch (type) | 12542 | switch (type) |
12543 | { | 12543 | { |
12544 | case ScriptBaseClass.CAMERA_FOCUS: | 12544 | case ScriptBaseClass.CAMERA_FOCUS: |
12545 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | 12545 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: |
12546 | case ScriptBaseClass.CAMERA_POSITION: | 12546 | case ScriptBaseClass.CAMERA_POSITION: |
12547 | LSL_Vector v = (LSL_Vector)data[i]; | 12547 | LSL_Vector v = (LSL_Vector)data[i]; |
12548 | try | 12548 | try |
12549 | { | 12549 | { |
12550 | parameters.Add(type + 1, (float)v.x); | 12550 | parameters.Add(type + 1, (float)v.x); |
12551 | } | 12551 | } |
12552 | catch | 12552 | catch |
12553 | { | 12553 | { |
12554 | switch(type) | 12554 | switch(type) |
12555 | { | 12555 | { |
12556 | case ScriptBaseClass.CAMERA_FOCUS: | 12556 | case ScriptBaseClass.CAMERA_FOCUS: |
12557 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter x is invalid"); | 12557 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter x is invalid"); |
12558 | return; | 12558 | return; |
12559 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | 12559 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: |
12560 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter x is invalid"); | 12560 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter x is invalid"); |
12561 | return; | 12561 | return; |
12562 | case ScriptBaseClass.CAMERA_POSITION: | 12562 | case ScriptBaseClass.CAMERA_POSITION: |
12563 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter x is invalid"); | 12563 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter x is invalid"); |
12564 | return; | 12564 | return; |
12565 | } | 12565 | } |
12566 | } | 12566 | } |
12567 | try | 12567 | try |
12568 | { | 12568 | { |
12569 | parameters.Add(type + 2, (float)v.y); | 12569 | parameters.Add(type + 2, (float)v.y); |
12570 | } | 12570 | } |
12571 | catch | 12571 | catch |
12572 | { | 12572 | { |
12573 | switch(type) | 12573 | switch(type) |
12574 | { | 12574 | { |
12575 | case ScriptBaseClass.CAMERA_FOCUS: | 12575 | case ScriptBaseClass.CAMERA_FOCUS: |
12576 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter y is invalid"); | 12576 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter y is invalid"); |
12577 | return; | 12577 | return; |
12578 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | 12578 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: |
12579 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter y is invalid"); | 12579 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter y is invalid"); |
12580 | return; | 12580 | return; |
12581 | case ScriptBaseClass.CAMERA_POSITION: | 12581 | case ScriptBaseClass.CAMERA_POSITION: |
12582 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter y is invalid"); | 12582 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter y is invalid"); |
12583 | return; | 12583 | return; |
12584 | } | 12584 | } |
12585 | } | 12585 | } |
12586 | try | 12586 | try |
12587 | { | 12587 | { |
12588 | parameters.Add(type + 3, (float)v.z); | 12588 | parameters.Add(type + 3, (float)v.z); |
12589 | } | 12589 | } |
12590 | catch | 12590 | catch |
12591 | { | 12591 | { |
12592 | switch(type) | 12592 | switch(type) |
12593 | { | 12593 | { |
12594 | case ScriptBaseClass.CAMERA_FOCUS: | 12594 | case ScriptBaseClass.CAMERA_FOCUS: |
12595 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter z is invalid"); | 12595 | Error("llSetCameraParams", "CAMERA_FOCUS: Parameter z is invalid"); |
12596 | return; | 12596 | return; |
12597 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | 12597 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: |
12598 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter z is invalid"); | 12598 | Error("llSetCameraParams", "CAMERA_FOCUS_OFFSET: Parameter z is invalid"); |
12599 | return; | 12599 | return; |
12600 | case ScriptBaseClass.CAMERA_POSITION: | 12600 | case ScriptBaseClass.CAMERA_POSITION: |
12601 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter z is invalid"); | 12601 | Error("llSetCameraParams", "CAMERA_POSITION: Parameter z is invalid"); |
12602 | return; | 12602 | return; |
12603 | } | 12603 | } |
12604 | } | 12604 | } |
12605 | break; | 12605 | break; |
12606 | default: | 12606 | default: |
12607 | // TODO: clean that up as soon as the implicit casts are in | 12607 | // TODO: clean that up as soon as the implicit casts are in |
12608 | if (data[i] is LSL_Float) | 12608 | if (data[i] is LSL_Float) |
12609 | parameters.Add(type, (float)((LSL_Float)data[i]).value); | 12609 | parameters.Add(type, (float)((LSL_Float)data[i]).value); |
12610 | else if (data[i] is LSL_Integer) | 12610 | else if (data[i] is LSL_Integer) |
12611 | parameters.Add(type, (float)((LSL_Integer)data[i]).value); | 12611 | parameters.Add(type, (float)((LSL_Integer)data[i]).value); |
12612 | else | 12612 | else |
12613 | { | 12613 | { |
12614 | try | 12614 | try |
12615 | { | 12615 | { |
12616 | parameters.Add(type, Convert.ToSingle(data[i])); | 12616 | parameters.Add(type, Convert.ToSingle(data[i])); |
12617 | } | 12617 | } |
12618 | catch | 12618 | catch |
12619 | { | 12619 | { |
12620 | Error("llSetCameraParams", string.Format("{0}: Parameter is invalid", type)); | 12620 | Error("llSetCameraParams", string.Format("{0}: Parameter is invalid", type)); |
12621 | } | 12621 | } |
12622 | } | 12622 | } |
12623 | break; | 12623 | break; |
12624 | } | 12624 | } |
12625 | } | 12625 | } |
12626 | if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters); | 12626 | if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters); |
12627 | } | 12627 | } |
12628 | 12628 | ||
12629 | public void llClearCameraParams() | 12629 | public void llClearCameraParams() |
12630 | { | 12630 | { |
12631 | m_host.AddScriptLPS(1); | 12631 | m_host.AddScriptLPS(1); |
12632 | 12632 | ||
12633 | // the object we are in | 12633 | // the object we are in |
12634 | UUID objectID = m_host.ParentUUID; | 12634 | UUID objectID = m_host.ParentUUID; |
12635 | if (objectID == UUID.Zero) | 12635 | if (objectID == UUID.Zero) |
12636 | return; | 12636 | return; |
12637 | 12637 | ||
12638 | // we need the permission first, to know which avatar we want to clear the camera for | 12638 | // we need the permission first, to know which avatar we want to clear the camera for |
12639 | UUID agentID = m_item.PermsGranter; | 12639 | UUID agentID = m_item.PermsGranter; |
12640 | 12640 | ||
12641 | if (agentID == UUID.Zero) | 12641 | if (agentID == UUID.Zero) |
12642 | return; | 12642 | return; |
12643 | 12643 | ||
12644 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) | 12644 | if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) |
12645 | return; | 12645 | return; |
12646 | 12646 | ||
12647 | ScenePresence presence = World.GetScenePresence(agentID); | 12647 | ScenePresence presence = World.GetScenePresence(agentID); |
12648 | 12648 | ||
12649 | // we are not interested in child-agents | 12649 | // we are not interested in child-agents |
12650 | if (presence.IsChildAgent) | 12650 | if (presence.IsChildAgent) |
12651 | return; | 12651 | return; |
12652 | 12652 | ||
12653 | presence.ControllingClient.SendClearFollowCamProperties(objectID); | 12653 | presence.ControllingClient.SendClearFollowCamProperties(objectID); |
12654 | } | 12654 | } |
12655 | 12655 | ||
12656 | public LSL_Float llListStatistics(int operation, LSL_List src) | 12656 | public LSL_Float llListStatistics(int operation, LSL_List src) |
12657 | { | 12657 | { |
12658 | m_host.AddScriptLPS(1); | 12658 | m_host.AddScriptLPS(1); |
12659 | switch (operation) | 12659 | switch (operation) |
12660 | { | 12660 | { |
12661 | case ScriptBaseClass.LIST_STAT_RANGE: | 12661 | case ScriptBaseClass.LIST_STAT_RANGE: |
12662 | return src.Range(); | 12662 | return src.Range(); |
12663 | case ScriptBaseClass.LIST_STAT_MIN: | 12663 | case ScriptBaseClass.LIST_STAT_MIN: |
12664 | return src.Min(); | 12664 | return src.Min(); |
12665 | case ScriptBaseClass.LIST_STAT_MAX: | 12665 | case ScriptBaseClass.LIST_STAT_MAX: |
12666 | return src.Max(); | 12666 | return src.Max(); |
12667 | case ScriptBaseClass.LIST_STAT_MEAN: | 12667 | case ScriptBaseClass.LIST_STAT_MEAN: |
12668 | return src.Mean(); | 12668 | return src.Mean(); |
12669 | case ScriptBaseClass.LIST_STAT_MEDIAN: | 12669 | case ScriptBaseClass.LIST_STAT_MEDIAN: |
12670 | return LSL_List.ToDoubleList(src).Median(); | 12670 | return LSL_List.ToDoubleList(src).Median(); |
12671 | case ScriptBaseClass.LIST_STAT_NUM_COUNT: | 12671 | case ScriptBaseClass.LIST_STAT_NUM_COUNT: |
12672 | return src.NumericLength(); | 12672 | return src.NumericLength(); |
12673 | case ScriptBaseClass.LIST_STAT_STD_DEV: | 12673 | case ScriptBaseClass.LIST_STAT_STD_DEV: |
12674 | return src.StdDev(); | 12674 | return src.StdDev(); |
12675 | case ScriptBaseClass.LIST_STAT_SUM: | 12675 | case ScriptBaseClass.LIST_STAT_SUM: |
12676 | return src.Sum(); | 12676 | return src.Sum(); |
12677 | case ScriptBaseClass.LIST_STAT_SUM_SQUARES: | 12677 | case ScriptBaseClass.LIST_STAT_SUM_SQUARES: |
12678 | return src.SumSqrs(); | 12678 | return src.SumSqrs(); |
12679 | case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: | 12679 | case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: |
12680 | return src.GeometricMean(); | 12680 | return src.GeometricMean(); |
12681 | case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: | 12681 | case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: |
12682 | return src.HarmonicMean(); | 12682 | return src.HarmonicMean(); |
12683 | default: | 12683 | default: |
12684 | return 0.0; | 12684 | return 0.0; |
12685 | } | 12685 | } |
12686 | } | 12686 | } |
12687 | 12687 | ||
12688 | public LSL_Integer llGetUnixTime() | 12688 | public LSL_Integer llGetUnixTime() |
12689 | { | 12689 | { |
12690 | m_host.AddScriptLPS(1); | 12690 | m_host.AddScriptLPS(1); |
12691 | return Util.UnixTimeSinceEpoch(); | 12691 | return Util.UnixTimeSinceEpoch(); |
12692 | } | 12692 | } |
12693 | 12693 | ||
12694 | public LSL_Integer llGetParcelFlags(LSL_Vector pos) | 12694 | public LSL_Integer llGetParcelFlags(LSL_Vector pos) |
12695 | { | 12695 | { |
12696 | m_host.AddScriptLPS(1); | 12696 | m_host.AddScriptLPS(1); |
12697 | return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).LandData.Flags; | 12697 | return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).LandData.Flags; |
12698 | } | 12698 | } |
12699 | 12699 | ||
12700 | public LSL_Integer llGetRegionFlags() | 12700 | public LSL_Integer llGetRegionFlags() |
12701 | { | 12701 | { |
12702 | m_host.AddScriptLPS(1); | 12702 | m_host.AddScriptLPS(1); |
12703 | IEstateModule estate = World.RequestModuleInterface<IEstateModule>(); | 12703 | IEstateModule estate = World.RequestModuleInterface<IEstateModule>(); |
12704 | if (estate == null) | 12704 | if (estate == null) |
12705 | return 67108864; | 12705 | return 67108864; |
12706 | return (int)estate.GetRegionFlags(); | 12706 | return (int)estate.GetRegionFlags(); |
12707 | } | 12707 | } |
12708 | 12708 | ||
12709 | public LSL_String llXorBase64StringsCorrect(string str1, string str2) | 12709 | public LSL_String llXorBase64StringsCorrect(string str1, string str2) |
12710 | { | 12710 | { |
12711 | m_host.AddScriptLPS(1); | 12711 | m_host.AddScriptLPS(1); |
12712 | string ret = String.Empty; | 12712 | string ret = String.Empty; |
12713 | string src1 = llBase64ToString(str1); | 12713 | string src1 = llBase64ToString(str1); |
12714 | string src2 = llBase64ToString(str2); | 12714 | string src2 = llBase64ToString(str2); |
12715 | int c = 0; | 12715 | int c = 0; |
12716 | for (int i = 0; i < src1.Length; i++) | 12716 | for (int i = 0; i < src1.Length; i++) |
12717 | { | 12717 | { |
12718 | ret += (char) (src1[i] ^ src2[c]); | 12718 | ret += (char) (src1[i] ^ src2[c]); |
12719 | 12719 | ||
12720 | c++; | 12720 | c++; |
12721 | if (c >= src2.Length) | 12721 | if (c >= src2.Length) |
12722 | c = 0; | 12722 | c = 0; |
12723 | } | 12723 | } |
12724 | return llStringToBase64(ret); | 12724 | return llStringToBase64(ret); |
12725 | } | 12725 | } |
12726 | 12726 | ||
12727 | public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) | 12727 | public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) |
12728 | { | 12728 | { |
12729 | // Partial implementation: support for parameter flags needed | 12729 | // Partial implementation: support for parameter flags needed |
12730 | // see http://wiki.secondlife.com/wiki/LlHTTPRequest | 12730 | // see http://wiki.secondlife.com/wiki/LlHTTPRequest |
12731 | // parameter flags support are implemented in ScriptsHttpRequests.cs | 12731 | // parameter flags support are implemented in ScriptsHttpRequests.cs |
12732 | // in StartHttpRequest | 12732 | // in StartHttpRequest |
12733 | 12733 | ||
12734 | m_host.AddScriptLPS(1); | 12734 | m_host.AddScriptLPS(1); |
12735 | IHttpRequestModule httpScriptMod = | 12735 | IHttpRequestModule httpScriptMod = |
12736 | m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); | 12736 | m_ScriptEngine.World.RequestModuleInterface<IHttpRequestModule>(); |
12737 | List<string> param = new List<string>(); | 12737 | List<string> param = new List<string>(); |
12738 | bool ok; | 12738 | bool ok; |
12739 | Int32 flag; | 12739 | Int32 flag; |
12740 | 12740 | ||
12741 | for (int i = 0; i < parameters.Data.Length; i += 2) | 12741 | for (int i = 0; i < parameters.Data.Length; i += 2) |
12742 | { | 12742 | { |
12743 | ok = Int32.TryParse(parameters.Data[i].ToString(), out flag); | 12743 | ok = Int32.TryParse(parameters.Data[i].ToString(), out flag); |
12744 | if (!ok || flag < 0 || | 12744 | if (!ok || flag < 0 || |
12745 | flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE) | 12745 | flag > (int)HttpRequestConstants.HTTP_PRAGMA_NO_CACHE) |
12746 | { | 12746 | { |
12747 | Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag"); | 12747 | Error("llHTTPRequest", "Parameter " + i.ToString() + " is an invalid flag"); |
12748 | } | 12748 | } |
12749 | 12749 | ||
12750 | param.Add(parameters.Data[i].ToString()); //Add parameter flag | 12750 | param.Add(parameters.Data[i].ToString()); //Add parameter flag |
12751 | 12751 | ||
12752 | if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER) | 12752 | if (flag != (int)HttpRequestConstants.HTTP_CUSTOM_HEADER) |
12753 | { | 12753 | { |
12754 | param.Add(parameters.Data[i+1].ToString()); //Add parameter value | 12754 | param.Add(parameters.Data[i+1].ToString()); //Add parameter value |
12755 | } | 12755 | } |
12756 | else | 12756 | else |
12757 | { | 12757 | { |
12758 | //Parameters are in pairs and custom header takes | 12758 | //Parameters are in pairs and custom header takes |
12759 | //arguments in pairs so adjust for header marker. | 12759 | //arguments in pairs so adjust for header marker. |
12760 | ++i; | 12760 | ++i; |
12761 | 12761 | ||
12762 | //Maximum of 8 headers are allowed based on the | 12762 | //Maximum of 8 headers are allowed based on the |
12763 | //Second Life documentation for llHTTPRequest. | 12763 | //Second Life documentation for llHTTPRequest. |
12764 | for (int count = 1; count <= 8; ++count) | 12764 | for (int count = 1; count <= 8; ++count) |
12765 | { | 12765 | { |
12766 | //Enough parameters remaining for (another) header? | 12766 | //Enough parameters remaining for (another) header? |
12767 | if (parameters.Data.Length - i < 2) | 12767 | if (parameters.Data.Length - i < 2) |
12768 | { | 12768 | { |
12769 | //There must be at least one name/value pair for custom header | 12769 | //There must be at least one name/value pair for custom header |
12770 | if (count == 1) | 12770 | if (count == 1) |
12771 | Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString()); | 12771 | Error("llHTTPRequest", "Missing name/value for custom header at parameter " + i.ToString()); |
12772 | break; | 12772 | break; |
12773 | } | 12773 | } |
12774 | 12774 | ||
12775 | if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase)) | 12775 | if (HttpStandardHeaders.Contains(parameters.Data[i].ToString(), StringComparer.OrdinalIgnoreCase)) |
12776 | Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString()); | 12776 | Error("llHTTPRequest", "Name is invalid as a custom header at parameter " + i.ToString()); |
12777 | 12777 | ||
12778 | param.Add(parameters.Data[i].ToString()); | 12778 | param.Add(parameters.Data[i].ToString()); |
12779 | param.Add(parameters.Data[i+1].ToString()); | 12779 | param.Add(parameters.Data[i+1].ToString()); |
12780 | 12780 | ||
12781 | //Have we reached the end of the list of headers? | 12781 | //Have we reached the end of the list of headers? |
12782 | //End is marked by a string with a single digit. | 12782 | //End is marked by a string with a single digit. |
12783 | if (i+2 >= parameters.Data.Length || | 12783 | if (i+2 >= parameters.Data.Length || |
12784 | Char.IsDigit(parameters.Data[i].ToString()[0])) | 12784 | Char.IsDigit(parameters.Data[i].ToString()[0])) |
12785 | { | 12785 | { |
12786 | break; | 12786 | break; |
12787 | } | 12787 | } |
12788 | 12788 | ||
12789 | i += 2; | 12789 | i += 2; |
12790 | } | 12790 | } |
12791 | } | 12791 | } |
12792 | } | 12792 | } |
12793 | 12793 | ||
12794 | Vector3 position = m_host.AbsolutePosition; | 12794 | Vector3 position = m_host.AbsolutePosition; |
12795 | Vector3 velocity = m_host.Velocity; | 12795 | Vector3 velocity = m_host.Velocity; |
12796 | Quaternion rotation = m_host.RotationOffset; | 12796 | Quaternion rotation = m_host.RotationOffset; |
12797 | string ownerName = String.Empty; | 12797 | string ownerName = String.Empty; |
12798 | ScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID); | 12798 | ScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID); |
12799 | if (scenePresence == null) | 12799 | if (scenePresence == null) |
12800 | ownerName = resolveName(m_host.OwnerID); | 12800 | ownerName = resolveName(m_host.OwnerID); |
12801 | else | 12801 | else |
12802 | ownerName = scenePresence.Name; | 12802 | ownerName = scenePresence.Name; |
12803 | 12803 | ||
12804 | RegionInfo regionInfo = World.RegionInfo; | 12804 | RegionInfo regionInfo = World.RegionInfo; |
12805 | 12805 | ||
12806 | Dictionary<string, string> httpHeaders = new Dictionary<string, string>(); | 12806 | Dictionary<string, string> httpHeaders = new Dictionary<string, string>(); |
12807 | 12807 | ||
12808 | string shard = "OpenSim"; | 12808 | string shard = "OpenSim"; |
12809 | IConfigSource config = m_ScriptEngine.ConfigSource; | 12809 | IConfigSource config = m_ScriptEngine.ConfigSource; |
12810 | if (config.Configs["Network"] != null) | 12810 | if (config.Configs["Network"] != null) |
12811 | { | 12811 | { |
12812 | shard = config.Configs["Network"].GetString("shard", shard); | 12812 | shard = config.Configs["Network"].GetString("shard", shard); |
12813 | } | 12813 | } |
12814 | 12814 | ||
12815 | httpHeaders["X-SecondLife-Shard"] = shard; | 12815 | httpHeaders["X-SecondLife-Shard"] = shard; |
12816 | httpHeaders["X-SecondLife-Object-Name"] = m_host.Name; | 12816 | httpHeaders["X-SecondLife-Object-Name"] = m_host.Name; |
12817 | httpHeaders["X-SecondLife-Object-Key"] = m_host.UUID.ToString(); | 12817 | httpHeaders["X-SecondLife-Object-Key"] = m_host.UUID.ToString(); |
12818 | httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY); | 12818 | httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY); |
12819 | httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z); | 12819 | httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z); |
12820 | httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z); | 12820 | httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z); |
12821 | httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W); | 12821 | httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W); |
12822 | httpHeaders["X-SecondLife-Owner-Name"] = ownerName; | 12822 | httpHeaders["X-SecondLife-Owner-Name"] = ownerName; |
12823 | httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString(); | 12823 | httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString(); |
12824 | string userAgent = config.Configs["Network"].GetString("user_agent", null); | 12824 | string userAgent = config.Configs["Network"].GetString("user_agent", null); |
12825 | if (userAgent != null) | 12825 | if (userAgent != null) |
12826 | httpHeaders["User-Agent"] = userAgent; | 12826 | httpHeaders["User-Agent"] = userAgent; |
12827 | 12827 | ||
12828 | string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; | 12828 | string authregex = @"^(https?:\/\/)(\w+):(\w+)@(.*)$"; |
12829 | Regex r = new Regex(authregex); | 12829 | Regex r = new Regex(authregex); |
12830 | int[] gnums = r.GetGroupNumbers(); | 12830 | int[] gnums = r.GetGroupNumbers(); |
12831 | Match m = r.Match(url); | 12831 | Match m = r.Match(url); |
12832 | if (m.Success) { | 12832 | if (m.Success) { |
12833 | for (int i = 1; i < gnums.Length; i++) { | 12833 | for (int i = 1; i < gnums.Length; i++) { |
12834 | //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; | 12834 | //System.Text.RegularExpressions.Group g = m.Groups[gnums[i]]; |
12835 | //CaptureCollection cc = g.Captures; | 12835 | //CaptureCollection cc = g.Captures; |
12836 | } | 12836 | } |
12837 | if (m.Groups.Count == 5) { | 12837 | if (m.Groups.Count == 5) { |
12838 | httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); | 12838 | httpHeaders["Authorization"] = String.Format("Basic {0}", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(m.Groups[2].ToString() + ":" + m.Groups[3].ToString()))); |
12839 | url = m.Groups[1].ToString() + m.Groups[4].ToString(); | 12839 | url = m.Groups[1].ToString() + m.Groups[4].ToString(); |
12840 | } | 12840 | } |
12841 | } | 12841 | } |
12842 | 12842 | ||
12843 | HttpInitialRequestStatus status; | 12843 | HttpInitialRequestStatus status; |
12844 | UUID reqID | 12844 | UUID reqID |
12845 | = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status); | 12845 | = httpScriptMod.StartHttpRequest(m_host.LocalId, m_item.ItemID, url, param, httpHeaders, body, out status); |
12846 | 12846 | ||
12847 | if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER) | 12847 | if (status == HttpInitialRequestStatus.DISALLOWED_BY_FILTER) |
12848 | Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url)); | 12848 | Error("llHttpRequest", string.Format("Request to {0} disallowed by filter", url)); |
12849 | 12849 | ||
12850 | if (reqID != UUID.Zero) | 12850 | if (reqID != UUID.Zero) |
12851 | return reqID.ToString(); | 12851 | return reqID.ToString(); |
12852 | else | 12852 | else |
12853 | return null; | 12853 | return null; |
12854 | } | 12854 | } |
12855 | 12855 | ||
12856 | 12856 | ||
12857 | public void llHTTPResponse(LSL_Key id, int status, string body) | 12857 | public void llHTTPResponse(LSL_Key id, int status, string body) |
12858 | { | 12858 | { |
12859 | // Partial implementation: support for parameter flags needed | 12859 | // Partial implementation: support for parameter flags needed |
12860 | // see http://wiki.secondlife.com/wiki/llHTTPResponse | 12860 | // see http://wiki.secondlife.com/wiki/llHTTPResponse |
12861 | 12861 | ||
12862 | m_host.AddScriptLPS(1); | 12862 | m_host.AddScriptLPS(1); |
12863 | 12863 | ||
12864 | if (m_UrlModule != null) | 12864 | if (m_UrlModule != null) |
12865 | m_UrlModule.HttpResponse(new UUID(id), status,body); | 12865 | m_UrlModule.HttpResponse(new UUID(id), status,body); |
12866 | } | 12866 | } |
12867 | 12867 | ||
12868 | public void llResetLandBanList() | 12868 | public void llResetLandBanList() |
12869 | { | 12869 | { |
12870 | m_host.AddScriptLPS(1); | 12870 | m_host.AddScriptLPS(1); |
12871 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; | 12871 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
12872 | if (land.OwnerID == m_host.OwnerID) | 12872 | if (land.OwnerID == m_host.OwnerID) |
12873 | { | 12873 | { |
12874 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 12874 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
12875 | { | 12875 | { |
12876 | if (entry.Flags == AccessList.Ban) | 12876 | if (entry.Flags == AccessList.Ban) |
12877 | { | 12877 | { |
12878 | land.ParcelAccessList.Remove(entry); | 12878 | land.ParcelAccessList.Remove(entry); |
12879 | } | 12879 | } |
12880 | } | 12880 | } |
12881 | } | 12881 | } |
12882 | ScriptSleep(m_sleepMsOnResetLandBanList); | 12882 | ScriptSleep(m_sleepMsOnResetLandBanList); |
12883 | } | 12883 | } |
12884 | 12884 | ||
12885 | public void llResetLandPassList() | 12885 | public void llResetLandPassList() |
12886 | { | 12886 | { |
12887 | m_host.AddScriptLPS(1); | 12887 | m_host.AddScriptLPS(1); |
12888 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; | 12888 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition).LandData; |
12889 | if (land.OwnerID == m_host.OwnerID) | 12889 | if (land.OwnerID == m_host.OwnerID) |
12890 | { | 12890 | { |
12891 | foreach (LandAccessEntry entry in land.ParcelAccessList) | 12891 | foreach (LandAccessEntry entry in land.ParcelAccessList) |
12892 | { | 12892 | { |
12893 | if (entry.Flags == AccessList.Access) | 12893 | if (entry.Flags == AccessList.Access) |
12894 | { | 12894 | { |
12895 | land.ParcelAccessList.Remove(entry); | 12895 | land.ParcelAccessList.Remove(entry); |
12896 | } | 12896 | } |
12897 | } | 12897 | } |
12898 | } | 12898 | } |
12899 | ScriptSleep(m_sleepMsOnResetLandPassList); | 12899 | ScriptSleep(m_sleepMsOnResetLandPassList); |
12900 | } | 12900 | } |
12901 | 12901 | ||
12902 | public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) | 12902 | public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) |
12903 | { | 12903 | { |
12904 | m_host.AddScriptLPS(1); | 12904 | m_host.AddScriptLPS(1); |
12905 | 12905 | ||
12906 | ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); | 12906 | ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); |
12907 | 12907 | ||
12908 | if (lo == null) | 12908 | if (lo == null) |
12909 | return 0; | 12909 | return 0; |
12910 | 12910 | ||
12911 | IPrimCounts pc = lo.PrimCounts; | 12911 | IPrimCounts pc = lo.PrimCounts; |
12912 | 12912 | ||
12913 | if (sim_wide != ScriptBaseClass.FALSE) | 12913 | if (sim_wide != ScriptBaseClass.FALSE) |
12914 | { | 12914 | { |
12915 | if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL) | 12915 | if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL) |
12916 | { | 12916 | { |
12917 | return pc.Simulator; | 12917 | return pc.Simulator; |
12918 | } | 12918 | } |
12919 | else | 12919 | else |
12920 | { | 12920 | { |
12921 | // counts not implemented yet | 12921 | // counts not implemented yet |
12922 | return 0; | 12922 | return 0; |
12923 | } | 12923 | } |
12924 | } | 12924 | } |
12925 | else | 12925 | else |
12926 | { | 12926 | { |
12927 | if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL) | 12927 | if (category == ScriptBaseClass.PARCEL_COUNT_TOTAL) |
12928 | return pc.Total; | 12928 | return pc.Total; |
12929 | else if (category == ScriptBaseClass.PARCEL_COUNT_OWNER) | 12929 | else if (category == ScriptBaseClass.PARCEL_COUNT_OWNER) |
12930 | return pc.Owner; | 12930 | return pc.Owner; |
12931 | else if (category == ScriptBaseClass.PARCEL_COUNT_GROUP) | 12931 | else if (category == ScriptBaseClass.PARCEL_COUNT_GROUP) |
12932 | return pc.Group; | 12932 | return pc.Group; |
12933 | else if (category == ScriptBaseClass.PARCEL_COUNT_OTHER) | 12933 | else if (category == ScriptBaseClass.PARCEL_COUNT_OTHER) |
12934 | return pc.Others; | 12934 | return pc.Others; |
12935 | else if (category == ScriptBaseClass.PARCEL_COUNT_SELECTED) | 12935 | else if (category == ScriptBaseClass.PARCEL_COUNT_SELECTED) |
12936 | return pc.Selected; | 12936 | return pc.Selected; |
12937 | else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP) | 12937 | else if (category == ScriptBaseClass.PARCEL_COUNT_TEMP) |
12938 | return 0; // counts not implemented yet | 12938 | return 0; // counts not implemented yet |
12939 | } | 12939 | } |
12940 | 12940 | ||
12941 | return 0; | 12941 | return 0; |
12942 | } | 12942 | } |
12943 | 12943 | ||
12944 | public LSL_List llGetParcelPrimOwners(LSL_Vector pos) | 12944 | public LSL_List llGetParcelPrimOwners(LSL_Vector pos) |
12945 | { | 12945 | { |
12946 | m_host.AddScriptLPS(1); | 12946 | m_host.AddScriptLPS(1); |
12947 | LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); | 12947 | LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); |
12948 | LSL_List ret = new LSL_List(); | 12948 | LSL_List ret = new LSL_List(); |
12949 | if (land != null) | 12949 | if (land != null) |
12950 | { | 12950 | { |
12951 | foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners()) | 12951 | foreach (KeyValuePair<UUID, int> detectedParams in land.GetLandObjectOwners()) |
12952 | { | 12952 | { |
12953 | ret.Add(new LSL_String(detectedParams.Key.ToString())); | 12953 | ret.Add(new LSL_String(detectedParams.Key.ToString())); |
12954 | ret.Add(new LSL_Integer(detectedParams.Value)); | 12954 | ret.Add(new LSL_Integer(detectedParams.Value)); |
12955 | } | 12955 | } |
12956 | } | 12956 | } |
12957 | ScriptSleep(m_sleepMsOnGetParcelPrimOwners); | 12957 | ScriptSleep(m_sleepMsOnGetParcelPrimOwners); |
12958 | return ret; | 12958 | return ret; |
12959 | } | 12959 | } |
12960 | 12960 | ||
12961 | public LSL_Integer llGetObjectPrimCount(string object_id) | 12961 | public LSL_Integer llGetObjectPrimCount(string object_id) |
12962 | { | 12962 | { |
12963 | m_host.AddScriptLPS(1); | 12963 | m_host.AddScriptLPS(1); |
12964 | SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id)); | 12964 | SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id)); |
12965 | if (part == null) | 12965 | if (part == null) |
12966 | { | 12966 | { |
12967 | return 0; | 12967 | return 0; |
12968 | } | 12968 | } |
12969 | else | 12969 | else |
12970 | { | 12970 | { |
12971 | return part.ParentGroup.PrimCount; | 12971 | return part.ParentGroup.PrimCount; |
12972 | } | 12972 | } |
12973 | } | 12973 | } |
12974 | 12974 | ||
12975 | public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide) | 12975 | public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide) |
12976 | { | 12976 | { |
12977 | m_host.AddScriptLPS(1); | 12977 | m_host.AddScriptLPS(1); |
12978 | 12978 | ||
12979 | ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); | 12979 | ILandObject lo = World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); |
12980 | 12980 | ||
12981 | if (lo == null) | 12981 | if (lo == null) |
12982 | return 0; | 12982 | return 0; |
12983 | 12983 | ||
12984 | if (sim_wide != 0) | 12984 | if (sim_wide != 0) |
12985 | return lo.GetSimulatorMaxPrimCount(); | 12985 | return lo.GetSimulatorMaxPrimCount(); |
12986 | else | 12986 | else |
12987 | return lo.GetParcelMaxPrimCount(); | 12987 | return lo.GetParcelMaxPrimCount(); |
12988 | } | 12988 | } |
12989 | 12989 | ||
12990 | public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) | 12990 | public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) |
12991 | { | 12991 | { |
12992 | m_host.AddScriptLPS(1); | 12992 | m_host.AddScriptLPS(1); |
12993 | LandData land = World.GetLandData(pos); | 12993 | LandData land = World.GetLandData(pos); |
12994 | if (land == null) | 12994 | if (land == null) |
12995 | { | 12995 | { |
12996 | return new LSL_List(0); | 12996 | return new LSL_List(0); |
12997 | } | 12997 | } |
12998 | LSL_List ret = new LSL_List(); | 12998 | LSL_List ret = new LSL_List(); |
12999 | foreach (object o in param.Data) | 12999 | foreach (object o in param.Data) |
13000 | { | 13000 | { |
13001 | switch (o.ToString()) | 13001 | switch (o.ToString()) |
13002 | { | 13002 | { |
13003 | case "0": | 13003 | case "0": |
13004 | ret.Add(new LSL_String(land.Name)); | 13004 | ret.Add(new LSL_String(land.Name)); |
13005 | break; | 13005 | break; |
13006 | case "1": | 13006 | case "1": |
13007 | ret.Add(new LSL_String(land.Description)); | 13007 | ret.Add(new LSL_String(land.Description)); |
13008 | break; | 13008 | break; |
13009 | case "2": | 13009 | case "2": |
13010 | ret.Add(new LSL_Key(land.OwnerID.ToString())); | 13010 | ret.Add(new LSL_Key(land.OwnerID.ToString())); |
13011 | break; | 13011 | break; |
13012 | case "3": | 13012 | case "3": |
13013 | ret.Add(new LSL_Key(land.GroupID.ToString())); | 13013 | ret.Add(new LSL_Key(land.GroupID.ToString())); |
13014 | break; | 13014 | break; |
13015 | case "4": | 13015 | case "4": |
13016 | ret.Add(new LSL_Integer(land.Area)); | 13016 | ret.Add(new LSL_Integer(land.Area)); |
13017 | break; | 13017 | break; |
13018 | case "5": | 13018 | case "5": |
13019 | ret.Add(new LSL_Key(land.GlobalID.ToString())); | 13019 | ret.Add(new LSL_Key(land.GlobalID.ToString())); |
13020 | break; | 13020 | break; |
13021 | default: | 13021 | default: |
13022 | ret.Add(new LSL_Integer(0)); | 13022 | ret.Add(new LSL_Integer(0)); |
13023 | break; | 13023 | break; |
13024 | } | 13024 | } |
13025 | } | 13025 | } |
13026 | return ret; | 13026 | return ret; |
13027 | } | 13027 | } |
13028 | 13028 | ||
13029 | public LSL_String llStringTrim(string src, int type) | 13029 | public LSL_String llStringTrim(string src, int type) |
13030 | { | 13030 | { |
13031 | m_host.AddScriptLPS(1); | 13031 | m_host.AddScriptLPS(1); |
13032 | if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } | 13032 | if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } |
13033 | if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } | 13033 | if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } |
13034 | if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); } | 13034 | if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); } |
13035 | return src; | 13035 | return src; |
13036 | } | 13036 | } |
13037 | 13037 | ||
13038 | public LSL_List llGetObjectDetails(string id, LSL_List args) | 13038 | public LSL_List llGetObjectDetails(string id, LSL_List args) |
13039 | { | 13039 | { |
13040 | m_host.AddScriptLPS(1); | 13040 | m_host.AddScriptLPS(1); |
13041 | 13041 | ||
13042 | LSL_List ret = new LSL_List(); | 13042 | LSL_List ret = new LSL_List(); |
13043 | UUID key = new UUID(); | 13043 | UUID key = new UUID(); |
13044 | if (UUID.TryParse(id, out key)) | 13044 | if (UUID.TryParse(id, out key)) |
13045 | { | 13045 | { |
13046 | ScenePresence av = World.GetScenePresence(key); | 13046 | ScenePresence av = World.GetScenePresence(key); |
13047 | 13047 | ||
13048 | if (av != null) | 13048 | if (av != null) |
13049 | { | 13049 | { |
13050 | foreach (object o in args.Data) | 13050 | foreach (object o in args.Data) |
13051 | { | 13051 | { |
13052 | switch (int.Parse(o.ToString())) | 13052 | switch (int.Parse(o.ToString())) |
13053 | { | 13053 | { |
13054 | case ScriptBaseClass.OBJECT_NAME: | 13054 | case ScriptBaseClass.OBJECT_NAME: |
13055 | ret.Add(new LSL_String(av.Firstname + " " + av.Lastname)); | 13055 | ret.Add(new LSL_String(av.Firstname + " " + av.Lastname)); |
13056 | break; | 13056 | break; |
13057 | case ScriptBaseClass.OBJECT_DESC: | 13057 | case ScriptBaseClass.OBJECT_DESC: |
13058 | ret.Add(new LSL_String("")); | 13058 | ret.Add(new LSL_String("")); |
13059 | break; | 13059 | break; |
13060 | case ScriptBaseClass.OBJECT_POS: | 13060 | case ScriptBaseClass.OBJECT_POS: |
13061 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); | 13061 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); |
13062 | break; | 13062 | break; |
13063 | case ScriptBaseClass.OBJECT_ROT: | 13063 | case ScriptBaseClass.OBJECT_ROT: |
13064 | ret.Add(new LSL_Rotation(av.GetWorldRotation())); | 13064 | ret.Add(new LSL_Rotation(av.GetWorldRotation())); |
13065 | break; | 13065 | break; |
13066 | case ScriptBaseClass.OBJECT_VELOCITY: | 13066 | case ScriptBaseClass.OBJECT_VELOCITY: |
13067 | ret.Add(new LSL_Vector(av.GetWorldVelocity())); | 13067 | ret.Add(new LSL_Vector(av.GetWorldVelocity())); |
13068 | break; | 13068 | break; |
13069 | case ScriptBaseClass.OBJECT_OWNER: | 13069 | case ScriptBaseClass.OBJECT_OWNER: |
13070 | ret.Add(new LSL_String(id)); | 13070 | ret.Add(new LSL_String(id)); |
13071 | break; | 13071 | break; |
13072 | case ScriptBaseClass.OBJECT_GROUP: | 13072 | case ScriptBaseClass.OBJECT_GROUP: |
13073 | ret.Add(new LSL_String(UUID.Zero.ToString())); | 13073 | ret.Add(new LSL_String(UUID.Zero.ToString())); |
13074 | break; | 13074 | break; |
13075 | case ScriptBaseClass.OBJECT_CREATOR: | 13075 | case ScriptBaseClass.OBJECT_CREATOR: |
13076 | ret.Add(new LSL_String(UUID.Zero.ToString())); | 13076 | ret.Add(new LSL_String(UUID.Zero.ToString())); |
13077 | break; | 13077 | break; |
13078 | // For the following 8 see the Object version below | 13078 | // For the following 8 see the Object version below |
13079 | case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: | 13079 | case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: |
13080 | ret.Add(new LSL_Integer(av.RunningScriptCount())); | 13080 | ret.Add(new LSL_Integer(av.RunningScriptCount())); |
13081 | break; | 13081 | break; |
13082 | case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: | 13082 | case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: |
13083 | ret.Add(new LSL_Integer(av.ScriptCount())); | 13083 | ret.Add(new LSL_Integer(av.ScriptCount())); |
13084 | break; | 13084 | break; |
13085 | case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: | 13085 | case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: |
13086 | ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384)); | 13086 | ret.Add(new LSL_Integer(av.RunningScriptCount() * 16384)); |
13087 | break; | 13087 | break; |
13088 | case ScriptBaseClass.OBJECT_SCRIPT_TIME: | 13088 | case ScriptBaseClass.OBJECT_SCRIPT_TIME: |
13089 | ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f)); | 13089 | ret.Add(new LSL_Float(av.ScriptExecutionTime() / 1000.0f)); |
13090 | break; | 13090 | break; |
13091 | case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: | 13091 | case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: |
13092 | ret.Add(new LSL_Integer(1)); | 13092 | ret.Add(new LSL_Integer(1)); |
13093 | break; | 13093 | break; |
13094 | case ScriptBaseClass.OBJECT_SERVER_COST: | 13094 | case ScriptBaseClass.OBJECT_SERVER_COST: |
13095 | ret.Add(new LSL_Float(0)); | 13095 | ret.Add(new LSL_Float(0)); |
13096 | break; | 13096 | break; |
13097 | case ScriptBaseClass.OBJECT_STREAMING_COST: | 13097 | case ScriptBaseClass.OBJECT_STREAMING_COST: |
13098 | ret.Add(new LSL_Float(0)); | 13098 | ret.Add(new LSL_Float(0)); |
13099 | break; | 13099 | break; |
13100 | case ScriptBaseClass.OBJECT_PHYSICS_COST: | 13100 | case ScriptBaseClass.OBJECT_PHYSICS_COST: |
13101 | ret.Add(new LSL_Float(0)); | 13101 | ret.Add(new LSL_Float(0)); |
13102 | break; | 13102 | break; |
13103 | case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding | 13103 | case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding |
13104 | ret.Add(new LSL_Float(0)); | 13104 | ret.Add(new LSL_Float(0)); |
13105 | break; | 13105 | break; |
13106 | case ScriptBaseClass.OBJECT_ROOT: | 13106 | case ScriptBaseClass.OBJECT_ROOT: |
13107 | SceneObjectPart p = av.ParentPart; | 13107 | SceneObjectPart p = av.ParentPart; |
13108 | if (p != null) | 13108 | if (p != null) |
13109 | { | 13109 | { |
13110 | ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString())); | 13110 | ret.Add(new LSL_String(p.ParentGroup.RootPart.UUID.ToString())); |
13111 | } | 13111 | } |
13112 | else | 13112 | else |
13113 | { | 13113 | { |
13114 | ret.Add(new LSL_String(id)); | 13114 | ret.Add(new LSL_String(id)); |
13115 | } | 13115 | } |
13116 | break; | 13116 | break; |
13117 | case ScriptBaseClass.OBJECT_ATTACHED_POINT: | 13117 | case ScriptBaseClass.OBJECT_ATTACHED_POINT: |
13118 | ret.Add(new LSL_Integer(0)); | 13118 | ret.Add(new LSL_Integer(0)); |
13119 | break; | 13119 | break; |
13120 | case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding | 13120 | case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: // Pathfinding |
13121 | ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR)); | 13121 | ret.Add(new LSL_Integer(ScriptBaseClass.OPT_AVATAR)); |
13122 | break; | 13122 | break; |
13123 | case ScriptBaseClass.OBJECT_PHYSICS: | 13123 | case ScriptBaseClass.OBJECT_PHYSICS: |
13124 | ret.Add(new LSL_Integer(0)); | 13124 | ret.Add(new LSL_Integer(0)); |
13125 | break; | 13125 | break; |
13126 | case ScriptBaseClass.OBJECT_PHANTOM: | 13126 | case ScriptBaseClass.OBJECT_PHANTOM: |
13127 | ret.Add(new LSL_Integer(0)); | 13127 | ret.Add(new LSL_Integer(0)); |
13128 | break; | 13128 | break; |
13129 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: | 13129 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: |
13130 | ret.Add(new LSL_Integer(0)); | 13130 | ret.Add(new LSL_Integer(0)); |
13131 | break; | 13131 | break; |
13132 | case ScriptBaseClass.OBJECT_RENDER_WEIGHT: | 13132 | case ScriptBaseClass.OBJECT_RENDER_WEIGHT: |
13133 | ret.Add(new LSL_Integer(-1)); | 13133 | ret.Add(new LSL_Integer(-1)); |
13134 | break; | 13134 | break; |
13135 | case ScriptBaseClass.OBJECT_HOVER_HEIGHT: | 13135 | case ScriptBaseClass.OBJECT_HOVER_HEIGHT: |
13136 | ret.Add(new LSL_Float(0)); | 13136 | ret.Add(new LSL_Float(0)); |
13137 | break; | 13137 | break; |
13138 | case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: | 13138 | case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: |
13139 | LSL_Float shapeType; | 13139 | LSL_Float shapeType; |
13140 | if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0) | 13140 | if (av.Appearance.VisualParams[(int)AvatarAppearance.VPElement.SHAPE_MALE] != 0) |
13141 | shapeType = new LSL_Float(1); | 13141 | shapeType = new LSL_Float(1); |
13142 | else | 13142 | else |
13143 | shapeType = new LSL_Float(0); | 13143 | shapeType = new LSL_Float(0); |
13144 | ret.Add(shapeType); | 13144 | ret.Add(shapeType); |
13145 | break; | 13145 | break; |
13146 | case ScriptBaseClass.OBJECT_LAST_OWNER_ID: | 13146 | case ScriptBaseClass.OBJECT_LAST_OWNER_ID: |
13147 | ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY)); | 13147 | ret.Add(new LSL_Key(ScriptBaseClass.NULL_KEY)); |
13148 | break; | 13148 | break; |
13149 | default: | 13149 | default: |
13150 | // Invalid or unhandled constant. | 13150 | // Invalid or unhandled constant. |
13151 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); | 13151 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); |
13152 | break; | 13152 | break; |
13153 | } | 13153 | } |
13154 | } | 13154 | } |
13155 | 13155 | ||
13156 | return ret; | 13156 | return ret; |
13157 | } | 13157 | } |
13158 | 13158 | ||
13159 | SceneObjectPart obj = World.GetSceneObjectPart(key); | 13159 | SceneObjectPart obj = World.GetSceneObjectPart(key); |
13160 | if (obj != null) | 13160 | if (obj != null) |
13161 | { | 13161 | { |
13162 | foreach (object o in args.Data) | 13162 | foreach (object o in args.Data) |
13163 | { | 13163 | { |
13164 | switch (int.Parse(o.ToString())) | 13164 | switch (int.Parse(o.ToString())) |
13165 | { | 13165 | { |
13166 | case ScriptBaseClass.OBJECT_NAME: | 13166 | case ScriptBaseClass.OBJECT_NAME: |
13167 | ret.Add(new LSL_String(obj.Name)); | 13167 | ret.Add(new LSL_String(obj.Name)); |
13168 | break; | 13168 | break; |
13169 | case ScriptBaseClass.OBJECT_DESC: | 13169 | case ScriptBaseClass.OBJECT_DESC: |
13170 | ret.Add(new LSL_String(obj.Description)); | 13170 | ret.Add(new LSL_String(obj.Description)); |
13171 | break; | 13171 | break; |
13172 | case ScriptBaseClass.OBJECT_POS: | 13172 | case ScriptBaseClass.OBJECT_POS: |
13173 | ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); | 13173 | ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); |
13174 | break; | 13174 | break; |
13175 | case ScriptBaseClass.OBJECT_ROT: | 13175 | case ScriptBaseClass.OBJECT_ROT: |
13176 | Quaternion rot = Quaternion.Identity; | 13176 | Quaternion rot = Quaternion.Identity; |
13177 | 13177 | ||
13178 | if (obj.ParentGroup.IsAttachment) | 13178 | if (obj.ParentGroup.IsAttachment) |
13179 | { | 13179 | { |
13180 | ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); | 13180 | ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); |
13181 | 13181 | ||
13182 | if (sp != null) | 13182 | if (sp != null) |
13183 | rot = sp.GetWorldRotation(); | 13183 | rot = sp.GetWorldRotation(); |
13184 | } | 13184 | } |
13185 | else | 13185 | else |
13186 | { | 13186 | { |
13187 | if (obj.ParentGroup.RootPart == obj) | 13187 | if (obj.ParentGroup.RootPart == obj) |
13188 | rot = obj.ParentGroup.GroupRotation; | 13188 | rot = obj.ParentGroup.GroupRotation; |
13189 | else | 13189 | else |
13190 | rot = obj.GetWorldRotation(); | 13190 | rot = obj.GetWorldRotation(); |
13191 | } | 13191 | } |
13192 | 13192 | ||
13193 | LSL_Rotation objrot = new LSL_Rotation(rot); | 13193 | LSL_Rotation objrot = new LSL_Rotation(rot); |
13194 | ret.Add(objrot); | 13194 | ret.Add(objrot); |
13195 | 13195 | ||
13196 | break; | 13196 | break; |
13197 | case ScriptBaseClass.OBJECT_VELOCITY: | 13197 | case ScriptBaseClass.OBJECT_VELOCITY: |
13198 | Vector3 vel = Vector3.Zero; | 13198 | Vector3 vel = Vector3.Zero; |
13199 | 13199 | ||
13200 | if (obj.ParentGroup.IsAttachment) | 13200 | if (obj.ParentGroup.IsAttachment) |
13201 | { | 13201 | { |
13202 | ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); | 13202 | ScenePresence sp = World.GetScenePresence(obj.ParentGroup.AttachedAvatar); |
13203 | 13203 | ||
13204 | if (sp != null) | 13204 | if (sp != null) |
13205 | vel = sp.GetWorldVelocity(); | 13205 | vel = sp.GetWorldVelocity(); |
13206 | } | 13206 | } |
13207 | else | 13207 | else |
13208 | { | 13208 | { |
13209 | vel = obj.Velocity; | 13209 | vel = obj.Velocity; |
13210 | } | 13210 | } |
13211 | 13211 | ||
13212 | ret.Add(vel); | 13212 | ret.Add(vel); |
13213 | break; | 13213 | break; |
13214 | case ScriptBaseClass.OBJECT_OWNER: | 13214 | case ScriptBaseClass.OBJECT_OWNER: |
13215 | ret.Add(new LSL_String(obj.OwnerID.ToString())); | 13215 | ret.Add(new LSL_String(obj.OwnerID.ToString())); |
13216 | break; | 13216 | break; |
13217 | case ScriptBaseClass.OBJECT_GROUP: | 13217 | case ScriptBaseClass.OBJECT_GROUP: |
13218 | ret.Add(new LSL_String(obj.GroupID.ToString())); | 13218 | ret.Add(new LSL_String(obj.GroupID.ToString())); |
13219 | break; | 13219 | break; |
13220 | case ScriptBaseClass.OBJECT_CREATOR: | 13220 | case ScriptBaseClass.OBJECT_CREATOR: |
13221 | ret.Add(new LSL_String(obj.CreatorID.ToString())); | 13221 | ret.Add(new LSL_String(obj.CreatorID.ToString())); |
13222 | break; | 13222 | break; |
13223 | case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: | 13223 | case ScriptBaseClass.OBJECT_RUNNING_SCRIPT_COUNT: |
13224 | ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount())); | 13224 | ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount())); |
13225 | break; | 13225 | break; |
13226 | case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: | 13226 | case ScriptBaseClass.OBJECT_TOTAL_SCRIPT_COUNT: |
13227 | ret.Add(new LSL_Integer(obj.ParentGroup.ScriptCount())); | 13227 | ret.Add(new LSL_Integer(obj.ParentGroup.ScriptCount())); |
13228 | break; | 13228 | break; |
13229 | case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: | 13229 | case ScriptBaseClass.OBJECT_SCRIPT_MEMORY: |
13230 | // The value returned in SL for mono scripts is 65536 * number of active scripts | 13230 | // The value returned in SL for mono scripts is 65536 * number of active scripts |
13231 | // and 16384 * number of active scripts for LSO. since llGetFreememory | 13231 | // and 16384 * number of active scripts for LSO. since llGetFreememory |
13232 | // is coded to give the LSO value use it here | 13232 | // is coded to give the LSO value use it here |
13233 | ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384)); | 13233 | ret.Add(new LSL_Integer(obj.ParentGroup.RunningScriptCount() * 16384)); |
13234 | break; | 13234 | break; |
13235 | case ScriptBaseClass.OBJECT_SCRIPT_TIME: | 13235 | case ScriptBaseClass.OBJECT_SCRIPT_TIME: |
13236 | // Average cpu time in seconds per simulator frame expended on all scripts in the object | 13236 | // Average cpu time in seconds per simulator frame expended on all scripts in the object |
13237 | ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f)); | 13237 | ret.Add(new LSL_Float(obj.ParentGroup.ScriptExecutionTime() / 1000.0f)); |
13238 | break; | 13238 | break; |
13239 | case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: | 13239 | case ScriptBaseClass.OBJECT_PRIM_EQUIVALENCE: |
13240 | // according to the SL wiki A prim or linkset will have prim | 13240 | // according to the SL wiki A prim or linkset will have prim |
13241 | // equivalent of the number of prims in a linkset if it does not | 13241 | // equivalent of the number of prims in a linkset if it does not |
13242 | // contain a mesh anywhere in the link set or is not a normal prim | 13242 | // contain a mesh anywhere in the link set or is not a normal prim |
13243 | // The value returned in SL for normal prims is prim count | 13243 | // The value returned in SL for normal prims is prim count |
13244 | ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); | 13244 | ret.Add(new LSL_Integer(obj.ParentGroup.PrimCount)); |
13245 | break; | 13245 | break; |
13246 | // The following 3 costs I have intentionaly coded to return zero. They are part of | 13246 | // The following 3 costs I have intentionaly coded to return zero. They are part of |
13247 | // "Land Impact" calculations. These calculations are probably not applicable | 13247 | // "Land Impact" calculations. These calculations are probably not applicable |
13248 | // to OpenSim and are not yet complete in SL | 13248 | // to OpenSim and are not yet complete in SL |
13249 | case ScriptBaseClass.OBJECT_SERVER_COST: | 13249 | case ScriptBaseClass.OBJECT_SERVER_COST: |
13250 | // The linden calculation is here | 13250 | // The linden calculation is here |
13251 | // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight | 13251 | // http://wiki.secondlife.com/wiki/Mesh/Mesh_Server_Weight |
13252 | // The value returned in SL for normal prims looks like the prim count | 13252 | // The value returned in SL for normal prims looks like the prim count |
13253 | ret.Add(new LSL_Float(0)); | 13253 | ret.Add(new LSL_Float(0)); |
13254 | break; | 13254 | break; |
13255 | case ScriptBaseClass.OBJECT_STREAMING_COST: | 13255 | case ScriptBaseClass.OBJECT_STREAMING_COST: |
13256 | // The linden calculation is here | 13256 | // The linden calculation is here |
13257 | // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost | 13257 | // http://wiki.secondlife.com/wiki/Mesh/Mesh_Streaming_Cost |
13258 | // The value returned in SL for normal prims looks like the prim count * 0.06 | 13258 | // The value returned in SL for normal prims looks like the prim count * 0.06 |
13259 | ret.Add(new LSL_Float(0)); | 13259 | ret.Add(new LSL_Float(0)); |
13260 | break; | 13260 | break; |
13261 | case ScriptBaseClass.OBJECT_PHYSICS_COST: | 13261 | case ScriptBaseClass.OBJECT_PHYSICS_COST: |
13262 | // The linden calculation is here | 13262 | // The linden calculation is here |
13263 | // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics | 13263 | // http://wiki.secondlife.com/wiki/Mesh/Mesh_physics |
13264 | // The value returned in SL for normal prims looks like the prim count | 13264 | // The value returned in SL for normal prims looks like the prim count |
13265 | ret.Add(new LSL_Float(0)); | 13265 | ret.Add(new LSL_Float(0)); |
13266 | break; | 13266 | break; |
13267 | case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding | 13267 | case ScriptBaseClass.OBJECT_CHARACTER_TIME: // Pathfinding |
13268 | ret.Add(new LSL_Float(0)); | 13268 | ret.Add(new LSL_Float(0)); |
13269 | break; | 13269 | break; |
13270 | case ScriptBaseClass.OBJECT_ROOT: | 13270 | case ScriptBaseClass.OBJECT_ROOT: |
13271 | ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString())); | 13271 | ret.Add(new LSL_String(obj.ParentGroup.RootPart.UUID.ToString())); |
13272 | break; | 13272 | break; |
13273 | case ScriptBaseClass.OBJECT_ATTACHED_POINT: | 13273 | case ScriptBaseClass.OBJECT_ATTACHED_POINT: |
13274 | ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint)); | 13274 | ret.Add(new LSL_Integer(obj.ParentGroup.AttachmentPoint)); |
13275 | break; | 13275 | break; |
13276 | case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: | 13276 | case ScriptBaseClass.OBJECT_PATHFINDING_TYPE: |
13277 | byte pcode = obj.Shape.PCode; | 13277 | byte pcode = obj.Shape.PCode; |
13278 | if (obj.ParentGroup.AttachmentPoint != 0 | 13278 | if (obj.ParentGroup.AttachmentPoint != 0 |
13279 | || pcode == (byte)PCode.Grass | 13279 | || pcode == (byte)PCode.Grass |
13280 | || pcode == (byte)PCode.Tree | 13280 | || pcode == (byte)PCode.Tree |
13281 | || pcode == (byte)PCode.NewTree) | 13281 | || pcode == (byte)PCode.NewTree) |
13282 | { | 13282 | { |
13283 | ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER)); | 13283 | ret.Add(new LSL_Integer(ScriptBaseClass.OPT_OTHER)); |
13284 | } | 13284 | } |
13285 | else | 13285 | else |
13286 | { | 13286 | { |
13287 | ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET)); | 13287 | ret.Add(new LSL_Integer(ScriptBaseClass.OPT_LEGACY_LINKSET)); |
13288 | } | 13288 | } |
13289 | break; | 13289 | break; |
13290 | case ScriptBaseClass.OBJECT_PHYSICS: | 13290 | case ScriptBaseClass.OBJECT_PHYSICS: |
13291 | if (obj.ParentGroup.AttachmentPoint != 0) | 13291 | if (obj.ParentGroup.AttachmentPoint != 0) |
13292 | { | 13292 | { |
13293 | ret.Add(new LSL_Integer(0)); // Always false if attached | 13293 | ret.Add(new LSL_Integer(0)); // Always false if attached |
13294 | } | 13294 | } |
13295 | else | 13295 | else |
13296 | { | 13296 | { |
13297 | ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0)); | 13297 | ret.Add(new LSL_Integer(obj.ParentGroup.UsesPhysics ? 1 : 0)); |
13298 | } | 13298 | } |
13299 | break; | 13299 | break; |
13300 | case ScriptBaseClass.OBJECT_PHANTOM: | 13300 | case ScriptBaseClass.OBJECT_PHANTOM: |
13301 | if (obj.ParentGroup.AttachmentPoint != 0) | 13301 | if (obj.ParentGroup.AttachmentPoint != 0) |
13302 | { | 13302 | { |
13303 | ret.Add(new LSL_Integer(0)); // Always false if attached | 13303 | ret.Add(new LSL_Integer(0)); // Always false if attached |
13304 | } | 13304 | } |
13305 | else | 13305 | else |
13306 | { | 13306 | { |
13307 | ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0)); | 13307 | ret.Add(new LSL_Integer(obj.ParentGroup.IsPhantom ? 1 : 0)); |
13308 | } | 13308 | } |
13309 | break; | 13309 | break; |
13310 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: | 13310 | case ScriptBaseClass.OBJECT_TEMP_ON_REZ: |
13311 | ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); | 13311 | ret.Add(new LSL_Integer(obj.ParentGroup.IsTemporary ? 1 : 0)); |
13312 | break; | 13312 | break; |
13313 | case ScriptBaseClass.OBJECT_RENDER_WEIGHT: | 13313 | case ScriptBaseClass.OBJECT_RENDER_WEIGHT: |
13314 | ret.Add(new LSL_Integer(0)); | 13314 | ret.Add(new LSL_Integer(0)); |
13315 | break; | 13315 | break; |
13316 | case ScriptBaseClass.OBJECT_HOVER_HEIGHT: | 13316 | case ScriptBaseClass.OBJECT_HOVER_HEIGHT: |
13317 | ret.Add(new LSL_Float(0)); | 13317 | ret.Add(new LSL_Float(0)); |
13318 | break; | 13318 | break; |
13319 | case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: | 13319 | case ScriptBaseClass.OBJECT_BODY_SHAPE_TYPE: |
13320 | ret.Add(new LSL_Float(-1)); | 13320 | ret.Add(new LSL_Float(-1)); |
13321 | break; | 13321 | break; |
13322 | case ScriptBaseClass.OBJECT_LAST_OWNER_ID: | 13322 | case ScriptBaseClass.OBJECT_LAST_OWNER_ID: |
13323 | ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString())); | 13323 | ret.Add(new LSL_Key(obj.ParentGroup.LastOwnerID.ToString())); |
13324 | break; | 13324 | break; |
13325 | default: | 13325 | default: |
13326 | // Invalid or unhandled constant. | 13326 | // Invalid or unhandled constant. |
13327 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); | 13327 | ret.Add(new LSL_Integer(ScriptBaseClass.OBJECT_UNKNOWN_DETAIL)); |
13328 | break; | 13328 | break; |
13329 | } | 13329 | } |
13330 | } | 13330 | } |
13331 | 13331 | ||
13332 | return ret; | 13332 | return ret; |
13333 | } | 13333 | } |
13334 | } | 13334 | } |
13335 | 13335 | ||
13336 | return new LSL_List(); | 13336 | return new LSL_List(); |
13337 | } | 13337 | } |
13338 | 13338 | ||
13339 | internal UUID GetScriptByName(string name) | 13339 | internal UUID GetScriptByName(string name) |
13340 | { | 13340 | { |
13341 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 13341 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); |
13342 | 13342 | ||
13343 | if (item == null || item.Type != 10) | 13343 | if (item == null || item.Type != 10) |
13344 | return UUID.Zero; | 13344 | return UUID.Zero; |
13345 | 13345 | ||
13346 | return item.ItemID; | 13346 | return item.ItemID; |
13347 | } | 13347 | } |
13348 | 13348 | ||
13349 | /// <summary> | 13349 | /// <summary> |
13350 | /// Reports the script error in the viewer's Script Warning/Error dialog and shouts it on the debug channel. | 13350 | /// Reports the script error in the viewer's Script Warning/Error dialog and shouts it on the debug channel. |
13351 | /// </summary> | 13351 | /// </summary> |
13352 | /// <param name="command">The name of the command that generated the error.</param> | 13352 | /// <param name="command">The name of the command that generated the error.</param> |
13353 | /// <param name="message">The error message to report to the user.</param> | 13353 | /// <param name="message">The error message to report to the user.</param> |
13354 | internal void Error(string command, string message) | 13354 | internal void Error(string command, string message) |
13355 | { | 13355 | { |
13356 | string text = command + ": " + message; | 13356 | string text = command + ": " + message; |
13357 | if (text.Length > 1023) | 13357 | if (text.Length > 1023) |
13358 | { | 13358 | { |
13359 | text = text.Substring(0, 1023); | 13359 | text = text.Substring(0, 1023); |
13360 | } | 13360 | } |
13361 | 13361 | ||
13362 | World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL, | 13362 | World.SimChat(Utils.StringToBytes(text), ChatTypeEnum.DebugChannel, ScriptBaseClass.DEBUG_CHANNEL, |
13363 | m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); | 13363 | m_host.ParentGroup.RootPart.AbsolutePosition, m_host.Name, m_host.UUID, false); |
13364 | 13364 | ||
13365 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | 13365 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); |
13366 | if (wComm != null) | 13366 | if (wComm != null) |
13367 | { | 13367 | { |
13368 | wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text); | 13368 | wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, text); |
13369 | } | 13369 | } |
13370 | } | 13370 | } |
13371 | 13371 | ||
13372 | /// <summary> | 13372 | /// <summary> |
13373 | /// Reports that the command is not implemented as a script error. | 13373 | /// Reports that the command is not implemented as a script error. |
13374 | /// </summary> | 13374 | /// </summary> |
13375 | /// <param name="command">The name of the command that is not implemented.</param> | 13375 | /// <param name="command">The name of the command that is not implemented.</param> |
13376 | /// <param name="message">Additional information to report to the user. (Optional)</param> | 13376 | /// <param name="message">Additional information to report to the user. (Optional)</param> |
13377 | internal void NotImplemented(string command, string message = "") | 13377 | internal void NotImplemented(string command, string message = "") |
13378 | { | 13378 | { |
13379 | if (throwErrorOnNotImplemented) | 13379 | if (throwErrorOnNotImplemented) |
13380 | { | 13380 | { |
13381 | if (message != "") | 13381 | if (message != "") |
13382 | { | 13382 | { |
13383 | message = " - " + message; | 13383 | message = " - " + message; |
13384 | } | 13384 | } |
13385 | 13385 | ||
13386 | throw new NotImplementedException("Command not implemented: " + command + message); | 13386 | throw new NotImplementedException("Command not implemented: " + command + message); |
13387 | } | 13387 | } |
13388 | else | 13388 | else |
13389 | { | 13389 | { |
13390 | string text = "Command not implemented"; | 13390 | string text = "Command not implemented"; |
13391 | if (message != "") | 13391 | if (message != "") |
13392 | { | 13392 | { |
13393 | text = text + " - " + message; | 13393 | text = text + " - " + message; |
13394 | } | 13394 | } |
13395 | 13395 | ||
13396 | Error(command, text); | 13396 | Error(command, text); |
13397 | } | 13397 | } |
13398 | } | 13398 | } |
13399 | 13399 | ||
13400 | /// <summary> | 13400 | /// <summary> |
13401 | /// Reports that the command is deprecated as a script error. | 13401 | /// Reports that the command is deprecated as a script error. |
13402 | /// </summary> | 13402 | /// </summary> |
13403 | /// <param name="command">The name of the command that is deprecated.</param> | 13403 | /// <param name="command">The name of the command that is deprecated.</param> |
13404 | /// <param name="message">Additional information to report to the user. (Optional)</param> | 13404 | /// <param name="message">Additional information to report to the user. (Optional)</param> |
13405 | internal void Deprecated(string command, string message = "") | 13405 | internal void Deprecated(string command, string message = "") |
13406 | { | 13406 | { |
13407 | string text = "Command deprecated"; | 13407 | string text = "Command deprecated"; |
13408 | if (message != "") | 13408 | if (message != "") |
13409 | { | 13409 | { |
13410 | text = text + " - " + message; | 13410 | text = text + " - " + message; |
13411 | } | 13411 | } |
13412 | 13412 | ||
13413 | Error(command, text); | 13413 | Error(command, text); |
13414 | } | 13414 | } |
13415 | 13415 | ||
13416 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); | 13416 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); |
13417 | protected void WithNotecard(UUID assetID, AssetRequestCallback cb) | 13417 | protected void WithNotecard(UUID assetID, AssetRequestCallback cb) |
13418 | { | 13418 | { |
13419 | World.AssetService.Get(assetID.ToString(), this, | 13419 | World.AssetService.Get(assetID.ToString(), this, |
13420 | delegate(string i, object sender, AssetBase a) | 13420 | delegate(string i, object sender, AssetBase a) |
13421 | { | 13421 | { |
13422 | UUID uuid = UUID.Zero; | 13422 | UUID uuid = UUID.Zero; |
13423 | UUID.TryParse(i, out uuid); | 13423 | UUID.TryParse(i, out uuid); |
13424 | cb(uuid, a); | 13424 | cb(uuid, a); |
13425 | }); | 13425 | }); |
13426 | } | 13426 | } |
13427 | 13427 | ||
13428 | public LSL_String llGetNumberOfNotecardLines(string name) | 13428 | public LSL_String llGetNumberOfNotecardLines(string name) |
13429 | { | 13429 | { |
13430 | m_host.AddScriptLPS(1); | 13430 | m_host.AddScriptLPS(1); |
13431 | 13431 | ||
13432 | UUID assetID = UUID.Zero; | 13432 | UUID assetID = UUID.Zero; |
13433 | 13433 | ||
13434 | if (!UUID.TryParse(name, out assetID)) | 13434 | if (!UUID.TryParse(name, out assetID)) |
13435 | { | 13435 | { |
13436 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 13436 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); |
13437 | 13437 | ||
13438 | if (item != null && item.Type == 7) | 13438 | if (item != null && item.Type == 7) |
13439 | assetID = item.AssetID; | 13439 | assetID = item.AssetID; |
13440 | } | 13440 | } |
13441 | 13441 | ||
13442 | if (assetID == UUID.Zero) | 13442 | if (assetID == UUID.Zero) |
13443 | { | 13443 | { |
13444 | // => complain loudly, as specified by the LSL docs | 13444 | // => complain loudly, as specified by the LSL docs |
13445 | Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); | 13445 | Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); |
13446 | 13446 | ||
13447 | return UUID.Zero.ToString(); | 13447 | return UUID.Zero.ToString(); |
13448 | } | 13448 | } |
13449 | 13449 | ||
13450 | string reqIdentifier = UUID.Random().ToString(); | 13450 | string reqIdentifier = UUID.Random().ToString(); |
13451 | 13451 | ||
13452 | // was: UUID tid = tid = AsyncCommands. | 13452 | // was: UUID tid = tid = AsyncCommands. |
13453 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); | 13453 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); |
13454 | 13454 | ||
13455 | if (NotecardCache.IsCached(assetID)) | 13455 | if (NotecardCache.IsCached(assetID)) |
13456 | { | 13456 | { |
13457 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString()); | 13457 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(assetID).ToString()); |
13458 | 13458 | ||
13459 | ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); | 13459 | ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); |
13460 | return tid.ToString(); | 13460 | return tid.ToString(); |
13461 | } | 13461 | } |
13462 | 13462 | ||
13463 | WithNotecard(assetID, delegate (UUID id, AssetBase a) | 13463 | WithNotecard(assetID, delegate (UUID id, AssetBase a) |
13464 | { | 13464 | { |
13465 | if (a == null || a.Type != 7) | 13465 | if (a == null || a.Type != 7) |
13466 | { | 13466 | { |
13467 | Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); | 13467 | Error("llGetNumberOfNotecardLines", "Can't find notecard '" + name + "'"); |
13468 | return; | 13468 | return; |
13469 | } | 13469 | } |
13470 | 13470 | ||
13471 | NotecardCache.Cache(id, a.Data); | 13471 | NotecardCache.Cache(id, a.Data); |
13472 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString()); | 13472 | AsyncCommands.DataserverPlugin.DataserverReply(reqIdentifier, NotecardCache.GetLines(id).ToString()); |
13473 | }); | 13473 | }); |
13474 | 13474 | ||
13475 | ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); | 13475 | ScriptSleep(m_sleepMsOnGetNumberOfNotecardLines); |
13476 | return tid.ToString(); | 13476 | return tid.ToString(); |
13477 | } | 13477 | } |
13478 | 13478 | ||
13479 | public LSL_String llGetNotecardLine(string name, int line) | 13479 | public LSL_String llGetNotecardLine(string name, int line) |
13480 | { | 13480 | { |
13481 | m_host.AddScriptLPS(1); | 13481 | m_host.AddScriptLPS(1); |
13482 | 13482 | ||
13483 | UUID assetID = UUID.Zero; | 13483 | UUID assetID = UUID.Zero; |
13484 | 13484 | ||
13485 | if (!UUID.TryParse(name, out assetID)) | 13485 | if (!UUID.TryParse(name, out assetID)) |
13486 | { | 13486 | { |
13487 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); | 13487 | TaskInventoryItem item = m_host.Inventory.GetInventoryItem(name); |
13488 | 13488 | ||
13489 | if (item != null && item.Type == 7) | 13489 | if (item != null && item.Type == 7) |
13490 | assetID = item.AssetID; | 13490 | assetID = item.AssetID; |
13491 | } | 13491 | } |
13492 | 13492 | ||
13493 | if (assetID == UUID.Zero) | 13493 | if (assetID == UUID.Zero) |
13494 | { | 13494 | { |
13495 | // => complain loudly, as specified by the LSL docs | 13495 | // => complain loudly, as specified by the LSL docs |
13496 | Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); | 13496 | Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); |
13497 | 13497 | ||
13498 | return UUID.Zero.ToString(); | 13498 | return UUID.Zero.ToString(); |
13499 | } | 13499 | } |
13500 | 13500 | ||
13501 | string reqIdentifier = UUID.Random().ToString(); | 13501 | string reqIdentifier = UUID.Random().ToString(); |
13502 | 13502 | ||
13503 | // was: UUID tid = tid = AsyncCommands. | 13503 | // was: UUID tid = tid = AsyncCommands. |
13504 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); | 13504 | UUID tid = AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, reqIdentifier); |
13505 | 13505 | ||
13506 | if (NotecardCache.IsCached(assetID)) | 13506 | if (NotecardCache.IsCached(assetID)) |
13507 | { | 13507 | { |
13508 | AsyncCommands.DataserverPlugin.DataserverReply( | 13508 | AsyncCommands.DataserverPlugin.DataserverReply( |
13509 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); | 13509 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); |
13510 | 13510 | ||
13511 | ScriptSleep(m_sleepMsOnGetNotecardLine); | 13511 | ScriptSleep(m_sleepMsOnGetNotecardLine); |
13512 | return tid.ToString(); | 13512 | return tid.ToString(); |
13513 | } | 13513 | } |
13514 | 13514 | ||
13515 | WithNotecard(assetID, delegate (UUID id, AssetBase a) | 13515 | WithNotecard(assetID, delegate (UUID id, AssetBase a) |
13516 | { | 13516 | { |
13517 | if (a == null || a.Type != 7) | 13517 | if (a == null || a.Type != 7) |
13518 | { | 13518 | { |
13519 | Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); | 13519 | Error("llGetNotecardLine", "Can't find notecard '" + name + "'"); |
13520 | return; | 13520 | return; |
13521 | } | 13521 | } |
13522 | 13522 | ||
13523 | string data = Encoding.UTF8.GetString(a.Data); | 13523 | string data = Encoding.UTF8.GetString(a.Data); |
13524 | //m_log.Debug(data); | 13524 | //m_log.Debug(data); |
13525 | NotecardCache.Cache(id, a.Data); | 13525 | NotecardCache.Cache(id, a.Data); |
13526 | AsyncCommands.DataserverPlugin.DataserverReply( | 13526 | AsyncCommands.DataserverPlugin.DataserverReply( |
13527 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); | 13527 | reqIdentifier, NotecardCache.GetLine(assetID, line, m_notecardLineReadCharsMax)); |
13528 | }); | 13528 | }); |
13529 | 13529 | ||
13530 | ScriptSleep(m_sleepMsOnGetNotecardLine); | 13530 | ScriptSleep(m_sleepMsOnGetNotecardLine); |
13531 | return tid.ToString(); | 13531 | return tid.ToString(); |
13532 | } | 13532 | } |
13533 | 13533 | ||
13534 | public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) | 13534 | public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) |
13535 | { | 13535 | { |
13536 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); | 13536 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); |
13537 | if (obj == null) | 13537 | if (obj == null) |
13538 | return; | 13538 | return; |
13539 | 13539 | ||
13540 | if (obj.OwnerID != m_host.OwnerID) | 13540 | if (obj.OwnerID != m_host.OwnerID) |
13541 | return; | 13541 | return; |
13542 | 13542 | ||
13543 | SetEntityParams(new List<ISceneEntity>() { obj }, rules, originFunc); | 13543 | SetEntityParams(new List<ISceneEntity>() { obj }, rules, originFunc); |
13544 | } | 13544 | } |
13545 | 13545 | ||
13546 | public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) | 13546 | public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) |
13547 | { | 13547 | { |
13548 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); | 13548 | SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); |
13549 | 13549 | ||
13550 | if (obj != null && obj.OwnerID == m_host.OwnerID) | 13550 | if (obj != null && obj.OwnerID == m_host.OwnerID) |
13551 | return GetEntityParams(obj, rules); | 13551 | return GetEntityParams(obj, rules); |
13552 | 13552 | ||
13553 | return new LSL_List(); | 13553 | return new LSL_List(); |
13554 | } | 13554 | } |
13555 | 13555 | ||
13556 | public void print(string str) | 13556 | public void print(string str) |
13557 | { | 13557 | { |
13558 | // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print | 13558 | // yes, this is a real LSL function. See: http://wiki.secondlife.com/wiki/Print |
13559 | IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); | 13559 | IOSSL_Api ossl = (IOSSL_Api)m_ScriptEngine.GetApi(m_item.ItemID, "OSSL"); |
13560 | if (ossl != null) | 13560 | if (ossl != null) |
13561 | { | 13561 | { |
13562 | ossl.CheckThreatLevel(ThreatLevel.High, "print"); | 13562 | ossl.CheckThreatLevel(ThreatLevel.High, "print"); |
13563 | m_log.Info("LSL print():" + str); | 13563 | m_log.Info("LSL print():" + str); |
13564 | } | 13564 | } |
13565 | } | 13565 | } |
13566 | 13566 | ||
13567 | private string Name2Username(string name) | 13567 | private string Name2Username(string name) |
13568 | { | 13568 | { |
13569 | string[] parts = name.Split(new char[] {' '}); | 13569 | string[] parts = name.Split(new char[] {' '}); |
13570 | if (parts.Length < 2) | 13570 | if (parts.Length < 2) |
13571 | return name.ToLower(); | 13571 | return name.ToLower(); |
13572 | if (parts[1] == "Resident") | 13572 | if (parts[1] == "Resident") |
13573 | return parts[0].ToLower(); | 13573 | return parts[0].ToLower(); |
13574 | 13574 | ||
13575 | return name.Replace(" ", ".").ToLower(); | 13575 | return name.Replace(" ", ".").ToLower(); |
13576 | } | 13576 | } |
13577 | 13577 | ||
13578 | public LSL_String llGetUsername(string id) | 13578 | public LSL_String llGetUsername(string id) |
13579 | { | 13579 | { |
13580 | return Name2Username(llKey2Name(id)); | 13580 | return Name2Username(llKey2Name(id)); |
13581 | } | 13581 | } |
13582 | 13582 | ||
13583 | public LSL_String llRequestUsername(string id) | 13583 | public LSL_String llRequestUsername(string id) |
13584 | { | 13584 | { |
13585 | UUID rq = UUID.Random(); | 13585 | UUID rq = UUID.Random(); |
13586 | 13586 | ||
13587 | AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); | 13587 | AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); |
13588 | 13588 | ||
13589 | AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id))); | 13589 | AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), Name2Username(llKey2Name(id))); |
13590 | 13590 | ||
13591 | return rq.ToString(); | 13591 | return rq.ToString(); |
13592 | } | 13592 | } |
13593 | 13593 | ||
13594 | public LSL_String llGetDisplayName(string id) | 13594 | public LSL_String llGetDisplayName(string id) |
13595 | { | 13595 | { |
13596 | return llKey2Name(id); | 13596 | return llKey2Name(id); |
13597 | } | 13597 | } |
13598 | 13598 | ||
13599 | public LSL_String llRequestDisplayName(string id) | 13599 | public LSL_String llRequestDisplayName(string id) |
13600 | { | 13600 | { |
13601 | UUID rq = UUID.Random(); | 13601 | UUID rq = UUID.Random(); |
13602 | 13602 | ||
13603 | AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); | 13603 | AsyncCommands.DataserverPlugin.RegisterRequest(m_host.LocalId, m_item.ItemID, rq.ToString()); |
13604 | 13604 | ||
13605 | AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id)); | 13605 | AsyncCommands.DataserverPlugin.DataserverReply(rq.ToString(), llKey2Name(id)); |
13606 | 13606 | ||
13607 | return rq.ToString(); | 13607 | return rq.ToString(); |
13608 | } | 13608 | } |
13609 | 13609 | ||
13610 | private struct Tri | 13610 | private struct Tri |
13611 | { | 13611 | { |
13612 | public Vector3 p1; | 13612 | public Vector3 p1; |
13613 | public Vector3 p2; | 13613 | public Vector3 p2; |
13614 | public Vector3 p3; | 13614 | public Vector3 p3; |
13615 | } | 13615 | } |
13616 | 13616 | ||
13617 | private bool InBoundingBox(ScenePresence avatar, Vector3 point) | 13617 | private bool InBoundingBox(ScenePresence avatar, Vector3 point) |
13618 | { | 13618 | { |
13619 | float height = avatar.Appearance.AvatarHeight; | 13619 | float height = avatar.Appearance.AvatarHeight; |
13620 | Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2); | 13620 | Vector3 b1 = avatar.AbsolutePosition + new Vector3(-0.22f, -0.22f, -height/2); |
13621 | Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2); | 13621 | Vector3 b2 = avatar.AbsolutePosition + new Vector3(0.22f, 0.22f, height/2); |
13622 | 13622 | ||
13623 | if (point.X > b1.X && point.X < b2.X && | 13623 | if (point.X > b1.X && point.X < b2.X && |
13624 | point.Y > b1.Y && point.Y < b2.Y && | 13624 | point.Y > b1.Y && point.Y < b2.Y && |
13625 | point.Z > b1.Z && point.Z < b2.Z) | 13625 | point.Z > b1.Z && point.Z < b2.Z) |
13626 | return true; | 13626 | return true; |
13627 | return false; | 13627 | return false; |
13628 | } | 13628 | } |
13629 | 13629 | ||
13630 | private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd) | 13630 | private ContactResult[] AvatarIntersection(Vector3 rayStart, Vector3 rayEnd) |
13631 | { | 13631 | { |
13632 | List<ContactResult> contacts = new List<ContactResult>(); | 13632 | List<ContactResult> contacts = new List<ContactResult>(); |
13633 | 13633 | ||
13634 | Vector3 ab = rayEnd - rayStart; | 13634 | Vector3 ab = rayEnd - rayStart; |
13635 | 13635 | ||
13636 | World.ForEachScenePresence(delegate(ScenePresence sp) | 13636 | World.ForEachScenePresence(delegate(ScenePresence sp) |
13637 | { | 13637 | { |
13638 | Vector3 ac = sp.AbsolutePosition - rayStart; | 13638 | Vector3 ac = sp.AbsolutePosition - rayStart; |
13639 | // Vector3 bc = sp.AbsolutePosition - rayEnd; | 13639 | // Vector3 bc = sp.AbsolutePosition - rayEnd; |
13640 | 13640 | ||
13641 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | 13641 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); |
13642 | 13642 | ||
13643 | if (d > 1.5) | 13643 | if (d > 1.5) |
13644 | return; | 13644 | return; |
13645 | 13645 | ||
13646 | double d2 = Vector3.Dot(Vector3.Negate(ab), ac); | 13646 | double d2 = Vector3.Dot(Vector3.Negate(ab), ac); |
13647 | 13647 | ||
13648 | if (d2 > 0) | 13648 | if (d2 > 0) |
13649 | return; | 13649 | return; |
13650 | 13650 | ||
13651 | double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d); | 13651 | double dp = Math.Sqrt(Vector3.Mag(ac) * Vector3.Mag(ac) - d * d); |
13652 | Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab)); | 13652 | Vector3 p = rayStart + Vector3.Divide(Vector3.Multiply(ab, (float)dp), (float)Vector3.Mag(ab)); |
13653 | 13653 | ||
13654 | if (!InBoundingBox(sp, p)) | 13654 | if (!InBoundingBox(sp, p)) |
13655 | return; | 13655 | return; |
13656 | 13656 | ||
13657 | ContactResult result = new ContactResult (); | 13657 | ContactResult result = new ContactResult (); |
13658 | result.ConsumerID = sp.LocalId; | 13658 | result.ConsumerID = sp.LocalId; |
13659 | result.Depth = Vector3.Distance(rayStart, p); | 13659 | result.Depth = Vector3.Distance(rayStart, p); |
13660 | result.Normal = Vector3.Zero; | 13660 | result.Normal = Vector3.Zero; |
13661 | result.Pos = p; | 13661 | result.Pos = p; |
13662 | 13662 | ||
13663 | contacts.Add(result); | 13663 | contacts.Add(result); |
13664 | }); | 13664 | }); |
13665 | 13665 | ||
13666 | return contacts.ToArray(); | 13666 | return contacts.ToArray(); |
13667 | } | 13667 | } |
13668 | 13668 | ||
13669 | private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom) | 13669 | private ContactResult[] ObjectIntersection(Vector3 rayStart, Vector3 rayEnd, bool includePhysical, bool includeNonPhysical, bool includePhantom) |
13670 | { | 13670 | { |
13671 | Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); | 13671 | Ray ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); |
13672 | List<ContactResult> contacts = new List<ContactResult>(); | 13672 | List<ContactResult> contacts = new List<ContactResult>(); |
13673 | 13673 | ||
13674 | Vector3 ab = rayEnd - rayStart; | 13674 | Vector3 ab = rayEnd - rayStart; |
13675 | 13675 | ||
13676 | World.ForEachSOG(delegate(SceneObjectGroup group) | 13676 | World.ForEachSOG(delegate(SceneObjectGroup group) |
13677 | { | 13677 | { |
13678 | if (m_host.ParentGroup == group) | 13678 | if (m_host.ParentGroup == group) |
13679 | return; | 13679 | return; |
13680 | 13680 | ||
13681 | if (group.IsAttachment) | 13681 | if (group.IsAttachment) |
13682 | return; | 13682 | return; |
13683 | 13683 | ||
13684 | if (group.RootPart.PhysActor == null) | 13684 | if (group.RootPart.PhysActor == null) |
13685 | { | 13685 | { |
13686 | if (!includePhantom) | 13686 | if (!includePhantom) |
13687 | return; | 13687 | return; |
13688 | } | 13688 | } |
13689 | else | 13689 | else |
13690 | { | 13690 | { |
13691 | if (group.RootPart.PhysActor.IsPhysical) | 13691 | if (group.RootPart.PhysActor.IsPhysical) |
13692 | { | 13692 | { |
13693 | if (!includePhysical) | 13693 | if (!includePhysical) |
13694 | return; | 13694 | return; |
13695 | } | 13695 | } |
13696 | else | 13696 | else |
13697 | { | 13697 | { |
13698 | if (!includeNonPhysical) | 13698 | if (!includeNonPhysical) |
13699 | return; | 13699 | return; |
13700 | } | 13700 | } |
13701 | } | 13701 | } |
13702 | 13702 | ||
13703 | // Find the radius ouside of which we don't even need to hit test | 13703 | // Find the radius ouside of which we don't even need to hit test |
13704 | float minX; | 13704 | float minX; |
13705 | float maxX; | 13705 | float maxX; |
13706 | float minY; | 13706 | float minY; |
13707 | float maxY; | 13707 | float maxY; |
13708 | float minZ; | 13708 | float minZ; |
13709 | float maxZ; | 13709 | float maxZ; |
13710 | 13710 | ||
13711 | float radius = 0.0f; | 13711 | float radius = 0.0f; |
13712 | 13712 | ||
13713 | group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ); | 13713 | group.GetAxisAlignedBoundingBoxRaw(out minX, out maxX, out minY, out maxY, out minZ, out maxZ); |
13714 | 13714 | ||
13715 | if (Math.Abs(minX) > radius) | 13715 | if (Math.Abs(minX) > radius) |
13716 | radius = Math.Abs(minX); | 13716 | radius = Math.Abs(minX); |
13717 | if (Math.Abs(minY) > radius) | 13717 | if (Math.Abs(minY) > radius) |
13718 | radius = Math.Abs(minY); | 13718 | radius = Math.Abs(minY); |
13719 | if (Math.Abs(minZ) > radius) | 13719 | if (Math.Abs(minZ) > radius) |
13720 | radius = Math.Abs(minZ); | 13720 | radius = Math.Abs(minZ); |
13721 | if (Math.Abs(maxX) > radius) | 13721 | if (Math.Abs(maxX) > radius) |
13722 | radius = Math.Abs(maxX); | 13722 | radius = Math.Abs(maxX); |
13723 | if (Math.Abs(maxY) > radius) | 13723 | if (Math.Abs(maxY) > radius) |
13724 | radius = Math.Abs(maxY); | 13724 | radius = Math.Abs(maxY); |
13725 | if (Math.Abs(maxZ) > radius) | 13725 | if (Math.Abs(maxZ) > radius) |
13726 | radius = Math.Abs(maxZ); | 13726 | radius = Math.Abs(maxZ); |
13727 | radius = radius*1.413f; | 13727 | radius = radius*1.413f; |
13728 | Vector3 ac = group.AbsolutePosition - rayStart; | 13728 | Vector3 ac = group.AbsolutePosition - rayStart; |
13729 | // Vector3 bc = group.AbsolutePosition - rayEnd; | 13729 | // Vector3 bc = group.AbsolutePosition - rayEnd; |
13730 | 13730 | ||
13731 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); | 13731 | double d = Math.Abs(Vector3.Mag(Vector3.Cross(ab, ac)) / Vector3.Distance(rayStart, rayEnd)); |
13732 | 13732 | ||
13733 | // Too far off ray, don't bother | 13733 | // Too far off ray, don't bother |
13734 | if (d > radius) | 13734 | if (d > radius) |
13735 | return; | 13735 | return; |
13736 | 13736 | ||
13737 | // Behind ray, drop | 13737 | // Behind ray, drop |
13738 | double d2 = Vector3.Dot(Vector3.Negate(ab), ac); | 13738 | double d2 = Vector3.Dot(Vector3.Negate(ab), ac); |
13739 | if (d2 > 0) | 13739 | if (d2 > 0) |
13740 | return; | 13740 | return; |
13741 | 13741 | ||
13742 | ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); | 13742 | ray = new Ray(rayStart, Vector3.Normalize(rayEnd - rayStart)); |
13743 | EntityIntersection intersection = group.TestIntersection(ray, true, false); | 13743 | EntityIntersection intersection = group.TestIntersection(ray, true, false); |
13744 | // Miss. | 13744 | // Miss. |
13745 | if (!intersection.HitTF) | 13745 | if (!intersection.HitTF) |
13746 | return; | 13746 | return; |
13747 | 13747 | ||
13748 | Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ); | 13748 | Vector3 b1 = group.AbsolutePosition + new Vector3(minX, minY, minZ); |
13749 | Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ); | 13749 | Vector3 b2 = group.AbsolutePosition + new Vector3(maxX, maxY, maxZ); |
13750 | //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z); | 13750 | //m_log.DebugFormat("[LLCASTRAY]: min<{0},{1},{2}>, max<{3},{4},{5}> = hitp<{6},{7},{8}>", b1.X,b1.Y,b1.Z,b2.X,b2.Y,b2.Z,intersection.ipoint.X,intersection.ipoint.Y,intersection.ipoint.Z); |
13751 | if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X && | 13751 | if (!(intersection.ipoint.X >= b1.X && intersection.ipoint.X <= b2.X && |
13752 | intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y && | 13752 | intersection.ipoint.Y >= b1.Y && intersection.ipoint.Y <= b2.Y && |
13753 | intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z)) | 13753 | intersection.ipoint.Z >= b1.Z && intersection.ipoint.Z <= b2.Z)) |
13754 | return; | 13754 | return; |
13755 | 13755 | ||
13756 | ContactResult result = new ContactResult (); | 13756 | ContactResult result = new ContactResult (); |
13757 | result.ConsumerID = group.LocalId; | 13757 | result.ConsumerID = group.LocalId; |
13758 | result.Depth = intersection.distance; | 13758 | result.Depth = intersection.distance; |
13759 | result.Normal = intersection.normal; | 13759 | result.Normal = intersection.normal; |
13760 | result.Pos = intersection.ipoint; | 13760 | result.Pos = intersection.ipoint; |
13761 | 13761 | ||
13762 | contacts.Add(result); | 13762 | contacts.Add(result); |
13763 | }); | 13763 | }); |
13764 | 13764 | ||
13765 | return contacts.ToArray(); | 13765 | return contacts.ToArray(); |
13766 | } | 13766 | } |
13767 | 13767 | ||
13768 | private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd) | 13768 | private ContactResult? GroundIntersection(Vector3 rayStart, Vector3 rayEnd) |
13769 | { | 13769 | { |
13770 | double[,] heightfield = World.Heightmap.GetDoubles(); | 13770 | double[,] heightfield = World.Heightmap.GetDoubles(); |
13771 | List<ContactResult> contacts = new List<ContactResult>(); | 13771 | List<ContactResult> contacts = new List<ContactResult>(); |
13772 | 13772 | ||
13773 | double min = 2048.0; | 13773 | double min = 2048.0; |
13774 | double max = 0.0; | 13774 | double max = 0.0; |
13775 | 13775 | ||
13776 | // Find the min and max of the heightfield | 13776 | // Find the min and max of the heightfield |
13777 | for (int x = 0 ; x < World.Heightmap.Width ; x++) | 13777 | for (int x = 0 ; x < World.Heightmap.Width ; x++) |
13778 | { | 13778 | { |
13779 | for (int y = 0 ; y < World.Heightmap.Height ; y++) | 13779 | for (int y = 0 ; y < World.Heightmap.Height ; y++) |
13780 | { | 13780 | { |
13781 | if (heightfield[x, y] > max) | 13781 | if (heightfield[x, y] > max) |
13782 | max = heightfield[x, y]; | 13782 | max = heightfield[x, y]; |
13783 | if (heightfield[x, y] < min) | 13783 | if (heightfield[x, y] < min) |
13784 | min = heightfield[x, y]; | 13784 | min = heightfield[x, y]; |
13785 | } | 13785 | } |
13786 | } | 13786 | } |
13787 | 13787 | ||
13788 | 13788 | ||
13789 | // A ray extends past rayEnd, but doesn't go back before | 13789 | // A ray extends past rayEnd, but doesn't go back before |
13790 | // rayStart. If the start is above the highest point of the ground | 13790 | // rayStart. If the start is above the highest point of the ground |
13791 | // and the ray goes up, we can't hit the ground. Ever. | 13791 | // and the ray goes up, we can't hit the ground. Ever. |
13792 | if (rayStart.Z > max && rayEnd.Z >= rayStart.Z) | 13792 | if (rayStart.Z > max && rayEnd.Z >= rayStart.Z) |
13793 | return null; | 13793 | return null; |
13794 | 13794 | ||
13795 | // Same for going down | 13795 | // Same for going down |
13796 | if (rayStart.Z < min && rayEnd.Z <= rayStart.Z) | 13796 | if (rayStart.Z < min && rayEnd.Z <= rayStart.Z) |
13797 | return null; | 13797 | return null; |
13798 | 13798 | ||
13799 | List<Tri> trilist = new List<Tri>(); | 13799 | List<Tri> trilist = new List<Tri>(); |
13800 | 13800 | ||
13801 | // Create our triangle list | 13801 | // Create our triangle list |
13802 | for (int x = 1 ; x < World.Heightmap.Width ; x++) | 13802 | for (int x = 1 ; x < World.Heightmap.Width ; x++) |
13803 | { | 13803 | { |
13804 | for (int y = 1 ; y < World.Heightmap.Height ; y++) | 13804 | for (int y = 1 ; y < World.Heightmap.Height ; y++) |
13805 | { | 13805 | { |
13806 | Tri t1 = new Tri(); | 13806 | Tri t1 = new Tri(); |
13807 | Tri t2 = new Tri(); | 13807 | Tri t2 = new Tri(); |
13808 | 13808 | ||
13809 | Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]); | 13809 | Vector3 p1 = new Vector3(x-1, y-1, (float)heightfield[x-1, y-1]); |
13810 | Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]); | 13810 | Vector3 p2 = new Vector3(x, y-1, (float)heightfield[x, y-1]); |
13811 | Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]); | 13811 | Vector3 p3 = new Vector3(x, y, (float)heightfield[x, y]); |
13812 | Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]); | 13812 | Vector3 p4 = new Vector3(x-1, y, (float)heightfield[x-1, y]); |
13813 | 13813 | ||
13814 | t1.p1 = p1; | 13814 | t1.p1 = p1; |
13815 | t1.p2 = p2; | 13815 | t1.p2 = p2; |
13816 | t1.p3 = p3; | 13816 | t1.p3 = p3; |
13817 | 13817 | ||
13818 | t2.p1 = p3; | 13818 | t2.p1 = p3; |
13819 | t2.p2 = p4; | 13819 | t2.p2 = p4; |
13820 | t2.p3 = p1; | 13820 | t2.p3 = p1; |
13821 | 13821 | ||
13822 | trilist.Add(t1); | 13822 | trilist.Add(t1); |
13823 | trilist.Add(t2); | 13823 | trilist.Add(t2); |
13824 | } | 13824 | } |
13825 | } | 13825 | } |
13826 | 13826 | ||
13827 | // Ray direction | 13827 | // Ray direction |
13828 | Vector3 rayDirection = rayEnd - rayStart; | 13828 | Vector3 rayDirection = rayEnd - rayStart; |
13829 | 13829 | ||
13830 | foreach (Tri t in trilist) | 13830 | foreach (Tri t in trilist) |
13831 | { | 13831 | { |
13832 | // Compute triangle plane normal and edges | 13832 | // Compute triangle plane normal and edges |
13833 | Vector3 u = t.p2 - t.p1; | 13833 | Vector3 u = t.p2 - t.p1; |
13834 | Vector3 v = t.p3 - t.p1; | 13834 | Vector3 v = t.p3 - t.p1; |
13835 | Vector3 n = Vector3.Cross(u, v); | 13835 | Vector3 n = Vector3.Cross(u, v); |
13836 | 13836 | ||
13837 | if (n == Vector3.Zero) | 13837 | if (n == Vector3.Zero) |
13838 | continue; | 13838 | continue; |
13839 | 13839 | ||
13840 | Vector3 w0 = rayStart - t.p1; | 13840 | Vector3 w0 = rayStart - t.p1; |
13841 | double a = -Vector3.Dot(n, w0); | 13841 | double a = -Vector3.Dot(n, w0); |
13842 | double b = Vector3.Dot(n, rayDirection); | 13842 | double b = Vector3.Dot(n, rayDirection); |
13843 | 13843 | ||
13844 | // Not intersecting the plane, or in plane (same thing) | 13844 | // Not intersecting the plane, or in plane (same thing) |
13845 | // Ignoring this MAY cause the ground to not be detected | 13845 | // Ignoring this MAY cause the ground to not be detected |
13846 | // sometimes | 13846 | // sometimes |
13847 | if (Math.Abs(b) < 0.000001) | 13847 | if (Math.Abs(b) < 0.000001) |
13848 | continue; | 13848 | continue; |
13849 | 13849 | ||
13850 | double r = a / b; | 13850 | double r = a / b; |
13851 | 13851 | ||
13852 | // ray points away from plane | 13852 | // ray points away from plane |
13853 | if (r < 0.0) | 13853 | if (r < 0.0) |
13854 | continue; | 13854 | continue; |
13855 | 13855 | ||
13856 | Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r); | 13856 | Vector3 ip = rayStart + Vector3.Multiply(rayDirection, (float)r); |
13857 | 13857 | ||
13858 | float uu = Vector3.Dot(u, u); | 13858 | float uu = Vector3.Dot(u, u); |
13859 | float uv = Vector3.Dot(u, v); | 13859 | float uv = Vector3.Dot(u, v); |
13860 | float vv = Vector3.Dot(v, v); | 13860 | float vv = Vector3.Dot(v, v); |
13861 | Vector3 w = ip - t.p1; | 13861 | Vector3 w = ip - t.p1; |
13862 | float wu = Vector3.Dot(w, u); | 13862 | float wu = Vector3.Dot(w, u); |
13863 | float wv = Vector3.Dot(w, v); | 13863 | float wv = Vector3.Dot(w, v); |
13864 | float d = uv * uv - uu * vv; | 13864 | float d = uv * uv - uu * vv; |
13865 | 13865 | ||
13866 | float cs = (uv * wv - vv * wu) / d; | 13866 | float cs = (uv * wv - vv * wu) / d; |
13867 | if (cs < 0 || cs > 1.0) | 13867 | if (cs < 0 || cs > 1.0) |
13868 | continue; | 13868 | continue; |
13869 | float ct = (uv * wu - uu * wv) / d; | 13869 | float ct = (uv * wu - uu * wv) / d; |
13870 | if (ct < 0 || (cs + ct) > 1.0) | 13870 | if (ct < 0 || (cs + ct) > 1.0) |
13871 | continue; | 13871 | continue; |
13872 | 13872 | ||
13873 | // Add contact point | 13873 | // Add contact point |
13874 | ContactResult result = new ContactResult (); | 13874 | ContactResult result = new ContactResult (); |
13875 | result.ConsumerID = 0; | 13875 | result.ConsumerID = 0; |
13876 | result.Depth = Vector3.Distance(rayStart, ip); | 13876 | result.Depth = Vector3.Distance(rayStart, ip); |
13877 | result.Normal = n; | 13877 | result.Normal = n; |
13878 | result.Pos = ip; | 13878 | result.Pos = ip; |
13879 | 13879 | ||
13880 | contacts.Add(result); | 13880 | contacts.Add(result); |
13881 | } | 13881 | } |
13882 | 13882 | ||
13883 | if (contacts.Count == 0) | 13883 | if (contacts.Count == 0) |
13884 | return null; | 13884 | return null; |
13885 | 13885 | ||
13886 | contacts.Sort(delegate(ContactResult a, ContactResult b) | 13886 | contacts.Sort(delegate(ContactResult a, ContactResult b) |
13887 | { | 13887 | { |
13888 | return (int)(a.Depth - b.Depth); | 13888 | return (int)(a.Depth - b.Depth); |
13889 | }); | 13889 | }); |
13890 | 13890 | ||
13891 | return contacts[0]; | 13891 | return contacts[0]; |
13892 | } | 13892 | } |
13893 | 13893 | ||
13894 | public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) | 13894 | public LSL_List llCastRay(LSL_Vector start, LSL_Vector end, LSL_List options) |
13895 | { | 13895 | { |
13896 | // Use llCastRay V3 if configured | 13896 | // Use llCastRay V3 if configured |
13897 | if (m_useCastRayV3) | 13897 | if (m_useCastRayV3) |
13898 | return llCastRayV3(start, end, options); | 13898 | return llCastRayV3(start, end, options); |
13899 | 13899 | ||
13900 | LSL_List list = new LSL_List(); | 13900 | LSL_List list = new LSL_List(); |
13901 | 13901 | ||
13902 | m_host.AddScriptLPS(1); | 13902 | m_host.AddScriptLPS(1); |
13903 | 13903 | ||
13904 | Vector3 rayStart = start; | 13904 | Vector3 rayStart = start; |
13905 | Vector3 rayEnd = end; | 13905 | Vector3 rayEnd = end; |
13906 | Vector3 dir = rayEnd - rayStart; | 13906 | Vector3 dir = rayEnd - rayStart; |
13907 | 13907 | ||
13908 | float dist = Vector3.Mag(dir); | 13908 | float dist = Vector3.Mag(dir); |
13909 | 13909 | ||
13910 | int count = 1; | 13910 | int count = 1; |
13911 | bool detectPhantom = false; | 13911 | bool detectPhantom = false; |
13912 | int dataFlags = 0; | 13912 | int dataFlags = 0; |
13913 | int rejectTypes = 0; | 13913 | int rejectTypes = 0; |
13914 | 13914 | ||
13915 | for (int i = 0; i < options.Length; i += 2) | 13915 | for (int i = 0; i < options.Length; i += 2) |
13916 | { | 13916 | { |
13917 | if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) | 13917 | if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) |
13918 | count = options.GetLSLIntegerItem(i + 1); | 13918 | count = options.GetLSLIntegerItem(i + 1); |
13919 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) | 13919 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) |
13920 | detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0); | 13920 | detectPhantom = (options.GetLSLIntegerItem(i + 1) > 0); |
13921 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) | 13921 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) |
13922 | dataFlags = options.GetLSLIntegerItem(i + 1); | 13922 | dataFlags = options.GetLSLIntegerItem(i + 1); |
13923 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) | 13923 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) |
13924 | rejectTypes = options.GetLSLIntegerItem(i + 1); | 13924 | rejectTypes = options.GetLSLIntegerItem(i + 1); |
13925 | } | 13925 | } |
13926 | 13926 | ||
13927 | if (count > 16) | 13927 | if (count > 16) |
13928 | count = 16; | 13928 | count = 16; |
13929 | 13929 | ||
13930 | List<ContactResult> results = new List<ContactResult>(); | 13930 | List<ContactResult> results = new List<ContactResult>(); |
13931 | 13931 | ||
13932 | bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); | 13932 | bool checkTerrain = !((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) == ScriptBaseClass.RC_REJECT_LAND); |
13933 | bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); | 13933 | bool checkAgents = !((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) == ScriptBaseClass.RC_REJECT_AGENTS); |
13934 | bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); | 13934 | bool checkNonPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) == ScriptBaseClass.RC_REJECT_NONPHYSICAL); |
13935 | bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); | 13935 | bool checkPhysical = !((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) == ScriptBaseClass.RC_REJECT_PHYSICAL); |
13936 | 13936 | ||
13937 | 13937 | ||
13938 | if (World.SupportsRayCastFiltered()) | 13938 | if (World.SupportsRayCastFiltered()) |
13939 | { | 13939 | { |
13940 | if (dist == 0) | 13940 | if (dist == 0) |
13941 | return list; | 13941 | return list; |
13942 | 13942 | ||
13943 | RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull; | 13943 | RayFilterFlags rayfilter = RayFilterFlags.ClosestAndBackCull; |
13944 | if (checkTerrain) | 13944 | if (checkTerrain) |
13945 | rayfilter |= RayFilterFlags.land; | 13945 | rayfilter |= RayFilterFlags.land; |
13946 | // if (checkAgents) | 13946 | // if (checkAgents) |
13947 | // rayfilter |= RayFilterFlags.agent; | 13947 | // rayfilter |= RayFilterFlags.agent; |
13948 | if (checkPhysical) | 13948 | if (checkPhysical) |
13949 | rayfilter |= RayFilterFlags.physical; | 13949 | rayfilter |= RayFilterFlags.physical; |
13950 | if (checkNonPhysical) | 13950 | if (checkNonPhysical) |
13951 | rayfilter |= RayFilterFlags.nonphysical; | 13951 | rayfilter |= RayFilterFlags.nonphysical; |
13952 | if (detectPhantom) | 13952 | if (detectPhantom) |
13953 | rayfilter |= RayFilterFlags.LSLPhantom; | 13953 | rayfilter |= RayFilterFlags.LSLPhantom; |
13954 | 13954 | ||
13955 | Vector3 direction = dir * ( 1/dist); | 13955 | Vector3 direction = dir * ( 1/dist); |
13956 | 13956 | ||
13957 | if(rayfilter == 0) | 13957 | if(rayfilter == 0) |
13958 | { | 13958 | { |
13959 | list.Add(new LSL_Integer(0)); | 13959 | list.Add(new LSL_Integer(0)); |
13960 | return list; | 13960 | return list; |
13961 | } | 13961 | } |
13962 | 13962 | ||
13963 | // get some more contacts to sort ??? | 13963 | // get some more contacts to sort ??? |
13964 | int physcount = 4 * count; | 13964 | int physcount = 4 * count; |
13965 | if (physcount > 20) | 13965 | if (physcount > 20) |
13966 | physcount = 20; | 13966 | physcount = 20; |
13967 | 13967 | ||
13968 | object physresults; | 13968 | object physresults; |
13969 | physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter); | 13969 | physresults = World.RayCastFiltered(rayStart, direction, dist, physcount, rayfilter); |
13970 | 13970 | ||
13971 | if (physresults == null) | 13971 | if (physresults == null) |
13972 | { | 13972 | { |
13973 | list.Add(new LSL_Integer(-3)); // timeout error | 13973 | list.Add(new LSL_Integer(-3)); // timeout error |
13974 | return list; | 13974 | return list; |
13975 | } | 13975 | } |
13976 | 13976 | ||
13977 | results = (List<ContactResult>)physresults; | 13977 | results = (List<ContactResult>)physresults; |
13978 | 13978 | ||
13979 | // for now physics doesn't detect sitted avatars so do it outside physics | 13979 | // for now physics doesn't detect sitted avatars so do it outside physics |
13980 | if (checkAgents) | 13980 | if (checkAgents) |
13981 | { | 13981 | { |
13982 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); | 13982 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); |
13983 | foreach (ContactResult r in agentHits) | 13983 | foreach (ContactResult r in agentHits) |
13984 | results.Add(r); | 13984 | results.Add(r); |
13985 | } | 13985 | } |
13986 | 13986 | ||
13987 | // TODO: Replace this with a better solution. ObjectIntersection can only | 13987 | // TODO: Replace this with a better solution. ObjectIntersection can only |
13988 | // detect nonphysical phantoms. They are detected by virtue of being | 13988 | // detect nonphysical phantoms. They are detected by virtue of being |
13989 | // nonphysical (e.g. no PhysActor) so will not conflict with detecting | 13989 | // nonphysical (e.g. no PhysActor) so will not conflict with detecting |
13990 | // physicsl phantoms as done by the physics scene | 13990 | // physicsl phantoms as done by the physics scene |
13991 | // We don't want anything else but phantoms here. | 13991 | // We don't want anything else but phantoms here. |
13992 | if (detectPhantom) | 13992 | if (detectPhantom) |
13993 | { | 13993 | { |
13994 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true); | 13994 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, false, false, true); |
13995 | foreach (ContactResult r in objectHits) | 13995 | foreach (ContactResult r in objectHits) |
13996 | results.Add(r); | 13996 | results.Add(r); |
13997 | } | 13997 | } |
13998 | } | 13998 | } |
13999 | else | 13999 | else |
14000 | { | 14000 | { |
14001 | if (checkAgents) | 14001 | if (checkAgents) |
14002 | { | 14002 | { |
14003 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); | 14003 | ContactResult[] agentHits = AvatarIntersection(rayStart, rayEnd); |
14004 | foreach (ContactResult r in agentHits) | 14004 | foreach (ContactResult r in agentHits) |
14005 | results.Add(r); | 14005 | results.Add(r); |
14006 | } | 14006 | } |
14007 | 14007 | ||
14008 | if (checkPhysical || checkNonPhysical || detectPhantom) | 14008 | if (checkPhysical || checkNonPhysical || detectPhantom) |
14009 | { | 14009 | { |
14010 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); | 14010 | ContactResult[] objectHits = ObjectIntersection(rayStart, rayEnd, checkPhysical, checkNonPhysical, detectPhantom); |
14011 | for (int iter = 0; iter < objectHits.Length; iter++) | 14011 | for (int iter = 0; iter < objectHits.Length; iter++) |
14012 | { | 14012 | { |
14013 | // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler. | 14013 | // Redistance the Depth because the Scene RayCaster returns distance from center to make the rezzing code simpler. |
14014 | objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart); | 14014 | objectHits[iter].Depth = Vector3.Distance(objectHits[iter].Pos, rayStart); |
14015 | results.Add(objectHits[iter]); | 14015 | results.Add(objectHits[iter]); |
14016 | } | 14016 | } |
14017 | } | 14017 | } |
14018 | } | 14018 | } |
14019 | 14019 | ||
14020 | if (checkTerrain) | 14020 | if (checkTerrain) |
14021 | { | 14021 | { |
14022 | ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); | 14022 | ContactResult? groundContact = GroundIntersection(rayStart, rayEnd); |
14023 | if (groundContact != null) | 14023 | if (groundContact != null) |
14024 | results.Add((ContactResult)groundContact); | 14024 | results.Add((ContactResult)groundContact); |
14025 | } | 14025 | } |
14026 | 14026 | ||
14027 | results.Sort(delegate(ContactResult a, ContactResult b) | 14027 | results.Sort(delegate(ContactResult a, ContactResult b) |
14028 | { | 14028 | { |
14029 | return a.Depth.CompareTo(b.Depth); | 14029 | return a.Depth.CompareTo(b.Depth); |
14030 | }); | 14030 | }); |
14031 | 14031 | ||
14032 | int values = 0; | 14032 | int values = 0; |
14033 | SceneObjectGroup thisgrp = m_host.ParentGroup; | 14033 | SceneObjectGroup thisgrp = m_host.ParentGroup; |
14034 | 14034 | ||
14035 | foreach (ContactResult result in results) | 14035 | foreach (ContactResult result in results) |
14036 | { | 14036 | { |
14037 | if (result.Depth > dist) | 14037 | if (result.Depth > dist) |
14038 | continue; | 14038 | continue; |
14039 | 14039 | ||
14040 | // physics ray can return colisions with host prim | 14040 | // physics ray can return colisions with host prim |
14041 | if (m_host.LocalId == result.ConsumerID) | 14041 | if (m_host.LocalId == result.ConsumerID) |
14042 | continue; | 14042 | continue; |
14043 | 14043 | ||
14044 | UUID itemID = UUID.Zero; | 14044 | UUID itemID = UUID.Zero; |
14045 | int linkNum = 0; | 14045 | int linkNum = 0; |
14046 | 14046 | ||
14047 | SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID); | 14047 | SceneObjectPart part = World.GetSceneObjectPart(result.ConsumerID); |
14048 | // It's a prim! | 14048 | // It's a prim! |
14049 | if (part != null) | 14049 | if (part != null) |
14050 | { | 14050 | { |
14051 | // dont detect members of same object ??? | 14051 | // dont detect members of same object ??? |
14052 | if (part.ParentGroup == thisgrp) | 14052 | if (part.ParentGroup == thisgrp) |
14053 | continue; | 14053 | continue; |
14054 | 14054 | ||
14055 | if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY) | 14055 | if ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) == ScriptBaseClass.RC_GET_ROOT_KEY) |
14056 | itemID = part.ParentGroup.UUID; | 14056 | itemID = part.ParentGroup.UUID; |
14057 | else | 14057 | else |
14058 | itemID = part.UUID; | 14058 | itemID = part.UUID; |
14059 | 14059 | ||
14060 | linkNum = part.LinkNum; | 14060 | linkNum = part.LinkNum; |
14061 | } | 14061 | } |
14062 | else | 14062 | else |
14063 | { | 14063 | { |
14064 | ScenePresence sp = World.GetScenePresence(result.ConsumerID); | 14064 | ScenePresence sp = World.GetScenePresence(result.ConsumerID); |
14065 | /// It it a boy? a girl? | 14065 | /// It it a boy? a girl? |
14066 | if (sp != null) | 14066 | if (sp != null) |
14067 | itemID = sp.UUID; | 14067 | itemID = sp.UUID; |
14068 | } | 14068 | } |
14069 | 14069 | ||
14070 | list.Add(new LSL_String(itemID.ToString())); | 14070 | list.Add(new LSL_String(itemID.ToString())); |
14071 | list.Add(new LSL_String(result.Pos.ToString())); | 14071 | list.Add(new LSL_String(result.Pos.ToString())); |
14072 | 14072 | ||
14073 | if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) | 14073 | if ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) == ScriptBaseClass.RC_GET_LINK_NUM) |
14074 | list.Add(new LSL_Integer(linkNum)); | 14074 | list.Add(new LSL_Integer(linkNum)); |
14075 | 14075 | ||
14076 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) | 14076 | if ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) == ScriptBaseClass.RC_GET_NORMAL) |
14077 | list.Add(new LSL_Vector(result.Normal)); | 14077 | list.Add(new LSL_Vector(result.Normal)); |
14078 | 14078 | ||
14079 | values++; | 14079 | values++; |
14080 | if (values >= count) | 14080 | if (values >= count) |
14081 | break; | 14081 | break; |
14082 | } | 14082 | } |
14083 | 14083 | ||
14084 | list.Add(new LSL_Integer(values)); | 14084 | list.Add(new LSL_Integer(values)); |
14085 | 14085 | ||
14086 | return list; | 14086 | return list; |
14087 | } | 14087 | } |
14088 | 14088 | ||
14089 | /// <summary> | 14089 | /// <summary> |
14090 | /// Implementation of llCastRay similar to SL 2015-04-21. | 14090 | /// Implementation of llCastRay similar to SL 2015-04-21. |
14091 | /// http://wiki.secondlife.com/wiki/LlCastRay | 14091 | /// http://wiki.secondlife.com/wiki/LlCastRay |
14092 | /// Uses pure geometry, bounding shapes, meshing and no physics | 14092 | /// Uses pure geometry, bounding shapes, meshing and no physics |
14093 | /// for prims, sculpts, meshes, avatars and terrain. | 14093 | /// for prims, sculpts, meshes, avatars and terrain. |
14094 | /// Implements all flags, reject types and data flags. | 14094 | /// Implements all flags, reject types and data flags. |
14095 | /// Can handle both objects/groups and prims/parts, by config. | 14095 | /// Can handle both objects/groups and prims/parts, by config. |
14096 | /// May sometimes be inaccurate owing to calculation precision, | 14096 | /// May sometimes be inaccurate owing to calculation precision, |
14097 | /// meshing detail level and a bug in libopenmetaverse PrimMesher. | 14097 | /// meshing detail level and a bug in libopenmetaverse PrimMesher. |
14098 | /// </summary> | 14098 | /// </summary> |
14099 | public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options) | 14099 | public LSL_List llCastRayV3(LSL_Vector start, LSL_Vector end, LSL_List options) |
14100 | { | 14100 | { |
14101 | m_host.AddScriptLPS(1); | 14101 | m_host.AddScriptLPS(1); |
14102 | LSL_List result = new LSL_List(); | 14102 | LSL_List result = new LSL_List(); |
14103 | 14103 | ||
14104 | // Prepare throttle data | 14104 | // Prepare throttle data |
14105 | int calledMs = Environment.TickCount; | 14105 | int calledMs = Environment.TickCount; |
14106 | Stopwatch stopWatch = new Stopwatch(); | 14106 | Stopwatch stopWatch = new Stopwatch(); |
14107 | stopWatch.Start(); | 14107 | stopWatch.Start(); |
14108 | UUID regionId = World.RegionInfo.RegionID; | 14108 | UUID regionId = World.RegionInfo.RegionID; |
14109 | UUID userId = UUID.Zero; | 14109 | UUID userId = UUID.Zero; |
14110 | int msAvailable = 0; | 14110 | int msAvailable = 0; |
14111 | // Throttle per owner when attachment or "vehicle" (sat upon) | 14111 | // Throttle per owner when attachment or "vehicle" (sat upon) |
14112 | if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0) | 14112 | if (m_host.ParentGroup.IsAttachment || m_host.ParentGroup.GetSittingAvatars().Count > 0) |
14113 | { | 14113 | { |
14114 | userId = m_host.OwnerID; | 14114 | userId = m_host.OwnerID; |
14115 | msAvailable = m_msPerAvatarInCastRay; | 14115 | msAvailable = m_msPerAvatarInCastRay; |
14116 | } | 14116 | } |
14117 | // Throttle per parcel when not attachment or vehicle | 14117 | // Throttle per parcel when not attachment or vehicle |
14118 | else | 14118 | else |
14119 | { | 14119 | { |
14120 | LandData land = World.GetLandData(m_host.GetWorldPosition()); | 14120 | LandData land = World.GetLandData(m_host.GetWorldPosition()); |
14121 | if (land != null) | 14121 | if (land != null) |
14122 | msAvailable = m_msPerRegionInCastRay * land.Area / 65536; | 14122 | msAvailable = m_msPerRegionInCastRay * land.Area / 65536; |
14123 | } | 14123 | } |
14124 | // Clamp for "oversized" parcels on varregions | 14124 | // Clamp for "oversized" parcels on varregions |
14125 | if (msAvailable > m_msMaxInCastRay) | 14125 | if (msAvailable > m_msMaxInCastRay) |
14126 | msAvailable = m_msMaxInCastRay; | 14126 | msAvailable = m_msMaxInCastRay; |
14127 | 14127 | ||
14128 | // Check throttle data | 14128 | // Check throttle data |
14129 | int fromCalledMs = calledMs - m_msThrottleInCastRay; | 14129 | int fromCalledMs = calledMs - m_msThrottleInCastRay; |
14130 | lock (m_castRayCalls) | 14130 | lock (m_castRayCalls) |
14131 | { | 14131 | { |
14132 | for (int i = m_castRayCalls.Count - 1; i >= 0; i--) | 14132 | for (int i = m_castRayCalls.Count - 1; i >= 0; i--) |
14133 | { | 14133 | { |
14134 | // Delete old calls from throttle data | 14134 | // Delete old calls from throttle data |
14135 | if (m_castRayCalls[i].CalledMs < fromCalledMs) | 14135 | if (m_castRayCalls[i].CalledMs < fromCalledMs) |
14136 | m_castRayCalls.RemoveAt(i); | 14136 | m_castRayCalls.RemoveAt(i); |
14137 | // Use current region (in multi-region sims) | 14137 | // Use current region (in multi-region sims) |
14138 | else if (m_castRayCalls[i].RegionId == regionId) | 14138 | else if (m_castRayCalls[i].RegionId == regionId) |
14139 | { | 14139 | { |
14140 | // Reduce available time with recent calls | 14140 | // Reduce available time with recent calls |
14141 | if (m_castRayCalls[i].UserId == userId) | 14141 | if (m_castRayCalls[i].UserId == userId) |
14142 | msAvailable -= m_castRayCalls[i].UsedMs; | 14142 | msAvailable -= m_castRayCalls[i].UsedMs; |
14143 | } | 14143 | } |
14144 | } | 14144 | } |
14145 | } | 14145 | } |
14146 | 14146 | ||
14147 | // Return failure if not enough available time | 14147 | // Return failure if not enough available time |
14148 | if (msAvailable < m_msMinInCastRay) | 14148 | if (msAvailable < m_msMinInCastRay) |
14149 | { | 14149 | { |
14150 | result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED)); | 14150 | result.Add(new LSL_Integer(ScriptBaseClass.RCERR_CAST_TIME_EXCEEDED)); |
14151 | return result; | 14151 | return result; |
14152 | } | 14152 | } |
14153 | 14153 | ||
14154 | // Initialize | 14154 | // Initialize |
14155 | List<RayHit> rayHits = new List<RayHit>(); | 14155 | List<RayHit> rayHits = new List<RayHit>(); |
14156 | float tol = m_floatToleranceInCastRay; | 14156 | float tol = m_floatToleranceInCastRay; |
14157 | Vector3 pos1Ray = start; | 14157 | Vector3 pos1Ray = start; |
14158 | Vector3 pos2Ray = end; | 14158 | Vector3 pos2Ray = end; |
14159 | 14159 | ||
14160 | // Get input options | 14160 | // Get input options |
14161 | int rejectTypes = 0; | 14161 | int rejectTypes = 0; |
14162 | int dataFlags = 0; | 14162 | int dataFlags = 0; |
14163 | int maxHits = 1; | 14163 | int maxHits = 1; |
14164 | bool detectPhantom = false; | 14164 | bool detectPhantom = false; |
14165 | for (int i = 0; i < options.Length; i += 2) | 14165 | for (int i = 0; i < options.Length; i += 2) |
14166 | { | 14166 | { |
14167 | if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) | 14167 | if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_REJECT_TYPES) |
14168 | rejectTypes = options.GetLSLIntegerItem(i + 1); | 14168 | rejectTypes = options.GetLSLIntegerItem(i + 1); |
14169 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) | 14169 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DATA_FLAGS) |
14170 | dataFlags = options.GetLSLIntegerItem(i + 1); | 14170 | dataFlags = options.GetLSLIntegerItem(i + 1); |
14171 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) | 14171 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_MAX_HITS) |
14172 | maxHits = options.GetLSLIntegerItem(i + 1); | 14172 | maxHits = options.GetLSLIntegerItem(i + 1); |
14173 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) | 14173 | else if (options.GetLSLIntegerItem(i) == ScriptBaseClass.RC_DETECT_PHANTOM) |
14174 | detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0); | 14174 | detectPhantom = (options.GetLSLIntegerItem(i + 1) != 0); |
14175 | } | 14175 | } |
14176 | if (maxHits > m_maxHitsInCastRay) | 14176 | if (maxHits > m_maxHitsInCastRay) |
14177 | maxHits = m_maxHitsInCastRay; | 14177 | maxHits = m_maxHitsInCastRay; |
14178 | bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0); | 14178 | bool rejectAgents = ((rejectTypes & ScriptBaseClass.RC_REJECT_AGENTS) != 0); |
14179 | bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0); | 14179 | bool rejectPhysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_PHYSICAL) != 0); |
14180 | bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0); | 14180 | bool rejectNonphysical = ((rejectTypes & ScriptBaseClass.RC_REJECT_NONPHYSICAL) != 0); |
14181 | bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0); | 14181 | bool rejectLand = ((rejectTypes & ScriptBaseClass.RC_REJECT_LAND) != 0); |
14182 | bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0); | 14182 | bool getNormal = ((dataFlags & ScriptBaseClass.RC_GET_NORMAL) != 0); |
14183 | bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0); | 14183 | bool getRootKey = ((dataFlags & ScriptBaseClass.RC_GET_ROOT_KEY) != 0); |
14184 | bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); | 14184 | bool getLinkNum = ((dataFlags & ScriptBaseClass.RC_GET_LINK_NUM) != 0); |
14185 | 14185 | ||
14186 | // Calculate some basic parameters | 14186 | // Calculate some basic parameters |
14187 | Vector3 vecRay = pos2Ray - pos1Ray; | 14187 | Vector3 vecRay = pos2Ray - pos1Ray; |
14188 | float rayLength = vecRay.Length(); | 14188 | float rayLength = vecRay.Length(); |
14189 | 14189 | ||
14190 | // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits | 14190 | // Try to get a mesher and return failure if none, degenerate ray, or max 0 hits |
14191 | IRendering primMesher = null; | 14191 | IRendering primMesher = null; |
14192 | List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); | 14192 | List<string> renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); |
14193 | if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) | 14193 | if (renderers.Count < 1 || rayLength < tol || m_maxHitsInCastRay < 1) |
14194 | { | 14194 | { |
14195 | result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); | 14195 | result.Add(new LSL_Integer(ScriptBaseClass.RCERR_UNKNOWN)); |
14196 | return result; | 14196 | return result; |
14197 | } | 14197 | } |
14198 | primMesher = RenderingLoader.LoadRenderer(renderers[0]); | 14198 | primMesher = RenderingLoader.LoadRenderer(renderers[0]); |
14199 | 14199 | ||
14200 | // Iterate over all objects/groups and prims/parts in region | 14200 | // Iterate over all objects/groups and prims/parts in region |
14201 | World.ForEachSOG( | 14201 | World.ForEachSOG( |
14202 | delegate(SceneObjectGroup group) | 14202 | delegate(SceneObjectGroup group) |
14203 | { | 14203 | { |
14204 | // Check group filters unless part filters are configured | 14204 | // Check group filters unless part filters are configured |
14205 | bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical); | 14205 | bool isPhysical = (group.RootPart != null && group.RootPart.PhysActor != null && group.RootPart.PhysActor.IsPhysical); |
14206 | bool isNonphysical = !isPhysical; | 14206 | bool isNonphysical = !isPhysical; |
14207 | bool isPhantom = group.IsPhantom || group.IsVolumeDetect; | 14207 | bool isPhantom = group.IsPhantom || group.IsVolumeDetect; |
14208 | bool isAttachment = group.IsAttachment; | 14208 | bool isAttachment = group.IsAttachment; |
14209 | bool doGroup = true; | 14209 | bool doGroup = true; |
14210 | if (isPhysical && rejectPhysical) | 14210 | if (isPhysical && rejectPhysical) |
14211 | doGroup = false; | 14211 | doGroup = false; |
14212 | if (isNonphysical && rejectNonphysical) | 14212 | if (isNonphysical && rejectNonphysical) |
14213 | doGroup = false; | 14213 | doGroup = false; |
14214 | if (isPhantom && detectPhantom) | 14214 | if (isPhantom && detectPhantom) |
14215 | doGroup = true; | 14215 | doGroup = true; |
14216 | if (m_filterPartsInCastRay) | 14216 | if (m_filterPartsInCastRay) |
14217 | doGroup = true; | 14217 | doGroup = true; |
14218 | if (isAttachment && !m_doAttachmentsInCastRay) | 14218 | if (isAttachment && !m_doAttachmentsInCastRay) |
14219 | doGroup = false; | 14219 | doGroup = false; |
14220 | // Parse object/group if passed filters | 14220 | // Parse object/group if passed filters |
14221 | if (doGroup) | 14221 | if (doGroup) |
14222 | { | 14222 | { |
14223 | // Iterate over all prims/parts in object/group | 14223 | // Iterate over all prims/parts in object/group |
14224 | foreach(SceneObjectPart part in group.Parts) | 14224 | foreach(SceneObjectPart part in group.Parts) |
14225 | { | 14225 | { |
14226 | // Check part filters if configured | 14226 | // Check part filters if configured |
14227 | if (m_filterPartsInCastRay) | 14227 | if (m_filterPartsInCastRay) |
14228 | { | 14228 | { |
14229 | isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical); | 14229 | isPhysical = (part.PhysActor != null && part.PhysActor.IsPhysical); |
14230 | isNonphysical = !isPhysical; | 14230 | isNonphysical = !isPhysical; |
14231 | isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive); | 14231 | isPhantom = ((part.Flags & PrimFlags.Phantom) != 0) || (part.VolumeDetectActive); |
14232 | bool doPart = true; | 14232 | bool doPart = true; |
14233 | if (isPhysical && rejectPhysical) | 14233 | if (isPhysical && rejectPhysical) |
14234 | doPart = false; | 14234 | doPart = false; |
14235 | if (isNonphysical && rejectNonphysical) | 14235 | if (isNonphysical && rejectNonphysical) |
14236 | doPart = false; | 14236 | doPart = false; |
14237 | if (isPhantom && detectPhantom) | 14237 | if (isPhantom && detectPhantom) |
14238 | doPart = true; | 14238 | doPart = true; |
14239 | if (!doPart) | 14239 | if (!doPart) |
14240 | continue; | 14240 | continue; |
14241 | } | 14241 | } |
14242 | 14242 | ||
14243 | // Parse prim/part and project ray if passed filters | 14243 | // Parse prim/part and project ray if passed filters |
14244 | Vector3 scalePart = part.Scale; | 14244 | Vector3 scalePart = part.Scale; |
14245 | Vector3 posPart = part.GetWorldPosition(); | 14245 | Vector3 posPart = part.GetWorldPosition(); |
14246 | Quaternion rotPart = part.GetWorldRotation(); | 14246 | Quaternion rotPart = part.GetWorldRotation(); |
14247 | Quaternion rotPartInv = Quaternion.Inverse(rotPart); | 14247 | Quaternion rotPartInv = Quaternion.Inverse(rotPart); |
14248 | Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; | 14248 | Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; |
14249 | Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; | 14249 | Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; |
14250 | 14250 | ||
14251 | // Filter parts by shape bounding boxes | 14251 | // Filter parts by shape bounding boxes |
14252 | Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f); | 14252 | Vector3 shapeBoxMax = new Vector3(0.5f, 0.5f, 0.5f); |
14253 | if (!part.Shape.SculptEntry) | 14253 | if (!part.Shape.SculptEntry) |
14254 | shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); | 14254 | shapeBoxMax = shapeBoxMax * (new Vector3(m_primSafetyCoeffX, m_primSafetyCoeffY, m_primSafetyCoeffZ)); |
14255 | shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol)); | 14255 | shapeBoxMax = shapeBoxMax + (new Vector3(tol, tol, tol)); |
14256 | if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) | 14256 | if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) |
14257 | { | 14257 | { |
14258 | // Prepare data needed to check for ray hits | 14258 | // Prepare data needed to check for ray hits |
14259 | RayTrans rayTrans = new RayTrans(); | 14259 | RayTrans rayTrans = new RayTrans(); |
14260 | rayTrans.PartId = part.UUID; | 14260 | rayTrans.PartId = part.UUID; |
14261 | rayTrans.GroupId = part.ParentGroup.UUID; | 14261 | rayTrans.GroupId = part.ParentGroup.UUID; |
14262 | rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; | 14262 | rayTrans.Link = group.PrimCount > 1 ? part.LinkNum : 0; |
14263 | rayTrans.ScalePart = scalePart; | 14263 | rayTrans.ScalePart = scalePart; |
14264 | rayTrans.PositionPart = posPart; | 14264 | rayTrans.PositionPart = posPart; |
14265 | rayTrans.RotationPart = rotPart; | 14265 | rayTrans.RotationPart = rotPart; |
14266 | rayTrans.ShapeNeedsEnds = true; | 14266 | rayTrans.ShapeNeedsEnds = true; |
14267 | rayTrans.Position1Ray = pos1Ray; | 14267 | rayTrans.Position1Ray = pos1Ray; |
14268 | rayTrans.Position1RayProj = pos1RayProj; | 14268 | rayTrans.Position1RayProj = pos1RayProj; |
14269 | rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; | 14269 | rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; |
14270 | 14270 | ||
14271 | // Get detail level depending on type | 14271 | // Get detail level depending on type |
14272 | int lod = 0; | 14272 | int lod = 0; |
14273 | // Mesh detail level | 14273 | // Mesh detail level |
14274 | if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) | 14274 | if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) |
14275 | lod = (int)m_meshLodInCastRay; | 14275 | lod = (int)m_meshLodInCastRay; |
14276 | // Sculpt detail level | 14276 | // Sculpt detail level |
14277 | else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) | 14277 | else if (part.Shape.SculptEntry && part.Shape.SculptType == (byte)SculptType.Mesh) |
14278 | lod = (int)m_sculptLodInCastRay; | 14278 | lod = (int)m_sculptLodInCastRay; |
14279 | // Shape detail level | 14279 | // Shape detail level |
14280 | else if (!part.Shape.SculptEntry) | 14280 | else if (!part.Shape.SculptEntry) |
14281 | lod = (int)m_primLodInCastRay; | 14281 | lod = (int)m_primLodInCastRay; |
14282 | 14282 | ||
14283 | // Try to get cached mesh if configured | 14283 | // Try to get cached mesh if configured |
14284 | ulong meshKey = 0; | 14284 | ulong meshKey = 0; |
14285 | FacetedMesh mesh = null; | 14285 | FacetedMesh mesh = null; |
14286 | if (m_useMeshCacheInCastRay) | 14286 | if (m_useMeshCacheInCastRay) |
14287 | { | 14287 | { |
14288 | meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); | 14288 | meshKey = part.Shape.GetMeshKey(Vector3.One, (float)(4 << lod)); |
14289 | lock (m_cachedMeshes) | 14289 | lock (m_cachedMeshes) |
14290 | { | 14290 | { |
14291 | m_cachedMeshes.TryGetValue(meshKey, out mesh); | 14291 | m_cachedMeshes.TryGetValue(meshKey, out mesh); |
14292 | } | 14292 | } |
14293 | } | 14293 | } |
14294 | 14294 | ||
14295 | // Create mesh if no cached mesh | 14295 | // Create mesh if no cached mesh |
14296 | if (mesh == null) | 14296 | if (mesh == null) |
14297 | { | 14297 | { |
14298 | // Make an OMV prim to be able to mesh part | 14298 | // Make an OMV prim to be able to mesh part |
14299 | Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); | 14299 | Primitive omvPrim = part.Shape.ToOmvPrimitive(posPart, rotPart); |
14300 | byte[] sculptAsset = null; | 14300 | byte[] sculptAsset = null; |
14301 | if (omvPrim.Sculpt != null) | 14301 | if (omvPrim.Sculpt != null) |
14302 | sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); | 14302 | sculptAsset = World.AssetService.GetData(omvPrim.Sculpt.SculptTexture.ToString()); |
14303 | 14303 | ||
14304 | // When part is mesh, get mesh | 14304 | // When part is mesh, get mesh |
14305 | if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) | 14305 | if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type == SculptType.Mesh && sculptAsset != null) |
14306 | { | 14306 | { |
14307 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); | 14307 | AssetMesh meshAsset = new AssetMesh(omvPrim.Sculpt.SculptTexture, sculptAsset); |
14308 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); | 14308 | FacetedMesh.TryDecodeFromAsset(omvPrim, meshAsset, m_meshLodInCastRay, out mesh); |
14309 | meshAsset = null; | 14309 | meshAsset = null; |
14310 | } | 14310 | } |
14311 | 14311 | ||
14312 | // When part is sculpt, create mesh | 14312 | // When part is sculpt, create mesh |
14313 | // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. | 14313 | // Quirk: Generated sculpt mesh is about 2.8% smaller in X and Y than visual sculpt. |
14314 | else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) | 14314 | else if (omvPrim.Sculpt != null && omvPrim.Sculpt.Type != SculptType.Mesh && sculptAsset != null) |
14315 | { | 14315 | { |
14316 | IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); | 14316 | IJ2KDecoder imgDecoder = World.RequestModuleInterface<IJ2KDecoder>(); |
14317 | if (imgDecoder != null) | 14317 | if (imgDecoder != null) |
14318 | { | 14318 | { |
14319 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); | 14319 | Image sculpt = imgDecoder.DecodeToImage(sculptAsset); |
14320 | if (sculpt != null) | 14320 | if (sculpt != null) |
14321 | { | 14321 | { |
14322 | mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); | 14322 | mesh = primMesher.GenerateFacetedSculptMesh(omvPrim, (Bitmap)sculpt, m_sculptLodInCastRay); |
14323 | sculpt.Dispose(); | 14323 | sculpt.Dispose(); |
14324 | } | 14324 | } |
14325 | } | 14325 | } |
14326 | } | 14326 | } |
14327 | 14327 | ||
14328 | // When part is shape, create mesh | 14328 | // When part is shape, create mesh |
14329 | else if (omvPrim.Sculpt == null) | 14329 | else if (omvPrim.Sculpt == null) |
14330 | { | 14330 | { |
14331 | if ( | 14331 | if ( |
14332 | omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && | 14332 | omvPrim.PrimData.PathBegin == 0.0 && omvPrim.PrimData.PathEnd == 1.0 && |
14333 | omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && | 14333 | omvPrim.PrimData.PathTaperX == 0.0 && omvPrim.PrimData.PathTaperY == 0.0 && |
14334 | omvPrim.PrimData.PathSkew == 0.0 && | 14334 | omvPrim.PrimData.PathSkew == 0.0 && |
14335 | omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 | 14335 | omvPrim.PrimData.PathTwist - omvPrim.PrimData.PathTwistBegin == 0.0 |
14336 | ) | 14336 | ) |
14337 | rayTrans.ShapeNeedsEnds = false; | 14337 | rayTrans.ShapeNeedsEnds = false; |
14338 | mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); | 14338 | mesh = primMesher.GenerateFacetedMesh(omvPrim, m_primLodInCastRay); |
14339 | } | 14339 | } |
14340 | 14340 | ||
14341 | // Cache mesh if configured | 14341 | // Cache mesh if configured |
14342 | if (m_useMeshCacheInCastRay && mesh != null) | 14342 | if (m_useMeshCacheInCastRay && mesh != null) |
14343 | { | 14343 | { |
14344 | lock(m_cachedMeshes) | 14344 | lock(m_cachedMeshes) |
14345 | { | 14345 | { |
14346 | if (!m_cachedMeshes.ContainsKey(meshKey)) | 14346 | if (!m_cachedMeshes.ContainsKey(meshKey)) |
14347 | m_cachedMeshes.Add(meshKey, mesh); | 14347 | m_cachedMeshes.Add(meshKey, mesh); |
14348 | } | 14348 | } |
14349 | } | 14349 | } |
14350 | } | 14350 | } |
14351 | // Check mesh for ray hits | 14351 | // Check mesh for ray hits |
14352 | AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); | 14352 | AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); |
14353 | mesh = null; | 14353 | mesh = null; |
14354 | } | 14354 | } |
14355 | } | 14355 | } |
14356 | } | 14356 | } |
14357 | } | 14357 | } |
14358 | ); | 14358 | ); |
14359 | 14359 | ||
14360 | // Check avatar filter | 14360 | // Check avatar filter |
14361 | if (!rejectAgents) | 14361 | if (!rejectAgents) |
14362 | { | 14362 | { |
14363 | // Iterate over all avatars in region | 14363 | // Iterate over all avatars in region |
14364 | World.ForEachRootScenePresence( | 14364 | World.ForEachRootScenePresence( |
14365 | delegate (ScenePresence sp) | 14365 | delegate (ScenePresence sp) |
14366 | { | 14366 | { |
14367 | // Get bounding box | 14367 | // Get bounding box |
14368 | Vector3 lower; | 14368 | Vector3 lower; |
14369 | Vector3 upper; | 14369 | Vector3 upper; |
14370 | BoundingBoxOfScenePresence(sp, out lower, out upper); | 14370 | BoundingBoxOfScenePresence(sp, out lower, out upper); |
14371 | // Parse avatar | 14371 | // Parse avatar |
14372 | Vector3 scalePart = upper - lower; | 14372 | Vector3 scalePart = upper - lower; |
14373 | Vector3 posPart = sp.AbsolutePosition; | 14373 | Vector3 posPart = sp.AbsolutePosition; |
14374 | Quaternion rotPart = sp.GetWorldRotation(); | 14374 | Quaternion rotPart = sp.GetWorldRotation(); |
14375 | Quaternion rotPartInv = Quaternion.Inverse(rotPart); | 14375 | Quaternion rotPartInv = Quaternion.Inverse(rotPart); |
14376 | posPart = posPart + (lower + upper) * 0.5f * rotPart; | 14376 | posPart = posPart + (lower + upper) * 0.5f * rotPart; |
14377 | // Project ray | 14377 | // Project ray |
14378 | Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; | 14378 | Vector3 pos1RayProj = ((pos1Ray - posPart) * rotPartInv) / scalePart; |
14379 | Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; | 14379 | Vector3 pos2RayProj = ((pos2Ray - posPart) * rotPartInv) / scalePart; |
14380 | 14380 | ||
14381 | // Filter avatars by shape bounding boxes | 14381 | // Filter avatars by shape bounding boxes |
14382 | Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol); | 14382 | Vector3 shapeBoxMax = new Vector3(0.5f + tol, 0.5f + tol, 0.5f + tol); |
14383 | if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) | 14383 | if (RayIntersectsShapeBox(pos1RayProj, pos2RayProj, shapeBoxMax)) |
14384 | { | 14384 | { |
14385 | // Prepare data needed to check for ray hits | 14385 | // Prepare data needed to check for ray hits |
14386 | RayTrans rayTrans = new RayTrans(); | 14386 | RayTrans rayTrans = new RayTrans(); |
14387 | rayTrans.PartId = sp.UUID; | 14387 | rayTrans.PartId = sp.UUID; |
14388 | rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; | 14388 | rayTrans.GroupId = sp.ParentPart != null ? sp.ParentPart.ParentGroup.UUID : sp.UUID; |
14389 | rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; | 14389 | rayTrans.Link = sp.ParentPart != null ? UUID2LinkNumber(sp.ParentPart, sp.UUID) : 0; |
14390 | rayTrans.ScalePart = scalePart; | 14390 | rayTrans.ScalePart = scalePart; |
14391 | rayTrans.PositionPart = posPart; | 14391 | rayTrans.PositionPart = posPart; |
14392 | rayTrans.RotationPart = rotPart; | 14392 | rayTrans.RotationPart = rotPart; |
14393 | rayTrans.ShapeNeedsEnds = false; | 14393 | rayTrans.ShapeNeedsEnds = false; |
14394 | rayTrans.Position1Ray = pos1Ray; | 14394 | rayTrans.Position1Ray = pos1Ray; |
14395 | rayTrans.Position1RayProj = pos1RayProj; | 14395 | rayTrans.Position1RayProj = pos1RayProj; |
14396 | rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; | 14396 | rayTrans.VectorRayProj = pos2RayProj - pos1RayProj; |
14397 | 14397 | ||
14398 | // Try to get cached mesh if configured | 14398 | // Try to get cached mesh if configured |
14399 | PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); | 14399 | PrimitiveBaseShape prim = PrimitiveBaseShape.CreateSphere(); |
14400 | int lod = (int)m_avatarLodInCastRay; | 14400 | int lod = (int)m_avatarLodInCastRay; |
14401 | ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod)); | 14401 | ulong meshKey = prim.GetMeshKey(Vector3.One, (float)(4 << lod)); |
14402 | FacetedMesh mesh = null; | 14402 | FacetedMesh mesh = null; |
14403 | if (m_useMeshCacheInCastRay) | 14403 | if (m_useMeshCacheInCastRay) |
14404 | { | 14404 | { |
14405 | lock (m_cachedMeshes) | 14405 | lock (m_cachedMeshes) |
14406 | { | 14406 | { |
14407 | m_cachedMeshes.TryGetValue(meshKey, out mesh); | 14407 | m_cachedMeshes.TryGetValue(meshKey, out mesh); |
14408 | } | 14408 | } |
14409 | } | 14409 | } |
14410 | 14410 | ||
14411 | // Create mesh if no cached mesh | 14411 | // Create mesh if no cached mesh |
14412 | if (mesh == null) | 14412 | if (mesh == null) |
14413 | { | 14413 | { |
14414 | // Make OMV prim and create mesh | 14414 | // Make OMV prim and create mesh |
14415 | prim.Scale = scalePart; | 14415 | prim.Scale = scalePart; |
14416 | Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); | 14416 | Primitive omvPrim = prim.ToOmvPrimitive(posPart, rotPart); |
14417 | mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay); | 14417 | mesh = primMesher.GenerateFacetedMesh(omvPrim, m_avatarLodInCastRay); |
14418 | 14418 | ||
14419 | // Cache mesh if configured | 14419 | // Cache mesh if configured |
14420 | if (m_useMeshCacheInCastRay && mesh != null) | 14420 | if (m_useMeshCacheInCastRay && mesh != null) |
14421 | { | 14421 | { |
14422 | lock(m_cachedMeshes) | 14422 | lock(m_cachedMeshes) |
14423 | { | 14423 | { |
14424 | if (!m_cachedMeshes.ContainsKey(meshKey)) | 14424 | if (!m_cachedMeshes.ContainsKey(meshKey)) |
14425 | m_cachedMeshes.Add(meshKey, mesh); | 14425 | m_cachedMeshes.Add(meshKey, mesh); |
14426 | } | 14426 | } |
14427 | } | 14427 | } |
14428 | } | 14428 | } |
14429 | 14429 | ||
14430 | // Check mesh for ray hits | 14430 | // Check mesh for ray hits |
14431 | AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); | 14431 | AddRayInFacetedMesh(mesh, rayTrans, ref rayHits); |
14432 | mesh = null; | 14432 | mesh = null; |
14433 | } | 14433 | } |
14434 | } | 14434 | } |
14435 | ); | 14435 | ); |
14436 | } | 14436 | } |
14437 | 14437 | ||
14438 | // Check terrain filter | 14438 | // Check terrain filter |
14439 | if (!rejectLand) | 14439 | if (!rejectLand) |
14440 | { | 14440 | { |
14441 | // Parse terrain | 14441 | // Parse terrain |
14442 | 14442 | ||
14443 | // Mesh terrain and check bounding box | 14443 | // Mesh terrain and check bounding box |
14444 | Vector3 lower; | 14444 | Vector3 lower; |
14445 | Vector3 upper; | 14445 | Vector3 upper; |
14446 | List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper); | 14446 | List<Tri> triangles = TrisFromHeightmapUnderRay(pos1Ray, pos2Ray, out lower, out upper); |
14447 | lower.Z -= tol; | 14447 | lower.Z -= tol; |
14448 | upper.Z += tol; | 14448 | upper.Z += tol; |
14449 | if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z)) | 14449 | if ((pos1Ray.Z >= lower.Z || pos2Ray.Z >= lower.Z) && (pos1Ray.Z <= upper.Z || pos2Ray.Z <= upper.Z)) |
14450 | { | 14450 | { |
14451 | // Prepare data needed to check for ray hits | 14451 | // Prepare data needed to check for ray hits |
14452 | RayTrans rayTrans = new RayTrans(); | 14452 | RayTrans rayTrans = new RayTrans(); |
14453 | rayTrans.PartId = UUID.Zero; | 14453 | rayTrans.PartId = UUID.Zero; |
14454 | rayTrans.GroupId = UUID.Zero; | 14454 | rayTrans.GroupId = UUID.Zero; |
14455 | rayTrans.Link = 0; | 14455 | rayTrans.Link = 0; |
14456 | rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f); | 14456 | rayTrans.ScalePart = new Vector3 (1.0f, 1.0f, 1.0f); |
14457 | rayTrans.PositionPart = Vector3.Zero; | 14457 | rayTrans.PositionPart = Vector3.Zero; |
14458 | rayTrans.RotationPart = Quaternion.Identity; | 14458 | rayTrans.RotationPart = Quaternion.Identity; |
14459 | rayTrans.ShapeNeedsEnds = true; | 14459 | rayTrans.ShapeNeedsEnds = true; |
14460 | rayTrans.Position1Ray = pos1Ray; | 14460 | rayTrans.Position1Ray = pos1Ray; |
14461 | rayTrans.Position1RayProj = pos1Ray; | 14461 | rayTrans.Position1RayProj = pos1Ray; |
14462 | rayTrans.VectorRayProj = vecRay; | 14462 | rayTrans.VectorRayProj = vecRay; |
14463 | 14463 | ||
14464 | // Check mesh | 14464 | // Check mesh |
14465 | AddRayInTris(triangles, rayTrans, ref rayHits); | 14465 | AddRayInTris(triangles, rayTrans, ref rayHits); |
14466 | triangles = null; | 14466 | triangles = null; |
14467 | } | 14467 | } |
14468 | } | 14468 | } |
14469 | 14469 | ||
14470 | // Sort hits by ascending distance | 14470 | // Sort hits by ascending distance |
14471 | rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance)); | 14471 | rayHits.Sort((s1, s2) => s1.Distance.CompareTo(s2.Distance)); |
14472 | 14472 | ||
14473 | // Check excess hits per part and group | 14473 | // Check excess hits per part and group |
14474 | for (int t = 0; t < 2; t++) | 14474 | for (int t = 0; t < 2; t++) |
14475 | { | 14475 | { |
14476 | int maxHitsPerType = 0; | 14476 | int maxHitsPerType = 0; |
14477 | UUID id = UUID.Zero; | 14477 | UUID id = UUID.Zero; |
14478 | if (t == 0) | 14478 | if (t == 0) |
14479 | maxHitsPerType = m_maxHitsPerPrimInCastRay; | 14479 | maxHitsPerType = m_maxHitsPerPrimInCastRay; |
14480 | else | 14480 | else |
14481 | maxHitsPerType = m_maxHitsPerObjectInCastRay; | 14481 | maxHitsPerType = m_maxHitsPerObjectInCastRay; |
14482 | 14482 | ||
14483 | // Handle excess hits only when needed | 14483 | // Handle excess hits only when needed |
14484 | if (maxHitsPerType < m_maxHitsInCastRay) | 14484 | if (maxHitsPerType < m_maxHitsInCastRay) |
14485 | { | 14485 | { |
14486 | // Find excess hits | 14486 | // Find excess hits |
14487 | Hashtable hits = new Hashtable(); | 14487 | Hashtable hits = new Hashtable(); |
14488 | for (int i = rayHits.Count - 1; i >= 0; i--) | 14488 | for (int i = rayHits.Count - 1; i >= 0; i--) |
14489 | { | 14489 | { |
14490 | if (t == 0) | 14490 | if (t == 0) |
14491 | id = rayHits[i].PartId; | 14491 | id = rayHits[i].PartId; |
14492 | else | 14492 | else |
14493 | id = rayHits[i].GroupId; | 14493 | id = rayHits[i].GroupId; |
14494 | if (hits.ContainsKey(id)) | 14494 | if (hits.ContainsKey(id)) |
14495 | hits[id] = (int)hits[id] + 1; | 14495 | hits[id] = (int)hits[id] + 1; |
14496 | else | 14496 | else |
14497 | hits[id] = 1; | 14497 | hits[id] = 1; |
14498 | } | 14498 | } |
14499 | 14499 | ||
14500 | // Remove excess hits | 14500 | // Remove excess hits |
14501 | for (int i = rayHits.Count - 1; i >= 0; i--) | 14501 | for (int i = rayHits.Count - 1; i >= 0; i--) |
14502 | { | 14502 | { |
14503 | if (t == 0) | 14503 | if (t == 0) |
14504 | id = rayHits[i].PartId; | 14504 | id = rayHits[i].PartId; |
14505 | else | 14505 | else |
14506 | id = rayHits[i].GroupId; | 14506 | id = rayHits[i].GroupId; |
14507 | int hit = (int)hits[id]; | 14507 | int hit = (int)hits[id]; |
14508 | if (hit > m_maxHitsPerPrimInCastRay) | 14508 | if (hit > m_maxHitsPerPrimInCastRay) |
14509 | { | 14509 | { |
14510 | rayHits.RemoveAt(i); | 14510 | rayHits.RemoveAt(i); |
14511 | hit--; | 14511 | hit--; |
14512 | hits[id] = hit; | 14512 | hits[id] = hit; |
14513 | } | 14513 | } |
14514 | } | 14514 | } |
14515 | } | 14515 | } |
14516 | } | 14516 | } |
14517 | 14517 | ||
14518 | // Parse hits into result list according to data flags | 14518 | // Parse hits into result list according to data flags |
14519 | int hitCount = rayHits.Count; | 14519 | int hitCount = rayHits.Count; |
14520 | if (hitCount > maxHits) | 14520 | if (hitCount > maxHits) |
14521 | hitCount = maxHits; | 14521 | hitCount = maxHits; |
14522 | for (int i = 0; i < hitCount; i++) | 14522 | for (int i = 0; i < hitCount; i++) |
14523 | { | 14523 | { |
14524 | RayHit rayHit = rayHits[i]; | 14524 | RayHit rayHit = rayHits[i]; |
14525 | if (getRootKey) | 14525 | if (getRootKey) |
14526 | result.Add(new LSL_Key(rayHit.GroupId.ToString())); | 14526 | result.Add(new LSL_Key(rayHit.GroupId.ToString())); |
14527 | else | 14527 | else |
14528 | result.Add(new LSL_Key(rayHit.PartId.ToString())); | 14528 | result.Add(new LSL_Key(rayHit.PartId.ToString())); |
14529 | result.Add(new LSL_Vector(rayHit.Position)); | 14529 | result.Add(new LSL_Vector(rayHit.Position)); |
14530 | if (getLinkNum) | 14530 | if (getLinkNum) |
14531 | result.Add(new LSL_Integer(rayHit.Link)); | 14531 | result.Add(new LSL_Integer(rayHit.Link)); |
14532 | if (getNormal) | 14532 | if (getNormal) |
14533 | result.Add(new LSL_Vector(rayHit.Normal)); | 14533 | result.Add(new LSL_Vector(rayHit.Normal)); |
14534 | } | 14534 | } |
14535 | result.Add(new LSL_Integer(hitCount)); | 14535 | result.Add(new LSL_Integer(hitCount)); |
14536 | 14536 | ||
14537 | // Add to throttle data | 14537 | // Add to throttle data |
14538 | stopWatch.Stop(); | 14538 | stopWatch.Stop(); |
14539 | CastRayCall castRayCall = new CastRayCall(); | 14539 | CastRayCall castRayCall = new CastRayCall(); |
14540 | castRayCall.RegionId = regionId; | 14540 | castRayCall.RegionId = regionId; |
14541 | castRayCall.UserId = userId; | 14541 | castRayCall.UserId = userId; |
14542 | castRayCall.CalledMs = calledMs; | 14542 | castRayCall.CalledMs = calledMs; |
14543 | castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds; | 14543 | castRayCall.UsedMs = (int)stopWatch.ElapsedMilliseconds; |
14544 | lock (m_castRayCalls) | 14544 | lock (m_castRayCalls) |
14545 | { | 14545 | { |
14546 | m_castRayCalls.Add(castRayCall); | 14546 | m_castRayCalls.Add(castRayCall); |
14547 | } | 14547 | } |
14548 | 14548 | ||
14549 | // Return hits | 14549 | // Return hits |
14550 | return result; | 14550 | return result; |
14551 | } | 14551 | } |
14552 | 14552 | ||
14553 | /// <summary> | 14553 | /// <summary> |
14554 | /// Struct for transmitting parameters required for finding llCastRay ray hits. | 14554 | /// Struct for transmitting parameters required for finding llCastRay ray hits. |
14555 | /// </summary> | 14555 | /// </summary> |
14556 | public struct RayTrans | 14556 | public struct RayTrans |
14557 | { | 14557 | { |
14558 | public UUID PartId; | 14558 | public UUID PartId; |
14559 | public UUID GroupId; | 14559 | public UUID GroupId; |
14560 | public int Link; | 14560 | public int Link; |
14561 | public Vector3 ScalePart; | 14561 | public Vector3 ScalePart; |
14562 | public Vector3 PositionPart; | 14562 | public Vector3 PositionPart; |
14563 | public Quaternion RotationPart; | 14563 | public Quaternion RotationPart; |
14564 | public bool ShapeNeedsEnds; | 14564 | public bool ShapeNeedsEnds; |
14565 | public Vector3 Position1Ray; | 14565 | public Vector3 Position1Ray; |
14566 | public Vector3 Position1RayProj; | 14566 | public Vector3 Position1RayProj; |
14567 | public Vector3 VectorRayProj; | 14567 | public Vector3 VectorRayProj; |
14568 | } | 14568 | } |
14569 | 14569 | ||
14570 | /// <summary> | 14570 | /// <summary> |
14571 | /// Struct for llCastRay ray hits. | 14571 | /// Struct for llCastRay ray hits. |
14572 | /// </summary> | 14572 | /// </summary> |
14573 | public struct RayHit | 14573 | public struct RayHit |
14574 | { | 14574 | { |
14575 | public UUID PartId; | 14575 | public UUID PartId; |
14576 | public UUID GroupId; | 14576 | public UUID GroupId; |
14577 | public int Link; | 14577 | public int Link; |
14578 | public Vector3 Position; | 14578 | public Vector3 Position; |
14579 | public Vector3 Normal; | 14579 | public Vector3 Normal; |
14580 | public float Distance; | 14580 | public float Distance; |
14581 | } | 14581 | } |
14582 | 14582 | ||
14583 | /// <summary> | 14583 | /// <summary> |
14584 | /// Struct for llCastRay throttle data. | 14584 | /// Struct for llCastRay throttle data. |
14585 | /// </summary> | 14585 | /// </summary> |
14586 | public struct CastRayCall | 14586 | public struct CastRayCall |
14587 | { | 14587 | { |
14588 | public UUID RegionId; | 14588 | public UUID RegionId; |
14589 | public UUID UserId; | 14589 | public UUID UserId; |
14590 | public int CalledMs; | 14590 | public int CalledMs; |
14591 | public int UsedMs; | 14591 | public int UsedMs; |
14592 | } | 14592 | } |
14593 | 14593 | ||
14594 | /// <summary> | 14594 | /// <summary> |
14595 | /// Helper to check if a ray intersects a shape bounding box. | 14595 | /// Helper to check if a ray intersects a shape bounding box. |
14596 | /// </summary> | 14596 | /// </summary> |
14597 | private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax) | 14597 | private bool RayIntersectsShapeBox(Vector3 pos1RayProj, Vector3 pos2RayProj, Vector3 shapeBoxMax) |
14598 | { | 14598 | { |
14599 | // Skip if ray can't intersect bounding box; | 14599 | // Skip if ray can't intersect bounding box; |
14600 | Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj); | 14600 | Vector3 rayBoxProjMin = Vector3.Min(pos1RayProj, pos2RayProj); |
14601 | Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj); | 14601 | Vector3 rayBoxProjMax = Vector3.Max(pos1RayProj, pos2RayProj); |
14602 | if ( | 14602 | if ( |
14603 | rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z || | 14603 | rayBoxProjMin.X > shapeBoxMax.X || rayBoxProjMin.Y > shapeBoxMax.Y || rayBoxProjMin.Z > shapeBoxMax.Z || |
14604 | rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z | 14604 | rayBoxProjMax.X < -shapeBoxMax.X || rayBoxProjMax.Y < -shapeBoxMax.Y || rayBoxProjMax.Z < -shapeBoxMax.Z |
14605 | ) | 14605 | ) |
14606 | return false; | 14606 | return false; |
14607 | 14607 | ||
14608 | // Check if ray intersect any bounding box side | 14608 | // Check if ray intersect any bounding box side |
14609 | int sign = 0; | 14609 | int sign = 0; |
14610 | float dist = 0.0f; | 14610 | float dist = 0.0f; |
14611 | Vector3 posProj = Vector3.Zero; | 14611 | Vector3 posProj = Vector3.Zero; |
14612 | Vector3 vecRayProj = pos2RayProj - pos1RayProj; | 14612 | Vector3 vecRayProj = pos2RayProj - pos1RayProj; |
14613 | 14613 | ||
14614 | // Check both X sides unless ray is parallell to them | 14614 | // Check both X sides unless ray is parallell to them |
14615 | if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay) | 14615 | if (Math.Abs(vecRayProj.X) > m_floatToleranceInCastRay) |
14616 | { | 14616 | { |
14617 | for (sign = -1; sign <= 1; sign += 2) | 14617 | for (sign = -1; sign <= 1; sign += 2) |
14618 | { | 14618 | { |
14619 | dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X; | 14619 | dist = ((float)sign * shapeBoxMax.X - pos1RayProj.X) / vecRayProj.X; |
14620 | posProj = pos1RayProj + vecRayProj * dist; | 14620 | posProj = pos1RayProj + vecRayProj * dist; |
14621 | if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z) | 14621 | if (Math.Abs(posProj.Y) <= shapeBoxMax.Y && Math.Abs(posProj.Z) <= shapeBoxMax.Z) |
14622 | return true; | 14622 | return true; |
14623 | } | 14623 | } |
14624 | } | 14624 | } |
14625 | 14625 | ||
14626 | // Check both Y sides unless ray is parallell to them | 14626 | // Check both Y sides unless ray is parallell to them |
14627 | if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay) | 14627 | if (Math.Abs(vecRayProj.Y) > m_floatToleranceInCastRay) |
14628 | { | 14628 | { |
14629 | for (sign = -1; sign <= 1; sign += 2) | 14629 | for (sign = -1; sign <= 1; sign += 2) |
14630 | { | 14630 | { |
14631 | dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y; | 14631 | dist = ((float)sign * shapeBoxMax.Y - pos1RayProj.Y) / vecRayProj.Y; |
14632 | posProj = pos1RayProj + vecRayProj * dist; | 14632 | posProj = pos1RayProj + vecRayProj * dist; |
14633 | if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z) | 14633 | if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Z) <= shapeBoxMax.Z) |
14634 | return true; | 14634 | return true; |
14635 | } | 14635 | } |
14636 | } | 14636 | } |
14637 | 14637 | ||
14638 | // Check both Z sides unless ray is parallell to them | 14638 | // Check both Z sides unless ray is parallell to them |
14639 | if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay) | 14639 | if (Math.Abs(vecRayProj.Z) > m_floatToleranceInCastRay) |
14640 | { | 14640 | { |
14641 | for (sign = -1; sign <= 1; sign += 2) | 14641 | for (sign = -1; sign <= 1; sign += 2) |
14642 | { | 14642 | { |
14643 | dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z; | 14643 | dist = ((float)sign * shapeBoxMax.Z - pos1RayProj.Z) / vecRayProj.Z; |
14644 | posProj = pos1RayProj + vecRayProj * dist; | 14644 | posProj = pos1RayProj + vecRayProj * dist; |
14645 | if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y) | 14645 | if (Math.Abs(posProj.X) <= shapeBoxMax.X && Math.Abs(posProj.Y) <= shapeBoxMax.Y) |
14646 | return true; | 14646 | return true; |
14647 | } | 14647 | } |
14648 | } | 14648 | } |
14649 | 14649 | ||
14650 | // No hits on bounding box so return false | 14650 | // No hits on bounding box so return false |
14651 | return false; | 14651 | return false; |
14652 | } | 14652 | } |
14653 | 14653 | ||
14654 | /// <summary> | 14654 | /// <summary> |
14655 | /// Helper to parse FacetedMesh for ray hits. | 14655 | /// Helper to parse FacetedMesh for ray hits. |
14656 | /// </summary> | 14656 | /// </summary> |
14657 | private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits) | 14657 | private void AddRayInFacetedMesh(FacetedMesh mesh, RayTrans rayTrans, ref List<RayHit> rayHits) |
14658 | { | 14658 | { |
14659 | if (mesh != null) | 14659 | if (mesh != null) |
14660 | { | 14660 | { |
14661 | foreach (Face face in mesh.Faces) | 14661 | foreach (Face face in mesh.Faces) |
14662 | { | 14662 | { |
14663 | for (int i = 0; i < face.Indices.Count; i += 3) | 14663 | for (int i = 0; i < face.Indices.Count; i += 3) |
14664 | { | 14664 | { |
14665 | Tri triangle = new Tri(); | 14665 | Tri triangle = new Tri(); |
14666 | triangle.p1 = face.Vertices[face.Indices[i]].Position; | 14666 | triangle.p1 = face.Vertices[face.Indices[i]].Position; |
14667 | triangle.p2 = face.Vertices[face.Indices[i + 1]].Position; | 14667 | triangle.p2 = face.Vertices[face.Indices[i + 1]].Position; |
14668 | triangle.p3 = face.Vertices[face.Indices[i + 2]].Position; | 14668 | triangle.p3 = face.Vertices[face.Indices[i + 2]].Position; |
14669 | AddRayInTri(triangle, rayTrans, ref rayHits); | 14669 | AddRayInTri(triangle, rayTrans, ref rayHits); |
14670 | } | 14670 | } |
14671 | } | 14671 | } |
14672 | } | 14672 | } |
14673 | } | 14673 | } |
14674 | 14674 | ||
14675 | /// <summary> | 14675 | /// <summary> |
14676 | /// Helper to parse Tri (triangle) List for ray hits. | 14676 | /// Helper to parse Tri (triangle) List for ray hits. |
14677 | /// </summary> | 14677 | /// </summary> |
14678 | private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits) | 14678 | private void AddRayInTris(List<Tri> triangles, RayTrans rayTrans, ref List<RayHit> rayHits) |
14679 | { | 14679 | { |
14680 | foreach (Tri triangle in triangles) | 14680 | foreach (Tri triangle in triangles) |
14681 | { | 14681 | { |
14682 | AddRayInTri(triangle, rayTrans, ref rayHits); | 14682 | AddRayInTri(triangle, rayTrans, ref rayHits); |
14683 | } | 14683 | } |
14684 | } | 14684 | } |
14685 | 14685 | ||
14686 | /// <summary> | 14686 | /// <summary> |
14687 | /// Helper to add ray hit in a Tri (triangle). | 14687 | /// Helper to add ray hit in a Tri (triangle). |
14688 | /// </summary> | 14688 | /// </summary> |
14689 | private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits) | 14689 | private void AddRayInTri(Tri triProj, RayTrans rayTrans, ref List<RayHit> rayHits) |
14690 | { | 14690 | { |
14691 | // Check for hit in triangle | 14691 | // Check for hit in triangle |
14692 | Vector3 posHitProj; | 14692 | Vector3 posHitProj; |
14693 | Vector3 normalProj; | 14693 | Vector3 normalProj; |
14694 | if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj)) | 14694 | if (HitRayInTri(triProj, rayTrans.Position1RayProj, rayTrans.VectorRayProj, out posHitProj, out normalProj)) |
14695 | { | 14695 | { |
14696 | // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center | 14696 | // Hack to circumvent ghost face bug in PrimMesher by removing hits in (ghost) face plane through shape center |
14697 | if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds) | 14697 | if (Math.Abs(Vector3.Dot(posHitProj, normalProj)) < m_floatToleranceInCastRay && !rayTrans.ShapeNeedsEnds) |
14698 | return; | 14698 | return; |
14699 | 14699 | ||
14700 | // Transform hit and normal to region coordinate system | 14700 | // Transform hit and normal to region coordinate system |
14701 | Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart; | 14701 | Vector3 posHit = rayTrans.PositionPart + (posHitProj * rayTrans.ScalePart) * rayTrans.RotationPart; |
14702 | Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart); | 14702 | Vector3 normal = Vector3.Normalize((normalProj * rayTrans.ScalePart) * rayTrans.RotationPart); |
14703 | 14703 | ||
14704 | // Remove duplicate hits at triangle intersections | 14704 | // Remove duplicate hits at triangle intersections |
14705 | float distance = Vector3.Distance(rayTrans.Position1Ray, posHit); | 14705 | float distance = Vector3.Distance(rayTrans.Position1Ray, posHit); |
14706 | for (int i = rayHits.Count - 1; i >= 0; i--) | 14706 | for (int i = rayHits.Count - 1; i >= 0; i--) |
14707 | { | 14707 | { |
14708 | if (rayHits[i].PartId != rayTrans.PartId) | 14708 | if (rayHits[i].PartId != rayTrans.PartId) |
14709 | break; | 14709 | break; |
14710 | if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay) | 14710 | if (Math.Abs(rayHits[i].Distance - distance) < m_floatTolerance2InCastRay) |
14711 | return; | 14711 | return; |
14712 | } | 14712 | } |
14713 | 14713 | ||
14714 | // Build result data set | 14714 | // Build result data set |
14715 | RayHit rayHit = new RayHit(); | 14715 | RayHit rayHit = new RayHit(); |
14716 | rayHit.PartId = rayTrans.PartId; | 14716 | rayHit.PartId = rayTrans.PartId; |
14717 | rayHit.GroupId = rayTrans.GroupId; | 14717 | rayHit.GroupId = rayTrans.GroupId; |
14718 | rayHit.Link = rayTrans.Link; | 14718 | rayHit.Link = rayTrans.Link; |
14719 | rayHit.Position = posHit; | 14719 | rayHit.Position = posHit; |
14720 | rayHit.Normal = normal; | 14720 | rayHit.Normal = normal; |
14721 | rayHit.Distance = distance; | 14721 | rayHit.Distance = distance; |
14722 | rayHits.Add(rayHit); | 14722 | rayHits.Add(rayHit); |
14723 | } | 14723 | } |
14724 | } | 14724 | } |
14725 | 14725 | ||
14726 | /// <summary> | 14726 | /// <summary> |
14727 | /// Helper to find ray hit in triangle | 14727 | /// Helper to find ray hit in triangle |
14728 | /// </summary> | 14728 | /// </summary> |
14729 | bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj) | 14729 | bool HitRayInTri(Tri triProj, Vector3 pos1RayProj, Vector3 vecRayProj, out Vector3 posHitProj, out Vector3 normalProj) |
14730 | { | 14730 | { |
14731 | float tol = m_floatToleranceInCastRay; | 14731 | float tol = m_floatToleranceInCastRay; |
14732 | posHitProj = Vector3.Zero; | 14732 | posHitProj = Vector3.Zero; |
14733 | 14733 | ||
14734 | // Calculate triangle edge vectors | 14734 | // Calculate triangle edge vectors |
14735 | Vector3 vec1Proj = triProj.p2 - triProj.p1; | 14735 | Vector3 vec1Proj = triProj.p2 - triProj.p1; |
14736 | Vector3 vec2Proj = triProj.p3 - triProj.p2; | 14736 | Vector3 vec2Proj = triProj.p3 - triProj.p2; |
14737 | Vector3 vec3Proj = triProj.p1 - triProj.p3; | 14737 | Vector3 vec3Proj = triProj.p1 - triProj.p3; |
14738 | 14738 | ||
14739 | // Calculate triangle normal | 14739 | // Calculate triangle normal |
14740 | normalProj = Vector3.Cross(vec1Proj, vec2Proj); | 14740 | normalProj = Vector3.Cross(vec1Proj, vec2Proj); |
14741 | 14741 | ||
14742 | // Skip if degenerate triangle or ray parallell with triangle plane | 14742 | // Skip if degenerate triangle or ray parallell with triangle plane |
14743 | float divisor = Vector3.Dot(vecRayProj, normalProj); | 14743 | float divisor = Vector3.Dot(vecRayProj, normalProj); |
14744 | if (Math.Abs(divisor) < tol) | 14744 | if (Math.Abs(divisor) < tol) |
14745 | return false; | 14745 | return false; |
14746 | 14746 | ||
14747 | // Skip if exit and not configured to detect | 14747 | // Skip if exit and not configured to detect |
14748 | if (divisor > tol && !m_detectExitsInCastRay) | 14748 | if (divisor > tol && !m_detectExitsInCastRay) |
14749 | return false; | 14749 | return false; |
14750 | 14750 | ||
14751 | // Skip if outside ray ends | 14751 | // Skip if outside ray ends |
14752 | float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor; | 14752 | float distanceProj = Vector3.Dot(triProj.p1 - pos1RayProj, normalProj) / divisor; |
14753 | if (distanceProj < -tol || distanceProj > 1 + tol) | 14753 | if (distanceProj < -tol || distanceProj > 1 + tol) |
14754 | return false; | 14754 | return false; |
14755 | 14755 | ||
14756 | // Calculate hit position in triangle | 14756 | // Calculate hit position in triangle |
14757 | posHitProj = pos1RayProj + vecRayProj * distanceProj; | 14757 | posHitProj = pos1RayProj + vecRayProj * distanceProj; |
14758 | 14758 | ||
14759 | // Skip if outside triangle bounding box | 14759 | // Skip if outside triangle bounding box |
14760 | Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3); | 14760 | Vector3 triProjMin = Vector3.Min(Vector3.Min(triProj.p1, triProj.p2), triProj.p3); |
14761 | Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3); | 14761 | Vector3 triProjMax = Vector3.Max(Vector3.Max(triProj.p1, triProj.p2), triProj.p3); |
14762 | if ( | 14762 | if ( |
14763 | posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol || | 14763 | posHitProj.X < triProjMin.X - tol || posHitProj.Y < triProjMin.Y - tol || posHitProj.Z < triProjMin.Z - tol || |
14764 | posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol | 14764 | posHitProj.X > triProjMax.X + tol || posHitProj.Y > triProjMax.Y + tol || posHitProj.Z > triProjMax.Z + tol |
14765 | ) | 14765 | ) |
14766 | return false; | 14766 | return false; |
14767 | 14767 | ||
14768 | // Skip if outside triangle | 14768 | // Skip if outside triangle |
14769 | if ( | 14769 | if ( |
14770 | Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol || | 14770 | Vector3.Dot(Vector3.Cross(vec1Proj, normalProj), posHitProj - triProj.p1) > tol || |
14771 | Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol || | 14771 | Vector3.Dot(Vector3.Cross(vec2Proj, normalProj), posHitProj - triProj.p2) > tol || |
14772 | Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol | 14772 | Vector3.Dot(Vector3.Cross(vec3Proj, normalProj), posHitProj - triProj.p3) > tol |
14773 | ) | 14773 | ) |
14774 | return false; | 14774 | return false; |
14775 | 14775 | ||
14776 | // Return hit | 14776 | // Return hit |
14777 | return true; | 14777 | return true; |
14778 | } | 14778 | } |
14779 | 14779 | ||
14780 | /// <summary> | 14780 | /// <summary> |
14781 | /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box. | 14781 | /// Helper to parse selected parts of HeightMap into a Tri (triangle) List and calculate bounding box. |
14782 | /// </summary> | 14782 | /// </summary> |
14783 | private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper) | 14783 | private List<Tri> TrisFromHeightmapUnderRay(Vector3 posStart, Vector3 posEnd, out Vector3 lower, out Vector3 upper) |
14784 | { | 14784 | { |
14785 | // Get bounding X-Y rectangle of terrain under ray | 14785 | // Get bounding X-Y rectangle of terrain under ray |
14786 | lower = Vector3.Min(posStart, posEnd); | 14786 | lower = Vector3.Min(posStart, posEnd); |
14787 | upper = Vector3.Max(posStart, posEnd); | 14787 | upper = Vector3.Max(posStart, posEnd); |
14788 | lower.X = (float)Math.Floor(lower.X); | 14788 | lower.X = (float)Math.Floor(lower.X); |
14789 | lower.Y = (float)Math.Floor(lower.Y); | 14789 | lower.Y = (float)Math.Floor(lower.Y); |
14790 | float zLower = float.MaxValue; | 14790 | float zLower = float.MaxValue; |
14791 | upper.X = (float)Math.Ceiling(upper.X); | 14791 | upper.X = (float)Math.Ceiling(upper.X); |
14792 | upper.Y = (float)Math.Ceiling(upper.Y); | 14792 | upper.Y = (float)Math.Ceiling(upper.Y); |
14793 | float zUpper = float.MinValue; | 14793 | float zUpper = float.MinValue; |
14794 | 14794 | ||
14795 | // Initialize Tri (triangle) List | 14795 | // Initialize Tri (triangle) List |
14796 | List<Tri> triangles = new List<Tri>(); | 14796 | List<Tri> triangles = new List<Tri>(); |
14797 | 14797 | ||
14798 | // Set parsing lane direction to major ray X-Y axis | 14798 | // Set parsing lane direction to major ray X-Y axis |
14799 | Vector3 vec = posEnd - posStart; | 14799 | Vector3 vec = posEnd - posStart; |
14800 | float xAbs = Math.Abs(vec.X); | 14800 | float xAbs = Math.Abs(vec.X); |
14801 | float yAbs = Math.Abs(vec.Y); | 14801 | float yAbs = Math.Abs(vec.Y); |
14802 | bool bigX = true; | 14802 | bool bigX = true; |
14803 | if (yAbs > xAbs) | 14803 | if (yAbs > xAbs) |
14804 | { | 14804 | { |
14805 | bigX = false; | 14805 | bigX = false; |
14806 | vec = vec / yAbs; | 14806 | vec = vec / yAbs; |
14807 | } | 14807 | } |
14808 | else if (xAbs > yAbs || xAbs > 0.0f) | 14808 | else if (xAbs > yAbs || xAbs > 0.0f) |
14809 | vec = vec / xAbs; | 14809 | vec = vec / xAbs; |
14810 | else | 14810 | else |
14811 | vec = new Vector3(1.0f, 1.0f, 0.0f); | 14811 | vec = new Vector3(1.0f, 1.0f, 0.0f); |
14812 | 14812 | ||
14813 | // Simplify by start parsing in lower end of lane | 14813 | // Simplify by start parsing in lower end of lane |
14814 | if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f)) | 14814 | if ((bigX && vec.X < 0.0f) || (!bigX && vec.Y < 0.0f)) |
14815 | { | 14815 | { |
14816 | Vector3 posTemp = posStart; | 14816 | Vector3 posTemp = posStart; |
14817 | posStart = posEnd; | 14817 | posStart = posEnd; |
14818 | posEnd = posTemp; | 14818 | posEnd = posTemp; |
14819 | vec = vec * -1.0f; | 14819 | vec = vec * -1.0f; |
14820 | } | 14820 | } |
14821 | 14821 | ||
14822 | // First 1x1 rectangle under ray | 14822 | // First 1x1 rectangle under ray |
14823 | float xFloorOld = 0.0f; | 14823 | float xFloorOld = 0.0f; |
14824 | float yFloorOld = 0.0f; | 14824 | float yFloorOld = 0.0f; |
14825 | Vector3 pos = posStart; | 14825 | Vector3 pos = posStart; |
14826 | float xFloor = (float)Math.Floor(pos.X); | 14826 | float xFloor = (float)Math.Floor(pos.X); |
14827 | float yFloor = (float)Math.Floor(pos.Y); | 14827 | float yFloor = (float)Math.Floor(pos.Y); |
14828 | AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); | 14828 | AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); |
14829 | 14829 | ||
14830 | // Parse every remaining 1x1 rectangle under ray | 14830 | // Parse every remaining 1x1 rectangle under ray |
14831 | while (pos != posEnd) | 14831 | while (pos != posEnd) |
14832 | { | 14832 | { |
14833 | // Next 1x1 rectangle under ray | 14833 | // Next 1x1 rectangle under ray |
14834 | xFloorOld = xFloor; | 14834 | xFloorOld = xFloor; |
14835 | yFloorOld = yFloor; | 14835 | yFloorOld = yFloor; |
14836 | pos = pos + vec; | 14836 | pos = pos + vec; |
14837 | 14837 | ||
14838 | // Clip position to 1x1 rectangle border | 14838 | // Clip position to 1x1 rectangle border |
14839 | xFloor = (float)Math.Floor(pos.X); | 14839 | xFloor = (float)Math.Floor(pos.X); |
14840 | yFloor = (float)Math.Floor(pos.Y); | 14840 | yFloor = (float)Math.Floor(pos.Y); |
14841 | if (bigX && pos.X > xFloor) | 14841 | if (bigX && pos.X > xFloor) |
14842 | { | 14842 | { |
14843 | pos.Y -= vec.Y * (pos.X - xFloor); | 14843 | pos.Y -= vec.Y * (pos.X - xFloor); |
14844 | pos.X = xFloor; | 14844 | pos.X = xFloor; |
14845 | } | 14845 | } |
14846 | else if (!bigX && pos.Y > yFloor) | 14846 | else if (!bigX && pos.Y > yFloor) |
14847 | { | 14847 | { |
14848 | pos.X -= vec.X * (pos.Y - yFloor); | 14848 | pos.X -= vec.X * (pos.Y - yFloor); |
14849 | pos.Y = yFloor; | 14849 | pos.Y = yFloor; |
14850 | } | 14850 | } |
14851 | 14851 | ||
14852 | // Last 1x1 rectangle under ray | 14852 | // Last 1x1 rectangle under ray |
14853 | if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y)) | 14853 | if ((bigX && pos.X >= posEnd.X) || (!bigX && pos.Y >= posEnd.Y)) |
14854 | { | 14854 | { |
14855 | pos = posEnd; | 14855 | pos = posEnd; |
14856 | xFloor = (float)Math.Floor(pos.X); | 14856 | xFloor = (float)Math.Floor(pos.X); |
14857 | yFloor = (float)Math.Floor(pos.Y); | 14857 | yFloor = (float)Math.Floor(pos.Y); |
14858 | } | 14858 | } |
14859 | 14859 | ||
14860 | // Add new 1x1 rectangle in lane | 14860 | // Add new 1x1 rectangle in lane |
14861 | if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld)) | 14861 | if ((bigX && xFloor != xFloorOld) || (!bigX && yFloor != yFloorOld)) |
14862 | AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); | 14862 | AddTrisFromHeightmap(xFloor, yFloor, ref triangles, ref zLower, ref zUpper); |
14863 | // Add last 1x1 rectangle in old lane at lane shift | 14863 | // Add last 1x1 rectangle in old lane at lane shift |
14864 | if (bigX && yFloor != yFloorOld) | 14864 | if (bigX && yFloor != yFloorOld) |
14865 | AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper); | 14865 | AddTrisFromHeightmap(xFloor, yFloorOld, ref triangles, ref zLower, ref zUpper); |
14866 | if (!bigX && xFloor != xFloorOld) | 14866 | if (!bigX && xFloor != xFloorOld) |
14867 | AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper); | 14867 | AddTrisFromHeightmap(xFloorOld, yFloor, ref triangles, ref zLower, ref zUpper); |
14868 | } | 14868 | } |
14869 | 14869 | ||
14870 | // Finalize bounding box Z | 14870 | // Finalize bounding box Z |
14871 | lower.Z = zLower; | 14871 | lower.Z = zLower; |
14872 | upper.Z = zUpper; | 14872 | upper.Z = zUpper; |
14873 | 14873 | ||
14874 | // Done and returning Tri (triangle)List | 14874 | // Done and returning Tri (triangle)List |
14875 | return triangles; | 14875 | return triangles; |
14876 | } | 14876 | } |
14877 | 14877 | ||
14878 | /// <summary> | 14878 | /// <summary> |
14879 | /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box. | 14879 | /// Helper to add HeightMap squares into Tri (triangle) List and adjust bounding box. |
14880 | /// </summary> | 14880 | /// </summary> |
14881 | private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper) | 14881 | private void AddTrisFromHeightmap(float xPos, float yPos, ref List<Tri> triangles, ref float zLower, ref float zUpper) |
14882 | { | 14882 | { |
14883 | int xInt = (int)xPos; | 14883 | int xInt = (int)xPos; |
14884 | int yInt = (int)yPos; | 14884 | int yInt = (int)yPos; |
14885 | 14885 | ||
14886 | // Corner 1 of 1x1 rectangle | 14886 | // Corner 1 of 1x1 rectangle |
14887 | int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); | 14887 | int x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); |
14888 | int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); | 14888 | int y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); |
14889 | Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]); | 14889 | Vector3 pos1 = new Vector3(x, y, (float)World.Heightmap[x, y]); |
14890 | // Adjust bounding box | 14890 | // Adjust bounding box |
14891 | zLower = Math.Min(zLower, pos1.Z); | 14891 | zLower = Math.Min(zLower, pos1.Z); |
14892 | zUpper = Math.Max(zUpper, pos1.Z); | 14892 | zUpper = Math.Max(zUpper, pos1.Z); |
14893 | 14893 | ||
14894 | // Corner 2 of 1x1 rectangle | 14894 | // Corner 2 of 1x1 rectangle |
14895 | x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); | 14895 | x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); |
14896 | y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); | 14896 | y = Util.Clamp<int>(yInt+1, 0, World.Heightmap.Height - 1); |
14897 | Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); | 14897 | Vector3 pos2 = new Vector3(x, y, (float)World.Heightmap[x, y]); |
14898 | // Adjust bounding box | 14898 | // Adjust bounding box |
14899 | zLower = Math.Min(zLower, pos2.Z); | 14899 | zLower = Math.Min(zLower, pos2.Z); |
14900 | zUpper = Math.Max(zUpper, pos2.Z); | 14900 | zUpper = Math.Max(zUpper, pos2.Z); |
14901 | 14901 | ||
14902 | // Corner 3 of 1x1 rectangle | 14902 | // Corner 3 of 1x1 rectangle |
14903 | x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); | 14903 | x = Util.Clamp<int>(xInt, 0, World.Heightmap.Width - 1); |
14904 | y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); | 14904 | y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); |
14905 | Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); | 14905 | Vector3 pos3 = new Vector3(x, y, (float)World.Heightmap[x, y]); |
14906 | // Adjust bounding box | 14906 | // Adjust bounding box |
14907 | zLower = Math.Min(zLower, pos3.Z); | 14907 | zLower = Math.Min(zLower, pos3.Z); |
14908 | zUpper = Math.Max(zUpper, pos3.Z); | 14908 | zUpper = Math.Max(zUpper, pos3.Z); |
14909 | 14909 | ||
14910 | // Corner 4 of 1x1 rectangle | 14910 | // Corner 4 of 1x1 rectangle |
14911 | x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); | 14911 | x = Util.Clamp<int>(xInt+1, 0, World.Heightmap.Width - 1); |
14912 | y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); | 14912 | y = Util.Clamp<int>(yInt, 0, World.Heightmap.Height - 1); |
14913 | Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); | 14913 | Vector3 pos4 = new Vector3(x, y, (float)World.Heightmap[x, y]); |
14914 | // Adjust bounding box | 14914 | // Adjust bounding box |
14915 | zLower = Math.Min(zLower, pos4.Z); | 14915 | zLower = Math.Min(zLower, pos4.Z); |
14916 | zUpper = Math.Max(zUpper, pos4.Z); | 14916 | zUpper = Math.Max(zUpper, pos4.Z); |
14917 | 14917 | ||
14918 | // Add triangle 1 | 14918 | // Add triangle 1 |
14919 | Tri triangle1 = new Tri(); | 14919 | Tri triangle1 = new Tri(); |
14920 | triangle1.p1 = pos1; | 14920 | triangle1.p1 = pos1; |
14921 | triangle1.p2 = pos2; | 14921 | triangle1.p2 = pos2; |
14922 | triangle1.p3 = pos3; | 14922 | triangle1.p3 = pos3; |
14923 | triangles.Add(triangle1); | 14923 | triangles.Add(triangle1); |
14924 | 14924 | ||
14925 | // Add triangle 2 | 14925 | // Add triangle 2 |
14926 | Tri triangle2 = new Tri(); | 14926 | Tri triangle2 = new Tri(); |
14927 | triangle2.p1 = pos3; | 14927 | triangle2.p1 = pos3; |
14928 | triangle2.p2 = pos4; | 14928 | triangle2.p2 = pos4; |
14929 | triangle2.p3 = pos1; | 14929 | triangle2.p3 = pos1; |
14930 | triangles.Add(triangle2); | 14930 | triangles.Add(triangle2); |
14931 | } | 14931 | } |
14932 | 14932 | ||
14933 | /// <summary> | 14933 | /// <summary> |
14934 | /// Helper to get link number for a UUID. | 14934 | /// Helper to get link number for a UUID. |
14935 | /// </summary> | 14935 | /// </summary> |
14936 | private int UUID2LinkNumber(SceneObjectPart part, UUID id) | 14936 | private int UUID2LinkNumber(SceneObjectPart part, UUID id) |
14937 | { | 14937 | { |
14938 | SceneObjectGroup group = part.ParentGroup; | 14938 | SceneObjectGroup group = part.ParentGroup; |
14939 | if (group != null) | 14939 | if (group != null) |
14940 | { | 14940 | { |
14941 | // Parse every link for UUID | 14941 | // Parse every link for UUID |
14942 | int linkCount = group.PrimCount + group.GetSittingAvatarsCount(); | 14942 | int linkCount = group.PrimCount + group.GetSittingAvatarsCount(); |
14943 | for (int link = linkCount; link > 0; link--) | 14943 | for (int link = linkCount; link > 0; link--) |
14944 | { | 14944 | { |
14945 | ISceneEntity entity = GetLinkEntity(part, link); | 14945 | ISceneEntity entity = GetLinkEntity(part, link); |
14946 | // Return link number if UUID match | 14946 | // Return link number if UUID match |
14947 | if (entity != null && entity.UUID == id) | 14947 | if (entity != null && entity.UUID == id) |
14948 | return link; | 14948 | return link; |
14949 | } | 14949 | } |
14950 | } | 14950 | } |
14951 | // Return link number 0 if no links or UUID matches | 14951 | // Return link number 0 if no links or UUID matches |
14952 | return 0; | 14952 | return 0; |
14953 | } | 14953 | } |
14954 | 14954 | ||
14955 | public LSL_Integer llManageEstateAccess(int action, string avatar) | 14955 | public LSL_Integer llManageEstateAccess(int action, string avatar) |
14956 | { | 14956 | { |
14957 | m_host.AddScriptLPS(1); | 14957 | m_host.AddScriptLPS(1); |
14958 | EstateSettings estate = World.RegionInfo.EstateSettings; | 14958 | EstateSettings estate = World.RegionInfo.EstateSettings; |
14959 | bool isAccount = false; | 14959 | bool isAccount = false; |
14960 | bool isGroup = false; | 14960 | bool isGroup = false; |
14961 | 14961 | ||
14962 | if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID)) | 14962 | if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManagerOrOwner(m_host.OwnerID)) |
14963 | return 0; | 14963 | return 0; |
14964 | 14964 | ||
14965 | UUID id = new UUID(); | 14965 | UUID id = new UUID(); |
14966 | if (!UUID.TryParse(avatar, out id)) | 14966 | if (!UUID.TryParse(avatar, out id)) |
14967 | return 0; | 14967 | return 0; |
14968 | 14968 | ||
14969 | UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, id); | 14969 | UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, id); |
14970 | isAccount = account != null ? true : false; | 14970 | isAccount = account != null ? true : false; |
14971 | if (!isAccount) | 14971 | if (!isAccount) |
14972 | { | 14972 | { |
14973 | IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>(); | 14973 | IGroupsModule groups = World.RequestModuleInterface<IGroupsModule>(); |
14974 | if (groups != null) | 14974 | if (groups != null) |
14975 | { | 14975 | { |
14976 | GroupRecord group = groups.GetGroupRecord(id); | 14976 | GroupRecord group = groups.GetGroupRecord(id); |
14977 | isGroup = group != null ? true : false; | 14977 | isGroup = group != null ? true : false; |
14978 | if (!isGroup) | 14978 | if (!isGroup) |
14979 | return 0; | 14979 | return 0; |
14980 | } | 14980 | } |
14981 | else | 14981 | else |
14982 | return 0; | 14982 | return 0; |
14983 | } | 14983 | } |
14984 | 14984 | ||
14985 | switch (action) | 14985 | switch (action) |
14986 | { | 14986 | { |
14987 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: | 14987 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: |
14988 | if (!isAccount) return 0; | 14988 | if (!isAccount) return 0; |
14989 | if (estate.HasAccess(id)) return 1; | 14989 | if (estate.HasAccess(id)) return 1; |
14990 | if (estate.IsBanned(id)) | 14990 | if (estate.IsBanned(id)) |
14991 | estate.RemoveBan(id); | 14991 | estate.RemoveBan(id); |
14992 | estate.AddEstateUser(id); | 14992 | estate.AddEstateUser(id); |
14993 | break; | 14993 | break; |
14994 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_REMOVE: | 14994 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_REMOVE: |
14995 | if (!isAccount || !estate.HasAccess(id)) return 0; | 14995 | if (!isAccount || !estate.HasAccess(id)) return 0; |
14996 | estate.RemoveEstateUser(id); | 14996 | estate.RemoveEstateUser(id); |
14997 | break; | 14997 | break; |
14998 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_ADD: | 14998 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_ADD: |
14999 | if (!isGroup) return 0; | 14999 | if (!isGroup) return 0; |
15000 | if (estate.GroupAccess(id)) return 1; | 15000 | if (estate.GroupAccess(id)) return 1; |
15001 | estate.AddEstateGroup(id); | 15001 | estate.AddEstateGroup(id); |
15002 | break; | 15002 | break; |
15003 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_REMOVE: | 15003 | case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_REMOVE: |
15004 | if (!isGroup || !estate.GroupAccess(id)) return 0; | 15004 | if (!isGroup || !estate.GroupAccess(id)) return 0; |
15005 | estate.RemoveEstateGroup(id); | 15005 | estate.RemoveEstateGroup(id); |
15006 | break; | 15006 | break; |
15007 | case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: | 15007 | case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: |
15008 | if (!isAccount) return 0; | 15008 | if (!isAccount) return 0; |
15009 | if (estate.IsBanned(id)) return 1; | 15009 | if (estate.IsBanned(id)) return 1; |
15010 | EstateBan ban = new EstateBan(); | 15010 | EstateBan ban = new EstateBan(); |
15011 | ban.EstateID = estate.EstateID; | 15011 | ban.EstateID = estate.EstateID; |
15012 | ban.BannedUserID = id; | 15012 | ban.BannedUserID = id; |
15013 | estate.AddBan(ban); | 15013 | estate.AddBan(ban); |
15014 | break; | 15014 | break; |
15015 | case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: | 15015 | case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: |
15016 | if (!isAccount || !estate.IsBanned(id)) return 0; | 15016 | if (!isAccount || !estate.IsBanned(id)) return 0; |
15017 | estate.RemoveBan(id); | 15017 | estate.RemoveBan(id); |
15018 | break; | 15018 | break; |
15019 | default: return 0; | 15019 | default: return 0; |
15020 | } | 15020 | } |
15021 | return 1; | 15021 | return 1; |
15022 | } | 15022 | } |
15023 | 15023 | ||
15024 | public LSL_Integer llGetMemoryLimit() | 15024 | public LSL_Integer llGetMemoryLimit() |
15025 | { | 15025 | { |
15026 | m_host.AddScriptLPS(1); | 15026 | m_host.AddScriptLPS(1); |
15027 | // The value returned for Mono scripts in SL | 15027 | // The value returned for Mono scripts in SL |
15028 | return 65536; | 15028 | return 65536; |
15029 | } | 15029 | } |
15030 | 15030 | ||
15031 | public LSL_Integer llSetMemoryLimit(LSL_Integer limit) | 15031 | public LSL_Integer llSetMemoryLimit(LSL_Integer limit) |
15032 | { | 15032 | { |
15033 | m_host.AddScriptLPS(1); | 15033 | m_host.AddScriptLPS(1); |
15034 | // Treat as an LSO script | 15034 | // Treat as an LSO script |
15035 | return ScriptBaseClass.FALSE; | 15035 | return ScriptBaseClass.FALSE; |
15036 | } | 15036 | } |
15037 | 15037 | ||
15038 | public LSL_Integer llGetSPMaxMemory() | 15038 | public LSL_Integer llGetSPMaxMemory() |
15039 | { | 15039 | { |
15040 | m_host.AddScriptLPS(1); | 15040 | m_host.AddScriptLPS(1); |
15041 | // The value returned for Mono scripts in SL | 15041 | // The value returned for Mono scripts in SL |
15042 | return 65536; | 15042 | return 65536; |
15043 | } | 15043 | } |
15044 | 15044 | ||
15045 | public virtual LSL_Integer llGetUsedMemory() | 15045 | public virtual LSL_Integer llGetUsedMemory() |
15046 | { | 15046 | { |
15047 | m_host.AddScriptLPS(1); | 15047 | m_host.AddScriptLPS(1); |
15048 | // The value returned for Mono scripts in SL | 15048 | // The value returned for Mono scripts in SL |
15049 | return 65536; | 15049 | return 65536; |
15050 | } | 15050 | } |
15051 | 15051 | ||
15052 | public void llScriptProfiler(LSL_Integer flags) | 15052 | public void llScriptProfiler(LSL_Integer flags) |
15053 | { | 15053 | { |
15054 | m_host.AddScriptLPS(1); | 15054 | m_host.AddScriptLPS(1); |
15055 | // This does nothing for LSO scripts in SL | 15055 | // This does nothing for LSO scripts in SL |
15056 | } | 15056 | } |
15057 | 15057 | ||
15058 | #region Not Implemented | 15058 | #region Not Implemented |
15059 | // | 15059 | // |
15060 | // Listing the unimplemented lsl functions here, please move | 15060 | // Listing the unimplemented lsl functions here, please move |
15061 | // them from this region as they are completed | 15061 | // them from this region as they are completed |
15062 | // | 15062 | // |
15063 | 15063 | ||
15064 | public void llSetSoundQueueing(int queue) | 15064 | public void llSetSoundQueueing(int queue) |
15065 | { | 15065 | { |
15066 | m_host.AddScriptLPS(1); | 15066 | m_host.AddScriptLPS(1); |
15067 | 15067 | ||
15068 | if (m_SoundModule != null) | 15068 | if (m_SoundModule != null) |
15069 | m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value); | 15069 | m_SoundModule.SetSoundQueueing(m_host.UUID, queue == ScriptBaseClass.TRUE.value); |
15070 | } | 15070 | } |
15071 | 15071 | ||
15072 | public void llCollisionSprite(string impact_sprite) | 15072 | public void llCollisionSprite(string impact_sprite) |
15073 | { | 15073 | { |
15074 | m_host.AddScriptLPS(1); | 15074 | m_host.AddScriptLPS(1); |
15075 | NotImplemented("llCollisionSprite"); | 15075 | NotImplemented("llCollisionSprite"); |
15076 | } | 15076 | } |
15077 | 15077 | ||
15078 | public void llGodLikeRezObject(string inventory, LSL_Vector pos) | 15078 | public void llGodLikeRezObject(string inventory, LSL_Vector pos) |
15079 | { | 15079 | { |
15080 | m_host.AddScriptLPS(1); | 15080 | m_host.AddScriptLPS(1); |
15081 | NotImplemented("llGodLikeRezObject"); | 15081 | NotImplemented("llGodLikeRezObject"); |
15082 | } | 15082 | } |
15083 | 15083 | ||
15084 | public LSL_String llTransferLindenDollars(string destination, int amount) | 15084 | public LSL_String llTransferLindenDollars(string destination, int amount) |
15085 | { | 15085 | { |
15086 | UUID txn = UUID.Random(); | 15086 | UUID txn = UUID.Random(); |
15087 | 15087 | ||
15088 | Util.FireAndForget(delegate(object x) | 15088 | Util.FireAndForget(delegate(object x) |
15089 | { | 15089 | { |
15090 | int replycode = 0; | 15090 | int replycode = 0; |
15091 | string replydata = destination + "," + amount.ToString(); | 15091 | string replydata = destination + "," + amount.ToString(); |
15092 | 15092 | ||
15093 | try | 15093 | try |
15094 | { | 15094 | { |
15095 | TaskInventoryItem item = m_item; | 15095 | TaskInventoryItem item = m_item; |
15096 | if (item == null) | 15096 | if (item == null) |
15097 | { | 15097 | { |
15098 | replydata = "SERVICE_ERROR"; | 15098 | replydata = "SERVICE_ERROR"; |
15099 | return; | 15099 | return; |
15100 | } | 15100 | } |
15101 | 15101 | ||
15102 | m_host.AddScriptLPS(1); | 15102 | m_host.AddScriptLPS(1); |
15103 | 15103 | ||
15104 | if (item.PermsGranter == UUID.Zero) | 15104 | if (item.PermsGranter == UUID.Zero) |
15105 | { | 15105 | { |
15106 | replydata = "MISSING_PERMISSION_DEBIT"; | 15106 | replydata = "MISSING_PERMISSION_DEBIT"; |
15107 | return; | 15107 | return; |
15108 | } | 15108 | } |
15109 | 15109 | ||
15110 | if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) | 15110 | if ((item.PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) |
15111 | { | 15111 | { |
15112 | replydata = "MISSING_PERMISSION_DEBIT"; | 15112 | replydata = "MISSING_PERMISSION_DEBIT"; |
15113 | return; | 15113 | return; |
15114 | } | 15114 | } |
15115 | 15115 | ||
15116 | UUID toID = new UUID(); | 15116 | UUID toID = new UUID(); |
15117 | 15117 | ||
15118 | if (!UUID.TryParse(destination, out toID)) | 15118 | if (!UUID.TryParse(destination, out toID)) |
15119 | { | 15119 | { |
15120 | replydata = "INVALID_AGENT"; | 15120 | replydata = "INVALID_AGENT"; |
15121 | return; | 15121 | return; |
15122 | } | 15122 | } |
15123 | 15123 | ||
15124 | IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); | 15124 | IMoneyModule money = World.RequestModuleInterface<IMoneyModule>(); |
15125 | 15125 | ||
15126 | if (money == null) | 15126 | if (money == null) |
15127 | { | 15127 | { |
15128 | replydata = "TRANSFERS_DISABLED"; | 15128 | replydata = "TRANSFERS_DISABLED"; |
15129 | return; | 15129 | return; |
15130 | } | 15130 | } |
15131 | 15131 | ||
15132 | bool result = money.ObjectGiveMoney( | 15132 | bool result = money.ObjectGiveMoney( |
15133 | m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); | 15133 | m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); |
15134 | 15134 | ||
15135 | if (result) | 15135 | if (result) |
15136 | { | 15136 | { |
15137 | replycode = 1; | 15137 | replycode = 1; |
15138 | return; | 15138 | return; |
15139 | } | 15139 | } |
15140 | 15140 | ||
15141 | replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS"; | 15141 | replydata = "LINDENDOLLAR_INSUFFICIENTFUNDS"; |
15142 | } | 15142 | } |
15143 | finally | 15143 | finally |
15144 | { | 15144 | { |
15145 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( | 15145 | m_ScriptEngine.PostScriptEvent(m_item.ItemID, new EventParams( |
15146 | "transaction_result", new Object[] { | 15146 | "transaction_result", new Object[] { |
15147 | new LSL_String(txn.ToString()), | 15147 | new LSL_String(txn.ToString()), |
15148 | new LSL_Integer(replycode), | 15148 | new LSL_Integer(replycode), |
15149 | new LSL_String(replydata) }, | 15149 | new LSL_String(replydata) }, |
15150 | new DetectParams[0])); | 15150 | new DetectParams[0])); |
15151 | } | 15151 | } |
15152 | }, null, "LSL_Api.llTransferLindenDollars"); | 15152 | }, null, "LSL_Api.llTransferLindenDollars"); |
15153 | 15153 | ||
15154 | return txn.ToString(); | 15154 | return txn.ToString(); |
15155 | } | 15155 | } |
15156 | 15156 | ||
15157 | #endregion | 15157 | #endregion |
15158 | } | 15158 | } |
15159 | 15159 | ||
15160 | public class NotecardCache | 15160 | public class NotecardCache |
15161 | { | 15161 | { |
15162 | protected class Notecard | 15162 | protected class Notecard |
15163 | { | 15163 | { |
15164 | public string[] text; | 15164 | public string[] text; |
15165 | public DateTime lastRef; | 15165 | public DateTime lastRef; |
15166 | } | 15166 | } |
15167 | 15167 | ||
15168 | private static Dictionary<UUID, Notecard> m_Notecards = | 15168 | private static Dictionary<UUID, Notecard> m_Notecards = |
15169 | new Dictionary<UUID, Notecard>(); | 15169 | new Dictionary<UUID, Notecard>(); |
15170 | 15170 | ||
15171 | public static void Cache(UUID assetID, byte[] text) | 15171 | public static void Cache(UUID assetID, byte[] text) |
15172 | { | 15172 | { |
15173 | CheckCache(); | 15173 | CheckCache(); |
15174 | 15174 | ||
15175 | lock (m_Notecards) | 15175 | lock (m_Notecards) |
15176 | { | 15176 | { |
15177 | if (m_Notecards.ContainsKey(assetID)) | 15177 | if (m_Notecards.ContainsKey(assetID)) |
15178 | return; | 15178 | return; |
15179 | 15179 | ||
15180 | Notecard nc = new Notecard(); | 15180 | Notecard nc = new Notecard(); |
15181 | nc.lastRef = DateTime.Now; | 15181 | nc.lastRef = DateTime.Now; |
15182 | try | 15182 | try |
15183 | { | 15183 | { |
15184 | nc.text = SLUtil.ParseNotecardToArray(text); | 15184 | nc.text = SLUtil.ParseNotecardToArray(text); |
15185 | } | 15185 | } |
15186 | catch(SLUtil.NotANotecardFormatException) | 15186 | catch(SLUtil.NotANotecardFormatException) |
15187 | { | 15187 | { |
15188 | nc.text = new string[0]; | 15188 | nc.text = new string[0]; |
15189 | } | 15189 | } |
15190 | m_Notecards[assetID] = nc; | 15190 | m_Notecards[assetID] = nc; |
15191 | } | 15191 | } |
15192 | } | 15192 | } |
15193 | 15193 | ||
15194 | public static bool IsCached(UUID assetID) | 15194 | public static bool IsCached(UUID assetID) |
15195 | { | 15195 | { |
15196 | lock (m_Notecards) | 15196 | lock (m_Notecards) |
15197 | { | 15197 | { |
15198 | return m_Notecards.ContainsKey(assetID); | 15198 | return m_Notecards.ContainsKey(assetID); |
15199 | } | 15199 | } |
15200 | } | 15200 | } |
15201 | 15201 | ||
15202 | public static int GetLines(UUID assetID) | 15202 | public static int GetLines(UUID assetID) |
15203 | { | 15203 | { |
15204 | if (!IsCached(assetID)) | 15204 | if (!IsCached(assetID)) |
15205 | return -1; | 15205 | return -1; |
15206 | 15206 | ||
15207 | lock (m_Notecards) | 15207 | lock (m_Notecards) |
15208 | { | 15208 | { |
15209 | m_Notecards[assetID].lastRef = DateTime.Now; | 15209 | m_Notecards[assetID].lastRef = DateTime.Now; |
15210 | return m_Notecards[assetID].text.Length; | 15210 | return m_Notecards[assetID].text.Length; |
15211 | } | 15211 | } |
15212 | } | 15212 | } |
15213 | 15213 | ||
15214 | /// <summary> | 15214 | /// <summary> |
15215 | /// Get a notecard line. | 15215 | /// Get a notecard line. |
15216 | /// </summary> | 15216 | /// </summary> |
15217 | /// <param name="assetID"></param> | 15217 | /// <param name="assetID"></param> |
15218 | /// <param name="lineNumber">Lines start at index 0</param> | 15218 | /// <param name="lineNumber">Lines start at index 0</param> |
15219 | /// <returns></returns> | 15219 | /// <returns></returns> |
15220 | public static string GetLine(UUID assetID, int lineNumber) | 15220 | public static string GetLine(UUID assetID, int lineNumber) |
15221 | { | 15221 | { |
15222 | if (lineNumber < 0) | 15222 | if (lineNumber < 0) |
15223 | return ""; | 15223 | return ""; |
15224 | 15224 | ||
15225 | string data; | 15225 | string data; |
15226 | 15226 | ||
15227 | if (!IsCached(assetID)) | 15227 | if (!IsCached(assetID)) |
15228 | return ""; | 15228 | return ""; |
15229 | 15229 | ||
15230 | lock (m_Notecards) | 15230 | lock (m_Notecards) |
15231 | { | 15231 | { |
15232 | m_Notecards[assetID].lastRef = DateTime.Now; | 15232 | m_Notecards[assetID].lastRef = DateTime.Now; |
15233 | 15233 | ||
15234 | if (lineNumber >= m_Notecards[assetID].text.Length) | 15234 | if (lineNumber >= m_Notecards[assetID].text.Length) |
15235 | return "\n\n\n"; | 15235 | return "\n\n\n"; |
15236 | 15236 | ||
15237 | data = m_Notecards[assetID].text[lineNumber]; | 15237 | data = m_Notecards[assetID].text[lineNumber]; |
15238 | 15238 | ||
15239 | return data; | 15239 | return data; |
15240 | } | 15240 | } |
15241 | } | 15241 | } |
15242 | 15242 | ||
15243 | /// <summary> | 15243 | /// <summary> |
15244 | /// Get a notecard line. | 15244 | /// Get a notecard line. |
15245 | /// </summary> | 15245 | /// </summary> |
15246 | /// <param name="assetID"></param> | 15246 | /// <param name="assetID"></param> |
15247 | /// <param name="lineNumber">Lines start at index 0</param> | 15247 | /// <param name="lineNumber">Lines start at index 0</param> |
15248 | /// <param name="maxLength"> | 15248 | /// <param name="maxLength"> |
15249 | /// Maximum length of the returned line. | 15249 | /// Maximum length of the returned line. |
15250 | /// </param> | 15250 | /// </param> |
15251 | /// <returns> | 15251 | /// <returns> |
15252 | /// If the line length is longer than <paramref name="maxLength"/>, | 15252 | /// If the line length is longer than <paramref name="maxLength"/>, |
15253 | /// the return string will be truncated. | 15253 | /// the return string will be truncated. |
15254 | /// </returns> | 15254 | /// </returns> |
15255 | public static string GetLine(UUID assetID, int lineNumber, int maxLength) | 15255 | public static string GetLine(UUID assetID, int lineNumber, int maxLength) |
15256 | { | 15256 | { |
15257 | string line = GetLine(assetID, lineNumber); | 15257 | string line = GetLine(assetID, lineNumber); |
15258 | 15258 | ||
15259 | if (line.Length > maxLength) | 15259 | if (line.Length > maxLength) |
15260 | line = line.Substring(0, maxLength); | 15260 | line = line.Substring(0, maxLength); |
15261 | 15261 | ||
15262 | return line; | 15262 | return line; |
15263 | } | 15263 | } |
15264 | 15264 | ||
15265 | public static void CheckCache() | 15265 | public static void CheckCache() |
15266 | { | 15266 | { |
15267 | lock (m_Notecards) | 15267 | lock (m_Notecards) |
15268 | { | 15268 | { |
15269 | foreach (UUID key in new List<UUID>(m_Notecards.Keys)) | 15269 | foreach (UUID key in new List<UUID>(m_Notecards.Keys)) |
15270 | { | 15270 | { |
15271 | Notecard nc = m_Notecards[key]; | 15271 | Notecard nc = m_Notecards[key]; |
15272 | if (nc.lastRef.AddSeconds(30) < DateTime.Now) | 15272 | if (nc.lastRef.AddSeconds(30) < DateTime.Now) |
15273 | m_Notecards.Remove(key); | 15273 | m_Notecards.Remove(key); |
15274 | } | 15274 | } |
15275 | } | 15275 | } |
15276 | } | 15276 | } |
15277 | } | 15277 | } |
15278 | } | 15278 | } |