diff options
author | Melanie Thielker | 2008-09-26 02:51:00 +0000 |
---|---|---|
committer | Melanie Thielker | 2008-09-26 02:51:00 +0000 |
commit | c21a8b99694e459408a9ccc43e525928038b2b22 (patch) | |
tree | 21190b513065cc7b1f3442d2cf2ed9ce1d2077f4 /OpenSim | |
parent | Mantis#2265. Thank you kindly, Idb for a patch that: (diff) | |
download | opensim-SC-c21a8b99694e459408a9ccc43e525928038b2b22.zip opensim-SC-c21a8b99694e459408a9ccc43e525928038b2b22.tar.gz opensim-SC-c21a8b99694e459408a9ccc43e525928038b2b22.tar.bz2 opensim-SC-c21a8b99694e459408a9ccc43e525928038b2b22.tar.xz |
Full API convergence. Api is back in LSL_Api.cs and OSSL_Api.cs.
The binaries are still different, but that is only a small step away now.
The OSSLPrim has been removed. This commit will breal all scripts
using Prim.Scale(), etc, syntax. It was not secure and will have to
be brought back in another form.
Diffstat (limited to '')
18 files changed, 8389 insertions, 9970 deletions
diff --git a/OpenSim/Region/ScriptEngine/Common/BuilIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/BuilIn_Commands.cs deleted file mode 100644 index 9c45ab5..0000000 --- a/OpenSim/Region/ScriptEngine/Common/BuilIn_Commands.cs +++ /dev/null | |||
@@ -1,43 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using OpenMetaverse; | ||
29 | using OpenSim.Region.Environment.Scenes; | ||
30 | |||
31 | namespace OpenSim.Region.ScriptEngine.Common | ||
32 | { | ||
33 | /// <summary> | ||
34 | /// This is the end of a chain of inherited builtin command implementations. This module will be instanced by script engines. | ||
35 | /// </summary> | ||
36 | public class BuilIn_Commands : OSSL_BuilIn_Commands | ||
37 | { | ||
38 | public BuilIn_Commands(ScriptEngineBase.ScriptEngine scriptEngine, SceneObjectPart host, uint localID, | ||
39 | UUID itemID) : base(scriptEngine, host, localID, itemID) | ||
40 | { | ||
41 | } | ||
42 | } | ||
43 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Common/IScript.cs b/OpenSim/Region/ScriptEngine/Common/IScript.cs index 754e86b..8d91071 100644 --- a/OpenSim/Region/ScriptEngine/Common/IScript.cs +++ b/OpenSim/Region/ScriptEngine/Common/IScript.cs | |||
@@ -27,6 +27,7 @@ | |||
27 | 27 | ||
28 | using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; | 28 | using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; |
29 | using OpenSim.Region.ScriptEngine.Shared; | 29 | using OpenSim.Region.ScriptEngine.Shared; |
30 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
30 | 31 | ||
31 | namespace OpenSim.Region.ScriptEngine.Common | 32 | namespace OpenSim.Region.ScriptEngine.Common |
32 | { | 33 | { |
@@ -36,6 +37,6 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
36 | int StartParam { get; set; } | 37 | int StartParam { get; set; } |
37 | ExecutorBase Exec { get; } | 38 | ExecutorBase Exec { get; } |
38 | string Source { get; set; } | 39 | string Source { get; set; } |
39 | void Start(BuilIn_Commands BuiltIn_Commands); | 40 | void InitApi(string api, IScriptApi LSL_Functions); |
40 | } | 41 | } |
41 | } | 42 | } |
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs deleted file mode 100644 index 8252bfc..0000000 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands.cs +++ /dev/null | |||
@@ -1,262 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Runtime.Remoting.Lifetime; | ||
32 | using System.Text; | ||
33 | using System.Threading; | ||
34 | using Nini.Config; | ||
35 | using OpenMetaverse; | ||
36 | using OpenMetaverse.Packets; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Framework.Communications.Cache; | ||
39 | using OpenSim.Region.Environment; | ||
40 | using OpenSim.Region.Interfaces; | ||
41 | using OpenSim.Region.Environment.Interfaces; | ||
42 | using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; | ||
43 | using OpenSim.Region.Environment.Modules.World.Land; | ||
44 | using OpenSim.Region.Environment.Scenes; | ||
45 | using OpenSim.Region.Physics.Manager; | ||
46 | using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; | ||
47 | using OpenSim.Region.ScriptEngine.Shared; | ||
48 | using OpenSim.Region.ScriptEngine.Shared.Api; | ||
49 | |||
50 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | ||
51 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | ||
52 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
53 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; | ||
54 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | ||
55 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
56 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | ||
57 | |||
58 | namespace OpenSim.Region.ScriptEngine.Common | ||
59 | { | ||
60 | /// <summary> | ||
61 | /// Contains all LSL ll-functions. This class will be in Default AppDomain. | ||
62 | /// </summary> | ||
63 | public class LSL_BuiltIn_Commands : LSL_Api_Base, LSL_BuiltIn_Commands_Interface | ||
64 | { | ||
65 | // private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | ||
66 | |||
67 | internal ScriptEngineBase.ScriptEngine m_ScriptEngineDirect; | ||
68 | |||
69 | public LSL_BuiltIn_Commands(ScriptEngineBase.ScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) | ||
70 | { | ||
71 | m_ScriptEngineDirect = ScriptEngine; | ||
72 | m_ScriptEngine = ScriptEngine; | ||
73 | m_host = host; | ||
74 | m_localID = localID; | ||
75 | m_itemID = itemID; | ||
76 | |||
77 | AsyncCommands = new AsyncCommandManager(m_ScriptEngine); | ||
78 | |||
79 | //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called. Hosted by [" + m_host.Name + ":" + m_host.UUID + "@" + m_host.AbsolutePosition + "]"); | ||
80 | |||
81 | |||
82 | IConfigSource config = new IniConfigSource(Application.iniFilePath); | ||
83 | if (config.Configs["LL-Functions"] == null) | ||
84 | config.AddConfig("LL-Functions"); | ||
85 | |||
86 | m_ScriptDelayFactor = config.Configs["LL-Functions"].GetFloat("ScriptDelayFactor", 1.0f); | ||
87 | m_ScriptDistanceFactor = config.Configs["LL-Functions"].GetFloat("ScriptDistanceLimitFactor", 1.0f); | ||
88 | |||
89 | } | ||
90 | |||
91 | private string m_state = "default"; | ||
92 | |||
93 | protected void ScriptSleep(int delay) | ||
94 | { | ||
95 | delay = (int)((float)delay * m_ScriptDelayFactor); | ||
96 | if (delay == 0) | ||
97 | return; | ||
98 | System.Threading.Thread.Sleep(delay); | ||
99 | } | ||
100 | |||
101 | // Object never expires | ||
102 | public override Object InitializeLifetimeService() | ||
103 | { | ||
104 | ILease lease = (ILease)base.InitializeLifetimeService(); | ||
105 | |||
106 | if (lease.CurrentState == LeaseState.Initial) | ||
107 | { | ||
108 | lease.InitialLeaseTime = TimeSpan.Zero; | ||
109 | } | ||
110 | return lease; | ||
111 | } | ||
112 | |||
113 | public string State | ||
114 | { | ||
115 | get { return m_state; } | ||
116 | set { | ||
117 | // Set it if it changed | ||
118 | if (m_state != value) | ||
119 | { | ||
120 | try | ||
121 | { | ||
122 | m_ScriptEngineDirect.m_EventManager.state_exit(m_localID); | ||
123 | |||
124 | } | ||
125 | catch (AppDomainUnloadedException) | ||
126 | { | ||
127 | Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); | ||
128 | } | ||
129 | m_state = value; | ||
130 | try | ||
131 | { | ||
132 | int eventFlags = m_ScriptEngineDirect.m_ScriptManager.GetStateEventFlags(m_localID, m_itemID); | ||
133 | m_host.SetScriptEvents(m_itemID, eventFlags); | ||
134 | m_ScriptEngineDirect.m_EventManager.state_entry(m_localID); | ||
135 | } | ||
136 | catch (AppDomainUnloadedException) | ||
137 | { | ||
138 | Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | } | ||
143 | |||
144 | // Extension commands use this: | ||
145 | public ICommander GetCommander(string name) | ||
146 | { | ||
147 | return World.GetCommander(name); | ||
148 | } | ||
149 | |||
150 | public LSL_Integer llGetScriptState(string name) | ||
151 | { | ||
152 | UUID item; | ||
153 | ScriptManager sm; | ||
154 | IScript script = null; | ||
155 | |||
156 | m_host.AddScriptLPS(1); | ||
157 | |||
158 | // These functions are supposed to be robust, | ||
159 | // so get the state one step at a time. | ||
160 | |||
161 | if ((item = ScriptByName(name)) != UUID.Zero) | ||
162 | { | ||
163 | if ((sm = m_ScriptEngineDirect.m_ScriptManager) != null) | ||
164 | { | ||
165 | if ((script = sm.GetScript(m_localID, item)) != null) | ||
166 | { | ||
167 | return script.Exec.Running?1:0; | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
172 | // Required by SL | ||
173 | |||
174 | if (script == null) | ||
175 | ShoutError("llGetScriptState: script "+name+" not found"); | ||
176 | |||
177 | // If we didn't find it, then it's safe to | ||
178 | // assume it is not running. | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | public void llResetOtherScript(string name) | ||
184 | { | ||
185 | UUID item; | ||
186 | ScriptManager sm; | ||
187 | IScript script = null; | ||
188 | |||
189 | m_host.AddScriptLPS(8000); | ||
190 | |||
191 | // These functions are supposed to be robust, | ||
192 | // so get the state one step at a time. | ||
193 | |||
194 | if ((item = ScriptByName(name)) != UUID.Zero) | ||
195 | if ((sm = m_ScriptEngineDirect.m_ScriptManager) != null) | ||
196 | sm.ResetScript(m_localID, item); | ||
197 | |||
198 | // Required by SL | ||
199 | |||
200 | if (script == null) | ||
201 | ShoutError("llResetOtherScript: script "+name+" not found"); | ||
202 | |||
203 | // If we didn't find it, then it's safe to | ||
204 | // assume it is not running. | ||
205 | } | ||
206 | |||
207 | public void llResetScript() | ||
208 | { | ||
209 | m_host.AddScriptLPS(800); | ||
210 | m_ScriptEngineDirect.m_ScriptManager.ResetScript(m_localID, m_itemID); | ||
211 | } | ||
212 | |||
213 | public void llSetScriptState(string name, int run) | ||
214 | { | ||
215 | UUID item; | ||
216 | ScriptManager sm; | ||
217 | IScript script = null; | ||
218 | |||
219 | m_host.AddScriptLPS(1); | ||
220 | |||
221 | // These functions are supposed to be robust, | ||
222 | // so get the state one step at a time. | ||
223 | |||
224 | if ((item = ScriptByName(name)) != UUID.Zero) | ||
225 | { | ||
226 | if ((sm = m_ScriptEngineDirect.m_ScriptManager) != null) | ||
227 | { | ||
228 | if (sm.Scripts.ContainsKey(m_localID)) | ||
229 | { | ||
230 | if ((script = sm.GetScript(m_localID, item)) != null) | ||
231 | { | ||
232 | script.Exec.Running = (run==0) ? false : true; | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | } | ||
237 | |||
238 | // Required by SL | ||
239 | |||
240 | if (script == null) | ||
241 | ShoutError("llSetScriptState: script "+name+" not found"); | ||
242 | |||
243 | // If we didn't find it, then it's safe to | ||
244 | // assume it is not running. | ||
245 | } | ||
246 | |||
247 | internal UUID ScriptByName(string name) | ||
248 | { | ||
249 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
250 | { | ||
251 | if (item.Type == 10 && item.Name == name) | ||
252 | return item.ItemID; | ||
253 | } | ||
254 | return UUID.Zero; | ||
255 | } | ||
256 | |||
257 | internal void ShoutError(string msg) | ||
258 | { | ||
259 | llShout(ScriptBaseClass.DEBUG_CHANNEL, msg); | ||
260 | } | ||
261 | } | ||
262 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs b/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs deleted file mode 100644 index e05849d..0000000 --- a/OpenSim/Region/ScriptEngine/Common/LSL_BuiltIn_Commands_Interface.cs +++ /dev/null | |||
@@ -1,391 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using OpenSim.Region.Environment.Interfaces; | ||
29 | |||
30 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | ||
31 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | ||
32 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
33 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; | ||
34 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | ||
35 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
36 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | ||
37 | |||
38 | namespace OpenSim.Region.ScriptEngine.Common | ||
39 | { | ||
40 | public interface LSL_BuiltIn_Commands_Interface | ||
41 | { | ||
42 | // Interface used for loading and executing scripts | ||
43 | |||
44 | string State { get; set; } | ||
45 | |||
46 | ICommander GetCommander(string name); | ||
47 | |||
48 | LSL_Integer llAbs(int i); | ||
49 | LSL_Float llAcos(double val); | ||
50 | void llAddToLandBanList(string avatar, double hours); | ||
51 | void llAddToLandPassList(string avatar, double hours); | ||
52 | void llAdjustSoundVolume(double volume); | ||
53 | void llAllowInventoryDrop(int add); | ||
54 | LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b); | ||
55 | void llApplyImpulse(LSL_Vector force, int local); | ||
56 | void llApplyRotationalImpulse(LSL_Vector force, int local); | ||
57 | LSL_Float llAsin(double val); | ||
58 | LSL_Float llAtan2(double x, double y); | ||
59 | void llAttachToAvatar(int attachment); | ||
60 | LSL_Key llAvatarOnSitTarget(); | ||
61 | LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up); | ||
62 | LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle); | ||
63 | LSL_Integer llBase64ToInteger(string str); | ||
64 | LSL_String llBase64ToString(string str); | ||
65 | void llBreakAllLinks(); | ||
66 | void llBreakLink(int linknum); | ||
67 | LSL_Integer llCeil(double f); | ||
68 | void llClearCameraParams(); | ||
69 | void llCloseRemoteDataChannel(string channel); | ||
70 | LSL_Float llCloud(LSL_Vector offset); | ||
71 | void llCollisionFilter(string name, string id, int accept); | ||
72 | void llCollisionSound(string impact_sound, double impact_volume); | ||
73 | void llCollisionSprite(string impact_sprite); | ||
74 | LSL_Float llCos(double f); | ||
75 | void llCreateLink(string target, int parent); | ||
76 | LSL_List llCSV2List(string src); | ||
77 | LSL_List llDeleteSubList(LSL_List src, int start, int end); | ||
78 | LSL_String llDeleteSubString(string src, int start, int end); | ||
79 | void llDetachFromAvatar(); | ||
80 | LSL_Vector llDetectedGrab(int number); | ||
81 | LSL_Integer llDetectedGroup(int number); | ||
82 | LSL_Key llDetectedKey(int number); | ||
83 | LSL_Integer llDetectedLinkNumber(int number); | ||
84 | LSL_String llDetectedName(int number); | ||
85 | LSL_Key llDetectedOwner(int number); | ||
86 | LSL_Vector llDetectedPos(int number); | ||
87 | LSL_Rotation llDetectedRot(int number); | ||
88 | LSL_Integer llDetectedType(int number); | ||
89 | LSL_Vector llDetectedTouchBinormal(int index); | ||
90 | LSL_Integer llDetectedTouchFace(int index); | ||
91 | LSL_Vector llDetectedTouchNormal(int index); | ||
92 | LSL_Vector llDetectedTouchPos(int index); | ||
93 | LSL_Vector llDetectedTouchST(int index); | ||
94 | LSL_Vector llDetectedTouchUV(int index); | ||
95 | LSL_Vector llDetectedVel(int number); | ||
96 | void llDialog(string avatar, string message, LSL_List buttons, int chat_channel); | ||
97 | void llDie(); | ||
98 | LSL_String llDumpList2String(LSL_List src, string seperator); | ||
99 | LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir); | ||
100 | void llEjectFromLand(string pest); | ||
101 | void llEmail(string address, string subject, string message); | ||
102 | LSL_String llEscapeURL(string url); | ||
103 | LSL_Rotation llEuler2Rot(LSL_Vector v); | ||
104 | LSL_Float llFabs(double f); | ||
105 | LSL_Integer llFloor(double f); | ||
106 | void llForceMouselook(int mouselook); | ||
107 | LSL_Float llFrand(double mag); | ||
108 | LSL_Vector llGetAccel(); | ||
109 | LSL_Integer llGetAgentInfo(string id); | ||
110 | LSL_Vector llGetAgentSize(string id); | ||
111 | LSL_Float llGetAlpha(int face); | ||
112 | LSL_Float llGetAndResetTime(); | ||
113 | LSL_String llGetAnimation(string id); | ||
114 | LSL_List llGetAnimationList(string id); | ||
115 | LSL_Integer llGetAttached(); | ||
116 | LSL_List llGetBoundingBox(string obj); | ||
117 | LSL_Vector llGetCameraPos(); | ||
118 | LSL_Rotation llGetCameraRot(); | ||
119 | LSL_Vector llGetCenterOfMass(); | ||
120 | LSL_Vector llGetColor(int face); | ||
121 | LSL_String llGetCreator(); | ||
122 | LSL_String llGetDate(); | ||
123 | LSL_Float llGetEnergy(); | ||
124 | LSL_Vector llGetForce(); | ||
125 | LSL_Integer llGetFreeMemory(); | ||
126 | LSL_Vector llGetGeometricCenter(); | ||
127 | LSL_Float llGetGMTclock(); | ||
128 | LSL_Key llGetInventoryCreator(string item); | ||
129 | LSL_Key llGetInventoryKey(string name); | ||
130 | LSL_String llGetInventoryName(int type, int number); | ||
131 | LSL_Integer llGetInventoryNumber(int type); | ||
132 | LSL_Integer llGetInventoryPermMask(string item, int mask); | ||
133 | LSL_Integer llGetInventoryType(string name); | ||
134 | LSL_Key llGetKey(); | ||
135 | LSL_Key llGetLandOwnerAt(LSL_Vector pos); | ||
136 | LSL_Key llGetLinkKey(int linknum); | ||
137 | LSL_String llGetLinkName(int linknum); | ||
138 | LSL_Integer llGetLinkNumber(); | ||
139 | LSL_Integer llGetListEntryType(LSL_List src, int index); | ||
140 | LSL_Integer llGetListLength(LSL_List src); | ||
141 | LSL_Vector llGetLocalPos(); | ||
142 | LSL_Rotation llGetLocalRot(); | ||
143 | LSL_Float llGetMass(); | ||
144 | void llGetNextEmail(string address, string subject); | ||
145 | LSL_String llGetNotecardLine(string name, int line); | ||
146 | LSL_Key llGetNumberOfNotecardLines(string name); | ||
147 | LSL_Integer llGetNumberOfPrims(); | ||
148 | LSL_Integer llGetNumberOfSides(); | ||
149 | LSL_String llGetObjectDesc(); | ||
150 | LSL_List llGetObjectDetails(string id, LSL_List args); | ||
151 | LSL_Float llGetObjectMass(string id); | ||
152 | LSL_String llGetObjectName(); | ||
153 | LSL_Integer llGetObjectPermMask(int mask); | ||
154 | LSL_Integer llGetObjectPrimCount(string object_id); | ||
155 | LSL_Vector llGetOmega(); | ||
156 | LSL_Key llGetOwner(); | ||
157 | LSL_Key llGetOwnerKey(string id); | ||
158 | LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param); | ||
159 | LSL_Integer llGetParcelFlags(LSL_Vector pos); | ||
160 | LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide); | ||
161 | LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide); | ||
162 | LSL_List llGetParcelPrimOwners(LSL_Vector pos); | ||
163 | LSL_Integer llGetPermissions(); | ||
164 | LSL_Key llGetPermissionsKey(); | ||
165 | LSL_Vector llGetPos(); | ||
166 | LSL_List llGetPrimitiveParams(LSL_List rules); | ||
167 | LSL_Integer llGetRegionAgentCount(); | ||
168 | LSL_Vector llGetRegionCorner(); | ||
169 | LSL_Integer llGetRegionFlags(); | ||
170 | LSL_Float llGetRegionFPS(); | ||
171 | LSL_String llGetRegionName(); | ||
172 | LSL_Float llGetRegionTimeDilation(); | ||
173 | LSL_Vector llGetRootPosition(); | ||
174 | LSL_Rotation llGetRootRotation(); | ||
175 | LSL_Rotation llGetRot(); | ||
176 | LSL_Vector llGetScale(); | ||
177 | LSL_String llGetScriptName(); | ||
178 | LSL_Integer llGetScriptState(string name); | ||
179 | LSL_String llGetSimulatorHostname(); | ||
180 | LSL_Integer llGetStartParameter(); | ||
181 | LSL_Integer llGetStatus(int status); | ||
182 | LSL_String llGetSubString(string src, int start, int end); | ||
183 | LSL_Vector llGetSunDirection(); | ||
184 | LSL_String llGetTexture(int face); | ||
185 | LSL_Vector llGetTextureOffset(int face); | ||
186 | LSL_Float llGetTextureRot(int side); | ||
187 | LSL_Vector llGetTextureScale(int side); | ||
188 | LSL_Float llGetTime(); | ||
189 | LSL_Float llGetTimeOfDay(); | ||
190 | LSL_String llGetTimestamp(); | ||
191 | LSL_Vector llGetTorque(); | ||
192 | LSL_Integer llGetUnixTime(); | ||
193 | LSL_Vector llGetVel(); | ||
194 | LSL_Float llGetWallclock(); | ||
195 | void llGiveInventory(string destination, string inventory); | ||
196 | void llGiveInventoryList(string destination, string category, LSL_List inventory); | ||
197 | LSL_Integer llGiveMoney(string destination, int amount); | ||
198 | void llGodLikeRezObject(string inventory, LSL_Vector pos); | ||
199 | LSL_Float llGround(LSL_Vector offset); | ||
200 | LSL_Vector llGroundContour(LSL_Vector offset); | ||
201 | LSL_Vector llGroundNormal(LSL_Vector offset); | ||
202 | void llGroundRepel(double height, int water, double tau); | ||
203 | LSL_Vector llGroundSlope(LSL_Vector offset); | ||
204 | LSL_String llHTTPRequest(string url, LSL_List parameters, string body); | ||
205 | LSL_String llInsertString(string dst, int position, string src); | ||
206 | void llInstantMessage(string user, string message); | ||
207 | LSL_String llIntegerToBase64(int number); | ||
208 | LSL_String llKey2Name(string id); | ||
209 | LSL_String llList2CSV(LSL_List src); | ||
210 | LSL_Float llList2Float(LSL_List src, int index); | ||
211 | LSL_Integer llList2Integer(LSL_List src, int index); | ||
212 | LSL_Key llList2Key(LSL_List src, int index); | ||
213 | LSL_List llList2List(LSL_List src, int start, int end); | ||
214 | LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride); | ||
215 | LSL_Rotation llList2Rot(LSL_List src, int index); | ||
216 | LSL_String llList2String(LSL_List src, int index); | ||
217 | LSL_Vector llList2Vector(LSL_List src, int index); | ||
218 | LSL_Integer llListen(int channelID, string name, string ID, string msg); | ||
219 | void llListenControl(int number, int active); | ||
220 | void llListenRemove(int number); | ||
221 | LSL_Integer llListFindList(LSL_List src, LSL_List test); | ||
222 | LSL_List llListInsertList(LSL_List dest, LSL_List src, int start); | ||
223 | LSL_List llListRandomize(LSL_List src, int stride); | ||
224 | LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end); | ||
225 | LSL_List llListSort(LSL_List src, int stride, int ascending); | ||
226 | LSL_Float llListStatistics(int operation, LSL_List src); | ||
227 | void llLoadURL(string avatar_id, string message, string url); | ||
228 | LSL_Float llLog(double val); | ||
229 | LSL_Float llLog10(double val); | ||
230 | void llLookAt(LSL_Vector target, double strength, double damping); | ||
231 | void llLoopSound(string sound, double volume); | ||
232 | void llLoopSoundMaster(string sound, double volume); | ||
233 | void llLoopSoundSlave(string sound, double volume); | ||
234 | void llMakeExplosion(); | ||
235 | void llMakeFire(); | ||
236 | void llMakeFountain(); | ||
237 | void llMakeSmoke(); | ||
238 | void llMapDestination(string simname, LSL_Vector pos, LSL_Vector look_at); | ||
239 | LSL_String llMD5String(string src, int nonce); | ||
240 | void llMessageLinked(int linknum, int num, string str, string id); | ||
241 | void llMinEventDelay(double delay); | ||
242 | void llModifyLand(int action, int brush); | ||
243 | LSL_Integer llModPow(int a, int b, int c); | ||
244 | void llMoveToTarget(LSL_Vector target, double tau); | ||
245 | void llOffsetTexture(double u, double v, int face); | ||
246 | void llOpenRemoteDataChannel(); | ||
247 | LSL_Integer llOverMyLand(string id); | ||
248 | void llOwnerSay(string msg); | ||
249 | void llParcelMediaCommandList(LSL_List commandList); | ||
250 | LSL_List llParcelMediaQuery(LSL_List aList); | ||
251 | LSL_List llParseString2List(string str, LSL_List separators, LSL_List spacers); | ||
252 | LSL_List llParseStringKeepNulls(string src, LSL_List seperators, LSL_List spacers); | ||
253 | void llParticleSystem(LSL_List rules); | ||
254 | void llPassCollisions(int pass); | ||
255 | void llPassTouches(int pass); | ||
256 | void llPlaySound(string sound, double volume); | ||
257 | void llPlaySoundSlave(string sound, double volume); | ||
258 | void llPointAt(); | ||
259 | LSL_Float llPow(double fbase, double fexponent); | ||
260 | void llPreloadSound(string sound); | ||
261 | void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local); | ||
262 | void llRefreshPrimURL(); | ||
263 | void llRegionSay(int channelID, string text); | ||
264 | void llReleaseCamera(string avatar); | ||
265 | void llReleaseControls(); | ||
266 | void llRemoteDataReply(string channel, string message_id, string sdata, int idata); | ||
267 | void llRemoteDataSetRegion(); | ||
268 | void llRemoteLoadScript(); | ||
269 | void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param); | ||
270 | void llRemoveFromLandBanList(string avatar); | ||
271 | void llRemoveFromLandPassList(string avatar); | ||
272 | void llRemoveInventory(string item); | ||
273 | void llRemoveVehicleFlags(int flags); | ||
274 | LSL_Key llRequestAgentData(string id, int data); | ||
275 | LSL_Key llRequestInventoryData(string name); | ||
276 | void llRequestPermissions(string agent, int perm); | ||
277 | LSL_Key llRequestSimulatorData(string simulator, int data); | ||
278 | void llResetLandBanList(); | ||
279 | void llResetLandPassList(); | ||
280 | void llResetOtherScript(string name); | ||
281 | void llResetScript(); | ||
282 | void llResetTime(); | ||
283 | void llRezAtRoot(string inventory, LSL_Vector position, LSL_Vector velocity, LSL_Rotation rot, int param); | ||
284 | void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param); | ||
285 | LSL_Float llRot2Angle(LSL_Rotation rot); | ||
286 | LSL_Vector llRot2Axis(LSL_Rotation rot); | ||
287 | LSL_Vector llRot2Euler(LSL_Rotation r); | ||
288 | LSL_Vector llRot2Fwd(LSL_Rotation r); | ||
289 | LSL_Vector llRot2Left(LSL_Rotation r); | ||
290 | LSL_Vector llRot2Up(LSL_Rotation r); | ||
291 | void llRotateTexture(double rotation, int face); | ||
292 | LSL_Rotation llRotBetween(LSL_Vector start, LSL_Vector end); | ||
293 | void llRotLookAt(LSL_Rotation target, double strength, double damping); | ||
294 | LSL_Integer llRotTarget(LSL_Rotation rot, double error); | ||
295 | void llRotTargetRemove(int number); | ||
296 | LSL_Integer llRound(double f); | ||
297 | LSL_Integer llSameGroup(string agent); | ||
298 | void llSay(int channelID, string text); | ||
299 | void llScaleTexture(double u, double v, int face); | ||
300 | LSL_Integer llScriptDanger(LSL_Vector pos); | ||
301 | LSL_Key llSendRemoteData(string channel, string dest, int idata, string sdata); | ||
302 | void llSensor(string name, string id, int type, double range, double arc); | ||
303 | void llSensorRemove(); | ||
304 | void llSensorRepeat(string name, string id, int type, double range, double arc, double rate); | ||
305 | void llSetAlpha(double alpha, int face); | ||
306 | void llSetBuoyancy(double buoyancy); | ||
307 | void llSetCameraAtOffset(LSL_Vector offset); | ||
308 | void llSetCameraEyeOffset(LSL_Vector offset); | ||
309 | void llSetCameraParams(LSL_List rules); | ||
310 | void llSetClickAction(int action); | ||
311 | void llSetColor(LSL_Vector color, int face); | ||
312 | void llSetDamage(double damage); | ||
313 | void llSetForce(LSL_Vector force, int local); | ||
314 | void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local); | ||
315 | void llSetHoverHeight(double height, int water, double tau); | ||
316 | void llSetInventoryPermMask(string item, int mask, int value); | ||
317 | void llSetLinkAlpha(int linknumber, double alpha, int face); | ||
318 | void llSetLinkColor(int linknumber, LSL_Vector color, int face); | ||
319 | void llSetLinkPrimitiveParams(int linknumber, LSL_List rules); | ||
320 | void llSetLinkTexture(int linknumber, string texture, int face); | ||
321 | void llSetLocalRot(LSL_Rotation rot); | ||
322 | void llSetObjectDesc(string desc); | ||
323 | void llSetObjectName(string name); | ||
324 | void llSetObjectPermMask(int mask, int value); | ||
325 | void llSetParcelMusicURL(string url); | ||
326 | void llSetPayPrice(int price, LSL_List quick_pay_buttons); | ||
327 | void llSetPos(LSL_Vector pos); | ||
328 | void llSetPrimitiveParams(LSL_List rules); | ||
329 | void llSetPrimURL(); | ||
330 | void llSetRemoteScriptAccessPin(int pin); | ||
331 | void llSetRot(LSL_Rotation rot); | ||
332 | void llSetScale(LSL_Vector scale); | ||
333 | void llSetScriptState(string name, int run); | ||
334 | void llSetSitText(string text); | ||
335 | void llSetSoundQueueing(int queue); | ||
336 | void llSetSoundRadius(double radius); | ||
337 | void llSetStatus(int status, int value); | ||
338 | void llSetText(string text, LSL_Vector color, double alpha); | ||
339 | void llSetTexture(string texture, int face); | ||
340 | void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate); | ||
341 | void llSetTimerEvent(double sec); | ||
342 | void llSetTorque(LSL_Vector torque, int local); | ||
343 | void llSetTouchText(string text); | ||
344 | void llSetVehicleFlags(int flags); | ||
345 | void llSetVehicleFloatParam(int param, float value); | ||
346 | void llSetVehicleRotationParam(int param, LSL_Rotation rot); | ||
347 | void llSetVehicleType(int type); | ||
348 | void llSetVehicleVectorParam(int param, LSL_Vector vec); | ||
349 | void llShout(int channelID, string text); | ||
350 | LSL_Float llSin(double f); | ||
351 | void llSitTarget(LSL_Vector offset, LSL_Rotation rot); | ||
352 | void llSleep(double sec); | ||
353 | void llSound(); | ||
354 | void llSoundPreload(); | ||
355 | LSL_Float llSqrt(double f); | ||
356 | void llStartAnimation(string anim); | ||
357 | void llStopAnimation(string anim); | ||
358 | void llStopHover(); | ||
359 | void llStopLookAt(); | ||
360 | void llStopMoveToTarget(); | ||
361 | void llStopPointAt(); | ||
362 | void llStopSound(); | ||
363 | LSL_Integer llStringLength(string str); | ||
364 | LSL_String llStringToBase64(string str); | ||
365 | LSL_String llStringTrim(string src, int type); | ||
366 | LSL_Integer llSubStringIndex(string source, string pattern); | ||
367 | void llTakeCamera(string avatar); | ||
368 | void llTakeControls(int controls, int accept, int pass_on); | ||
369 | LSL_Float llTan(double f); | ||
370 | LSL_Integer llTarget(LSL_Vector position, double range); | ||
371 | void llTargetOmega(LSL_Vector axis, double spinrate, double gain); | ||
372 | void llTargetRemove(int number); | ||
373 | void llTeleportAgentHome(string agent); | ||
374 | void llTextBox(string avatar, string message, int chat_channel); | ||
375 | LSL_String llToLower(string source); | ||
376 | LSL_String llToUpper(string source); | ||
377 | void llTriggerSound(string sound, double volume); | ||
378 | void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, LSL_Vector bottom_south_west); | ||
379 | LSL_String llUnescapeURL(string url); | ||
380 | void llUnSit(string id); | ||
381 | LSL_Float llVecDist(LSL_Vector a, LSL_Vector b); | ||
382 | LSL_Float llVecMag(LSL_Vector v); | ||
383 | LSL_Vector llVecNorm(LSL_Vector v); | ||
384 | void llVolumeDetect(int detect); | ||
385 | LSL_Float llWater(LSL_Vector offset); | ||
386 | void llWhisper(int channelID, string text); | ||
387 | LSL_Vector llWind(LSL_Vector offset); | ||
388 | void llXorBase64Strings(); | ||
389 | LSL_String llXorBase64StringsCorrect(string str1, string str2); | ||
390 | } | ||
391 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs b/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs deleted file mode 100644 index 7b2d229..0000000 --- a/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands.cs +++ /dev/null | |||
@@ -1,817 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | using System; | ||
28 | using System.Collections; | ||
29 | using OpenMetaverse; | ||
30 | using Nini.Config; | ||
31 | using OpenSim.Framework.Console; | ||
32 | using OpenSim.Region.Environment.Interfaces; | ||
33 | using OpenSim.Region.Environment.Scenes; | ||
34 | using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; | ||
35 | using TPFlags = OpenSim.Framework.Constants.TeleportFlags; | ||
36 | //using OpenSim.Region.ScriptEngine.DotNetEngine.Compiler.LSL; | ||
37 | using OpenSim.Region.ScriptEngine.Shared; | ||
38 | |||
39 | namespace OpenSim.Region.ScriptEngine.Common | ||
40 | { | ||
41 | public class OSSL_BuilIn_Commands : LSL_BuiltIn_Commands, OSSL_BuilIn_Commands_Interface | ||
42 | { | ||
43 | internal ScriptEngineBase.ScriptEngine m_ScriptEngineDirect; | ||
44 | |||
45 | public OSSL_BuilIn_Commands(ScriptEngineBase.ScriptEngine scriptEngine, SceneObjectPart host, uint localID, | ||
46 | UUID itemID) | ||
47 | : base(scriptEngine, host, localID, itemID) | ||
48 | { | ||
49 | m_ScriptEngineDirect = scriptEngine; | ||
50 | Prim = new OSSLPrim(this); | ||
51 | } | ||
52 | |||
53 | public OSSLPrim Prim; | ||
54 | |||
55 | [Serializable] | ||
56 | public class OSSLPrim | ||
57 | { | ||
58 | internal OSSL_BuilIn_Commands OSSL; | ||
59 | public OSSLPrim(OSSL_BuilIn_Commands bc) | ||
60 | { | ||
61 | OSSL = bc; | ||
62 | Position = new OSSLPrim_Position(this); | ||
63 | Rotation = new OSSLPrim_Rotation(this); | ||
64 | } | ||
65 | |||
66 | public OSSLPrim_Position Position; | ||
67 | public OSSLPrim_Rotation Rotation; | ||
68 | //public LSL_Types.Vector3 Position | ||
69 | //{ | ||
70 | // get { return OSSL.llGetPos(); } | ||
71 | // set { OSSL.llSetPos(value); } | ||
72 | //} | ||
73 | //public LSL_Types.Quaternion Rotation | ||
74 | //{ | ||
75 | // get { return OSSL.llGetRot(); } | ||
76 | // set { OSSL.llSetRot(value); } | ||
77 | //} | ||
78 | private TextStruct _text; | ||
79 | public TextStruct Text | ||
80 | { | ||
81 | get { return _text; } | ||
82 | set | ||
83 | { | ||
84 | _text = value; | ||
85 | OSSL.llSetText(_text.Text, _text.color, _text.alpha); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | [Serializable] | ||
90 | public struct TextStruct | ||
91 | { | ||
92 | public string Text; | ||
93 | public LSL_Types.Vector3 color; | ||
94 | public double alpha; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | [Serializable] | ||
99 | public class OSSLPrim_Position | ||
100 | { | ||
101 | private OSSLPrim prim; | ||
102 | private LSL_Types.Vector3 Position; | ||
103 | public OSSLPrim_Position(OSSLPrim _prim) | ||
104 | { | ||
105 | prim = _prim; | ||
106 | } | ||
107 | private void Load() | ||
108 | { | ||
109 | Position = prim.OSSL.llGetPos(); | ||
110 | } | ||
111 | private void Save() | ||
112 | { | ||
113 | if (Position.x > 255) | ||
114 | Position.x = 255; | ||
115 | if (Position.x < 0) | ||
116 | Position.x = 0; | ||
117 | if (Position.y > 255) | ||
118 | Position.y = 255; | ||
119 | if (Position.y < 0) | ||
120 | Position.y = 0; | ||
121 | if (Position.z > 768) | ||
122 | Position.z = 768; | ||
123 | if (Position.z < 0) | ||
124 | Position.z = 0; | ||
125 | prim.OSSL.llSetPos(Position); | ||
126 | } | ||
127 | |||
128 | public double x | ||
129 | { | ||
130 | get | ||
131 | { | ||
132 | Load(); | ||
133 | return Position.x; | ||
134 | } | ||
135 | set | ||
136 | { | ||
137 | Load(); | ||
138 | Position.x = value; | ||
139 | Save(); | ||
140 | } | ||
141 | } | ||
142 | public double y | ||
143 | { | ||
144 | get | ||
145 | { | ||
146 | Load(); | ||
147 | return Position.y; | ||
148 | } | ||
149 | set | ||
150 | { | ||
151 | Load(); | ||
152 | Position.y = value; | ||
153 | Save(); | ||
154 | } | ||
155 | } | ||
156 | public double z | ||
157 | { | ||
158 | get | ||
159 | { | ||
160 | Load(); | ||
161 | return Position.z; | ||
162 | } | ||
163 | set | ||
164 | { | ||
165 | Load(); | ||
166 | Position.z = value; | ||
167 | Save(); | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
172 | [Serializable] | ||
173 | public class OSSLPrim_Rotation | ||
174 | { | ||
175 | private OSSLPrim prim; | ||
176 | private LSL_Types.Quaternion Rotation; | ||
177 | public OSSLPrim_Rotation(OSSLPrim _prim) | ||
178 | { | ||
179 | prim = _prim; | ||
180 | } | ||
181 | private void Load() | ||
182 | { | ||
183 | Rotation = prim.OSSL.llGetRot(); | ||
184 | } | ||
185 | private void Save() | ||
186 | { | ||
187 | prim.OSSL.llSetRot(Rotation); | ||
188 | } | ||
189 | |||
190 | public double x | ||
191 | { | ||
192 | get | ||
193 | { | ||
194 | Load(); | ||
195 | return Rotation.x; | ||
196 | } | ||
197 | set | ||
198 | { | ||
199 | Load(); | ||
200 | Rotation.x = value; | ||
201 | Save(); | ||
202 | } | ||
203 | } | ||
204 | public double y | ||
205 | { | ||
206 | get | ||
207 | { | ||
208 | Load(); | ||
209 | return Rotation.y; | ||
210 | } | ||
211 | set | ||
212 | { | ||
213 | Load(); | ||
214 | Rotation.y = value; | ||
215 | Save(); | ||
216 | } | ||
217 | } | ||
218 | public double z | ||
219 | { | ||
220 | get | ||
221 | { | ||
222 | Load(); | ||
223 | return Rotation.z; | ||
224 | } | ||
225 | set | ||
226 | { | ||
227 | Load(); | ||
228 | Rotation.z = value; | ||
229 | Save(); | ||
230 | } | ||
231 | } | ||
232 | public double s | ||
233 | { | ||
234 | get | ||
235 | { | ||
236 | Load(); | ||
237 | return Rotation.s; | ||
238 | } | ||
239 | set | ||
240 | { | ||
241 | Load(); | ||
242 | Rotation.s = value; | ||
243 | Save(); | ||
244 | } | ||
245 | } | ||
246 | } | ||
247 | //public struct OSSLPrim_Rotation | ||
248 | //{ | ||
249 | // public double X; | ||
250 | // public double Y; | ||
251 | // public double Z; | ||
252 | // public double R; | ||
253 | //} | ||
254 | |||
255 | |||
256 | // | ||
257 | // OpenSim functions | ||
258 | // | ||
259 | |||
260 | public int osTerrainSetHeight(int x, int y, double val) | ||
261 | { | ||
262 | m_host.AddScriptLPS(1); | ||
263 | if (x > 255 || x < 0 || y > 255 || y < 0) | ||
264 | LSLError("osTerrainSetHeight: Coordinate out of bounds"); | ||
265 | |||
266 | if (World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new Vector3(x, y, 0))) | ||
267 | { | ||
268 | World.Heightmap[x, y] = val; | ||
269 | return 1; | ||
270 | } | ||
271 | else | ||
272 | { | ||
273 | return 0; | ||
274 | } | ||
275 | } | ||
276 | |||
277 | public double osTerrainGetHeight(int x, int y) | ||
278 | { | ||
279 | m_host.AddScriptLPS(1); | ||
280 | if (x > 255 || x < 0 || y > 255 || y < 0) | ||
281 | LSLError("osTerrainGetHeight: Coordinate out of bounds"); | ||
282 | |||
283 | return World.Heightmap[x, y]; | ||
284 | } | ||
285 | |||
286 | public int osRegionRestart(double seconds) | ||
287 | { | ||
288 | m_host.AddScriptLPS(1); | ||
289 | if (World.ExternalChecks.ExternalChecksCanIssueEstateCommand(m_host.OwnerID, false)) | ||
290 | { | ||
291 | World.Restart((float)seconds); | ||
292 | return 1; | ||
293 | } | ||
294 | else | ||
295 | { | ||
296 | return 0; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | public void osRegionNotice(string msg) | ||
301 | { | ||
302 | m_host.AddScriptLPS(1); | ||
303 | World.SendGeneralAlert(msg); | ||
304 | } | ||
305 | |||
306 | public void osSetRot(UUID target, Quaternion rotation) | ||
307 | { | ||
308 | m_host.AddScriptLPS(1); | ||
309 | if (World.Entities.ContainsKey(target)) | ||
310 | { | ||
311 | World.Entities[target].Rotation = rotation; | ||
312 | } | ||
313 | else | ||
314 | { | ||
315 | LSLError("osSetRot: Invalid target"); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, | ||
320 | int timer) | ||
321 | { | ||
322 | m_host.AddScriptLPS(1); | ||
323 | if (dynamicID == String.Empty) | ||
324 | { | ||
325 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); | ||
326 | UUID createdTexture = | ||
327 | textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, | ||
328 | extraParams, timer); | ||
329 | return createdTexture.ToString(); | ||
330 | } | ||
331 | else | ||
332 | { | ||
333 | //TODO update existing dynamic textures | ||
334 | } | ||
335 | |||
336 | return UUID.Zero.ToString(); | ||
337 | } | ||
338 | |||
339 | public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, | ||
340 | int timer, int alpha) | ||
341 | { | ||
342 | m_host.AddScriptLPS(1); | ||
343 | if (dynamicID == String.Empty) | ||
344 | { | ||
345 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); | ||
346 | UUID createdTexture = | ||
347 | textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, | ||
348 | extraParams, timer, true, (byte) alpha); | ||
349 | return createdTexture.ToString(); | ||
350 | } | ||
351 | else | ||
352 | { | ||
353 | //TODO update existing dynamic textures | ||
354 | } | ||
355 | |||
356 | return UUID.Zero.ToString(); | ||
357 | } | ||
358 | |||
359 | public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, | ||
360 | int timer) | ||
361 | { | ||
362 | m_host.AddScriptLPS(1); | ||
363 | if (dynamicID == String.Empty) | ||
364 | { | ||
365 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); | ||
366 | if (textureManager != null) | ||
367 | { | ||
368 | if (extraParams == String.Empty) | ||
369 | { | ||
370 | extraParams = "256"; | ||
371 | } | ||
372 | UUID createdTexture = | ||
373 | textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, | ||
374 | extraParams, timer); | ||
375 | return createdTexture.ToString(); | ||
376 | } | ||
377 | } | ||
378 | else | ||
379 | { | ||
380 | //TODO update existing dynamic textures | ||
381 | } | ||
382 | |||
383 | return UUID.Zero.ToString(); | ||
384 | } | ||
385 | |||
386 | public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, | ||
387 | int timer, int alpha) | ||
388 | { | ||
389 | m_host.AddScriptLPS(1); | ||
390 | if (dynamicID == String.Empty) | ||
391 | { | ||
392 | IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>(); | ||
393 | if (textureManager != null) | ||
394 | { | ||
395 | if (extraParams == String.Empty) | ||
396 | { | ||
397 | extraParams = "256"; | ||
398 | } | ||
399 | UUID createdTexture = | ||
400 | textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, | ||
401 | extraParams, timer, true, (byte) alpha); | ||
402 | return createdTexture.ToString(); | ||
403 | } | ||
404 | } | ||
405 | else | ||
406 | { | ||
407 | //TODO update existing dynamic textures | ||
408 | } | ||
409 | |||
410 | return UUID.Zero.ToString(); | ||
411 | } | ||
412 | |||
413 | public bool osConsoleCommand(string command) | ||
414 | { | ||
415 | m_host.AddScriptLPS(1); | ||
416 | IConfigSource config = new IniConfigSource(Application.iniFilePath); | ||
417 | if (config.Configs["LL-Functions"] == null) | ||
418 | config.AddConfig("LL-Functions"); | ||
419 | |||
420 | if (config.Configs["LL-Functions"].GetBoolean("AllowosConsoleCommand", false)) | ||
421 | { | ||
422 | if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID)) | ||
423 | { | ||
424 | MainConsole.Instance.RunCommand(command); | ||
425 | return true; | ||
426 | } | ||
427 | return false; | ||
428 | } | ||
429 | return false; | ||
430 | } | ||
431 | public void osSetPrimFloatOnWater(int floatYN) | ||
432 | { | ||
433 | m_host.AddScriptLPS(1); | ||
434 | if (m_host.ParentGroup != null) | ||
435 | { | ||
436 | if (m_host.ParentGroup.RootPart != null) | ||
437 | { | ||
438 | m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN); | ||
439 | } | ||
440 | } | ||
441 | } | ||
442 | |||
443 | // Teleport functions | ||
444 | public void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) | ||
445 | { | ||
446 | m_host.AddScriptLPS(1); | ||
447 | UUID agentId = new UUID(); | ||
448 | if (UUID.TryParse(agent, out agentId)) | ||
449 | { | ||
450 | ScenePresence presence = World.GetScenePresence(agentId); | ||
451 | if (presence != null) | ||
452 | { | ||
453 | // agent must be over owners land to avoid abuse | ||
454 | if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y)) | ||
455 | { | ||
456 | World.RequestTeleportLocation(presence.ControllingClient, regionName, | ||
457 | new Vector3((float)position.x, (float)position.y, (float)position.z), | ||
458 | new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); | ||
459 | // ScriptSleep(5000); | ||
460 | |||
461 | } | ||
462 | } | ||
463 | } | ||
464 | } | ||
465 | |||
466 | public void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) | ||
467 | { | ||
468 | osTeleportAgent(agent, World.RegionInfo.RegionName, position, lookat); | ||
469 | } | ||
470 | |||
471 | // Adam's super super custom animation functions | ||
472 | public void osAvatarPlayAnimation(string avatar, string animation) | ||
473 | { | ||
474 | m_host.AddScriptLPS(1); | ||
475 | if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence) | ||
476 | { | ||
477 | ScenePresence target = (ScenePresence)World.Entities[avatar]; | ||
478 | target.AddAnimation(avatar); | ||
479 | } | ||
480 | } | ||
481 | |||
482 | public void osAvatarStopAnimation(string avatar, string animation) | ||
483 | { | ||
484 | m_host.AddScriptLPS(1); | ||
485 | if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence) | ||
486 | { | ||
487 | ScenePresence target = (ScenePresence)World.Entities[avatar]; | ||
488 | target.RemoveAnimation(animation); | ||
489 | } | ||
490 | } | ||
491 | |||
492 | //Texture draw functions | ||
493 | public string osMovePen(string drawList, int x, int y) | ||
494 | { | ||
495 | m_host.AddScriptLPS(1); | ||
496 | drawList += "MoveTo " + x + "," + y + ";"; | ||
497 | return drawList; | ||
498 | } | ||
499 | |||
500 | public string osDrawLine(string drawList, int startX, int startY, int endX, int endY) | ||
501 | { | ||
502 | m_host.AddScriptLPS(1); | ||
503 | drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; "; | ||
504 | return drawList; | ||
505 | } | ||
506 | |||
507 | public string osDrawLine(string drawList, int endX, int endY) | ||
508 | { | ||
509 | m_host.AddScriptLPS(1); | ||
510 | drawList += "LineTo " + endX + "," + endY + "; "; | ||
511 | return drawList; | ||
512 | } | ||
513 | |||
514 | public string osDrawText(string drawList, string text) | ||
515 | { | ||
516 | m_host.AddScriptLPS(1); | ||
517 | drawList += "Text " + text + "; "; | ||
518 | return drawList; | ||
519 | } | ||
520 | |||
521 | public string osDrawEllipse(string drawList, int width, int height) | ||
522 | { | ||
523 | m_host.AddScriptLPS(1); | ||
524 | drawList += "Ellipse " + width + "," + height + "; "; | ||
525 | return drawList; | ||
526 | } | ||
527 | |||
528 | public string osDrawRectangle(string drawList, int width, int height) | ||
529 | { | ||
530 | m_host.AddScriptLPS(1); | ||
531 | drawList += "Rectangle " + width + "," + height + "; "; | ||
532 | return drawList; | ||
533 | } | ||
534 | |||
535 | public string osDrawFilledRectangle(string drawList, int width, int height) | ||
536 | { | ||
537 | m_host.AddScriptLPS(1); | ||
538 | drawList += "FillRectangle " + width + "," + height + "; "; | ||
539 | return drawList; | ||
540 | } | ||
541 | |||
542 | public string osSetFontSize(string drawList, int fontSize) | ||
543 | { | ||
544 | m_host.AddScriptLPS(1); | ||
545 | drawList += "FontSize "+ fontSize +"; "; | ||
546 | return drawList; | ||
547 | } | ||
548 | |||
549 | public string osSetPenSize(string drawList, int penSize) | ||
550 | { | ||
551 | m_host.AddScriptLPS(1); | ||
552 | drawList += "PenSize " + penSize + "; "; | ||
553 | return drawList; | ||
554 | } | ||
555 | |||
556 | public string osSetPenColour(string drawList, string colour) | ||
557 | { | ||
558 | m_host.AddScriptLPS(1); | ||
559 | drawList += "PenColour " + colour + "; "; | ||
560 | return drawList; | ||
561 | } | ||
562 | |||
563 | public string osDrawImage(string drawList, int width, int height, string imageUrl) | ||
564 | { | ||
565 | m_host.AddScriptLPS(1); | ||
566 | drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ; | ||
567 | return drawList; | ||
568 | } | ||
569 | |||
570 | public void osSetStateEvents(int events) | ||
571 | { | ||
572 | m_host.SetScriptEvents(m_itemID, events); | ||
573 | } | ||
574 | |||
575 | public void osOpenRemoteDataChannel(string channel) | ||
576 | { | ||
577 | m_host.AddScriptLPS(1); | ||
578 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
579 | if (xmlrpcMod.IsEnabled()) | ||
580 | { | ||
581 | UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, new UUID(channel)); | ||
582 | object[] resobj = new object[] { new LSL_Types.LSLInteger(1), new LSL_Types.LSLString(channelID.ToString()), new LSL_Types.LSLString(UUID.Zero.ToString()), new LSL_Types.LSLString(String.Empty), new LSL_Types.LSLInteger(0), new LSL_Types.LSLString(String.Empty) }; | ||
583 | m_ScriptEngineDirect.m_EventQueueManager.AddToScriptQueue(m_localID, m_itemID, "remote_data", new DetectParams[0], resobj); | ||
584 | } | ||
585 | } | ||
586 | |||
587 | public void osSetParcelMediaURL(string url) | ||
588 | { | ||
589 | m_host.AddScriptLPS(1); | ||
590 | UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
591 | |||
592 | if (landowner == UUID.Zero) | ||
593 | { | ||
594 | return; | ||
595 | } | ||
596 | |||
597 | if (landowner != m_host.ObjectOwner) | ||
598 | { | ||
599 | return; | ||
600 | } | ||
601 | |||
602 | World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); | ||
603 | } | ||
604 | |||
605 | public string osGetScriptEngineName() | ||
606 | { | ||
607 | m_host.AddScriptLPS(1); | ||
608 | |||
609 | int scriptEngineNameIndex = 0; | ||
610 | |||
611 | if (!String.IsNullOrEmpty(m_ScriptEngineDirect.ScriptEngineName)) | ||
612 | { | ||
613 | // parse off the "ScriptEngine." | ||
614 | scriptEngineNameIndex = m_ScriptEngineDirect.ScriptEngineName.IndexOf(".", scriptEngineNameIndex); | ||
615 | scriptEngineNameIndex++; // get past delimiter | ||
616 | |||
617 | int scriptEngineNameLength = m_ScriptEngineDirect.ScriptEngineName.Length - scriptEngineNameIndex; | ||
618 | |||
619 | // create char array then a string that is only the script engine name | ||
620 | Char[] scriptEngineNameCharArray = m_ScriptEngineDirect.ScriptEngineName.ToCharArray(scriptEngineNameIndex, scriptEngineNameLength); | ||
621 | String scriptEngineName = new String(scriptEngineNameCharArray); | ||
622 | |||
623 | return scriptEngineName; | ||
624 | } | ||
625 | else | ||
626 | { | ||
627 | return String.Empty; | ||
628 | } | ||
629 | } | ||
630 | |||
631 | //for testing purposes only | ||
632 | public void osSetParcelMediaTime(double time) | ||
633 | { | ||
634 | World.ParcelMediaSetTime((float)time); | ||
635 | } | ||
636 | |||
637 | public Hashtable osParseJSON(string JSON) | ||
638 | { | ||
639 | m_host.AddScriptLPS(1); | ||
640 | |||
641 | // see http://www.json.org/ for more details on JSON | ||
642 | |||
643 | string currentKey=null; | ||
644 | Stack objectStack = new Stack(); // objects in JSON can be nested so we need to keep a track of this | ||
645 | Hashtable jsondata = new Hashtable(); // the hashtable to be returned | ||
646 | |||
647 | try | ||
648 | { | ||
649 | |||
650 | // iterate through the serialised stream of tokens and store at the right depth in the hashtable | ||
651 | // the top level hashtable may contain more nested hashtables within it each containing an objects representation | ||
652 | for (int i=0;i<JSON.Length; i++) | ||
653 | { | ||
654 | |||
655 | // Console.WriteLine(""+JSON[i]); | ||
656 | switch (JSON[i]) | ||
657 | { | ||
658 | case '{': | ||
659 | // create hashtable and add it to the stack or array if we are populating one, we can have a lot of nested objects in JSON | ||
660 | |||
661 | Hashtable currentObject = new Hashtable(); | ||
662 | if (objectStack.Count==0) // the stack should only be empty for the first outer object | ||
663 | { | ||
664 | |||
665 | objectStack.Push(jsondata); | ||
666 | } | ||
667 | else if (objectStack.Peek().ToString()=="System.Collections.ArrayList") | ||
668 | { | ||
669 | // add it to the parent array | ||
670 | ((ArrayList)objectStack.Peek()).Add(currentObject); | ||
671 | objectStack.Push(currentObject); | ||
672 | } | ||
673 | else | ||
674 | { | ||
675 | // add it to the parent hashtable | ||
676 | ((Hashtable)objectStack.Peek()).Add(currentKey,currentObject); | ||
677 | objectStack.Push(currentObject); | ||
678 | } | ||
679 | |||
680 | // clear the key | ||
681 | currentKey=null; | ||
682 | break; | ||
683 | case '}': | ||
684 | // pop the hashtable off the stack | ||
685 | objectStack.Pop(); | ||
686 | break; | ||
687 | case '"':// string boundary | ||
688 | |||
689 | string tokenValue=""; | ||
690 | i++; // move to next char | ||
691 | |||
692 | // just loop through until the next quote mark storing the string | ||
693 | while (JSON[i]!='"') | ||
694 | { | ||
695 | tokenValue+=JSON[i++]; | ||
696 | } | ||
697 | |||
698 | // ok we've got a string, if we've got an array on the top of the stack then we store it | ||
699 | if (objectStack.Peek().ToString()=="System.Collections.ArrayList") | ||
700 | { | ||
701 | ((ArrayList)objectStack.Peek()).Add(tokenValue); | ||
702 | } | ||
703 | else if (currentKey==null) // no key stored and its not an array this must be a key so store it | ||
704 | { | ||
705 | currentKey = tokenValue; | ||
706 | } | ||
707 | else | ||
708 | { | ||
709 | // we have a key so lets store this value | ||
710 | ((Hashtable)objectStack.Peek()).Add(currentKey,tokenValue); | ||
711 | // now lets clear the key, we're done with it and moving on | ||
712 | currentKey=null; | ||
713 | } | ||
714 | |||
715 | break; | ||
716 | case ':':// key : value separator | ||
717 | // just ignore | ||
718 | break; | ||
719 | case ' ':// spaces | ||
720 | // just ignore | ||
721 | break; | ||
722 | case '[': // array start | ||
723 | ArrayList currentArray = new ArrayList(); | ||
724 | |||
725 | if (objectStack.Peek().ToString()=="System.Collections.ArrayList") | ||
726 | { | ||
727 | ((ArrayList)objectStack.Peek()).Add(currentArray); | ||
728 | } | ||
729 | else | ||
730 | { | ||
731 | ((Hashtable)objectStack.Peek()).Add(currentKey,currentArray); | ||
732 | // clear the key | ||
733 | currentKey=null; | ||
734 | } | ||
735 | objectStack.Push(currentArray); | ||
736 | |||
737 | break; | ||
738 | case ',':// seperator | ||
739 | // just ignore | ||
740 | break; | ||
741 | case ']'://Array end | ||
742 | // pop the array off the stack | ||
743 | objectStack.Pop(); | ||
744 | break; | ||
745 | case 't': // we've found a character start not in quotes, it must be a boolean true | ||
746 | |||
747 | if (objectStack.Peek().ToString()=="System.Collections.ArrayList") | ||
748 | { | ||
749 | ((ArrayList)objectStack.Peek()).Add(true); | ||
750 | } | ||
751 | else | ||
752 | { | ||
753 | ((Hashtable)objectStack.Peek()).Add(currentKey,true); | ||
754 | } | ||
755 | |||
756 | //advance the counter to the letter 'e' | ||
757 | i = i+3; | ||
758 | break; | ||
759 | case 'f': // we've found a character start not in quotes, it must be a boolean false | ||
760 | |||
761 | if (objectStack.Peek().ToString()=="System.Collections.ArrayList") | ||
762 | { | ||
763 | ((ArrayList)objectStack.Peek()).Add(false); | ||
764 | } | ||
765 | else | ||
766 | { | ||
767 | ((Hashtable)objectStack.Peek()).Add(currentKey,false); | ||
768 | } | ||
769 | //advance the counter to the letter 'e' | ||
770 | i = i+4; | ||
771 | break; | ||
772 | |||
773 | default: | ||
774 | // ok here we're catching all numeric types int,double,long we might want to spit these up mr accurately | ||
775 | // but for now we'll just do them as strings | ||
776 | |||
777 | string numberValue=""; | ||
778 | |||
779 | // just loop through until the next known marker quote mark storing the string | ||
780 | while (JSON[i] != '"' && JSON[i] != ',' && JSON[i] != ']' && JSON[i] != '}' && JSON[i] != ' ') | ||
781 | { | ||
782 | numberValue+=""+JSON[i++]; | ||
783 | } | ||
784 | |||
785 | i--; // we want to process this caracter that marked the end of this string in the main loop | ||
786 | |||
787 | // ok we've got a string, if we've got an array on the top of the stack then we store it | ||
788 | if (objectStack.Peek().ToString()=="System.Collections.ArrayList") | ||
789 | { | ||
790 | ((ArrayList)objectStack.Peek()).Add(numberValue); | ||
791 | } | ||
792 | else | ||
793 | { | ||
794 | // we have a key so lets store this value | ||
795 | ((Hashtable)objectStack.Peek()).Add(currentKey,numberValue); | ||
796 | // now lets clear the key, we're done with it and moving on | ||
797 | currentKey=null; | ||
798 | } | ||
799 | |||
800 | break; | ||
801 | } | ||
802 | } | ||
803 | } | ||
804 | catch(Exception) | ||
805 | { | ||
806 | LSLError("osParseJSON: The JSON string is not valid " + JSON); | ||
807 | } | ||
808 | |||
809 | return jsondata; | ||
810 | } | ||
811 | |||
812 | internal void LSLError(string msg) | ||
813 | { | ||
814 | throw new Exception("LSL Runtime Error: " + msg); | ||
815 | } | ||
816 | } | ||
817 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands_Interface.cs b/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands_Interface.cs deleted file mode 100644 index 49f92b5..0000000 --- a/OpenSim/Region/ScriptEngine/Common/OSSL_BuilIn_Commands_Interface.cs +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | using OpenSim.Region.ScriptEngine.Shared; | ||
28 | |||
29 | namespace OpenSim.Region.ScriptEngine.Common | ||
30 | { | ||
31 | public interface OSSL_BuilIn_Commands_Interface | ||
32 | { | ||
33 | //OpenSim functions | ||
34 | string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer); | ||
35 | string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, | ||
36 | int timer, int alpha); | ||
37 | string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer); | ||
38 | string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, | ||
39 | int timer, int alpha); | ||
40 | double osTerrainGetHeight(int x, int y); | ||
41 | int osTerrainSetHeight(int x, int y, double val); | ||
42 | int osRegionRestart(double seconds); | ||
43 | void osRegionNotice(string msg); | ||
44 | bool osConsoleCommand(string Command); | ||
45 | void osSetParcelMediaURL(string url); | ||
46 | void osSetPrimFloatOnWater(int floatYN); | ||
47 | |||
48 | // Teleport commands | ||
49 | void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); | ||
50 | void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); | ||
51 | |||
52 | // Animation commands | ||
53 | void osAvatarPlayAnimation(string avatar, string animation); | ||
54 | void osAvatarStopAnimation(string avatar, string animation); | ||
55 | |||
56 | //texture draw functions | ||
57 | string osMovePen(string drawList, int x, int y); | ||
58 | string osDrawLine(string drawList, int startX, int startY, int endX, int endY); | ||
59 | string osDrawLine(string drawList, int endX, int endY); | ||
60 | string osDrawText(string drawList, string text); | ||
61 | string osDrawEllipse(string drawList, int width, int height); | ||
62 | string osDrawRectangle(string drawList, int width, int height); | ||
63 | string osDrawFilledRectangle(string drawList, int width, int height); | ||
64 | string osSetFontSize(string drawList, int fontSize); | ||
65 | string osSetPenSize(string drawList, int penSize); | ||
66 | string osSetPenColour(string drawList, string colour); | ||
67 | string osDrawImage(string drawList, int width, int height, string imageUrl); | ||
68 | void osSetStateEvents(int events); | ||
69 | |||
70 | void osOpenRemoteDataChannel(string channel); | ||
71 | |||
72 | System.Collections.Hashtable osParseJSON(string JSON); | ||
73 | |||
74 | string osGetScriptEngineName(); | ||
75 | void osSetParcelMediaTime(double time); | ||
76 | |||
77 | } | ||
78 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs b/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs index d665bcc..927ab2c 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptBaseClass.cs | |||
@@ -31,6 +31,8 @@ using System.Threading; | |||
31 | using OpenSim.Region.Environment.Interfaces; | 31 | using OpenSim.Region.Environment.Interfaces; |
32 | using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; | 32 | using OpenSim.Region.ScriptEngine.Common.ScriptEngineBase; |
33 | using OpenSim.Region.ScriptEngine.Shared; | 33 | using OpenSim.Region.ScriptEngine.Shared; |
34 | using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; | ||
35 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
34 | 36 | ||
35 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | 37 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; |
36 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | 38 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; |
@@ -42,7 +44,7 @@ using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | |||
42 | 44 | ||
43 | namespace OpenSim.Region.ScriptEngine.Common | 45 | namespace OpenSim.Region.ScriptEngine.Common |
44 | { | 46 | { |
45 | public class ScriptBaseClass : MarshalByRefObject, LSL_BuiltIn_Commands_Interface, OSSL_BuilIn_Commands_Interface, IScript | 47 | public class ScriptBaseClass : MarshalByRefObject, IScript |
46 | { | 48 | { |
47 | // | 49 | // |
48 | // Included as base for any LSL-script that is compiled. | 50 | // Included as base for any LSL-script that is compiled. |
@@ -71,6 +73,19 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
71 | 73 | ||
72 | private Executor m_Exec; | 74 | private Executor m_Exec; |
73 | 75 | ||
76 | private string m_state = "default"; | ||
77 | |||
78 | public String State | ||
79 | { | ||
80 | get { return m_state; } | ||
81 | set { m_state = value; } | ||
82 | } | ||
83 | |||
84 | public void state(string newState) | ||
85 | { | ||
86 | m_LSL_Functions.state(newState); | ||
87 | } | ||
88 | |||
74 | ExecutorBase IScript.Exec | 89 | ExecutorBase IScript.Exec |
75 | { | 90 | { |
76 | get | 91 | get |
@@ -82,7 +97,8 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
82 | } | 97 | } |
83 | 98 | ||
84 | 99 | ||
85 | public BuilIn_Commands m_LSL_Functions; | 100 | public ILSL_Api m_LSL_Functions; |
101 | public IOSSL_Api m_OSSL_Functions; | ||
86 | private string _Source = String.Empty; | 102 | private string _Source = String.Empty; |
87 | public string Source | 103 | public string Source |
88 | { | 104 | { |
@@ -104,20 +120,12 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
104 | { | 120 | { |
105 | } | 121 | } |
106 | 122 | ||
107 | public string State | 123 | public void InitApi(string api, IScriptApi LSL_Functions) |
108 | { | ||
109 | get { return m_LSL_Functions.State; } | ||
110 | set { m_LSL_Functions.State = value; } | ||
111 | } | ||
112 | public void state(string state) | ||
113 | { | ||
114 | State = state; | ||
115 | |||
116 | } | ||
117 | |||
118 | public void Start(BuilIn_Commands LSL_Functions) | ||
119 | { | 124 | { |
120 | m_LSL_Functions = LSL_Functions; | 125 | if (api == "LSL") |
126 | m_LSL_Functions = (ILSL_Api)LSL_Functions; | ||
127 | if (api == "OSSL") | ||
128 | m_OSSL_Functions = (IOSSL_Api)LSL_Functions; | ||
121 | 129 | ||
122 | //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called."); | 130 | //m_log.Info(ScriptEngineName, "LSL_BaseClass.Start() called."); |
123 | 131 | ||
@@ -142,9 +150,9 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
142 | 150 | ||
143 | 151 | ||
144 | 152 | ||
145 | public OSSL_BuilIn_Commands.OSSLPrim Prim { | 153 | // public OSSL_BuilIn_Commands.OSSLPrim Prim { |
146 | get { return m_LSL_Functions.Prim; } | 154 | // get { return m_LSL_Functions.Prim; } |
147 | } | 155 | // } |
148 | 156 | ||
149 | 157 | ||
150 | // | 158 | // |
@@ -153,10 +161,10 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
153 | // They are only forwarders to LSL_BuiltIn_Commands.cs | 161 | // They are only forwarders to LSL_BuiltIn_Commands.cs |
154 | // | 162 | // |
155 | 163 | ||
156 | public ICommander GetCommander(string name) | 164 | // public ICommander GetCommander(string name) |
157 | { | 165 | // { |
158 | return m_LSL_Functions.GetCommander(name); | 166 | // return m_LSL_Functions.GetCommander(name); |
159 | } | 167 | // } |
160 | 168 | ||
161 | public LSL_Integer llAbs(int i) | 169 | public LSL_Integer llAbs(int i) |
162 | { | 170 | { |
@@ -1874,84 +1882,84 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
1874 | public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, | 1882 | public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, |
1875 | int timer) | 1883 | int timer) |
1876 | { | 1884 | { |
1877 | return m_LSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer); | 1885 | return m_OSSL_Functions.osSetDynamicTextureURL(dynamicID, contentType, url, extraParams, timer); |
1878 | } | 1886 | } |
1879 | 1887 | ||
1880 | public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, | 1888 | public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, |
1881 | int timer) | 1889 | int timer) |
1882 | { | 1890 | { |
1883 | return m_LSL_Functions.osSetDynamicTextureData(dynamicID, contentType, data, extraParams, timer); | 1891 | return m_OSSL_Functions.osSetDynamicTextureData(dynamicID, contentType, data, extraParams, timer); |
1884 | } | 1892 | } |
1885 | 1893 | ||
1886 | public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, | 1894 | public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, |
1887 | int timer, int alpha) | 1895 | int timer, int alpha) |
1888 | { | 1896 | { |
1889 | return m_LSL_Functions.osSetDynamicTextureURLBlend(dynamicID, contentType, url, extraParams, timer, alpha); | 1897 | return m_OSSL_Functions.osSetDynamicTextureURLBlend(dynamicID, contentType, url, extraParams, timer, alpha); |
1890 | } | 1898 | } |
1891 | 1899 | ||
1892 | public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, | 1900 | public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, |
1893 | int timer, int alpha) | 1901 | int timer, int alpha) |
1894 | { | 1902 | { |
1895 | return m_LSL_Functions.osSetDynamicTextureDataBlend(dynamicID, contentType, data, extraParams, timer, alpha); | 1903 | return m_OSSL_Functions.osSetDynamicTextureDataBlend(dynamicID, contentType, data, extraParams, timer, alpha); |
1896 | } | 1904 | } |
1897 | 1905 | ||
1898 | public double osTerrainGetHeight(int x, int y) | 1906 | public double osTerrainGetHeight(int x, int y) |
1899 | { | 1907 | { |
1900 | return m_LSL_Functions.osTerrainGetHeight(x, y); | 1908 | return m_OSSL_Functions.osTerrainGetHeight(x, y); |
1901 | } | 1909 | } |
1902 | 1910 | ||
1903 | public int osTerrainSetHeight(int x, int y, double val) | 1911 | public int osTerrainSetHeight(int x, int y, double val) |
1904 | { | 1912 | { |
1905 | return m_LSL_Functions.osTerrainSetHeight(x, y, val); | 1913 | return m_OSSL_Functions.osTerrainSetHeight(x, y, val); |
1906 | } | 1914 | } |
1907 | 1915 | ||
1908 | public int osRegionRestart(double seconds) | 1916 | public int osRegionRestart(double seconds) |
1909 | { | 1917 | { |
1910 | return m_LSL_Functions.osRegionRestart(seconds); | 1918 | return m_OSSL_Functions.osRegionRestart(seconds); |
1911 | } | 1919 | } |
1912 | 1920 | ||
1913 | public void osRegionNotice(string msg) | 1921 | public void osRegionNotice(string msg) |
1914 | { | 1922 | { |
1915 | m_LSL_Functions.osRegionNotice(msg); | 1923 | m_OSSL_Functions.osRegionNotice(msg); |
1916 | } | 1924 | } |
1917 | 1925 | ||
1918 | public bool osConsoleCommand(string Command) | 1926 | public bool osConsoleCommand(string Command) |
1919 | { | 1927 | { |
1920 | return m_LSL_Functions.osConsoleCommand(Command); | 1928 | return m_OSSL_Functions.osConsoleCommand(Command); |
1921 | } | 1929 | } |
1922 | 1930 | ||
1923 | public void osSetParcelMediaURL(string url) | 1931 | public void osSetParcelMediaURL(string url) |
1924 | { | 1932 | { |
1925 | m_LSL_Functions.osSetParcelMediaURL(url); | 1933 | m_OSSL_Functions.osSetParcelMediaURL(url); |
1926 | } | 1934 | } |
1927 | 1935 | ||
1928 | public void osSetPrimFloatOnWater(int floatYN) | 1936 | public void osSetPrimFloatOnWater(int floatYN) |
1929 | { | 1937 | { |
1930 | m_LSL_Functions.osSetPrimFloatOnWater(floatYN); | 1938 | m_OSSL_Functions.osSetPrimFloatOnWater(floatYN); |
1931 | } | 1939 | } |
1932 | 1940 | ||
1933 | // Teleport Functions | 1941 | // Teleport Functions |
1934 | 1942 | ||
1935 | public void osTeleportAgent(string agent, string regionName, LSL_Vector position, LSL_Vector lookat) | 1943 | public void osTeleportAgent(string agent, string regionName, LSL_Vector position, LSL_Vector lookat) |
1936 | { | 1944 | { |
1937 | m_LSL_Functions.osTeleportAgent(agent, regionName, position, lookat); | 1945 | m_OSSL_Functions.osTeleportAgent(agent, regionName, position, lookat); |
1938 | } | 1946 | } |
1939 | 1947 | ||
1940 | public void osTeleportAgent(string agent, LSL_Vector position, LSL_Vector lookat) | 1948 | public void osTeleportAgent(string agent, LSL_Vector position, LSL_Vector lookat) |
1941 | { | 1949 | { |
1942 | m_LSL_Functions.osTeleportAgent(agent, position, lookat); | 1950 | m_OSSL_Functions.osTeleportAgent(agent, position, lookat); |
1943 | } | 1951 | } |
1944 | 1952 | ||
1945 | // Animation Functions | 1953 | // Animation Functions |
1946 | 1954 | ||
1947 | public void osAvatarPlayAnimation(string avatar, string animation) | 1955 | public void osAvatarPlayAnimation(string avatar, string animation) |
1948 | { | 1956 | { |
1949 | m_LSL_Functions.osAvatarPlayAnimation(avatar, animation); | 1957 | m_OSSL_Functions.osAvatarPlayAnimation(avatar, animation); |
1950 | } | 1958 | } |
1951 | 1959 | ||
1952 | public void osAvatarStopAnimation(string avatar, string animation) | 1960 | public void osAvatarStopAnimation(string avatar, string animation) |
1953 | { | 1961 | { |
1954 | m_LSL_Functions.osAvatarStopAnimation(avatar, animation); | 1962 | m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); |
1955 | } | 1963 | } |
1956 | 1964 | ||
1957 | 1965 | ||
@@ -1959,83 +1967,83 @@ namespace OpenSim.Region.ScriptEngine.Common | |||
1959 | 1967 | ||
1960 | public string osMovePen(string drawList, int x, int y) | 1968 | public string osMovePen(string drawList, int x, int y) |
1961 | { | 1969 | { |
1962 | return m_LSL_Functions.osMovePen(drawList, x, y); | 1970 | return m_OSSL_Functions.osMovePen(drawList, x, y); |
1963 | } | 1971 | } |
1964 | 1972 | ||
1965 | public string osDrawLine(string drawList, int startX, int startY, int endX, int endY) | 1973 | public string osDrawLine(string drawList, int startX, int startY, int endX, int endY) |
1966 | { | 1974 | { |
1967 | return m_LSL_Functions.osDrawLine(drawList, startX, startY, endX, endY); | 1975 | return m_OSSL_Functions.osDrawLine(drawList, startX, startY, endX, endY); |
1968 | } | 1976 | } |
1969 | 1977 | ||
1970 | public string osDrawLine(string drawList, int endX, int endY) | 1978 | public string osDrawLine(string drawList, int endX, int endY) |
1971 | { | 1979 | { |
1972 | return m_LSL_Functions.osDrawLine(drawList, endX, endY); | 1980 | return m_OSSL_Functions.osDrawLine(drawList, endX, endY); |
1973 | } | 1981 | } |
1974 | 1982 | ||
1975 | public string osDrawText(string drawList, string text) | 1983 | public string osDrawText(string drawList, string text) |
1976 | { | 1984 | { |
1977 | return m_LSL_Functions.osDrawText(drawList, text); | 1985 | return m_OSSL_Functions.osDrawText(drawList, text); |
1978 | } | 1986 | } |
1979 | 1987 | ||
1980 | public string osDrawEllipse(string drawList, int width, int height) | 1988 | public string osDrawEllipse(string drawList, int width, int height) |
1981 | { | 1989 | { |
1982 | return m_LSL_Functions.osDrawEllipse(drawList, width, height); | 1990 | return m_OSSL_Functions.osDrawEllipse(drawList, width, height); |
1983 | } | 1991 | } |
1984 | 1992 | ||
1985 | public string osDrawRectangle(string drawList, int width, int height) | 1993 | public string osDrawRectangle(string drawList, int width, int height) |
1986 | { | 1994 | { |
1987 | return m_LSL_Functions.osDrawRectangle(drawList, width, height); | 1995 | return m_OSSL_Functions.osDrawRectangle(drawList, width, height); |
1988 | } | 1996 | } |
1989 | 1997 | ||
1990 | public string osDrawFilledRectangle(string drawList, int width, int height) | 1998 | public string osDrawFilledRectangle(string drawList, int width, int height) |
1991 | { | 1999 | { |
1992 | return m_LSL_Functions.osDrawFilledRectangle(drawList, width, height); | 2000 | return m_OSSL_Functions.osDrawFilledRectangle(drawList, width, height); |
1993 | } | 2001 | } |
1994 | 2002 | ||
1995 | public string osSetFontSize(string drawList, int fontSize) | 2003 | public string osSetFontSize(string drawList, int fontSize) |
1996 | { | 2004 | { |
1997 | return m_LSL_Functions.osSetFontSize(drawList, fontSize); | 2005 | return m_OSSL_Functions.osSetFontSize(drawList, fontSize); |
1998 | } | 2006 | } |
1999 | 2007 | ||
2000 | public string osSetPenSize(string drawList, int penSize) | 2008 | public string osSetPenSize(string drawList, int penSize) |
2001 | { | 2009 | { |
2002 | return m_LSL_Functions.osSetPenSize(drawList, penSize); | 2010 | return m_OSSL_Functions.osSetPenSize(drawList, penSize); |
2003 | } | 2011 | } |
2004 | 2012 | ||
2005 | public string osSetPenColour(string drawList, string colour) | 2013 | public string osSetPenColour(string drawList, string colour) |
2006 | { | 2014 | { |
2007 | return m_LSL_Functions.osSetPenColour(drawList, colour); | 2015 | return m_OSSL_Functions.osSetPenColour(drawList, colour); |
2008 | } | 2016 | } |
2009 | 2017 | ||
2010 | public string osDrawImage(string drawList, int width, int height, string imageUrl) | 2018 | public string osDrawImage(string drawList, int width, int height, string imageUrl) |
2011 | { | 2019 | { |
2012 | return m_LSL_Functions.osDrawImage(drawList, width, height, imageUrl); | 2020 | return m_OSSL_Functions.osDrawImage(drawList, width, height, imageUrl); |
2013 | } | 2021 | } |
2014 | 2022 | ||
2015 | public void osSetStateEvents(int events) | 2023 | public void osSetStateEvents(int events) |
2016 | { | 2024 | { |
2017 | m_LSL_Functions.osSetStateEvents(events); | 2025 | m_OSSL_Functions.osSetStateEvents(events); |
2018 | } | 2026 | } |
2019 | 2027 | ||
2020 | public void osOpenRemoteDataChannel(string channel) | 2028 | // public void osOpenRemoteDataChannel(string channel) |
2021 | { | 2029 | // { |
2022 | m_LSL_Functions.osOpenRemoteDataChannel(channel); | 2030 | // m_OSSL_Functions.osOpenRemoteDataChannel(channel); |
2023 | } | 2031 | // } |
2024 | 2032 | ||
2025 | public string osGetScriptEngineName() | 2033 | public string osGetScriptEngineName() |
2026 | { | 2034 | { |
2027 | return m_LSL_Functions.osGetScriptEngineName(); | 2035 | return m_OSSL_Functions.osGetScriptEngineName(); |
2028 | } | 2036 | } |
2029 | 2037 | ||
2030 | public System.Collections.Hashtable osParseJSON(string JSON) | 2038 | public System.Collections.Hashtable osParseJSON(string JSON) |
2031 | { | 2039 | { |
2032 | return m_LSL_Functions.osParseJSON(JSON); | 2040 | return m_OSSL_Functions.osParseJSON(JSON); |
2033 | } | 2041 | } |
2034 | 2042 | ||
2035 | //for testing purposes only | 2043 | //for testing purposes only |
2036 | public void osSetParcelMediaTime(double time) | 2044 | public void osSetParcelMediaTime(double time) |
2037 | { | 2045 | { |
2038 | m_LSL_Functions.osSetParcelMediaTime(time); | 2046 | m_OSSL_Functions.osSetParcelMediaTime(time); |
2039 | } | 2047 | } |
2040 | 2048 | ||
2041 | // LSL CONSTANTS | 2049 | // LSL CONSTANTS |
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs index 18925e0..88f7b41 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptEngine.cs | |||
@@ -66,6 +66,11 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
66 | private bool m_enabled = false; | 66 | private bool m_enabled = false; |
67 | private bool m_hookUpToServer = false; | 67 | private bool m_hookUpToServer = false; |
68 | 68 | ||
69 | public IConfig Config | ||
70 | { | ||
71 | get { return ScriptConfigSource; } | ||
72 | } | ||
73 | |||
69 | /// <summary> | 74 | /// <summary> |
70 | /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. | 75 | /// How many seconds between re-reading config-file. 0 = never. ScriptEngine will try to adjust to new config changes. |
71 | /// </summary> | 76 | /// </summary> |
@@ -120,6 +125,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
120 | m_EventManager = new EventManager(this, HookUpToServer); | 125 | m_EventManager = new EventManager(this, HookUpToServer); |
121 | // We need to start it | 126 | // We need to start it |
122 | m_ScriptManager = newScriptManager; | 127 | m_ScriptManager = newScriptManager; |
128 | m_ScriptManager.Setup(); | ||
123 | m_AppDomainManager = new AppDomainManager(this); | 129 | m_AppDomainManager = new AppDomainManager(this); |
124 | if (m_MaintenanceThread == null) | 130 | if (m_MaintenanceThread == null) |
125 | m_MaintenanceThread = new MaintenanceThread(); | 131 | m_MaintenanceThread = new MaintenanceThread(); |
@@ -229,23 +235,88 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
229 | 235 | ||
230 | public void SetState(UUID itemID, string state) | 236 | public void SetState(UUID itemID, string state) |
231 | { | 237 | { |
238 | uint localID = m_ScriptManager.GetLocalID(itemID); | ||
239 | if (localID == 0) | ||
240 | return; | ||
241 | |||
242 | IScript Script = m_ScriptManager.GetScript(localID, itemID); | ||
243 | |||
244 | if (Script == null) | ||
245 | return; | ||
246 | |||
247 | string currentState = Script.State; | ||
248 | |||
249 | if (currentState != state) | ||
250 | { | ||
251 | try | ||
252 | { | ||
253 | m_EventManager.state_exit(localID); | ||
254 | |||
255 | } | ||
256 | catch (AppDomainUnloadedException) | ||
257 | { | ||
258 | Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); | ||
259 | } | ||
260 | |||
261 | Script.State = state; | ||
262 | |||
263 | try | ||
264 | { | ||
265 | int eventFlags = m_ScriptManager.GetStateEventFlags(localID, itemID); | ||
266 | SceneObjectPart part = m_Scene.GetSceneObjectPart(itemID); | ||
267 | if (part != null) | ||
268 | part.SetScriptEvents(itemID, eventFlags); | ||
269 | m_EventManager.state_entry(localID); | ||
270 | } | ||
271 | catch (AppDomainUnloadedException) | ||
272 | { | ||
273 | Console.WriteLine("[SCRIPT]: state change called when script was unloaded. Nothing to worry about, but noting the occurance"); | ||
274 | } | ||
275 | } | ||
232 | } | 276 | } |
233 | 277 | ||
234 | public bool GetScriptState(UUID itemID) | 278 | public bool GetScriptState(UUID itemID) |
235 | { | 279 | { |
236 | return true; | 280 | uint localID = m_ScriptManager.GetLocalID(itemID); |
281 | if (localID == 0) | ||
282 | return false; | ||
283 | |||
284 | IScript script = m_ScriptManager.GetScript(localID, itemID); | ||
285 | if (script == null) | ||
286 | return false; | ||
287 | |||
288 | return script.Exec.Running?true:false; | ||
237 | } | 289 | } |
238 | 290 | ||
239 | public void SetScriptState(UUID itemID, bool state) | 291 | public void SetScriptState(UUID itemID, bool state) |
240 | { | 292 | { |
293 | uint localID = m_ScriptManager.GetLocalID(itemID); | ||
294 | if (localID == 0) | ||
295 | return; | ||
296 | |||
297 | IScript script = m_ScriptManager.GetScript(localID, itemID); | ||
298 | if (script == null) | ||
299 | return; | ||
300 | |||
301 | script.Exec.Running = state; | ||
241 | } | 302 | } |
242 | 303 | ||
243 | public void ApiResetScript(UUID itemID) | 304 | public void ApiResetScript(UUID itemID) |
244 | { | 305 | { |
306 | uint localID = m_ScriptManager.GetLocalID(itemID); | ||
307 | if (localID == 0) | ||
308 | return; | ||
309 | |||
310 | m_ScriptManager.ResetScript(localID, itemID); | ||
245 | } | 311 | } |
246 | 312 | ||
247 | public void ResetScript(UUID itemID) | 313 | public void ResetScript(UUID itemID) |
248 | { | 314 | { |
315 | uint localID = m_ScriptManager.GetLocalID(itemID); | ||
316 | if (localID == 0) | ||
317 | return; | ||
318 | |||
319 | m_ScriptManager.ResetScript(localID, itemID); | ||
249 | } | 320 | } |
250 | } | 321 | } |
251 | } | 322 | } |
diff --git a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs index 095e11f..987a0a0 100644 --- a/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/Common/ScriptEngineBase/ScriptManager.cs | |||
@@ -120,12 +120,15 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
120 | m_scriptEngine = scriptEngine; | 120 | m_scriptEngine = scriptEngine; |
121 | } | 121 | } |
122 | public abstract void Initialize(); | 122 | public abstract void Initialize(); |
123 | public void Setup() | ||
124 | { | ||
125 | ReadConfig(); | ||
126 | Initialize(); | ||
127 | } | ||
123 | public void Start() | 128 | public void Start() |
124 | { | 129 | { |
125 | m_started = true; | 130 | m_started = true; |
126 | 131 | ||
127 | ReadConfig(); | ||
128 | Initialize(); | ||
129 | 132 | ||
130 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); | 133 | AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); |
131 | 134 | ||
@@ -225,6 +228,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
225 | { | 228 | { |
226 | if (LUQueue.Count > 0) | 229 | if (LUQueue.Count > 0) |
227 | { | 230 | { |
231 | m_scriptEngine.Log.InfoFormat("[{0}]: Loading script", m_scriptEngine.ScriptEngineName); | ||
228 | LUStruct item = LUQueue.Dequeue(); | 232 | LUStruct item = LUQueue.Dequeue(); |
229 | 233 | ||
230 | if (item.Action == LUType.Unload) | 234 | if (item.Action == LUType.Unload) |
@@ -281,6 +285,7 @@ namespace OpenSim.Region.ScriptEngine.Common.ScriptEngineBase | |||
281 | ls.startParam = startParam; | 285 | ls.startParam = startParam; |
282 | ls.postOnRez = postOnRez; | 286 | ls.postOnRez = postOnRez; |
283 | LUQueue.Enqueue(ls); | 287 | LUQueue.Enqueue(ls); |
288 | m_scriptEngine.Log.InfoFormat("[{0}]: Queued script for load", m_scriptEngine.ScriptEngineName); | ||
284 | } | 289 | } |
285 | } | 290 | } |
286 | 291 | ||
diff --git a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs index 624b20b..8ff3bfd 100644 --- a/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs +++ b/OpenSim/Region/ScriptEngine/DotNetEngine/ScriptManager.cs | |||
@@ -132,10 +132,16 @@ namespace OpenSim.Region.ScriptEngine.DotNetEngine | |||
132 | // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. | 132 | // this private copy will contain Read-Only FullitemID so that it can bring that on to the server whenever needed. |
133 | 133 | ||
134 | 134 | ||
135 | BuilIn_Commands LSLB = new BuilIn_Commands(m_scriptEngine, m_host, localID, itemID); | 135 | // OSSL_BuilIn_Commands LSLB = new OSSL_BuilIn_Commands(m_scriptEngine, m_host, localID, itemID); |
136 | LSL_Api LSL = new LSL_Api(); | ||
137 | OSSL_Api OSSL = new OSSL_Api(); | ||
138 | |||
139 | LSL.Initialize(m_scriptEngine, m_host, localID, itemID); | ||
140 | OSSL.Initialize(m_scriptEngine, m_host, localID, itemID); | ||
136 | 141 | ||
137 | // Start the script - giving it BuiltIns | 142 | // Start the script - giving it BuiltIns |
138 | CompiledScript.Start(LSLB); | 143 | CompiledScript.InitApi("LSL", LSL); |
144 | CompiledScript.InitApi("OSSL", OSSL); | ||
139 | 145 | ||
140 | // Fire the first start-event | 146 | // Fire the first start-event |
141 | int eventFlags = m_scriptEngine.m_ScriptManager.GetStateEventFlags(localID, itemID); | 147 | int eventFlags = m_scriptEngine.m_ScriptManager.GetStateEventFlags(localID, itemID); |
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs b/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs index 7fad02c..084e279 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IEventReceiver.cs | |||
@@ -63,5 +63,8 @@ namespace OpenSim.Region.ScriptEngine.Interfaces | |||
63 | void SetState(UUID itemID, string newState); | 63 | void SetState(UUID itemID, string newState); |
64 | void ApiResetScript(UUID itemID); | 64 | void ApiResetScript(UUID itemID); |
65 | void ResetScript(UUID itemID); | 65 | void ResetScript(UUID itemID); |
66 | IConfig Config { get; } | ||
67 | string ScriptEngineName { get; } | ||
68 | ILog Log { get; } | ||
66 | } | 69 | } |
67 | } | 70 | } |
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs index e94de68..13f043d 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptApi.cs | |||
@@ -38,6 +38,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces | |||
38 | // Each API has an identifier, which is used to load the | 38 | // Each API has an identifier, which is used to load the |
39 | // proper runtime assembly at load time. | 39 | // proper runtime assembly at load time. |
40 | // | 40 | // |
41 | void Initialize(IScriptEngine engine, SceneObjectPart part, uint localID, UUID item); | 41 | void Initialize(IEventReceiver engine, SceneObjectPart part, uint localID, UUID item); |
42 | } | 42 | } |
43 | } | 43 | } |
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs index 7af346d..ccfbca8 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs | |||
@@ -42,10 +42,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces | |||
42 | /// </summary> | 42 | /// </summary> |
43 | public interface IScriptEngine : IEventReceiver | 43 | public interface IScriptEngine : IEventReceiver |
44 | { | 44 | { |
45 | IConfig Config { get; } | ||
46 | ILog Log { get; } | ||
47 | string ScriptEngineName { get; } | ||
48 | |||
49 | /// <summary> | 45 | /// <summary> |
50 | /// Queue an event for execution | 46 | /// Queue an event for execution |
51 | /// </summary> | 47 | /// </summary> |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d782c56..93a168a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | |||
@@ -63,16 +63,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
63 | /// <summary> | 63 | /// <summary> |
64 | /// Contains all LSL ll-functions. This class will be in Default AppDomain. | 64 | /// Contains all LSL ll-functions. This class will be in Default AppDomain. |
65 | /// </summary> | 65 | /// </summary> |
66 | public class LSL_Api : LSL_Api_Base, ILSL_Api, IScriptApi | 66 | public class LSL_Api : MarshalByRefObject, ILSL_Api, IScriptApi |
67 | { | 67 | { |
68 | private IScriptEngine m_ScriptEngineDirect; | 68 | protected IEventReceiver m_ScriptEngine; |
69 | protected SceneObjectPart m_host; | ||
70 | protected uint m_localID; | ||
71 | protected UUID m_itemID; | ||
72 | protected bool throwErrorOnNotImplemented = true; | ||
73 | protected AsyncCommandManager AsyncCommands = null; | ||
74 | protected float m_ScriptDelayFactor = 1.0f; | ||
75 | protected float m_ScriptDistanceFactor = 1.0f; | ||
76 | |||
77 | private DateTime m_timer = DateTime.Now; | ||
78 | private bool m_waitingForScriptAnswer=false; | ||
69 | 79 | ||
70 | //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); | 80 | //private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
71 | 81 | ||
72 | public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) | 82 | public void Initialize(IEventReceiver ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) |
73 | { | 83 | { |
74 | m_ScriptEngine = ScriptEngine; | 84 | m_ScriptEngine = ScriptEngine; |
75 | m_ScriptEngineDirect = ScriptEngine; | ||
76 | m_host = host; | 85 | m_host = host; |
77 | m_localID = localID; | 86 | m_localID = localID; |
78 | m_itemID = itemID; | 87 | m_itemID = itemID; |
@@ -89,16 +98,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
89 | AsyncCommands = new AsyncCommandManager(ScriptEngine); | 98 | AsyncCommands = new AsyncCommandManager(ScriptEngine); |
90 | } | 99 | } |
91 | 100 | ||
92 | private DateTime m_timer = DateTime.Now; | ||
93 | private bool m_waitingForScriptAnswer=false; | ||
94 | protected void ScriptSleep(int delay) | ||
95 | { | ||
96 | delay = (int)((float)delay * m_ScriptDelayFactor); | ||
97 | if (delay == 0) | ||
98 | return; | ||
99 | System.Threading.Thread.Sleep(delay); | ||
100 | } | ||
101 | |||
102 | // Object never expires | 101 | // Object never expires |
103 | public override Object InitializeLifetimeService() | 102 | public override Object InitializeLifetimeService() |
104 | { | 103 | { |
@@ -111,10 +110,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
111 | return lease; | 110 | return lease; |
112 | } | 111 | } |
113 | 112 | ||
114 | public void state(string newState) | 113 | protected void ScriptSleep(int delay) |
114 | { | ||
115 | delay = (int)((float)delay * m_ScriptDelayFactor); | ||
116 | if (delay == 0) | ||
117 | return; | ||
118 | System.Threading.Thread.Sleep(delay); | ||
119 | } | ||
120 | |||
121 | public Scene World | ||
115 | { | 122 | { |
116 | m_ScriptEngineDirect.SetState(m_itemID, newState); | 123 | get { return m_ScriptEngine.World; } |
117 | throw new EventAbortException(); | ||
118 | } | 124 | } |
119 | 125 | ||
120 | // Extension commands use this: | 126 | // Extension commands use this: |
@@ -123,6 +129,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
123 | return World.GetCommander(name); | 129 | return World.GetCommander(name); |
124 | } | 130 | } |
125 | 131 | ||
132 | public void state(string newState) | ||
133 | { | ||
134 | m_ScriptEngine.SetState(m_itemID, newState); | ||
135 | } | ||
136 | |||
137 | public void llResetScript() | ||
138 | { | ||
139 | m_host.AddScriptLPS(1); | ||
140 | m_ScriptEngine.ApiResetScript(m_itemID); | ||
141 | } | ||
142 | |||
143 | public void llResetOtherScript(string name) | ||
144 | { | ||
145 | UUID item; | ||
146 | |||
147 | m_host.AddScriptLPS(1); | ||
148 | |||
149 | if ((item = ScriptByName(name)) != UUID.Zero) | ||
150 | m_ScriptEngine.ResetScript(item); | ||
151 | else | ||
152 | ShoutError("llResetOtherScript: script "+name+" not found"); | ||
153 | } | ||
154 | |||
126 | public LSL_Integer llGetScriptState(string name) | 155 | public LSL_Integer llGetScriptState(string name) |
127 | { | 156 | { |
128 | UUID item; | 157 | UUID item; |
@@ -131,7 +160,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
131 | 160 | ||
132 | if ((item = ScriptByName(name)) != UUID.Zero) | 161 | if ((item = ScriptByName(name)) != UUID.Zero) |
133 | { | 162 | { |
134 | return m_ScriptEngineDirect.GetScriptState(item) ?1:0; | 163 | return m_ScriptEngine.GetScriptState(item) ?1:0; |
135 | } | 164 | } |
136 | 165 | ||
137 | ShoutError("llGetScriptState: script "+name+" not found"); | 166 | ShoutError("llGetScriptState: script "+name+" not found"); |
@@ -142,41 +171,8207 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
142 | return 0; | 171 | return 0; |
143 | } | 172 | } |
144 | 173 | ||
145 | public void llResetOtherScript(string name) | 174 | public void llSetScriptState(string name, int run) |
146 | { | 175 | { |
147 | UUID item; | 176 | UUID item; |
148 | 177 | ||
149 | m_host.AddScriptLPS(1); | 178 | m_host.AddScriptLPS(1); |
150 | 179 | ||
180 | // These functions are supposed to be robust, | ||
181 | // so get the state one step at a time. | ||
182 | |||
151 | if ((item = ScriptByName(name)) != UUID.Zero) | 183 | if ((item = ScriptByName(name)) != UUID.Zero) |
152 | m_ScriptEngineDirect.ResetScript(item); | 184 | { |
185 | m_ScriptEngine.SetScriptState(item, run == 0 ? false : true); | ||
186 | } | ||
153 | else | 187 | else |
154 | ShoutError("llResetOtherScript: script "+name+" not found"); | 188 | { |
189 | ShoutError("llSetScriptState: script "+name+" not found"); | ||
190 | } | ||
155 | } | 191 | } |
156 | 192 | ||
157 | public void llResetScript() | 193 | private List<SceneObjectPart> GetLinkParts(int linkType) |
194 | { | ||
195 | List<SceneObjectPart> ret = new List<SceneObjectPart>(); | ||
196 | ret.Add(m_host); | ||
197 | |||
198 | switch (linkType) | ||
199 | { | ||
200 | case ScriptBaseClass.LINK_SET: | ||
201 | if (m_host.ParentGroup != null) | ||
202 | return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); | ||
203 | return ret; | ||
204 | |||
205 | case ScriptBaseClass.LINK_ROOT: | ||
206 | if (m_host.ParentGroup != null) | ||
207 | { | ||
208 | ret = new List<SceneObjectPart>(); | ||
209 | ret.Add(m_host.ParentGroup.RootPart); | ||
210 | return ret; | ||
211 | } | ||
212 | return ret; | ||
213 | |||
214 | case ScriptBaseClass.LINK_ALL_OTHERS: | ||
215 | if (m_host.ParentGroup == null) | ||
216 | return new List<SceneObjectPart>(); | ||
217 | ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); | ||
218 | if (ret.Contains(m_host)) | ||
219 | ret.Remove(m_host); | ||
220 | return ret; | ||
221 | |||
222 | case ScriptBaseClass.LINK_ALL_CHILDREN: | ||
223 | if (m_host.ParentGroup == null) | ||
224 | return new List<SceneObjectPart>(); | ||
225 | ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); | ||
226 | if (ret.Contains(m_host.ParentGroup.RootPart)) | ||
227 | ret.Remove(m_host.ParentGroup.RootPart); | ||
228 | return ret; | ||
229 | |||
230 | case ScriptBaseClass.LINK_THIS: | ||
231 | return ret; | ||
232 | |||
233 | default: | ||
234 | if (linkType < 0 || m_host.ParentGroup == null) | ||
235 | return new List<SceneObjectPart>(); | ||
236 | SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType); | ||
237 | if (target == null) | ||
238 | return new List<SceneObjectPart>(); | ||
239 | ret = new List<SceneObjectPart>(); | ||
240 | ret.Add(target); | ||
241 | return ret; | ||
242 | |||
243 | } | ||
244 | } | ||
245 | |||
246 | private UUID InventorySelf() | ||
247 | { | ||
248 | UUID invItemID = new UUID(); | ||
249 | |||
250 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
251 | { | ||
252 | if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) | ||
253 | { | ||
254 | invItemID = inv.Key; | ||
255 | break; | ||
256 | } | ||
257 | } | ||
258 | |||
259 | return invItemID; | ||
260 | } | ||
261 | |||
262 | private UUID InventoryKey(string name, int type) | ||
158 | { | 263 | { |
159 | m_host.AddScriptLPS(1); | 264 | m_host.AddScriptLPS(1); |
160 | m_ScriptEngineDirect.ApiResetScript(m_itemID); | 265 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) |
161 | throw new EventAbortException(); | 266 | { |
267 | if (inv.Value.Name == name) | ||
268 | { | ||
269 | if (inv.Value.Type != type) | ||
270 | return UUID.Zero; | ||
271 | |||
272 | return inv.Value.AssetID.ToString(); | ||
273 | } | ||
274 | } | ||
275 | return UUID.Zero; | ||
162 | } | 276 | } |
163 | 277 | ||
164 | public void llSetScriptState(string name, int run) | 278 | private UUID InventoryKey(string name) |
165 | { | 279 | { |
166 | UUID item; | 280 | m_host.AddScriptLPS(1); |
281 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
282 | { | ||
283 | if (inv.Value.Name == name) | ||
284 | { | ||
285 | return inv.Value.AssetID.ToString(); | ||
286 | } | ||
287 | } | ||
288 | return UUID.Zero; | ||
289 | } | ||
290 | |||
167 | 291 | ||
292 | /// <summary> | ||
293 | /// accepts a valid UUID, -or- a name of an inventory item. | ||
294 | /// Returns a valid UUID or UUID.Zero if key invalid and item not found | ||
295 | /// in prim inventory. | ||
296 | /// </summary> | ||
297 | /// <param name="k"></param> | ||
298 | /// <returns></returns> | ||
299 | private UUID KeyOrName(string k) | ||
300 | { | ||
301 | UUID key = UUID.Zero; | ||
302 | |||
303 | // if we can parse the string as a key, use it. | ||
304 | if (UUID.TryParse(k, out key)) | ||
305 | { | ||
306 | return key; | ||
307 | } | ||
308 | // else try to locate the name in inventory of object. found returns key, | ||
309 | // not found returns UUID.Zero which will translate to the default particle texture | ||
310 | else | ||
311 | { | ||
312 | return InventoryKey(k); | ||
313 | } | ||
314 | } | ||
315 | |||
316 | //These are the implementations of the various ll-functions used by the LSL scripts. | ||
317 | public LSL_Float llSin(double f) | ||
318 | { | ||
168 | m_host.AddScriptLPS(1); | 319 | m_host.AddScriptLPS(1); |
320 | return (double)Math.Sin(f); | ||
321 | } | ||
169 | 322 | ||
170 | // These functions are supposed to be robust, | 323 | public LSL_Float llCos(double f) |
171 | // so get the state one step at a time. | 324 | { |
325 | m_host.AddScriptLPS(1); | ||
326 | return (double)Math.Cos(f); | ||
327 | } | ||
172 | 328 | ||
173 | if ((item = ScriptByName(name)) != UUID.Zero) | 329 | public LSL_Float llTan(double f) |
330 | { | ||
331 | m_host.AddScriptLPS(1); | ||
332 | return (double)Math.Tan(f); | ||
333 | } | ||
334 | |||
335 | public LSL_Float llAtan2(double x, double y) | ||
336 | { | ||
337 | m_host.AddScriptLPS(1); | ||
338 | return (double)Math.Atan2(y, x); | ||
339 | } | ||
340 | |||
341 | public LSL_Float llSqrt(double f) | ||
342 | { | ||
343 | m_host.AddScriptLPS(1); | ||
344 | return (double)Math.Sqrt(f); | ||
345 | } | ||
346 | |||
347 | public LSL_Float llPow(double fbase, double fexponent) | ||
348 | { | ||
349 | m_host.AddScriptLPS(1); | ||
350 | return (double)Math.Pow(fbase, fexponent); | ||
351 | } | ||
352 | |||
353 | public LSL_Integer llAbs(int i) | ||
354 | { | ||
355 | m_host.AddScriptLPS(1); | ||
356 | return (int)Math.Abs(i); | ||
357 | } | ||
358 | |||
359 | public LSL_Float llFabs(double f) | ||
360 | { | ||
361 | m_host.AddScriptLPS(1); | ||
362 | return (double)Math.Abs(f); | ||
363 | } | ||
364 | |||
365 | public LSL_Float llFrand(double mag) | ||
366 | { | ||
367 | m_host.AddScriptLPS(1); | ||
368 | lock (Util.RandomClass) | ||
174 | { | 369 | { |
175 | m_ScriptEngineDirect.SetScriptState(item, run == 0 ? false : true); | 370 | return Util.RandomClass.NextDouble() * mag; |
176 | } | 371 | } |
372 | } | ||
373 | |||
374 | public LSL_Integer llFloor(double f) | ||
375 | { | ||
376 | m_host.AddScriptLPS(1); | ||
377 | return (int)Math.Floor(f); | ||
378 | } | ||
379 | |||
380 | public LSL_Integer llCeil(double f) | ||
381 | { | ||
382 | m_host.AddScriptLPS(1); | ||
383 | return (int)Math.Ceiling(f); | ||
384 | } | ||
385 | |||
386 | // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven) | ||
387 | public LSL_Integer llRound(double f) | ||
388 | { | ||
389 | m_host.AddScriptLPS(1); | ||
390 | return (int)Math.Round(f, MidpointRounding.AwayFromZero); | ||
391 | } | ||
392 | |||
393 | //This next group are vector operations involving squaring and square root. ckrinke | ||
394 | public LSL_Float llVecMag(LSL_Vector v) | ||
395 | { | ||
396 | m_host.AddScriptLPS(1); | ||
397 | return LSL_Vector.Mag(v); | ||
398 | } | ||
399 | |||
400 | public LSL_Vector llVecNorm(LSL_Vector v) | ||
401 | { | ||
402 | m_host.AddScriptLPS(1); | ||
403 | double mag = LSL_Vector.Mag(v); | ||
404 | LSL_Vector nor = new LSL_Vector(); | ||
405 | nor.x = v.x / mag; | ||
406 | nor.y = v.y / mag; | ||
407 | nor.z = v.z / mag; | ||
408 | return nor; | ||
409 | } | ||
410 | |||
411 | public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) | ||
412 | { | ||
413 | m_host.AddScriptLPS(1); | ||
414 | double dx = a.x - b.x; | ||
415 | double dy = a.y - b.y; | ||
416 | double dz = a.z - b.z; | ||
417 | return Math.Sqrt(dx * dx + dy * dy + dz * dz); | ||
418 | } | ||
419 | |||
420 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke | ||
421 | |||
422 | // Utility function for llRot2Euler | ||
423 | |||
424 | // normalize an angle between 0 - 2*PI (0 and 360 degrees) | ||
425 | private double NormalizeAngle(double angle) | ||
426 | { | ||
427 | angle = angle % (Math.PI * 2); | ||
428 | if (angle < 0) angle = angle + Math.PI * 2; | ||
429 | return angle; | ||
430 | } | ||
431 | |||
432 | // Old implementation of llRot2Euler, now normalized | ||
433 | |||
434 | public LSL_Vector llRot2Euler(LSL_Rotation r) | ||
435 | { | ||
436 | m_host.AddScriptLPS(1); | ||
437 | //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke | ||
438 | LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); | ||
439 | double m = (t.x + t.y + t.z + t.s); | ||
440 | if (m == 0) return new LSL_Vector(); | ||
441 | double n = 2 * (r.y * r.s + r.x * r.z); | ||
442 | double p = m * m - n * n; | ||
443 | if (p > 0) | ||
444 | return new LSL_Vector(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))), | ||
445 | NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), | ||
446 | NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)))); | ||
447 | else if (n > 0) | ||
448 | return new LSL_Vector(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); | ||
177 | else | 449 | else |
450 | return new LSL_Vector(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); | ||
451 | } | ||
452 | |||
453 | /* From wiki: | ||
454 | The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes | ||
455 | in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, | ||
456 | a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting | ||
457 | vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. | ||
458 | */ | ||
459 | |||
460 | /* How we arrived at this llEuler2Rot | ||
461 | * | ||
462 | * Experiment in SL to determine conventions: | ||
463 | * llEuler2Rot(<PI,0,0>)=<1,0,0,0> | ||
464 | * llEuler2Rot(<0,PI,0>)=<0,1,0,0> | ||
465 | * llEuler2Rot(<0,0,PI>)=<0,0,1,0> | ||
466 | * | ||
467 | * Important facts about Quaternions | ||
468 | * - multiplication is non-commutative (a*b != b*a) | ||
469 | * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication | ||
470 | * | ||
471 | * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot): | ||
472 | * Qx = c1+i*s1 | ||
473 | * Qy = c2+j*s2; | ||
474 | * Qz = c3+k*s3; | ||
475 | * | ||
476 | * Rotations applied in order (from above) Z, Y, X | ||
477 | * Q = (Qz * Qy) * Qx | ||
478 | * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3) | ||
479 | * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3) | ||
480 | * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3) | ||
481 | * 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 | ||
482 | * 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 | ||
483 | * regroup: x=i*(s1*c2*c3+c1*s2*s3) | ||
484 | * y=j*(c1*s2*c3-s1*c2*s3) | ||
485 | * z=k*(s1*s2*c3+c1*c2*s3) | ||
486 | * s= c1*c2*c3-s1*s2*s3 | ||
487 | * | ||
488 | * This implementation agrees with the functions found here: | ||
489 | * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions | ||
490 | * And with the results in SL. | ||
491 | * | ||
492 | * It's also possible to calculate llEuler2Rot by direct multiplication of | ||
493 | * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function | ||
494 | * from the wiki). | ||
495 | * Apparently in some cases this is better from a numerical precision perspective? | ||
496 | */ | ||
497 | |||
498 | public LSL_Rotation llEuler2Rot(LSL_Vector v) | ||
499 | { | ||
500 | m_host.AddScriptLPS(1); | ||
501 | |||
502 | double x,y,z,s; | ||
503 | |||
504 | double c1 = Math.Cos(v.x/2.0); | ||
505 | double c2 = Math.Cos(v.y/2.0); | ||
506 | double c3 = Math.Cos(v.z/2.0); | ||
507 | double s1 = Math.Sin(v.x/2.0); | ||
508 | double s2 = Math.Sin(v.y/2.0); | ||
509 | double s3 = Math.Sin(v.z/2.0); | ||
510 | |||
511 | x = s1*c2*c3+c1*s2*s3; | ||
512 | y = c1*s2*c3-s1*c2*s3; | ||
513 | z = s1*s2*c3+c1*c2*s3; | ||
514 | s = c1*c2*c3-s1*s2*s3; | ||
515 | |||
516 | return new LSL_Rotation(x, y, z, s); | ||
517 | } | ||
518 | |||
519 | public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up) | ||
520 | { | ||
521 | m_host.AddScriptLPS(1); | ||
522 | double x, y, z, s; | ||
523 | int f = 0; | ||
524 | // Important Note: q1=<x,y,z,s> is equal to q2=<-x,-y,-z,-s> | ||
525 | // Computing quaternion x,y,z,s values | ||
526 | x = ((fwd.x - left.y - up.z + 1) / 4); | ||
527 | x *= x; | ||
528 | x = Math.Sqrt(Math.Sqrt(x)); | ||
529 | y = ((1 - up.z) / 2 - x * x); | ||
530 | y *= y; | ||
531 | y = Math.Sqrt(Math.Sqrt(y)); | ||
532 | z = ((1 - left.y) / 2 - x * x); | ||
533 | z *= z; | ||
534 | z = Math.Sqrt(Math.Sqrt(z)); | ||
535 | s = (1 - x * x - y * y - z * z); | ||
536 | s *= s; | ||
537 | s = Math.Sqrt(Math.Sqrt(s)); | ||
538 | |||
539 | // Set f for signs detection | ||
540 | if (fwd.y + left.x >= 0) { f += 1; } | ||
541 | if (fwd.z + up.x >= 0) { f += 2; } | ||
542 | if (left.z - up.y >= 0) { f += 4; } | ||
543 | // Set correct quaternion signs based on f value | ||
544 | if (f == 0) { x = -x; } | ||
545 | if (f == 1) { x = -x; y = -y; } | ||
546 | if (f == 2) { x = -x; z = -z; } | ||
547 | if (f == 3) { s = -s; } | ||
548 | if (f == 4) { x = -x; s = -s; } | ||
549 | if (f == 5) { z = -z; } | ||
550 | if (f == 6) { y = -y; } | ||
551 | |||
552 | LSL_Rotation result = new LSL_Rotation(x, y, z, s); | ||
553 | |||
554 | // a hack to correct a few questionable angles :( | ||
555 | if (llVecDist(llRot2Fwd(result), fwd) > 0.001 || llVecDist(llRot2Left(result), left) > 0.001) | ||
556 | result.s = -s; | ||
557 | |||
558 | return result; | ||
559 | } | ||
560 | |||
561 | public LSL_Vector llRot2Fwd(LSL_Rotation r) | ||
562 | { | ||
563 | m_host.AddScriptLPS(1); | ||
564 | |||
565 | double x, y, z, m; | ||
566 | |||
567 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | ||
568 | // m is always greater than zero | ||
569 | // if m is not equal to 1 then Rotation needs to be normalized | ||
570 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | ||
178 | { | 571 | { |
179 | ShoutError("llSetScriptState: script "+name+" not found"); | 572 | m = 1.0 / Math.Sqrt(m); |
573 | r.x *= m; | ||
574 | r.y *= m; | ||
575 | r.z *= m; | ||
576 | r.s *= m; | ||
577 | } | ||
578 | |||
579 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | ||
580 | x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s; | ||
581 | y = 2 * (r.x * r.y + r.z * r.s); | ||
582 | z = 2 * (r.x * r.z - r.y * r.s); | ||
583 | return (new LSL_Vector(x, y, z)); | ||
584 | } | ||
585 | |||
586 | public LSL_Vector llRot2Left(LSL_Rotation r) | ||
587 | { | ||
588 | m_host.AddScriptLPS(1); | ||
589 | |||
590 | double x, y, z, m; | ||
591 | |||
592 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | ||
593 | // m is always greater than zero | ||
594 | // if m is not equal to 1 then Rotation needs to be normalized | ||
595 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | ||
596 | { | ||
597 | m = 1.0 / Math.Sqrt(m); | ||
598 | r.x *= m; | ||
599 | r.y *= m; | ||
600 | r.z *= m; | ||
601 | r.s *= m; | ||
602 | } | ||
603 | |||
604 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | ||
605 | x = 2 * (r.x * r.y - r.z * r.s); | ||
606 | y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s; | ||
607 | z = 2 * (r.x * r.s + r.y * r.z); | ||
608 | return (new LSL_Vector(x, y, z)); | ||
609 | } | ||
610 | |||
611 | public LSL_Vector llRot2Up(LSL_Rotation r) | ||
612 | { | ||
613 | m_host.AddScriptLPS(1); | ||
614 | double x, y, z, m; | ||
615 | |||
616 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | ||
617 | // m is always greater than zero | ||
618 | // if m is not equal to 1 then Rotation needs to be normalized | ||
619 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | ||
620 | { | ||
621 | m = 1.0 / Math.Sqrt(m); | ||
622 | r.x *= m; | ||
623 | r.y *= m; | ||
624 | r.z *= m; | ||
625 | r.s *= m; | ||
626 | } | ||
627 | |||
628 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | ||
629 | x = 2 * (r.x * r.z + r.y * r.s); | ||
630 | y = 2 * (-r.x * r.s + r.y * r.z); | ||
631 | z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s; | ||
632 | return (new LSL_Vector(x, y, z)); | ||
633 | } | ||
634 | |||
635 | public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b) | ||
636 | { | ||
637 | //A and B should both be normalized | ||
638 | m_host.AddScriptLPS(1); | ||
639 | double dotProduct = LSL_Vector.Dot(a, b); | ||
640 | LSL_Vector crossProduct = LSL_Vector.Cross(a, b); | ||
641 | double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b); | ||
642 | double angle = Math.Acos(dotProduct / magProduct); | ||
643 | LSL_Vector axis = LSL_Vector.Norm(crossProduct); | ||
644 | double s = Math.Sin(angle / 2); | ||
645 | |||
646 | double x = axis.x * s; | ||
647 | double y = axis.y * s; | ||
648 | double z = axis.z * s; | ||
649 | double w = Math.Cos(angle / 2); | ||
650 | |||
651 | if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w)) | ||
652 | return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); | ||
653 | |||
654 | return new LSL_Rotation((float)x, (float)y, (float)z, (float)w); | ||
655 | } | ||
656 | |||
657 | public void llWhisper(int channelID, string text) | ||
658 | { | ||
659 | m_host.AddScriptLPS(1); | ||
660 | |||
661 | if (text.Length > 1023) | ||
662 | text = text.Substring(0, 1023); | ||
663 | |||
664 | World.SimChat(Utils.StringToBytes(text), | ||
665 | ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
666 | |||
667 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
668 | wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); | ||
669 | } | ||
670 | |||
671 | public void llSay(int channelID, string text) | ||
672 | { | ||
673 | m_host.AddScriptLPS(1); | ||
674 | |||
675 | if (text.Length > 1023) | ||
676 | text = text.Substring(0, 1023); | ||
677 | |||
678 | World.SimChat(Utils.StringToBytes(text), | ||
679 | ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
680 | |||
681 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
682 | wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text); | ||
683 | } | ||
684 | |||
685 | public void llShout(int channelID, string text) | ||
686 | { | ||
687 | m_host.AddScriptLPS(1); | ||
688 | |||
689 | if (text.Length > 1023) | ||
690 | text = text.Substring(0, 1023); | ||
691 | |||
692 | World.SimChat(Utils.StringToBytes(text), | ||
693 | ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true); | ||
694 | |||
695 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
696 | wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text); | ||
697 | } | ||
698 | |||
699 | public void llRegionSay(int channelID, string text) | ||
700 | { | ||
701 | if (channelID == 0) | ||
702 | { | ||
703 | LSLError("Cannot use llRegionSay() on channel 0"); | ||
704 | return; | ||
705 | } | ||
706 | |||
707 | if (text.Length > 1023) | ||
708 | text = text.Substring(0, 1023); | ||
709 | |||
710 | m_host.AddScriptLPS(1); | ||
711 | |||
712 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
713 | wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); | ||
714 | } | ||
715 | |||
716 | public LSL_Integer llListen(int channelID, string name, string ID, string msg) | ||
717 | { | ||
718 | m_host.AddScriptLPS(1); | ||
719 | UUID keyID; | ||
720 | UUID.TryParse(ID, out keyID); | ||
721 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
722 | return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg); | ||
723 | } | ||
724 | |||
725 | public void llListenControl(int number, int active) | ||
726 | { | ||
727 | m_host.AddScriptLPS(1); | ||
728 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
729 | wComm.ListenControl(m_itemID, number, active); | ||
730 | } | ||
731 | |||
732 | public void llListenRemove(int number) | ||
733 | { | ||
734 | m_host.AddScriptLPS(1); | ||
735 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
736 | wComm.ListenRemove(m_itemID, number); | ||
737 | } | ||
738 | |||
739 | public void llSensor(string name, string id, int type, double range, double arc) | ||
740 | { | ||
741 | m_host.AddScriptLPS(1); | ||
742 | UUID keyID = UUID.Zero; | ||
743 | UUID.TryParse(id, out keyID); | ||
744 | |||
745 | AsyncCommands.SensorRepeatPlugin.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host); | ||
746 | } | ||
747 | |||
748 | public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) | ||
749 | { | ||
750 | m_host.AddScriptLPS(1); | ||
751 | UUID keyID = UUID.Zero; | ||
752 | UUID.TryParse(id, out keyID); | ||
753 | |||
754 | AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host); | ||
755 | } | ||
756 | |||
757 | public void llSensorRemove() | ||
758 | { | ||
759 | m_host.AddScriptLPS(1); | ||
760 | AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_localID, m_itemID); | ||
761 | } | ||
762 | |||
763 | public string resolveName(UUID objecUUID) | ||
764 | { | ||
765 | // try avatar username surname | ||
766 | CachedUserInfo profile = World.CommsManager.UserProfileCacheService.GetUserDetails(objecUUID); | ||
767 | if (profile != null && profile.UserProfile != null) | ||
768 | { | ||
769 | string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName; | ||
770 | return avatarname; | ||
771 | } | ||
772 | // try an scene object | ||
773 | SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID); | ||
774 | if (SOP != null) | ||
775 | { | ||
776 | string objectname = SOP.Name; | ||
777 | return objectname; | ||
778 | } | ||
779 | |||
780 | EntityBase SensedObject; | ||
781 | lock (World.Entities) | ||
782 | { | ||
783 | World.Entities.TryGetValue(objecUUID, out SensedObject); | ||
784 | } | ||
785 | |||
786 | if (SensedObject == null) | ||
787 | return String.Empty; | ||
788 | return SensedObject.Name; | ||
789 | } | ||
790 | |||
791 | public LSL_String llDetectedName(int number) | ||
792 | { | ||
793 | m_host.AddScriptLPS(1); | ||
794 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
795 | if (d == null) | ||
796 | return String.Empty; | ||
797 | return d.Name; | ||
798 | } | ||
799 | |||
800 | public LSL_String llDetectedKey(int number) | ||
801 | { | ||
802 | m_host.AddScriptLPS(1); | ||
803 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
804 | if (d == null) | ||
805 | return String.Empty; | ||
806 | return d.Key.ToString(); | ||
807 | } | ||
808 | |||
809 | public LSL_String llDetectedOwner(int number) | ||
810 | { | ||
811 | m_host.AddScriptLPS(1); | ||
812 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
813 | if (d == null) | ||
814 | return String.Empty; | ||
815 | return d.Owner.ToString(); | ||
816 | } | ||
817 | |||
818 | public LSL_Integer llDetectedType(int number) | ||
819 | { | ||
820 | m_host.AddScriptLPS(1); | ||
821 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
822 | if (d == null) | ||
823 | return 0; | ||
824 | return new LSL_Integer(d.Type); | ||
825 | } | ||
826 | |||
827 | public LSL_Vector llDetectedPos(int number) | ||
828 | { | ||
829 | m_host.AddScriptLPS(1); | ||
830 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
831 | if (d == null) | ||
832 | return new LSL_Vector(); | ||
833 | return d.Position; | ||
834 | } | ||
835 | |||
836 | public LSL_Vector llDetectedVel(int number) | ||
837 | { | ||
838 | m_host.AddScriptLPS(1); | ||
839 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
840 | if (d == null) | ||
841 | return new LSL_Vector(); | ||
842 | return d.Velocity; | ||
843 | } | ||
844 | |||
845 | public LSL_Vector llDetectedGrab(int number) | ||
846 | { | ||
847 | m_host.AddScriptLPS(1); | ||
848 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
849 | if (parms == null) | ||
850 | return new LSL_Vector(0, 0, 0); | ||
851 | |||
852 | return parms.OffsetPos; | ||
853 | } | ||
854 | |||
855 | public LSL_Rotation llDetectedRot(int number) | ||
856 | { | ||
857 | m_host.AddScriptLPS(1); | ||
858 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
859 | if (d == null) | ||
860 | return new LSL_Rotation(); | ||
861 | return d.Rotation; | ||
862 | } | ||
863 | |||
864 | public LSL_Integer llDetectedGroup(int number) | ||
865 | { | ||
866 | m_host.AddScriptLPS(1); | ||
867 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
868 | if (d == null) | ||
869 | return new LSL_Integer(0); | ||
870 | if (m_host.GroupID == d.Group) | ||
871 | return new LSL_Integer(1); | ||
872 | return new LSL_Integer(0); | ||
873 | } | ||
874 | |||
875 | public LSL_Integer llDetectedLinkNumber(int number) | ||
876 | { | ||
877 | m_host.AddScriptLPS(1); | ||
878 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
879 | if (parms == null) | ||
880 | return new LSL_Integer(0); | ||
881 | |||
882 | return new LSL_Integer(parms.LinkNum); | ||
883 | } | ||
884 | |||
885 | public LSL_Vector llDetectedTouchBinormal(int index) | ||
886 | { | ||
887 | m_host.AddScriptLPS(1); | ||
888 | NotImplemented("llDetectedTouchBinormal"); | ||
889 | return new LSL_Vector(); | ||
890 | } | ||
891 | |||
892 | public LSL_Integer llDetectedTouchFace(int index) | ||
893 | { | ||
894 | m_host.AddScriptLPS(1); | ||
895 | NotImplemented("llDetectedTouchFace"); | ||
896 | return new LSL_Integer(0); | ||
897 | } | ||
898 | |||
899 | public LSL_Vector llDetectedTouchNormal(int index) | ||
900 | { | ||
901 | m_host.AddScriptLPS(1); | ||
902 | NotImplemented("llDetectedTouchNormal"); | ||
903 | return new LSL_Vector(); | ||
904 | } | ||
905 | |||
906 | public LSL_Vector llDetectedTouchPos(int index) | ||
907 | { | ||
908 | m_host.AddScriptLPS(1); | ||
909 | NotImplemented("llDetectedTouchPos"); | ||
910 | return new LSL_Vector(); | ||
911 | } | ||
912 | |||
913 | public LSL_Vector llDetectedTouchST(int index) | ||
914 | { | ||
915 | m_host.AddScriptLPS(1); | ||
916 | NotImplemented("llDetectedTouchST"); | ||
917 | return new LSL_Vector(); | ||
918 | } | ||
919 | |||
920 | public LSL_Vector llDetectedTouchUV(int index) | ||
921 | { | ||
922 | m_host.AddScriptLPS(1); | ||
923 | NotImplemented("llDetectedTouchUV"); | ||
924 | return new LSL_Vector(); | ||
925 | } | ||
926 | |||
927 | public void llDie() | ||
928 | { | ||
929 | m_host.AddScriptLPS(1); | ||
930 | throw new SelfDeleteException(); | ||
931 | } | ||
932 | |||
933 | public LSL_Float llGround(LSL_Vector offset) | ||
934 | { | ||
935 | m_host.AddScriptLPS(1); | ||
936 | int x = (int)(m_host.OffsetPosition.X + offset.x); | ||
937 | int y = (int)(m_host.OffsetPosition.Y + offset.y); | ||
938 | return World.GetLandHeight(x, y); | ||
939 | } | ||
940 | |||
941 | public LSL_Float llCloud(LSL_Vector offset) | ||
942 | { | ||
943 | m_host.AddScriptLPS(1); | ||
944 | return 0; | ||
945 | } | ||
946 | |||
947 | public LSL_Vector llWind(LSL_Vector offset) | ||
948 | { | ||
949 | m_host.AddScriptLPS(1); | ||
950 | return new LSL_Vector(); | ||
951 | } | ||
952 | |||
953 | public void llSetStatus(int status, int value) | ||
954 | { | ||
955 | m_host.AddScriptLPS(1); | ||
956 | |||
957 | int statusrotationaxis = 0; | ||
958 | |||
959 | if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS) | ||
960 | { | ||
961 | if (value == 1) | ||
962 | { | ||
963 | SceneObjectGroup group = m_host.ParentGroup; | ||
964 | if (group == null) | ||
965 | return; | ||
966 | bool allow = true; | ||
967 | foreach (SceneObjectPart part in group.Children.Values) | ||
968 | { | ||
969 | if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) | ||
970 | { | ||
971 | allow = false; | ||
972 | break; | ||
973 | } | ||
974 | } | ||
975 | |||
976 | if (!allow) | ||
977 | return; | ||
978 | m_host.ScriptSetPhysicsStatus(true); | ||
979 | } | ||
980 | else | ||
981 | m_host.ScriptSetPhysicsStatus(false); | ||
982 | } | ||
983 | |||
984 | if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM) | ||
985 | { | ||
986 | if (value == 1) | ||
987 | m_host.ScriptSetPhantomStatus(true); | ||
988 | else | ||
989 | m_host.ScriptSetPhantomStatus(false); | ||
990 | } | ||
991 | |||
992 | if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS) | ||
993 | { | ||
994 | m_host.AddFlag(PrimFlags.CastShadows); | ||
995 | } | ||
996 | |||
997 | if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X) | ||
998 | { | ||
999 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X; | ||
1000 | } | ||
1001 | |||
1002 | if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y) | ||
1003 | { | ||
1004 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y; | ||
1005 | } | ||
1006 | |||
1007 | if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z) | ||
1008 | { | ||
1009 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z; | ||
1010 | } | ||
1011 | |||
1012 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) | ||
1013 | { | ||
1014 | NotImplemented("llSetStatus - STATUS_BLOCK_GRAB"); | ||
1015 | } | ||
1016 | |||
1017 | if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) | ||
1018 | { | ||
1019 | if (value == 1) | ||
1020 | m_host.SetDieAtEdge(true); | ||
1021 | else | ||
1022 | m_host.SetDieAtEdge(false); | ||
1023 | } | ||
1024 | |||
1025 | if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE) | ||
1026 | { | ||
1027 | NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE"); | ||
1028 | } | ||
1029 | |||
1030 | if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX) | ||
1031 | { | ||
1032 | NotImplemented("llSetStatus - STATUS_SANDBOX"); | ||
1033 | } | ||
1034 | |||
1035 | if (statusrotationaxis != 0) | ||
1036 | { | ||
1037 | m_host.SetAxisRotation(statusrotationaxis, value); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
1041 | public LSL_Integer llGetStatus(int status) | ||
1042 | { | ||
1043 | m_host.AddScriptLPS(1); | ||
1044 | // Console.WriteLine(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString()); | ||
1045 | switch (status) | ||
1046 | { | ||
1047 | case ScriptBaseClass.STATUS_PHYSICS: | ||
1048 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics) | ||
1049 | { | ||
1050 | return 1; | ||
1051 | } | ||
1052 | return 0; | ||
1053 | |||
1054 | case ScriptBaseClass.STATUS_PHANTOM: | ||
1055 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) | ||
1056 | { | ||
1057 | return 1; | ||
1058 | } | ||
1059 | return 0; | ||
1060 | |||
1061 | case ScriptBaseClass.STATUS_CAST_SHADOWS: | ||
1062 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows) | ||
1063 | { | ||
1064 | return 1; | ||
1065 | } | ||
1066 | return 0; | ||
1067 | |||
1068 | case ScriptBaseClass.STATUS_BLOCK_GRAB: | ||
1069 | NotImplemented("llGetStatus - STATUS_BLOCK_GRAB"); | ||
1070 | return 0; | ||
1071 | |||
1072 | case ScriptBaseClass.STATUS_DIE_AT_EDGE: | ||
1073 | if (m_host.GetDieAtEdge()) | ||
1074 | return 1; | ||
1075 | else | ||
1076 | return 0; | ||
1077 | |||
1078 | case ScriptBaseClass.STATUS_RETURN_AT_EDGE: | ||
1079 | NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE"); | ||
1080 | return 0; | ||
1081 | |||
1082 | case ScriptBaseClass.STATUS_ROTATE_X: | ||
1083 | NotImplemented("llGetStatus - STATUS_ROTATE_X"); | ||
1084 | return 0; | ||
1085 | |||
1086 | case ScriptBaseClass.STATUS_ROTATE_Y: | ||
1087 | NotImplemented("llGetStatus - STATUS_ROTATE_Y"); | ||
1088 | return 0; | ||
1089 | |||
1090 | case ScriptBaseClass.STATUS_ROTATE_Z: | ||
1091 | NotImplemented("llGetStatus - STATUS_ROTATE_Z"); | ||
1092 | return 0; | ||
1093 | |||
1094 | case ScriptBaseClass.STATUS_SANDBOX: | ||
1095 | NotImplemented("llGetStatus - STATUS_SANDBOX"); | ||
1096 | return 0; | ||
1097 | } | ||
1098 | return 0; | ||
1099 | } | ||
1100 | |||
1101 | public void llSetScale(LSL_Vector scale) | ||
1102 | { | ||
1103 | m_host.AddScriptLPS(1); | ||
1104 | SetScale(m_host, scale); | ||
1105 | } | ||
1106 | |||
1107 | private void SetScale(SceneObjectPart part, LSL_Vector scale) | ||
1108 | { | ||
1109 | // TODO: this needs to trigger a persistance save as well | ||
1110 | |||
1111 | if (part == null || part.ParentGroup == null || part.ParentGroup.RootPart == null) | ||
1112 | return; | ||
1113 | |||
1114 | if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical) | ||
1115 | { | ||
1116 | if (scale.x > World.m_maxPhys) | ||
1117 | scale.x = World.m_maxPhys; | ||
1118 | if (scale.y > World.m_maxPhys) | ||
1119 | scale.y = World.m_maxPhys; | ||
1120 | if (scale.z > World.m_maxPhys) | ||
1121 | scale.z = World.m_maxPhys; | ||
1122 | } | ||
1123 | if (scale.x > World.m_maxNonphys) | ||
1124 | scale.x = World.m_maxNonphys; | ||
1125 | if (scale.y > World.m_maxNonphys) | ||
1126 | scale.y = World.m_maxNonphys; | ||
1127 | if (scale.z > World.m_maxNonphys) | ||
1128 | scale.z = World.m_maxNonphys; | ||
1129 | Vector3 tmp = part.Scale; | ||
1130 | tmp.X = (float)scale.x; | ||
1131 | tmp.Y = (float)scale.y; | ||
1132 | tmp.Z = (float)scale.z; | ||
1133 | part.Scale = tmp; | ||
1134 | part.SendFullUpdateToAllClients(); | ||
1135 | } | ||
1136 | |||
1137 | public LSL_Vector llGetScale() | ||
1138 | { | ||
1139 | m_host.AddScriptLPS(1); | ||
1140 | return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); | ||
1141 | } | ||
1142 | |||
1143 | public void llSetClickAction(int action) | ||
1144 | { | ||
1145 | m_host.AddScriptLPS(1); | ||
1146 | NotImplemented("llSetClickAction"); | ||
1147 | return; | ||
1148 | } | ||
1149 | |||
1150 | public void llSetColor(LSL_Vector color, int face) | ||
1151 | { | ||
1152 | m_host.AddScriptLPS(1); | ||
1153 | |||
1154 | SetColor(m_host, color, face); | ||
1155 | } | ||
1156 | |||
1157 | private void SetColor(SceneObjectPart part, LSL_Vector color, int face) | ||
1158 | { | ||
1159 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1160 | Color4 texcolor; | ||
1161 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1162 | { | ||
1163 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
1164 | texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1165 | texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1166 | texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1167 | tex.FaceTextures[face].RGBA = texcolor; | ||
1168 | part.UpdateTexture(tex); | ||
1169 | return; | ||
1170 | } | ||
1171 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1172 | { | ||
1173 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1174 | { | ||
1175 | if (tex.FaceTextures[i] != null) | ||
1176 | { | ||
1177 | texcolor = tex.FaceTextures[i].RGBA; | ||
1178 | texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1179 | texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1180 | texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1181 | tex.FaceTextures[i].RGBA = texcolor; | ||
1182 | } | ||
1183 | texcolor = tex.DefaultTexture.RGBA; | ||
1184 | texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1185 | texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1186 | texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1187 | tex.DefaultTexture.RGBA = texcolor; | ||
1188 | } | ||
1189 | part.UpdateTexture(tex); | ||
1190 | return; | ||
1191 | } | ||
1192 | } | ||
1193 | |||
1194 | public void SetGlow(SceneObjectPart part, int face, float glow) | ||
1195 | { | ||
1196 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1197 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1198 | { | ||
1199 | tex.CreateFace((uint) face); | ||
1200 | tex.FaceTextures[face].Glow = glow; | ||
1201 | part.UpdateTexture(tex); | ||
1202 | return; | ||
1203 | } | ||
1204 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1205 | { | ||
1206 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1207 | { | ||
1208 | if (tex.FaceTextures[i] != null) | ||
1209 | { | ||
1210 | tex.FaceTextures[i].Glow = glow; | ||
1211 | } | ||
1212 | tex.DefaultTexture.Glow = glow; | ||
1213 | } | ||
1214 | part.UpdateTexture(tex); | ||
1215 | return; | ||
1216 | } | ||
1217 | } | ||
1218 | |||
1219 | public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) | ||
1220 | { | ||
1221 | |||
1222 | Shininess sval = new Shininess(); | ||
1223 | |||
1224 | switch (shiny) | ||
1225 | { | ||
1226 | case 0: | ||
1227 | sval = Shininess.None; | ||
1228 | break; | ||
1229 | case 1: | ||
1230 | sval = Shininess.Low; | ||
1231 | break; | ||
1232 | case 2: | ||
1233 | sval = Shininess.Medium; | ||
1234 | break; | ||
1235 | case 3: | ||
1236 | sval = Shininess.High; | ||
1237 | break; | ||
1238 | default: | ||
1239 | sval = Shininess.None; | ||
1240 | break; | ||
1241 | } | ||
1242 | |||
1243 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1244 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1245 | { | ||
1246 | tex.CreateFace((uint) face); | ||
1247 | tex.FaceTextures[face].Shiny = sval; | ||
1248 | tex.FaceTextures[face].Bump = bump; | ||
1249 | part.UpdateTexture(tex); | ||
1250 | return; | ||
1251 | } | ||
1252 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1253 | { | ||
1254 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1255 | { | ||
1256 | if (tex.FaceTextures[i] != null) | ||
1257 | { | ||
1258 | tex.FaceTextures[i].Shiny = sval; | ||
1259 | tex.FaceTextures[i].Bump = bump;; | ||
1260 | } | ||
1261 | tex.DefaultTexture.Shiny = sval; | ||
1262 | tex.DefaultTexture.Bump = bump; | ||
1263 | } | ||
1264 | part.UpdateTexture(tex); | ||
1265 | return; | ||
1266 | } | ||
1267 | } | ||
1268 | |||
1269 | public void SetFullBright(SceneObjectPart part, int face, bool bright) | ||
1270 | { | ||
1271 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1272 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1273 | { | ||
1274 | tex.CreateFace((uint) face); | ||
1275 | tex.FaceTextures[face].Fullbright = bright; | ||
1276 | part.UpdateTexture(tex); | ||
1277 | return; | ||
1278 | } | ||
1279 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1280 | { | ||
1281 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1282 | { | ||
1283 | if (tex.FaceTextures[i] != null) | ||
1284 | { | ||
1285 | tex.FaceTextures[i].Fullbright = bright; | ||
1286 | } | ||
1287 | } | ||
1288 | tex.DefaultTexture.Fullbright = bright; | ||
1289 | part.UpdateTexture(tex); | ||
1290 | return; | ||
1291 | } | ||
1292 | } | ||
1293 | |||
1294 | public LSL_Float llGetAlpha(int face) | ||
1295 | { | ||
1296 | m_host.AddScriptLPS(1); | ||
1297 | |||
1298 | return GetAlpha(m_host, face); | ||
1299 | } | ||
1300 | |||
1301 | private LSL_Float GetAlpha(SceneObjectPart part, int face) | ||
1302 | { | ||
1303 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1304 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1305 | { | ||
1306 | int i; | ||
1307 | double sum = 0.0; | ||
1308 | for (i = 0 ; i < GetNumberOfSides(part) ; i++) | ||
1309 | sum += (double)tex.GetFace((uint)i).RGBA.A; | ||
1310 | return sum; | ||
1311 | } | ||
1312 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1313 | { | ||
1314 | return (double)tex.GetFace((uint)face).RGBA.A; | ||
1315 | } | ||
1316 | return 0.0; | ||
1317 | } | ||
1318 | |||
1319 | public void llSetAlpha(double alpha, int face) | ||
1320 | { | ||
1321 | m_host.AddScriptLPS(1); | ||
1322 | |||
1323 | SetAlpha(m_host, alpha, face); | ||
1324 | } | ||
1325 | |||
1326 | private void SetAlpha(SceneObjectPart part, double alpha, int face) | ||
1327 | { | ||
1328 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1329 | Color4 texcolor; | ||
1330 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1331 | { | ||
1332 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
1333 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
1334 | tex.FaceTextures[face].RGBA = texcolor; | ||
1335 | part.UpdateTexture(tex); | ||
1336 | return; | ||
1337 | } | ||
1338 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1339 | { | ||
1340 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1341 | { | ||
1342 | if (tex.FaceTextures[i] != null) | ||
1343 | { | ||
1344 | texcolor = tex.FaceTextures[i].RGBA; | ||
1345 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
1346 | tex.FaceTextures[i].RGBA = texcolor; | ||
1347 | } | ||
1348 | } | ||
1349 | texcolor = tex.DefaultTexture.RGBA; | ||
1350 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
1351 | tex.DefaultTexture.RGBA = texcolor; | ||
1352 | part.UpdateTexture(tex); | ||
1353 | return; | ||
1354 | } | ||
1355 | } | ||
1356 | |||
1357 | /// <summary> | ||
1358 | /// Set flexi parameters of a part. | ||
1359 | /// | ||
1360 | /// FIXME: Much of this code should probably be within the part itself. | ||
1361 | /// </summary> | ||
1362 | /// <param name="part"></param> | ||
1363 | /// <param name="flexi"></param> | ||
1364 | /// <param name="softness"></param> | ||
1365 | /// <param name="gravity"></param> | ||
1366 | /// <param name="friction"></param> | ||
1367 | /// <param name="wind"></param> | ||
1368 | /// <param name="tension"></param> | ||
1369 | /// <param name="Force"></param> | ||
1370 | private void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, | ||
1371 | float wind, float tension, LSL_Vector Force) | ||
1372 | { | ||
1373 | if (part == null) | ||
1374 | return; | ||
1375 | |||
1376 | bool needs_fakedelete = false; | ||
1377 | if (flexi) | ||
1378 | { | ||
1379 | if (!part.Shape.FlexiEntry) | ||
1380 | { | ||
1381 | needs_fakedelete = true; | ||
1382 | } | ||
1383 | part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do | ||
1384 | // work once the prim is already flexi | ||
1385 | part.Shape.FlexiSoftness = softness; | ||
1386 | part.Shape.FlexiGravity = gravity; | ||
1387 | part.Shape.FlexiDrag = friction; | ||
1388 | part.Shape.FlexiWind = wind; | ||
1389 | part.Shape.FlexiTension = tension; | ||
1390 | part.Shape.FlexiForceX = (float)Force.x; | ||
1391 | part.Shape.FlexiForceY = (float)Force.y; | ||
1392 | part.Shape.FlexiForceZ = (float)Force.z; | ||
1393 | part.Shape.PathCurve = 0x80; | ||
1394 | |||
1395 | } | ||
1396 | else | ||
1397 | { | ||
1398 | if (part.Shape.FlexiEntry) | ||
1399 | { | ||
1400 | needs_fakedelete = true; | ||
1401 | } | ||
1402 | part.Shape.FlexiEntry = false; | ||
1403 | } | ||
1404 | |||
1405 | needs_fakedelete = false; | ||
1406 | if (needs_fakedelete) | ||
1407 | { | ||
1408 | if (part.ParentGroup != null) | ||
1409 | { | ||
1410 | part.ParentGroup.FakeDeleteGroup(); | ||
1411 | } | ||
1412 | } | ||
1413 | |||
1414 | part.ParentGroup.HasGroupChanged = true; | ||
1415 | part.ScheduleFullUpdate(); | ||
1416 | } | ||
1417 | |||
1418 | /// <summary> | ||
1419 | /// Set a light point on a part | ||
1420 | /// | ||
1421 | /// FIXME: Much of this code should probably be in SceneObjectGroup | ||
1422 | /// </summary> | ||
1423 | /// <param name="part"></param> | ||
1424 | /// <param name="light"></param> | ||
1425 | /// <param name="color"></param> | ||
1426 | /// <param name="intensity"></param> | ||
1427 | /// <param name="radius"></param> | ||
1428 | /// <param name="falloff"></param> | ||
1429 | private void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) | ||
1430 | { | ||
1431 | if (part == null) | ||
1432 | return; | ||
1433 | |||
1434 | if (light) | ||
1435 | { | ||
1436 | part.Shape.LightEntry = true; | ||
1437 | part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1438 | part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1439 | part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1440 | part.Shape.LightIntensity = intensity; | ||
1441 | part.Shape.LightRadius = radius; | ||
1442 | part.Shape.LightFalloff = falloff; | ||
1443 | } | ||
1444 | else | ||
1445 | { | ||
1446 | part.Shape.LightEntry = false; | ||
1447 | } | ||
1448 | |||
1449 | part.ParentGroup.HasGroupChanged = true; | ||
1450 | part.ScheduleFullUpdate(); | ||
1451 | } | ||
1452 | |||
1453 | public LSL_Vector llGetColor(int face) | ||
1454 | { | ||
1455 | m_host.AddScriptLPS(1); | ||
1456 | return GetColor(m_host, face); | ||
1457 | } | ||
1458 | |||
1459 | private LSL_Vector GetColor(SceneObjectPart part, int face) | ||
1460 | { | ||
1461 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1462 | Color4 texcolor; | ||
1463 | LSL_Vector rgb = new LSL_Vector(); | ||
1464 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1465 | { | ||
1466 | int i; | ||
1467 | |||
1468 | for (i = 0 ; i < GetNumberOfSides(part) ; i++) | ||
1469 | { | ||
1470 | texcolor = tex.GetFace((uint)i).RGBA; | ||
1471 | rgb.x += texcolor.R; | ||
1472 | rgb.y += texcolor.G; | ||
1473 | rgb.z += texcolor.B; | ||
1474 | } | ||
1475 | |||
1476 | rgb.x /= (float)GetNumberOfSides(part); | ||
1477 | rgb.y /= (float)GetNumberOfSides(part); | ||
1478 | rgb.z /= (float)GetNumberOfSides(part); | ||
1479 | |||
1480 | return rgb; | ||
1481 | } | ||
1482 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1483 | { | ||
1484 | texcolor = tex.GetFace((uint)face).RGBA; | ||
1485 | rgb.x = texcolor.R; | ||
1486 | rgb.y = texcolor.G; | ||
1487 | rgb.z = texcolor.B; | ||
1488 | return rgb; | ||
1489 | } | ||
1490 | else | ||
1491 | { | ||
1492 | return new LSL_Vector(); | ||
1493 | } | ||
1494 | } | ||
1495 | |||
1496 | public void llSetTexture(string texture, int face) | ||
1497 | { | ||
1498 | m_host.AddScriptLPS(1); | ||
1499 | SetTexture(m_host, texture, face); | ||
1500 | // ScriptSleep(200); | ||
1501 | } | ||
1502 | |||
1503 | private void SetTexture(SceneObjectPart part, string texture, int face) | ||
1504 | { | ||
1505 | UUID textureID=new UUID(); | ||
1506 | |||
1507 | if (!UUID.TryParse(texture, out textureID)) | ||
1508 | { | ||
1509 | textureID=InventoryKey(texture, (int)AssetType.Texture); | ||
1510 | } | ||
1511 | |||
1512 | if (textureID == UUID.Zero) | ||
1513 | return; | ||
1514 | |||
1515 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1516 | |||
1517 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1518 | { | ||
1519 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1520 | texface.TextureID = textureID; | ||
1521 | tex.FaceTextures[face] = texface; | ||
1522 | part.UpdateTexture(tex); | ||
1523 | return; | ||
1524 | } | ||
1525 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1526 | { | ||
1527 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1528 | { | ||
1529 | if (tex.FaceTextures[i] != null) | ||
1530 | { | ||
1531 | tex.FaceTextures[i].TextureID = textureID; | ||
1532 | } | ||
1533 | } | ||
1534 | tex.DefaultTexture.TextureID = textureID; | ||
1535 | part.UpdateTexture(tex); | ||
1536 | return; | ||
1537 | } | ||
1538 | } | ||
1539 | |||
1540 | public void llScaleTexture(double u, double v, int face) | ||
1541 | { | ||
1542 | m_host.AddScriptLPS(1); | ||
1543 | |||
1544 | ScaleTexture(m_host, u, v, face); | ||
1545 | // ScriptSleep(200); | ||
1546 | } | ||
1547 | |||
1548 | private void ScaleTexture(SceneObjectPart part, double u, double v, int face) | ||
1549 | { | ||
1550 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1551 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1552 | { | ||
1553 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1554 | texface.RepeatU = (float)u; | ||
1555 | texface.RepeatV = (float)v; | ||
1556 | tex.FaceTextures[face] = texface; | ||
1557 | part.UpdateTexture(tex); | ||
1558 | return; | ||
1559 | } | ||
1560 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1561 | { | ||
1562 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1563 | { | ||
1564 | if (tex.FaceTextures[i] != null) | ||
1565 | { | ||
1566 | tex.FaceTextures[i].RepeatU = (float)u; | ||
1567 | tex.FaceTextures[i].RepeatV = (float)v; | ||
1568 | } | ||
1569 | } | ||
1570 | tex.DefaultTexture.RepeatU = (float)u; | ||
1571 | tex.DefaultTexture.RepeatV = (float)v; | ||
1572 | part.UpdateTexture(tex); | ||
1573 | return; | ||
1574 | } | ||
1575 | } | ||
1576 | |||
1577 | public void llOffsetTexture(double u, double v, int face) | ||
1578 | { | ||
1579 | m_host.AddScriptLPS(1); | ||
1580 | OffsetTexture(m_host, u, v, face); | ||
1581 | // ScriptSleep(200); | ||
1582 | } | ||
1583 | |||
1584 | private void OffsetTexture(SceneObjectPart part, double u, double v, int face) | ||
1585 | { | ||
1586 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1587 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1588 | { | ||
1589 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1590 | texface.OffsetU = (float)u; | ||
1591 | texface.OffsetV = (float)v; | ||
1592 | tex.FaceTextures[face] = texface; | ||
1593 | part.UpdateTexture(tex); | ||
1594 | return; | ||
1595 | } | ||
1596 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1597 | { | ||
1598 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1599 | { | ||
1600 | if (tex.FaceTextures[i] != null) | ||
1601 | { | ||
1602 | tex.FaceTextures[i].OffsetU = (float)u; | ||
1603 | tex.FaceTextures[i].OffsetV = (float)v; | ||
1604 | } | ||
1605 | } | ||
1606 | tex.DefaultTexture.OffsetU = (float)u; | ||
1607 | tex.DefaultTexture.OffsetV = (float)v; | ||
1608 | part.UpdateTexture(tex); | ||
1609 | return; | ||
1610 | } | ||
1611 | } | ||
1612 | |||
1613 | public void llRotateTexture(double rotation, int face) | ||
1614 | { | ||
1615 | m_host.AddScriptLPS(1); | ||
1616 | RotateTexture(m_host, rotation, face); | ||
1617 | // ScriptSleep(200); | ||
1618 | } | ||
1619 | |||
1620 | private void RotateTexture(SceneObjectPart part, double rotation, int face) | ||
1621 | { | ||
1622 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1623 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1624 | { | ||
1625 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1626 | texface.Rotation = (float)rotation; | ||
1627 | tex.FaceTextures[face] = texface; | ||
1628 | part.UpdateTexture(tex); | ||
1629 | return; | ||
1630 | } | ||
1631 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1632 | { | ||
1633 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1634 | { | ||
1635 | if (tex.FaceTextures[i] != null) | ||
1636 | { | ||
1637 | tex.FaceTextures[i].Rotation = (float)rotation; | ||
1638 | } | ||
1639 | } | ||
1640 | tex.DefaultTexture.Rotation = (float)rotation; | ||
1641 | part.UpdateTexture(tex); | ||
1642 | return; | ||
1643 | } | ||
1644 | } | ||
1645 | |||
1646 | public LSL_String llGetTexture(int face) | ||
1647 | { | ||
1648 | m_host.AddScriptLPS(1); | ||
1649 | return GetTexture(m_host, face); | ||
1650 | } | ||
1651 | |||
1652 | private LSL_String GetTexture(SceneObjectPart part, int face) | ||
1653 | { | ||
1654 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1655 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1656 | { | ||
1657 | face = 0; | ||
1658 | } | ||
1659 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1660 | { | ||
1661 | Primitive.TextureEntryFace texface; | ||
1662 | texface = tex.GetFace((uint)face); | ||
1663 | return texface.TextureID.ToString(); | ||
1664 | } | ||
1665 | else | ||
1666 | { | ||
1667 | return String.Empty; | ||
1668 | } | ||
1669 | } | ||
1670 | |||
1671 | public void llSetPos(LSL_Vector pos) | ||
1672 | { | ||
1673 | m_host.AddScriptLPS(1); | ||
1674 | |||
1675 | SetPos(m_host, pos); | ||
1676 | |||
1677 | ScriptSleep(200); | ||
1678 | } | ||
1679 | |||
1680 | private void SetPos(SceneObjectPart part, LSL_Vector targetPos) | ||
1681 | { | ||
1682 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) | ||
1683 | LSL_Vector currentPos = llGetLocalPos(); | ||
1684 | if (llVecDist(currentPos, targetPos) > 10.0f * m_ScriptDistanceFactor) | ||
1685 | { | ||
1686 | targetPos = currentPos + m_ScriptDistanceFactor * 10.0f * llVecNorm(targetPos - currentPos); | ||
1687 | } | ||
1688 | |||
1689 | if (part.ParentID != 0) | ||
1690 | { | ||
1691 | part.UpdateOffSet(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z)); | ||
1692 | } | ||
1693 | else | ||
1694 | { | ||
1695 | part.UpdateGroupPosition(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z)); | ||
1696 | } | ||
1697 | } | ||
1698 | |||
1699 | public LSL_Vector llGetPos() | ||
1700 | { | ||
1701 | m_host.AddScriptLPS(1); | ||
1702 | return new LSL_Vector(m_host.AbsolutePosition.X, | ||
1703 | m_host.AbsolutePosition.Y, | ||
1704 | m_host.AbsolutePosition.Z); | ||
1705 | } | ||
1706 | |||
1707 | public LSL_Vector llGetLocalPos() | ||
1708 | { | ||
1709 | m_host.AddScriptLPS(1); | ||
1710 | if (m_host.ParentID != 0) | ||
1711 | { | ||
1712 | return new LSL_Vector(m_host.OffsetPosition.X, | ||
1713 | m_host.OffsetPosition.Y, | ||
1714 | m_host.OffsetPosition.Z); | ||
1715 | } | ||
1716 | else | ||
1717 | { | ||
1718 | return new LSL_Vector(m_host.AbsolutePosition.X, | ||
1719 | m_host.AbsolutePosition.Y, | ||
1720 | m_host.AbsolutePosition.Z); | ||
1721 | } | ||
1722 | } | ||
1723 | |||
1724 | public void llSetRot(LSL_Rotation rot) | ||
1725 | { | ||
1726 | m_host.AddScriptLPS(1); | ||
1727 | |||
1728 | SetRot(m_host, rot); | ||
1729 | |||
1730 | ScriptSleep(200); | ||
1731 | } | ||
1732 | |||
1733 | private void SetRot(SceneObjectPart part, LSL_Rotation rot) | ||
1734 | { | ||
1735 | part.UpdateRotation(new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s)); | ||
1736 | // Update rotation does not move the object in the physics scene if it's a linkset. | ||
1737 | part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; | ||
1738 | } | ||
1739 | |||
1740 | public LSL_Rotation llGetRot() | ||
1741 | { | ||
1742 | m_host.AddScriptLPS(1); | ||
1743 | Quaternion q = m_host.RotationOffset; | ||
1744 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | ||
1745 | } | ||
1746 | |||
1747 | public LSL_Rotation llGetLocalRot() | ||
1748 | { | ||
1749 | m_host.AddScriptLPS(1); | ||
1750 | return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); | ||
1751 | } | ||
1752 | |||
1753 | public void llSetForce(LSL_Vector force, int local) | ||
1754 | { | ||
1755 | m_host.AddScriptLPS(1); | ||
1756 | |||
1757 | if (m_host.ParentGroup != null) | ||
1758 | { | ||
1759 | if (m_host.ParentGroup.RootPart != null) | ||
1760 | { | ||
1761 | if (local != 0) | ||
1762 | force *= llGetRot(); | ||
1763 | |||
1764 | m_host.ParentGroup.RootPart.SetForce(new PhysicsVector((float)force.x, (float)force.y, (float)force.z)); | ||
1765 | } | ||
1766 | } | ||
1767 | } | ||
1768 | |||
1769 | public LSL_Vector llGetForce() | ||
1770 | { | ||
1771 | LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0); | ||
1772 | |||
1773 | m_host.AddScriptLPS(1); | ||
1774 | |||
1775 | if (m_host.ParentGroup != null) | ||
1776 | { | ||
1777 | if (m_host.ParentGroup.RootPart != null) | ||
1778 | { | ||
1779 | PhysicsVector tmpForce = m_host.ParentGroup.RootPart.GetForce(); | ||
1780 | force.x = tmpForce.X; | ||
1781 | force.y = tmpForce.Y; | ||
1782 | force.z = tmpForce.Z; | ||
1783 | } | ||
1784 | } | ||
1785 | |||
1786 | return force; | ||
1787 | } | ||
1788 | |||
1789 | public LSL_Integer llTarget(LSL_Vector position, double range) | ||
1790 | { | ||
1791 | m_host.AddScriptLPS(1); | ||
1792 | return m_host.registerTargetWaypoint(new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); | ||
1793 | } | ||
1794 | |||
1795 | public void llTargetRemove(int number) | ||
1796 | { | ||
1797 | m_host.AddScriptLPS(1); | ||
1798 | m_host.unregisterTargetWaypoint(number); | ||
1799 | } | ||
1800 | |||
1801 | public LSL_Integer llRotTarget(LSL_Rotation rot, double error) | ||
1802 | { | ||
1803 | m_host.AddScriptLPS(1); | ||
1804 | NotImplemented("llRotTarget"); | ||
1805 | return 0; | ||
1806 | } | ||
1807 | |||
1808 | public void llRotTargetRemove(int number) | ||
1809 | { | ||
1810 | m_host.AddScriptLPS(1); | ||
1811 | NotImplemented("llRotTargetRemove"); | ||
1812 | } | ||
1813 | |||
1814 | public void llMoveToTarget(LSL_Vector target, double tau) | ||
1815 | { | ||
1816 | m_host.AddScriptLPS(1); | ||
1817 | m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); | ||
1818 | } | ||
1819 | |||
1820 | public void llStopMoveToTarget() | ||
1821 | { | ||
1822 | m_host.AddScriptLPS(1); | ||
1823 | m_host.StopMoveToTarget(); | ||
1824 | } | ||
1825 | |||
1826 | public void llApplyImpulse(LSL_Vector force, int local) | ||
1827 | { | ||
1828 | m_host.AddScriptLPS(1); | ||
1829 | //No energy force yet | ||
1830 | |||
1831 | if (force.x > 20000) | ||
1832 | force.x = 20000; | ||
1833 | if (force.y > 20000) | ||
1834 | force.y = 20000; | ||
1835 | if (force.z > 20000) | ||
1836 | force.z = 20000; | ||
1837 | |||
1838 | m_host.ApplyImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); | ||
1839 | } | ||
1840 | |||
1841 | public void llApplyRotationalImpulse(LSL_Vector force, int local) | ||
1842 | { | ||
1843 | m_host.AddScriptLPS(1); | ||
1844 | NotImplemented("llApplyRotationalImpulse"); | ||
1845 | } | ||
1846 | |||
1847 | public void llSetTorque(LSL_Vector torque, int local) | ||
1848 | { | ||
1849 | m_host.AddScriptLPS(1); | ||
1850 | NotImplemented("llSetTorque"); | ||
1851 | } | ||
1852 | |||
1853 | public LSL_Vector llGetTorque() | ||
1854 | { | ||
1855 | m_host.AddScriptLPS(1); | ||
1856 | NotImplemented("llGetTorque"); | ||
1857 | return new LSL_Vector(); | ||
1858 | } | ||
1859 | |||
1860 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) | ||
1861 | { | ||
1862 | m_host.AddScriptLPS(1); | ||
1863 | NotImplemented("llSetForceAndTorque"); | ||
1864 | } | ||
1865 | |||
1866 | public LSL_Vector llGetVel() | ||
1867 | { | ||
1868 | m_host.AddScriptLPS(1); | ||
1869 | return new LSL_Vector(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z); | ||
1870 | } | ||
1871 | |||
1872 | public LSL_Vector llGetAccel() | ||
1873 | { | ||
1874 | m_host.AddScriptLPS(1); | ||
1875 | return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); | ||
1876 | } | ||
1877 | |||
1878 | public LSL_Vector llGetOmega() | ||
1879 | { | ||
1880 | m_host.AddScriptLPS(1); | ||
1881 | return new LSL_Vector(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z); | ||
1882 | } | ||
1883 | |||
1884 | public LSL_Float llGetTimeOfDay() | ||
1885 | { | ||
1886 | m_host.AddScriptLPS(1); | ||
1887 | return (double)(((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)) * World.TimeDilation); | ||
1888 | } | ||
1889 | |||
1890 | public LSL_Float llGetWallclock() | ||
1891 | { | ||
1892 | m_host.AddScriptLPS(1); | ||
1893 | return DateTime.Now.TimeOfDay.TotalSeconds; | ||
1894 | } | ||
1895 | |||
1896 | public LSL_Float llGetTime() | ||
1897 | { | ||
1898 | m_host.AddScriptLPS(1); | ||
1899 | TimeSpan ScriptTime = DateTime.Now - m_timer; | ||
1900 | return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation); | ||
1901 | } | ||
1902 | |||
1903 | public void llResetTime() | ||
1904 | { | ||
1905 | m_host.AddScriptLPS(1); | ||
1906 | m_timer = DateTime.Now; | ||
1907 | } | ||
1908 | |||
1909 | public LSL_Float llGetAndResetTime() | ||
1910 | { | ||
1911 | m_host.AddScriptLPS(1); | ||
1912 | TimeSpan ScriptTime = DateTime.Now - m_timer; | ||
1913 | m_timer = DateTime.Now; | ||
1914 | return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation); | ||
1915 | } | ||
1916 | |||
1917 | public void llSound() | ||
1918 | { | ||
1919 | m_host.AddScriptLPS(1); | ||
1920 | // This function has been deprecated | ||
1921 | // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound | ||
1922 | Deprecated("llSound"); | ||
1923 | } | ||
1924 | |||
1925 | // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound | ||
1926 | // 20080530 Updated to remove code duplication | ||
1927 | public void llPlaySound(string sound, double volume) | ||
1928 | { | ||
1929 | m_host.AddScriptLPS(1); | ||
1930 | |||
1931 | // send the sound, once, to all clients in range | ||
1932 | m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0); | ||
1933 | } | ||
1934 | |||
1935 | // Xantor 20080528 we should do this differently. | ||
1936 | // 1) apply the sound to the object | ||
1937 | // 2) schedule full update | ||
1938 | // just sending the sound out once doesn't work so well when other avatars come in view later on | ||
1939 | // or when the prim gets moved, changed, sat on, whatever | ||
1940 | // see large number of mantises (mantes?) | ||
1941 | // 20080530 Updated to remove code duplication | ||
1942 | // 20080530 Stop sound if there is one, otherwise volume only changes don't work | ||
1943 | public void llLoopSound(string sound, double volume) | ||
1944 | { | ||
1945 | m_host.AddScriptLPS(1); | ||
1946 | |||
1947 | if (m_host.Sound != UUID.Zero) | ||
1948 | llStopSound(); | ||
1949 | |||
1950 | m_host.Sound = KeyOrName(sound); | ||
1951 | m_host.SoundGain = volume; | ||
1952 | m_host.SoundFlags = 1; // looping | ||
1953 | m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? | ||
1954 | |||
1955 | m_host.ScheduleFullUpdate(); | ||
1956 | m_host.SendFullUpdateToAllClients(); | ||
1957 | } | ||
1958 | |||
1959 | public void llLoopSoundMaster(string sound, double volume) | ||
1960 | { | ||
1961 | m_host.AddScriptLPS(1); | ||
1962 | NotImplemented("llLoopSoundMaster"); | ||
1963 | } | ||
1964 | |||
1965 | public void llLoopSoundSlave(string sound, double volume) | ||
1966 | { | ||
1967 | m_host.AddScriptLPS(1); | ||
1968 | NotImplemented("llLoopSoundSlave"); | ||
1969 | } | ||
1970 | |||
1971 | public void llPlaySoundSlave(string sound, double volume) | ||
1972 | { | ||
1973 | m_host.AddScriptLPS(1); | ||
1974 | NotImplemented("llPlaySoundSlave"); | ||
1975 | } | ||
1976 | |||
1977 | public void llTriggerSound(string sound, double volume) | ||
1978 | { | ||
1979 | m_host.AddScriptLPS(1); | ||
1980 | // send the sound, once, to all clients in range | ||
1981 | m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0); | ||
1982 | } | ||
1983 | |||
1984 | // Xantor 20080528: Clear prim data of sound instead | ||
1985 | public void llStopSound() | ||
1986 | { | ||
1987 | m_host.AddScriptLPS(1); | ||
1988 | |||
1989 | m_host.Sound = UUID.Zero; | ||
1990 | m_host.SoundGain = 0; | ||
1991 | m_host.SoundFlags = 0; | ||
1992 | m_host.SoundRadius = 0; | ||
1993 | |||
1994 | m_host.ScheduleFullUpdate(); | ||
1995 | m_host.SendFullUpdateToAllClients(); | ||
1996 | |||
1997 | // m_host.SendSound(UUID.Zero.ToString(), 1.0, false, 2); | ||
1998 | } | ||
1999 | |||
2000 | public void llPreloadSound(string sound) | ||
2001 | { | ||
2002 | m_host.AddScriptLPS(1); | ||
2003 | m_host.PreloadSound(sound); | ||
2004 | // ScriptSleep(1000); | ||
2005 | } | ||
2006 | |||
2007 | /// <summary> | ||
2008 | /// Return a portion of the designated string bounded by | ||
2009 | /// inclusive indices (start and end). As usual, the negative | ||
2010 | /// indices, and the tolerance for out-of-bound values, makes | ||
2011 | /// this more complicated than it might otherwise seem. | ||
2012 | /// </summary> | ||
2013 | |||
2014 | public LSL_String llGetSubString(string src, int start, int end) | ||
2015 | { | ||
2016 | |||
2017 | m_host.AddScriptLPS(1); | ||
2018 | |||
2019 | // Normalize indices (if negative). | ||
2020 | // After normlaization they may still be | ||
2021 | // negative, but that is now relative to | ||
2022 | // the start, rather than the end, of the | ||
2023 | // sequence. | ||
2024 | |||
2025 | if (start < 0) | ||
2026 | { | ||
2027 | start = src.Length+start; | ||
2028 | } | ||
2029 | if (end < 0) | ||
2030 | { | ||
2031 | end = src.Length+end; | ||
2032 | } | ||
2033 | |||
2034 | // Conventional substring | ||
2035 | if (start <= end) | ||
2036 | { | ||
2037 | // Implies both bounds are out-of-range. | ||
2038 | if (end < 0 || start >= src.Length) | ||
2039 | { | ||
2040 | return String.Empty; | ||
2041 | } | ||
2042 | // If end is positive, then it directly | ||
2043 | // corresponds to the lengt of the substring | ||
2044 | // needed (plus one of course). BUT, it | ||
2045 | // must be within bounds. | ||
2046 | if (end >= src.Length) | ||
2047 | { | ||
2048 | end = src.Length-1; | ||
2049 | } | ||
2050 | |||
2051 | if (start < 0) | ||
2052 | { | ||
2053 | return src.Substring(0,end+1); | ||
2054 | } | ||
2055 | // Both indices are positive | ||
2056 | return src.Substring(start, (end+1) - start); | ||
2057 | } | ||
2058 | |||
2059 | // Inverted substring (end < start) | ||
2060 | else | ||
2061 | { | ||
2062 | // Implies both indices are below the | ||
2063 | // lower bound. In the inverted case, that | ||
2064 | // means the entire string will be returned | ||
2065 | // unchanged. | ||
2066 | if (start < 0) | ||
2067 | { | ||
2068 | return src; | ||
2069 | } | ||
2070 | // If both indices are greater than the upper | ||
2071 | // bound the result may seem initially counter | ||
2072 | // intuitive. | ||
2073 | if (end >= src.Length) | ||
2074 | { | ||
2075 | return src; | ||
2076 | } | ||
2077 | |||
2078 | if (end < 0) | ||
2079 | { | ||
2080 | if (start < src.Length) | ||
2081 | { | ||
2082 | return src.Substring(start); | ||
2083 | } | ||
2084 | else | ||
2085 | { | ||
2086 | return String.Empty; | ||
2087 | } | ||
2088 | } | ||
2089 | else | ||
2090 | { | ||
2091 | if (start < src.Length) | ||
2092 | { | ||
2093 | return src.Substring(0,end+1) + src.Substring(start); | ||
2094 | } | ||
2095 | else | ||
2096 | { | ||
2097 | return src.Substring(0,end+1); | ||
2098 | } | ||
2099 | } | ||
2100 | } | ||
2101 | } | ||
2102 | |||
2103 | /// <summary> | ||
2104 | /// Delete substring removes the specified substring bounded | ||
2105 | /// by the inclusive indices start and end. Indices may be | ||
2106 | /// negative (indicating end-relative) and may be inverted, | ||
2107 | /// i.e. end < start. | ||
2108 | /// </summary> | ||
2109 | |||
2110 | public LSL_String llDeleteSubString(string src, int start, int end) | ||
2111 | { | ||
2112 | |||
2113 | m_host.AddScriptLPS(1); | ||
2114 | |||
2115 | // Normalize indices (if negative). | ||
2116 | // After normlaization they may still be | ||
2117 | // negative, but that is now relative to | ||
2118 | // the start, rather than the end, of the | ||
2119 | // sequence. | ||
2120 | if (start < 0) | ||
2121 | { | ||
2122 | start = src.Length+start; | ||
2123 | } | ||
2124 | if (end < 0) | ||
2125 | { | ||
2126 | end = src.Length+end; | ||
2127 | } | ||
2128 | // Conventionally delimited substring | ||
2129 | if (start <= end) | ||
2130 | { | ||
2131 | // If both bounds are outside of the existing | ||
2132 | // string, then return unchanges. | ||
2133 | if (end < 0 || start >= src.Length) | ||
2134 | { | ||
2135 | return src; | ||
2136 | } | ||
2137 | // At least one bound is in-range, so we | ||
2138 | // need to clip the out-of-bound argument. | ||
2139 | if (start < 0) | ||
2140 | { | ||
2141 | start = 0; | ||
2142 | } | ||
2143 | |||
2144 | if (end >= src.Length) | ||
2145 | { | ||
2146 | end = src.Length-1; | ||
2147 | } | ||
2148 | |||
2149 | return src.Remove(start,end-start+1); | ||
2150 | } | ||
2151 | // Inverted substring | ||
2152 | else | ||
2153 | { | ||
2154 | // In this case, out of bounds means that | ||
2155 | // the existing string is part of the cut. | ||
2156 | if (start < 0 || end >= src.Length) | ||
2157 | { | ||
2158 | return String.Empty; | ||
2159 | } | ||
2160 | |||
2161 | if (end > 0) | ||
2162 | { | ||
2163 | if (start < src.Length) | ||
2164 | { | ||
2165 | return src.Remove(start).Remove(0,end+1); | ||
2166 | } | ||
2167 | else | ||
2168 | { | ||
2169 | return src.Remove(0,end+1); | ||
2170 | } | ||
2171 | } | ||
2172 | else | ||
2173 | { | ||
2174 | if (start < src.Length) | ||
2175 | { | ||
2176 | return src.Remove(start); | ||
2177 | } | ||
2178 | else | ||
2179 | { | ||
2180 | return src; | ||
2181 | } | ||
2182 | } | ||
2183 | } | ||
2184 | } | ||
2185 | |||
2186 | /// <summary> | ||
2187 | /// Insert string inserts the specified string identified by src | ||
2188 | /// at the index indicated by index. Index may be negative, in | ||
2189 | /// which case it is end-relative. The index may exceed either | ||
2190 | /// string bound, with the result being a concatenation. | ||
2191 | /// </summary> | ||
2192 | |||
2193 | public LSL_String llInsertString(string dest, int index, string src) | ||
2194 | { | ||
2195 | |||
2196 | m_host.AddScriptLPS(1); | ||
2197 | |||
2198 | // Normalize indices (if negative). | ||
2199 | // After normlaization they may still be | ||
2200 | // negative, but that is now relative to | ||
2201 | // the start, rather than the end, of the | ||
2202 | // sequence. | ||
2203 | if (index < 0) | ||
2204 | { | ||
2205 | index = dest.Length+index; | ||
2206 | |||
2207 | // Negative now means it is less than the lower | ||
2208 | // bound of the string. | ||
2209 | |||
2210 | if (index < 0) | ||
2211 | { | ||
2212 | return src+dest; | ||
2213 | } | ||
2214 | |||
2215 | } | ||
2216 | |||
2217 | if (index >= dest.Length) | ||
2218 | { | ||
2219 | return dest+src; | ||
2220 | } | ||
2221 | |||
2222 | // The index is in bounds. | ||
2223 | // In this case the index refers to the index that will | ||
2224 | // be assigned to the first character of the inserted string. | ||
2225 | // So unlike the other string operations, we do not add one | ||
2226 | // to get the correct string length. | ||
2227 | return dest.Substring(0,index)+src+dest.Substring(index); | ||
2228 | |||
2229 | } | ||
2230 | |||
2231 | public LSL_String llToUpper(string src) | ||
2232 | { | ||
2233 | m_host.AddScriptLPS(1); | ||
2234 | return src.ToUpper(); | ||
2235 | } | ||
2236 | |||
2237 | public LSL_String llToLower(string src) | ||
2238 | { | ||
2239 | m_host.AddScriptLPS(1); | ||
2240 | return src.ToLower(); | ||
2241 | } | ||
2242 | |||
2243 | public LSL_Integer llGiveMoney(string destination, int amount) | ||
2244 | { | ||
2245 | UUID invItemID=InventorySelf(); | ||
2246 | if (invItemID == UUID.Zero) | ||
2247 | return 0; | ||
2248 | |||
2249 | m_host.AddScriptLPS(1); | ||
2250 | |||
2251 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
2252 | return 0; | ||
2253 | |||
2254 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) | ||
2255 | { | ||
2256 | LSLError("No permissions to give money"); | ||
2257 | return 0; | ||
2258 | } | ||
2259 | |||
2260 | UUID toID=new UUID(); | ||
2261 | |||
2262 | if (!UUID.TryParse(destination, out toID)) | ||
2263 | { | ||
2264 | LSLError("Bad key in llGiveMoney"); | ||
2265 | return 0; | ||
2266 | } | ||
2267 | |||
2268 | IMoneyModule money=World.RequestModuleInterface<IMoneyModule>(); | ||
2269 | |||
2270 | if (money == null) | ||
2271 | { | ||
2272 | NotImplemented("llGiveMoney"); | ||
2273 | return 0; | ||
2274 | } | ||
2275 | |||
2276 | bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); | ||
2277 | |||
2278 | if (result) | ||
2279 | return 1; | ||
2280 | |||
2281 | return 0; | ||
2282 | } | ||
2283 | |||
2284 | public void llMakeExplosion() | ||
2285 | { | ||
2286 | m_host.AddScriptLPS(1); | ||
2287 | Deprecated("llMakeExplosion"); | ||
2288 | // ScriptSleep(100); | ||
2289 | } | ||
2290 | |||
2291 | public void llMakeFountain() | ||
2292 | { | ||
2293 | m_host.AddScriptLPS(1); | ||
2294 | Deprecated("llMakeFountain"); | ||
2295 | // ScriptSleep(100); | ||
2296 | } | ||
2297 | |||
2298 | public void llMakeSmoke() | ||
2299 | { | ||
2300 | m_host.AddScriptLPS(1); | ||
2301 | Deprecated("llMakeSmoke"); | ||
2302 | // ScriptSleep(100); | ||
2303 | } | ||
2304 | |||
2305 | public void llMakeFire() | ||
2306 | { | ||
2307 | m_host.AddScriptLPS(1); | ||
2308 | Deprecated("llMakeFire"); | ||
2309 | // ScriptSleep(100); | ||
2310 | } | ||
2311 | |||
2312 | public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | ||
2313 | { | ||
2314 | m_host.AddScriptLPS(1); | ||
2315 | |||
2316 | if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) | ||
2317 | return; | ||
2318 | float dist = (float)llVecDist(llGetPos(), pos); | ||
2319 | |||
2320 | if (dist > m_ScriptDistanceFactor * 10.0f) | ||
2321 | return; | ||
2322 | |||
2323 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
2324 | { | ||
2325 | if (inv.Value.Name == inventory) | ||
2326 | { | ||
2327 | // make sure we're an object. | ||
2328 | if (inv.Value.InvType != (int)InventoryType.Object) | ||
2329 | { | ||
2330 | llSay(0, "Unable to create requested object. Object is missing from database."); | ||
2331 | return; | ||
2332 | } | ||
2333 | |||
2334 | Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); | ||
2335 | |||
2336 | // test if we're further away then 10m | ||
2337 | if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10) | ||
2338 | return; // wiki says, if it's further away then 10m, silently fail. | ||
2339 | |||
2340 | Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); | ||
2341 | |||
2342 | // need the magnitude later | ||
2343 | float velmag = (float)Util.GetMagnitude(llvel); | ||
2344 | |||
2345 | SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param); | ||
2346 | |||
2347 | // If either of these are null, then there was an unknown error. | ||
2348 | if (new_group == null) | ||
2349 | continue; | ||
2350 | if (new_group.RootPart == null) | ||
2351 | continue; | ||
2352 | |||
2353 | // objects rezzed with this method are die_at_edge by default. | ||
2354 | new_group.RootPart.SetDieAtEdge(true); | ||
2355 | |||
2356 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2357 | "object_rez", new Object[] { | ||
2358 | new LSL_String( | ||
2359 | new_group.RootPart.UUID.ToString()) }, | ||
2360 | new DetectParams[0])); | ||
2361 | |||
2362 | float groupmass = new_group.GetMass(); | ||
2363 | |||
2364 | //Recoil. | ||
2365 | llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); | ||
2366 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) | ||
2367 | ScriptSleep((int)((groupmass * velmag) / 10)); | ||
2368 | // ScriptSleep(100); | ||
2369 | return; | ||
2370 | } | ||
2371 | } | ||
2372 | llSay(0, "Could not find object " + inventory); | ||
2373 | } | ||
2374 | |||
2375 | public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | ||
2376 | { | ||
2377 | llRezAtRoot(inventory, pos, vel, rot, param); | ||
2378 | } | ||
2379 | |||
2380 | public void llLookAt(LSL_Vector target, double strength, double damping) | ||
2381 | { | ||
2382 | m_host.AddScriptLPS(1); | ||
2383 | NotImplemented("llLookAt"); | ||
2384 | } | ||
2385 | |||
2386 | public void llStopLookAt() | ||
2387 | { | ||
2388 | m_host.AddScriptLPS(1); | ||
2389 | NotImplemented("llStopLookAt"); | ||
2390 | } | ||
2391 | |||
2392 | public void llSetTimerEvent(double sec) | ||
2393 | { | ||
2394 | m_host.AddScriptLPS(1); | ||
2395 | // Setting timer repeat | ||
2396 | AsyncCommands.TimerPlugin.SetTimerEvent(m_localID, m_itemID, sec); | ||
2397 | } | ||
2398 | |||
2399 | public void llSleep(double sec) | ||
2400 | { | ||
2401 | m_host.AddScriptLPS(1); | ||
2402 | Thread.Sleep((int)(sec * 1000)); | ||
2403 | } | ||
2404 | |||
2405 | public LSL_Float llGetMass() | ||
2406 | { | ||
2407 | m_host.AddScriptLPS(1); | ||
2408 | return m_host.GetMass(); | ||
2409 | } | ||
2410 | |||
2411 | public void llCollisionFilter(string name, string id, int accept) | ||
2412 | { | ||
2413 | m_host.AddScriptLPS(1); | ||
2414 | NotImplemented("llCollisionFilter"); | ||
2415 | } | ||
2416 | |||
2417 | public void llTakeControls(int controls, int accept, int pass_on) | ||
2418 | { | ||
2419 | if (!m_host.TaskInventory.ContainsKey(InventorySelf())) | ||
2420 | { | ||
2421 | return; | ||
2422 | } | ||
2423 | |||
2424 | if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero) | ||
2425 | { | ||
2426 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); | ||
2427 | |||
2428 | if (presence != null) | ||
2429 | { | ||
2430 | if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) | ||
2431 | { | ||
2432 | presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID); | ||
2433 | |||
2434 | } | ||
2435 | } | ||
2436 | } | ||
2437 | |||
2438 | m_host.AddScriptLPS(1); | ||
2439 | } | ||
2440 | |||
2441 | public void llReleaseControls() | ||
2442 | { | ||
2443 | m_host.AddScriptLPS(1); | ||
2444 | |||
2445 | if (!m_host.TaskInventory.ContainsKey(InventorySelf())) | ||
2446 | { | ||
2447 | return; | ||
2448 | } | ||
2449 | |||
2450 | if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero) | ||
2451 | { | ||
2452 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); | ||
2453 | |||
2454 | if (presence != null) | ||
2455 | { | ||
2456 | if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) | ||
2457 | { | ||
2458 | // Unregister controls from Presence | ||
2459 | presence.UnRegisterControlEventsToScript(m_localID, m_itemID); | ||
2460 | // Remove Take Control permission. | ||
2461 | m_host.TaskInventory[InventorySelf()].PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; | ||
2462 | } | ||
2463 | } | ||
2464 | } | ||
2465 | } | ||
2466 | |||
2467 | public void llAttachToAvatar(int attachment) | ||
2468 | { | ||
2469 | m_host.AddScriptLPS(1); | ||
2470 | NotImplemented("llAttachToAvatar"); | ||
2471 | } | ||
2472 | |||
2473 | public void llDetachFromAvatar() | ||
2474 | { | ||
2475 | m_host.AddScriptLPS(1); | ||
2476 | NotImplemented("llDetachFromAvatar"); | ||
2477 | } | ||
2478 | |||
2479 | public void llTakeCamera(string avatar) | ||
2480 | { | ||
2481 | m_host.AddScriptLPS(1); | ||
2482 | Deprecated("llTakeCamera"); | ||
2483 | } | ||
2484 | |||
2485 | public void llReleaseCamera(string avatar) | ||
2486 | { | ||
2487 | m_host.AddScriptLPS(1); | ||
2488 | Deprecated("llReleaseCamera"); | ||
2489 | } | ||
2490 | |||
2491 | public LSL_String llGetOwner() | ||
2492 | { | ||
2493 | m_host.AddScriptLPS(1); | ||
2494 | |||
2495 | return m_host.ObjectOwner.ToString(); | ||
2496 | } | ||
2497 | |||
2498 | public void llInstantMessage(string user, string message) | ||
2499 | { | ||
2500 | m_host.AddScriptLPS(1); | ||
2501 | |||
2502 | // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. | ||
2503 | // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, | ||
2504 | // but I don't think we have a list of scenes available from here. | ||
2505 | // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.) | ||
2506 | |||
2507 | // user is a UUID | ||
2508 | |||
2509 | // TODO: figure out values for client, fromSession, and imSessionID | ||
2510 | // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); | ||
2511 | UUID friendTransactionID = UUID.Random(); | ||
2512 | |||
2513 | //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); | ||
2514 | |||
2515 | GridInstantMessage msg = new GridInstantMessage(); | ||
2516 | msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; | ||
2517 | msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID; | ||
2518 | msg.toAgentID = new Guid(user); // toAgentID.Guid; | ||
2519 | msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here | ||
2520 | // Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); | ||
2521 | // Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); | ||
2522 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; | ||
2523 | //if (client != null) | ||
2524 | //{ | ||
2525 | msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; | ||
2526 | //} | ||
2527 | //else | ||
2528 | //{ | ||
2529 | // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it | ||
2530 | //} | ||
2531 | msg.message = message; | ||
2532 | msg.dialog = (byte)19; // messgage from script ??? // dialog; | ||
2533 | msg.fromGroup = false;// fromGroup; | ||
2534 | msg.offline = (byte)0; //offline; | ||
2535 | msg.ParentEstateID = 0; //ParentEstateID; | ||
2536 | msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition); | ||
2537 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; | ||
2538 | msg.binaryBucket = new byte[0];// binaryBucket; | ||
2539 | World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); | ||
2540 | // ScriptSleep(2000); | ||
2541 | } | ||
2542 | |||
2543 | public void llEmail(string address, string subject, string message) | ||
2544 | { | ||
2545 | m_host.AddScriptLPS(1); | ||
2546 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | ||
2547 | if (emailModule == null) | ||
2548 | return; | ||
2549 | |||
2550 | emailModule.SendEmail(m_host.UUID, address, subject, message); | ||
2551 | // ScriptSleep(20000); | ||
2552 | } | ||
2553 | |||
2554 | public void llGetNextEmail(string address, string subject) | ||
2555 | { | ||
2556 | m_host.AddScriptLPS(1); | ||
2557 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | ||
2558 | if (emailModule == null) | ||
2559 | return; | ||
2560 | Email email; | ||
2561 | |||
2562 | email = emailModule.GetNextEmail(m_host.UUID, address, subject); | ||
2563 | |||
2564 | if (email == null) | ||
2565 | return; | ||
2566 | |||
2567 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, | ||
2568 | new EventParams("email", | ||
2569 | new Object[] { | ||
2570 | new LSL_String(email.time), | ||
2571 | new LSL_String(email.sender), | ||
2572 | new LSL_String(email.subject), | ||
2573 | new LSL_String(email.message), | ||
2574 | new LSL_Integer(email.numLeft)}, | ||
2575 | new DetectParams[0])); | ||
2576 | |||
2577 | } | ||
2578 | |||
2579 | public LSL_String llGetKey() | ||
2580 | { | ||
2581 | m_host.AddScriptLPS(1); | ||
2582 | return m_host.UUID.ToString(); | ||
2583 | } | ||
2584 | |||
2585 | public void llSetBuoyancy(double buoyancy) | ||
2586 | { | ||
2587 | m_host.AddScriptLPS(1); | ||
2588 | if (m_host.ParentGroup != null) | ||
2589 | { | ||
2590 | if (m_host.ParentGroup.RootPart != null) | ||
2591 | { | ||
2592 | m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy); | ||
2593 | } | ||
2594 | } | ||
2595 | } | ||
2596 | |||
2597 | |||
2598 | |||
2599 | public void llSetHoverHeight(double height, int water, double tau) | ||
2600 | { | ||
2601 | m_host.AddScriptLPS(1); | ||
2602 | NotImplemented("llSetHoverHeight"); | ||
2603 | } | ||
2604 | |||
2605 | public void llStopHover() | ||
2606 | { | ||
2607 | m_host.AddScriptLPS(1); | ||
2608 | NotImplemented("llStopHover"); | ||
2609 | } | ||
2610 | |||
2611 | public void llMinEventDelay(double delay) | ||
2612 | { | ||
2613 | m_host.AddScriptLPS(1); | ||
2614 | NotImplemented("llMinEventDelay"); | ||
2615 | } | ||
2616 | |||
2617 | public void llSoundPreload() | ||
2618 | { | ||
2619 | m_host.AddScriptLPS(1); | ||
2620 | Deprecated("llSoundPreload"); | ||
2621 | } | ||
2622 | |||
2623 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) | ||
2624 | { | ||
2625 | m_host.AddScriptLPS(1); | ||
2626 | NotImplemented("llRotLookAt"); | ||
2627 | } | ||
2628 | |||
2629 | public LSL_Integer llStringLength(string str) | ||
2630 | { | ||
2631 | m_host.AddScriptLPS(1); | ||
2632 | if (str.Length > 0) | ||
2633 | { | ||
2634 | return str.Length; | ||
2635 | } | ||
2636 | else | ||
2637 | { | ||
2638 | return 0; | ||
2639 | } | ||
2640 | } | ||
2641 | |||
2642 | public void llStartAnimation(string anim) | ||
2643 | { | ||
2644 | m_host.AddScriptLPS(1); | ||
2645 | |||
2646 | UUID invItemID=InventorySelf(); | ||
2647 | if (invItemID == UUID.Zero) | ||
2648 | return; | ||
2649 | |||
2650 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
2651 | return; | ||
2652 | |||
2653 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) | ||
2654 | { | ||
2655 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); | ||
2656 | |||
2657 | if (presence != null) | ||
2658 | { | ||
2659 | // Do NOT try to parse UUID, animations cannot be triggered by ID | ||
2660 | UUID animID=InventoryKey(anim, (int)AssetType.Animation); | ||
2661 | if (animID == UUID.Zero) | ||
2662 | presence.AddAnimation(anim); | ||
2663 | else | ||
2664 | presence.AddAnimation(animID); | ||
2665 | } | ||
2666 | } | ||
2667 | } | ||
2668 | |||
2669 | public void llStopAnimation(string anim) | ||
2670 | { | ||
2671 | m_host.AddScriptLPS(1); | ||
2672 | |||
2673 | UUID invItemID=InventorySelf(); | ||
2674 | if (invItemID == UUID.Zero) | ||
2675 | return; | ||
2676 | |||
2677 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
2678 | return; | ||
2679 | |||
2680 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) | ||
2681 | { | ||
2682 | UUID animID = new UUID(); | ||
2683 | |||
2684 | if (!UUID.TryParse(anim, out animID)) | ||
2685 | { | ||
2686 | animID=InventoryKey(anim); | ||
2687 | } | ||
2688 | |||
2689 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); | ||
2690 | |||
2691 | if (presence != null) | ||
2692 | { | ||
2693 | if (animID == UUID.Zero) | ||
2694 | presence.RemoveAnimation(anim); | ||
2695 | else | ||
2696 | presence.RemoveAnimation(animID); | ||
2697 | } | ||
2698 | } | ||
2699 | } | ||
2700 | |||
2701 | public void llPointAt() | ||
2702 | { | ||
2703 | m_host.AddScriptLPS(1); | ||
2704 | NotImplemented("llPointAt"); | ||
2705 | } | ||
2706 | |||
2707 | public void llStopPointAt() | ||
2708 | { | ||
2709 | m_host.AddScriptLPS(1); | ||
2710 | NotImplemented("llStopPointAt"); | ||
2711 | } | ||
2712 | |||
2713 | public void llTargetOmega(LSL_Vector axis, double spinrate, double gain) | ||
2714 | { | ||
2715 | m_host.AddScriptLPS(1); | ||
2716 | m_host.RotationalVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); | ||
2717 | m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); | ||
2718 | m_host.ScheduleTerseUpdate(); | ||
2719 | m_host.SendTerseUpdateToAllClients(); | ||
2720 | m_host.ParentGroup.HasGroupChanged = true; | ||
2721 | } | ||
2722 | |||
2723 | public LSL_Integer llGetStartParameter() | ||
2724 | { | ||
2725 | m_host.AddScriptLPS(1); | ||
2726 | return m_ScriptEngine.GetStartParameter(m_itemID); | ||
2727 | } | ||
2728 | |||
2729 | public void llGodLikeRezObject(string inventory, LSL_Vector pos) | ||
2730 | { | ||
2731 | m_host.AddScriptLPS(1); | ||
2732 | NotImplemented("llGodLikeRezObject"); | ||
2733 | } | ||
2734 | |||
2735 | public void llRequestPermissions(string agent, int perm) | ||
2736 | { | ||
2737 | UUID agentID=new UUID(); | ||
2738 | |||
2739 | if (!UUID.TryParse(agent, out agentID)) | ||
2740 | return; | ||
2741 | |||
2742 | UUID invItemID=InventorySelf(); | ||
2743 | |||
2744 | if (invItemID == UUID.Zero) | ||
2745 | return; // Not in a prim? How?? | ||
2746 | |||
2747 | if (agentID == UUID.Zero || perm == 0) // Releasing permissions | ||
2748 | { | ||
2749 | llReleaseControls(); | ||
2750 | |||
2751 | m_host.TaskInventory[invItemID].PermsGranter=UUID.Zero; | ||
2752 | m_host.TaskInventory[invItemID].PermsMask=0; | ||
2753 | |||
2754 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2755 | "run_time_permissions", new Object[] { | ||
2756 | new LSL_Integer(0) }, | ||
2757 | new DetectParams[0])); | ||
2758 | |||
2759 | return; | ||
2760 | } | ||
2761 | |||
2762 | if ( m_host.TaskInventory[invItemID].PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) | ||
2763 | llReleaseControls(); | ||
2764 | |||
2765 | m_host.AddScriptLPS(1); | ||
2766 | |||
2767 | if (m_host.ParentGroup.RootPart.IsAttachment && agent == m_host.ParentGroup.RootPart.AttachedAvatar) | ||
2768 | { | ||
2769 | // When attached, certain permissions are implicit if requested from owner | ||
2770 | int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | | ||
2771 | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | ||
2772 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | | ||
2773 | ScriptBaseClass.PERMISSION_ATTACH; | ||
2774 | |||
2775 | if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms | ||
2776 | { | ||
2777 | m_host.TaskInventory[invItemID].PermsGranter=agentID; | ||
2778 | m_host.TaskInventory[invItemID].PermsMask=perm; | ||
2779 | |||
2780 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2781 | "run_time_permissions", new Object[] { | ||
2782 | new LSL_Integer(perm) }, | ||
2783 | new DetectParams[0])); | ||
2784 | |||
2785 | return; | ||
2786 | } | ||
2787 | } | ||
2788 | else if (m_host.SitTargetAvatar == agentID) // Sitting avatar | ||
2789 | { | ||
2790 | // When agent is sitting, certain permissions are implicit if requested from sitting agent | ||
2791 | int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | ||
2792 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | | ||
2793 | ScriptBaseClass.PERMISSION_TRACK_CAMERA; | ||
2794 | |||
2795 | if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms | ||
2796 | { | ||
2797 | m_host.TaskInventory[invItemID].PermsGranter=agentID; | ||
2798 | m_host.TaskInventory[invItemID].PermsMask=perm; | ||
2799 | |||
2800 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2801 | "run_time_permissions", new Object[] { | ||
2802 | new LSL_Integer(perm) }, | ||
2803 | new DetectParams[0])); | ||
2804 | |||
2805 | return; | ||
2806 | } | ||
2807 | } | ||
2808 | |||
2809 | ScenePresence presence = World.GetScenePresence(agentID); | ||
2810 | |||
2811 | if (presence != null) | ||
2812 | { | ||
2813 | string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID); | ||
2814 | if (ownerName == String.Empty) | ||
2815 | ownerName="(hippos)"; | ||
2816 | |||
2817 | if (!m_waitingForScriptAnswer) | ||
2818 | { | ||
2819 | m_host.TaskInventory[invItemID].PermsGranter=agentID; | ||
2820 | m_host.TaskInventory[invItemID].PermsMask=0; | ||
2821 | presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer; | ||
2822 | m_waitingForScriptAnswer=true; | ||
2823 | } | ||
2824 | |||
2825 | presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm); | ||
2826 | return; | ||
2827 | } | ||
2828 | |||
2829 | // Requested agent is not in range, refuse perms | ||
2830 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2831 | "run_time_permissions", new Object[] { | ||
2832 | new LSL_Integer(0) }, | ||
2833 | new DetectParams[0])); | ||
2834 | } | ||
2835 | |||
2836 | void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer) | ||
2837 | { | ||
2838 | if (taskID != m_host.UUID) | ||
2839 | return; | ||
2840 | |||
2841 | UUID invItemID=InventorySelf(); | ||
2842 | |||
2843 | if (invItemID == UUID.Zero) | ||
2844 | return; | ||
2845 | |||
2846 | client.OnScriptAnswer-=handleScriptAnswer; | ||
2847 | m_waitingForScriptAnswer=false; | ||
2848 | |||
2849 | if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) | ||
2850 | llReleaseControls(); | ||
2851 | |||
2852 | m_host.TaskInventory[invItemID].PermsMask=answer; | ||
2853 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2854 | "run_time_permissions", new Object[] { | ||
2855 | new LSL_Integer(answer) }, | ||
2856 | new DetectParams[0])); | ||
2857 | } | ||
2858 | |||
2859 | public LSL_String llGetPermissionsKey() | ||
2860 | { | ||
2861 | m_host.AddScriptLPS(1); | ||
2862 | |||
2863 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
2864 | { | ||
2865 | if (item.Type == 10 && item.ItemID == m_itemID) | ||
2866 | { | ||
2867 | return item.PermsGranter.ToString(); | ||
2868 | } | ||
2869 | } | ||
2870 | |||
2871 | return UUID.Zero.ToString(); | ||
2872 | } | ||
2873 | |||
2874 | public LSL_Integer llGetPermissions() | ||
2875 | { | ||
2876 | m_host.AddScriptLPS(1); | ||
2877 | |||
2878 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
2879 | { | ||
2880 | if (item.Type == 10 && item.ItemID == m_itemID) | ||
2881 | { | ||
2882 | return item.PermsMask; | ||
2883 | } | ||
2884 | } | ||
2885 | |||
2886 | return 0; | ||
2887 | } | ||
2888 | |||
2889 | public LSL_Integer llGetLinkNumber() | ||
2890 | { | ||
2891 | m_host.AddScriptLPS(1); | ||
2892 | |||
2893 | if (m_host.ParentGroup.Children.Count > 1) | ||
2894 | { | ||
2895 | return m_host.LinkNum; | ||
2896 | } | ||
2897 | else | ||
2898 | { | ||
2899 | return 0; | ||
2900 | } | ||
2901 | } | ||
2902 | |||
2903 | public void llSetLinkColor(int linknumber, LSL_Vector color, int face) | ||
2904 | { | ||
2905 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | ||
2906 | |||
2907 | foreach (SceneObjectPart part in parts) | ||
2908 | SetColor(part, color, face); | ||
2909 | } | ||
2910 | |||
2911 | public void llCreateLink(string target, int parent) | ||
2912 | { | ||
2913 | m_host.AddScriptLPS(1); | ||
2914 | UUID invItemID = InventorySelf(); | ||
2915 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0) { | ||
2916 | ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); | ||
2917 | return; | ||
2918 | } | ||
2919 | IClientAPI client = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter).ControllingClient; | ||
2920 | SceneObjectPart targetPart = World.GetSceneObjectPart(target); | ||
2921 | SceneObjectGroup parentPrim = null, childPrim = null; | ||
2922 | if (targetPart != null) | ||
2923 | { | ||
2924 | if (parent != 0) { | ||
2925 | parentPrim = m_host.ParentGroup; | ||
2926 | childPrim = targetPart.ParentGroup; | ||
2927 | } | ||
2928 | else | ||
2929 | { | ||
2930 | parentPrim = targetPart.ParentGroup; | ||
2931 | childPrim = m_host.ParentGroup; | ||
2932 | } | ||
2933 | // byte uf = childPrim.RootPart.UpdateFlag; | ||
2934 | childPrim.RootPart.UpdateFlag = 0; | ||
2935 | parentPrim.LinkToGroup(childPrim); | ||
2936 | // if (uf != (Byte)0) | ||
2937 | // parent.RootPart.UpdateFlag = uf; | ||
2938 | } | ||
2939 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
2940 | parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected); | ||
2941 | parentPrim.HasGroupChanged = true; | ||
2942 | parentPrim.ScheduleGroupForFullUpdate(); | ||
2943 | parentPrim.GetProperties(client); | ||
2944 | |||
2945 | ScriptSleep(1000); | ||
2946 | } | ||
2947 | |||
2948 | public void llBreakLink(int linknum) | ||
2949 | { | ||
2950 | m_host.AddScriptLPS(1); | ||
2951 | UUID invItemID = InventorySelf(); | ||
2952 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0) | ||
2953 | { | ||
2954 | ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); | ||
2955 | return; | ||
2956 | } | ||
2957 | if (linknum < ScriptBaseClass.LINK_THIS) | ||
2958 | return; | ||
2959 | SceneObjectGroup parentPrim = m_host.ParentGroup; | ||
2960 | SceneObjectPart childPrim = null; | ||
2961 | switch (linknum) | ||
2962 | { | ||
2963 | case ScriptBaseClass.LINK_ROOT: | ||
2964 | break; | ||
2965 | case ScriptBaseClass.LINK_SET: | ||
2966 | case ScriptBaseClass.LINK_ALL_OTHERS: | ||
2967 | case ScriptBaseClass.LINK_ALL_CHILDREN: | ||
2968 | case ScriptBaseClass.LINK_THIS: | ||
2969 | foreach (SceneObjectPart part in parentPrim.Children.Values) | ||
2970 | { | ||
2971 | if (part.UUID != m_host.UUID) | ||
2972 | { | ||
2973 | childPrim = part; | ||
2974 | break; | ||
2975 | } | ||
2976 | } | ||
2977 | break; | ||
2978 | default: | ||
2979 | childPrim = parentPrim.GetLinkNumPart(linknum); | ||
2980 | if (childPrim.UUID == m_host.UUID) | ||
2981 | childPrim = null; | ||
2982 | break; | ||
2983 | } | ||
2984 | if (linknum == ScriptBaseClass.LINK_ROOT) | ||
2985 | { | ||
2986 | // Restructuring Multiple Prims. | ||
2987 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); | ||
2988 | parts.Remove(parentPrim.RootPart); | ||
2989 | foreach (SceneObjectPart part in parts) | ||
2990 | { | ||
2991 | parentPrim.DelinkFromGroup(part.LocalId, true); | ||
2992 | } | ||
2993 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
2994 | if (parts.Count > 0) { | ||
2995 | SceneObjectPart newRoot = parts[0]; | ||
2996 | parts.Remove(newRoot); | ||
2997 | foreach (SceneObjectPart part in parts) | ||
2998 | { | ||
2999 | part.UpdateFlag = 0; | ||
3000 | newRoot.ParentGroup.LinkToGroup(part.ParentGroup); | ||
3001 | } | ||
3002 | } | ||
3003 | } | ||
3004 | else | ||
3005 | { | ||
3006 | if (childPrim == null) | ||
3007 | return; | ||
3008 | parentPrim.DelinkFromGroup(childPrim.LocalId, true); | ||
3009 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
3010 | } | ||
3011 | } | ||
3012 | |||
3013 | public void llBreakAllLinks() | ||
3014 | { | ||
3015 | m_host.AddScriptLPS(1); | ||
3016 | SceneObjectGroup parentPrim = m_host.ParentGroup; | ||
3017 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); | ||
3018 | parts.Remove(parentPrim.RootPart); | ||
3019 | foreach (SceneObjectPart part in parts) | ||
3020 | { | ||
3021 | parentPrim.DelinkFromGroup(part.LocalId, true); | ||
3022 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
3023 | } | ||
3024 | } | ||
3025 | |||
3026 | public LSL_String llGetLinkKey(int linknum) | ||
3027 | { | ||
3028 | m_host.AddScriptLPS(1); | ||
3029 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); | ||
3030 | if (part != null) | ||
3031 | { | ||
3032 | return part.UUID.ToString(); | ||
3033 | } | ||
3034 | else | ||
3035 | { | ||
3036 | return UUID.Zero.ToString(); | ||
3037 | } | ||
3038 | } | ||
3039 | |||
3040 | public LSL_String llGetLinkName(int linknum) | ||
3041 | { | ||
3042 | m_host.AddScriptLPS(1); | ||
3043 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); | ||
3044 | if (part != null) | ||
3045 | { | ||
3046 | return part.Name; | ||
3047 | } | ||
3048 | else | ||
3049 | { | ||
3050 | return ""; | ||
3051 | } | ||
3052 | } | ||
3053 | |||
3054 | public LSL_Integer llGetInventoryNumber(int type) | ||
3055 | { | ||
3056 | m_host.AddScriptLPS(1); | ||
3057 | int count = 0; | ||
3058 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
3059 | { | ||
3060 | if (inv.Value.Type == type || type == -1) | ||
3061 | { | ||
3062 | count = count + 1; | ||
3063 | } | ||
3064 | } | ||
3065 | return count; | ||
3066 | } | ||
3067 | |||
3068 | public LSL_String llGetInventoryName(int type, int number) | ||
3069 | { | ||
3070 | m_host.AddScriptLPS(1); | ||
3071 | ArrayList keys = new ArrayList(); | ||
3072 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
3073 | { | ||
3074 | if (inv.Value.Type == type || type == -1) | ||
3075 | { | ||
3076 | keys.Add(inv.Value.Name); | ||
3077 | } | ||
3078 | } | ||
3079 | if (keys.Count == 0) | ||
3080 | { | ||
3081 | return String.Empty; | ||
3082 | } | ||
3083 | keys.Sort(); | ||
3084 | if (keys.Count > number) | ||
3085 | { | ||
3086 | return (string)keys[number]; | ||
3087 | } | ||
3088 | return String.Empty; | ||
3089 | } | ||
3090 | |||
3091 | public LSL_Float llGetEnergy() | ||
3092 | { | ||
3093 | m_host.AddScriptLPS(1); | ||
3094 | // TODO: figure out real energy value | ||
3095 | return 1.0f; | ||
3096 | } | ||
3097 | |||
3098 | public void llGiveInventory(string destination, string inventory) | ||
3099 | { | ||
3100 | m_host.AddScriptLPS(1); | ||
3101 | bool found = false; | ||
3102 | UUID destId = UUID.Zero; | ||
3103 | UUID objId = UUID.Zero; | ||
3104 | |||
3105 | if (!UUID.TryParse(destination, out destId)) | ||
3106 | { | ||
3107 | llSay(0, "Could not parse key " + destination); | ||
3108 | return; | ||
3109 | } | ||
3110 | |||
3111 | // move the first object found with this inventory name | ||
3112 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
3113 | { | ||
3114 | if (inv.Value.Name == inventory) | ||
3115 | { | ||
3116 | found = true; | ||
3117 | objId = inv.Key; | ||
3118 | break; | ||
3119 | } | ||
3120 | } | ||
3121 | |||
3122 | if (!found) | ||
3123 | { | ||
3124 | llSay(0, String.Format("Could not find object '{0}'", inventory)); | ||
3125 | throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); | ||
3126 | } | ||
3127 | |||
3128 | // check if destination is an avatar | ||
3129 | if (World.GetScenePresence(destId) != null) | ||
3130 | { | ||
3131 | // destination is an avatar | ||
3132 | World.MoveTaskInventoryItem(destId, null, m_host, objId); | ||
3133 | } | ||
3134 | else | ||
3135 | { | ||
3136 | // destination is an object | ||
3137 | World.MoveTaskInventoryItem(destId, m_host, objId); | ||
3138 | } | ||
3139 | // ScriptSleep(3000); | ||
3140 | } | ||
3141 | |||
3142 | public void llRemoveInventory(string name) | ||
3143 | { | ||
3144 | m_host.AddScriptLPS(1); | ||
3145 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3146 | { | ||
3147 | if (item.Name == name) | ||
3148 | { | ||
3149 | m_host.RemoveInventoryItem(item.ItemID); | ||
3150 | return; | ||
3151 | } | ||
3152 | } | ||
3153 | } | ||
3154 | |||
3155 | public void llSetText(string text, LSL_Vector color, double alpha) | ||
3156 | { | ||
3157 | m_host.AddScriptLPS(1); | ||
3158 | Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), | ||
3159 | Util.Clip((float)color.y, 0.0f, 1.0f), | ||
3160 | Util.Clip((float)color.z, 0.0f, 1.0f)); | ||
3161 | m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); | ||
3162 | m_host.ParentGroup.HasGroupChanged = true; | ||
3163 | } | ||
3164 | |||
3165 | public LSL_Float llWater(LSL_Vector offset) | ||
3166 | { | ||
3167 | m_host.AddScriptLPS(1); | ||
3168 | return World.RegionInfo.RegionSettings.WaterHeight; | ||
3169 | } | ||
3170 | |||
3171 | public void llPassTouches(int pass) | ||
3172 | { | ||
3173 | m_host.AddScriptLPS(1); | ||
3174 | NotImplemented("llPassTouches"); | ||
3175 | } | ||
3176 | |||
3177 | public LSL_String llRequestAgentData(string id, int data) | ||
3178 | { | ||
3179 | m_host.AddScriptLPS(1); | ||
3180 | |||
3181 | UserProfileData userProfile = | ||
3182 | World.CommsManager.UserService.GetUserProfile(id); | ||
3183 | |||
3184 | UserAgentData userAgent = | ||
3185 | World.CommsManager.UserService.GetAgentByUUID(id); | ||
3186 | |||
3187 | if (userProfile == null || userAgent == null) | ||
3188 | return UUID.Zero.ToString(); | ||
3189 | |||
3190 | string reply = String.Empty; | ||
3191 | |||
3192 | switch (data) | ||
3193 | { | ||
3194 | case 1: // DATA_ONLINE (0|1) | ||
3195 | // TODO: implement fetching of this information | ||
3196 | if (userProfile.CurrentAgent.AgentOnline) | ||
3197 | reply = "1"; | ||
3198 | else | ||
3199 | reply = "0"; | ||
3200 | break; | ||
3201 | case 2: // DATA_NAME (First Last) | ||
3202 | reply = userProfile.FirstName + " " + userProfile.SurName; | ||
3203 | break; | ||
3204 | case 3: // DATA_BORN (YYYY-MM-DD) | ||
3205 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); | ||
3206 | born = born.AddSeconds(userProfile.Created); | ||
3207 | reply = born.ToString("yyyy-MM-dd"); | ||
3208 | break; | ||
3209 | case 4: // DATA_RATING (0,0,0,0,0,0) | ||
3210 | reply = "0,0,0,0,0,0"; | ||
3211 | break; | ||
3212 | case 8: // DATA_PAYINFO (0|1|2|3) | ||
3213 | reply = "0"; | ||
3214 | break; | ||
3215 | default: | ||
3216 | return UUID.Zero.ToString(); // Raise no event | ||
3217 | } | ||
3218 | |||
3219 | UUID rq = UUID.Random(); | ||
3220 | |||
3221 | UUID tid = AsyncCommands. | ||
3222 | DataserverPlugin.RegisterRequest(m_localID, | ||
3223 | m_itemID, rq.ToString()); | ||
3224 | |||
3225 | AsyncCommands. | ||
3226 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | ||
3227 | |||
3228 | // ScriptSleep(100); | ||
3229 | return tid.ToString(); | ||
3230 | } | ||
3231 | |||
3232 | public LSL_String llRequestInventoryData(string name) | ||
3233 | { | ||
3234 | m_host.AddScriptLPS(1); | ||
3235 | |||
3236 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3237 | { | ||
3238 | if (item.Type == 3 && item.Name == name) | ||
3239 | { | ||
3240 | UUID tid = AsyncCommands. | ||
3241 | DataserverPlugin.RegisterRequest(m_localID, | ||
3242 | m_itemID, item.AssetID.ToString()); | ||
3243 | |||
3244 | Vector3 region = new Vector3( | ||
3245 | World.RegionInfo.RegionLocX * Constants.RegionSize, | ||
3246 | World.RegionInfo.RegionLocY * Constants.RegionSize, | ||
3247 | 0); | ||
3248 | |||
3249 | World.AssetCache.GetAsset(item.AssetID, | ||
3250 | delegate(UUID i, AssetBase a) | ||
3251 | { | ||
3252 | AssetLandmark lm = new AssetLandmark(a); | ||
3253 | |||
3254 | float rx = (uint)(lm.RegionHandle >> 32); | ||
3255 | float ry = (uint)lm.RegionHandle; | ||
3256 | region = lm.Position + new Vector3(rx, ry, 0) - region; | ||
3257 | |||
3258 | string reply = region.ToString(); | ||
3259 | AsyncCommands. | ||
3260 | DataserverPlugin.DataserverReply(i.ToString(), | ||
3261 | reply); | ||
3262 | }, false); | ||
3263 | |||
3264 | // ScriptSleep(1000); | ||
3265 | return tid.ToString(); | ||
3266 | } | ||
3267 | } | ||
3268 | // ScriptSleep(1000); | ||
3269 | return String.Empty; | ||
3270 | } | ||
3271 | |||
3272 | public void llSetDamage(double damage) | ||
3273 | { | ||
3274 | m_host.AddScriptLPS(1); | ||
3275 | NotImplemented("llSetDamage"); | ||
3276 | } | ||
3277 | |||
3278 | public void llTeleportAgentHome(string agent) | ||
3279 | { | ||
3280 | m_host.AddScriptLPS(1); | ||
3281 | UUID agentId = new UUID(); | ||
3282 | if (UUID.TryParse(agent, out agentId)) | ||
3283 | { | ||
3284 | ScenePresence presence = World.GetScenePresence(agentId); | ||
3285 | if (presence != null) | ||
3286 | { | ||
3287 | // agent must be over the owners land | ||
3288 | if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y)) | ||
3289 | World.TeleportClientHome(agentId, presence.ControllingClient); | ||
3290 | } | ||
3291 | } | ||
3292 | // ScriptSleep(5000); | ||
3293 | } | ||
3294 | |||
3295 | public void llTextBox(string avatar, string message, int chat_channel) | ||
3296 | { | ||
3297 | m_host.AddScriptLPS(1); | ||
3298 | NotImplemented("llTextBox"); | ||
3299 | } | ||
3300 | |||
3301 | public void llModifyLand(int action, int brush) | ||
3302 | { | ||
3303 | m_host.AddScriptLPS(1); | ||
3304 | World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new Vector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0)); | ||
3305 | } | ||
3306 | |||
3307 | public void llCollisionSound(string impact_sound, double impact_volume) | ||
3308 | { | ||
3309 | m_host.AddScriptLPS(1); | ||
3310 | NotImplemented("llCollisionSound"); | ||
3311 | } | ||
3312 | |||
3313 | public void llCollisionSprite(string impact_sprite) | ||
3314 | { | ||
3315 | m_host.AddScriptLPS(1); | ||
3316 | NotImplemented("llCollisionSprite"); | ||
3317 | } | ||
3318 | |||
3319 | public LSL_String llGetAnimation(string id) | ||
3320 | { | ||
3321 | m_host.AddScriptLPS(1); | ||
3322 | NotImplemented("llGetAnimation"); | ||
3323 | return String.Empty; | ||
3324 | } | ||
3325 | |||
3326 | public void llMessageLinked(int linknum, int num, string msg, string id) | ||
3327 | { | ||
3328 | |||
3329 | m_host.AddScriptLPS(1); | ||
3330 | |||
3331 | // uint partLocalID; | ||
3332 | UUID partItemID; | ||
3333 | |||
3334 | switch ((int)linknum) | ||
3335 | { | ||
3336 | |||
3337 | case (int)ScriptBaseClass.LINK_ROOT: | ||
3338 | |||
3339 | SceneObjectPart part = m_host.ParentGroup.RootPart; | ||
3340 | |||
3341 | foreach (TaskInventoryItem item in part.TaskInventory.Values) | ||
3342 | { | ||
3343 | if (item.Type == 10) | ||
3344 | { | ||
3345 | // partLocalID = part.LocalId; | ||
3346 | partItemID = item.ItemID; | ||
3347 | |||
3348 | object[] resobj = new object[] | ||
3349 | { | ||
3350 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3351 | }; | ||
3352 | |||
3353 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3354 | new EventParams("link_message", | ||
3355 | resobj, new DetectParams[0])); | ||
3356 | } | ||
3357 | } | ||
3358 | |||
3359 | break; | ||
3360 | |||
3361 | case (int)ScriptBaseClass.LINK_SET: | ||
3362 | |||
3363 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3364 | { | ||
3365 | |||
3366 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3367 | { | ||
3368 | if (item.Type == 10) | ||
3369 | { | ||
3370 | // partLocalID = partInst.LocalId; | ||
3371 | partItemID = item.ItemID; | ||
3372 | Object[] resobj = new object[] | ||
3373 | { | ||
3374 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3375 | }; | ||
3376 | |||
3377 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3378 | new EventParams("link_message", | ||
3379 | resobj, new DetectParams[0])); | ||
3380 | } | ||
3381 | } | ||
3382 | } | ||
3383 | |||
3384 | break; | ||
3385 | |||
3386 | case (int)ScriptBaseClass.LINK_ALL_OTHERS: | ||
3387 | |||
3388 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3389 | { | ||
3390 | |||
3391 | if (partInst.LocalId != m_host.LocalId) | ||
3392 | { | ||
3393 | |||
3394 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3395 | { | ||
3396 | if (item.Type == 10) | ||
3397 | { | ||
3398 | // partLocalID = partInst.LocalId; | ||
3399 | partItemID = item.ItemID; | ||
3400 | Object[] resobj = new object[] | ||
3401 | { | ||
3402 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3403 | }; | ||
3404 | |||
3405 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3406 | new EventParams("link_message", | ||
3407 | resobj, new DetectParams[0])); | ||
3408 | } | ||
3409 | } | ||
3410 | |||
3411 | } | ||
3412 | } | ||
3413 | |||
3414 | break; | ||
3415 | |||
3416 | case (int)ScriptBaseClass.LINK_ALL_CHILDREN: | ||
3417 | |||
3418 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3419 | { | ||
3420 | |||
3421 | if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId) | ||
3422 | { | ||
3423 | |||
3424 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3425 | { | ||
3426 | if (item.Type == 10) | ||
3427 | { | ||
3428 | // partLocalID = partInst.LocalId; | ||
3429 | partItemID = item.ItemID; | ||
3430 | Object[] resobj = new object[] | ||
3431 | { | ||
3432 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3433 | }; | ||
3434 | |||
3435 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3436 | new EventParams("link_message", | ||
3437 | resobj, new DetectParams[0])); | ||
3438 | } | ||
3439 | } | ||
3440 | |||
3441 | } | ||
3442 | } | ||
3443 | |||
3444 | break; | ||
3445 | |||
3446 | case (int)ScriptBaseClass.LINK_THIS: | ||
3447 | |||
3448 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3449 | { | ||
3450 | if (item.Type == 10) | ||
3451 | { | ||
3452 | partItemID = item.ItemID; | ||
3453 | |||
3454 | object[] resobj = new object[] | ||
3455 | { | ||
3456 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3457 | }; | ||
3458 | |||
3459 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3460 | new EventParams("link_message", | ||
3461 | resobj, new DetectParams[0])); | ||
3462 | } | ||
3463 | } | ||
3464 | |||
3465 | break; | ||
3466 | |||
3467 | default: | ||
3468 | |||
3469 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3470 | { | ||
3471 | |||
3472 | if ((partInst.LinkNum) == linknum) | ||
3473 | { | ||
3474 | |||
3475 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3476 | { | ||
3477 | if (item.Type == 10) | ||
3478 | { | ||
3479 | // partLocalID = partInst.LocalId; | ||
3480 | partItemID = item.ItemID; | ||
3481 | Object[] resObjDef = new object[] | ||
3482 | { | ||
3483 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3484 | }; | ||
3485 | |||
3486 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3487 | new EventParams("link_message", | ||
3488 | resObjDef, new DetectParams[0])); | ||
3489 | } | ||
3490 | } | ||
3491 | |||
3492 | } | ||
3493 | } | ||
3494 | |||
3495 | break; | ||
3496 | |||
3497 | } | ||
3498 | |||
3499 | } | ||
3500 | |||
3501 | public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local) | ||
3502 | { | ||
3503 | m_host.AddScriptLPS(1); | ||
3504 | SceneObjectPart targ = World.GetSceneObjectPart(target); | ||
3505 | if (targ == null) | ||
3506 | return; | ||
3507 | targ.ApplyImpulse(new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z), local != 0); | ||
3508 | } | ||
3509 | |||
3510 | public void llPassCollisions(int pass) | ||
3511 | { | ||
3512 | m_host.AddScriptLPS(1); | ||
3513 | NotImplemented("llPassCollisions"); | ||
3514 | } | ||
3515 | |||
3516 | public LSL_String llGetScriptName() | ||
3517 | { | ||
3518 | |||
3519 | string result = String.Empty; | ||
3520 | |||
3521 | m_host.AddScriptLPS(1); | ||
3522 | |||
3523 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3524 | { | ||
3525 | if (item.Type == 10 && item.ItemID == m_itemID) | ||
3526 | { | ||
3527 | result = item.Name!=null?item.Name:String.Empty; | ||
3528 | break; | ||
3529 | } | ||
3530 | } | ||
3531 | |||
3532 | return result; | ||
3533 | |||
3534 | } | ||
3535 | |||
3536 | // this function to understand which shape it is (taken from meshmerizer) | ||
3537 | // quite useful can be used by meshmerizer to have a centralized point of understanding the shape | ||
3538 | // except that it refers to scripting constants | ||
3539 | private int getScriptPrimType(PrimitiveBaseShape primShape) | ||
3540 | { | ||
3541 | if (primShape.SculptEntry) | ||
3542 | return ScriptBaseClass.PRIM_TYPE_SCULPT; | ||
3543 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
3544 | { | ||
3545 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
3546 | return ScriptBaseClass.PRIM_TYPE_BOX; | ||
3547 | else if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
3548 | return ScriptBaseClass.PRIM_TYPE_TUBE; | ||
3549 | } | ||
3550 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
3551 | { | ||
3552 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
3553 | return ScriptBaseClass.PRIM_TYPE_CYLINDER; | ||
3554 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits | ||
3555 | else if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
3556 | return ScriptBaseClass.PRIM_TYPE_TORUS; | ||
3557 | } | ||
3558 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
3559 | { | ||
3560 | if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte)Extrusion.Curve2) | ||
3561 | return ScriptBaseClass.PRIM_TYPE_SPHERE; | ||
3562 | } | ||
3563 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
3564 | { | ||
3565 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
3566 | return ScriptBaseClass.PRIM_TYPE_PRISM; | ||
3567 | else if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
3568 | return ScriptBaseClass.PRIM_TYPE_RING; | ||
3569 | } | ||
3570 | return ScriptBaseClass.PRIM_TYPE_BOX; | ||
3571 | } | ||
3572 | |||
3573 | // Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces | ||
3574 | private void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow, | ||
3575 | out bool hasDimple, out bool hasProfileCut) | ||
3576 | { | ||
3577 | if (primType == ScriptBaseClass.PRIM_TYPE_BOX | ||
3578 | || | ||
3579 | primType == ScriptBaseClass.PRIM_TYPE_CYLINDER | ||
3580 | || | ||
3581 | primType == ScriptBaseClass.PRIM_TYPE_PRISM) | ||
3582 | |||
3583 | hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); | ||
3584 | else | ||
3585 | hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0); | ||
3586 | |||
3587 | hasHollow = shape.ProfileHollow > 0; | ||
3588 | hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms | ||
3589 | hasProfileCut = hasDimple; // is it the same thing? | ||
3590 | |||
3591 | } | ||
3592 | |||
3593 | public LSL_Integer llGetNumberOfSides() | ||
3594 | { | ||
3595 | m_host.AddScriptLPS(1); | ||
3596 | |||
3597 | return GetNumberOfSides(m_host); | ||
3598 | } | ||
3599 | |||
3600 | private int GetNumberOfSides(SceneObjectPart part) | ||
3601 | { | ||
3602 | int ret = 0; | ||
3603 | bool hasCut; | ||
3604 | bool hasHollow; | ||
3605 | bool hasDimple; | ||
3606 | bool hasProfileCut; | ||
3607 | |||
3608 | int primType = getScriptPrimType(part.Shape); | ||
3609 | hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut); | ||
3610 | |||
3611 | switch (primType) | ||
3612 | { | ||
3613 | case ScriptBaseClass.PRIM_TYPE_BOX: | ||
3614 | ret = 6; | ||
3615 | if (hasCut) ret += 2; | ||
3616 | if (hasHollow) ret += 1; | ||
3617 | break; | ||
3618 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
3619 | ret = 3; | ||
3620 | if (hasCut) ret += 2; | ||
3621 | if (hasHollow) ret += 1; | ||
3622 | break; | ||
3623 | case ScriptBaseClass.PRIM_TYPE_PRISM: | ||
3624 | ret = 5; | ||
3625 | if (hasCut) ret += 2; | ||
3626 | if (hasHollow) ret += 1; | ||
3627 | break; | ||
3628 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
3629 | ret = 1; | ||
3630 | if (hasCut) ret += 2; | ||
3631 | if (hasDimple) ret += 2; | ||
3632 | if (hasHollow) ret += 3; // Emulate lsl on secondlife (according to documentation it should have added only +1) | ||
3633 | break; | ||
3634 | case ScriptBaseClass.PRIM_TYPE_TORUS: | ||
3635 | ret = 1; | ||
3636 | if (hasCut) ret += 2; | ||
3637 | if (hasProfileCut) ret += 2; | ||
3638 | if (hasHollow) ret += 1; | ||
3639 | break; | ||
3640 | case ScriptBaseClass.PRIM_TYPE_TUBE: | ||
3641 | ret = 4; | ||
3642 | if (hasCut) ret += 2; | ||
3643 | if (hasProfileCut) ret += 2; | ||
3644 | if (hasHollow) ret += 1; | ||
3645 | break; | ||
3646 | case ScriptBaseClass.PRIM_TYPE_RING: | ||
3647 | ret = 3; | ||
3648 | if (hasCut) ret += 2; | ||
3649 | if (hasProfileCut) ret += 2; | ||
3650 | if (hasHollow) ret += 1; | ||
3651 | break; | ||
3652 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
3653 | ret = 1; | ||
3654 | break; | ||
3655 | } | ||
3656 | return ret; | ||
3657 | } | ||
3658 | |||
3659 | |||
3660 | /* The new / changed functions were tested with the following LSL script: | ||
3661 | |||
3662 | default | ||
3663 | { | ||
3664 | state_entry() | ||
3665 | { | ||
3666 | rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD); | ||
3667 | |||
3668 | llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot)); | ||
3669 | llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG)); | ||
3670 | |||
3671 | // convert back and forth between quaternion <-> vector and angle | ||
3672 | |||
3673 | rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot)); | ||
3674 | |||
3675 | llOwnerSay("Old rotation was: "+(string) rot); | ||
3676 | llOwnerSay("re-converted rotation is: "+(string) newrot); | ||
3677 | |||
3678 | llSetRot(rot); // to check the parameters in the prim | ||
3679 | } | ||
3680 | } | ||
3681 | */ | ||
3682 | |||
3683 | |||
3684 | |||
3685 | // Xantor 29/apr/2008 | ||
3686 | // Returns rotation described by rotating angle radians about axis. | ||
3687 | // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2)) | ||
3688 | public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle) | ||
3689 | { | ||
3690 | m_host.AddScriptLPS(1); | ||
3691 | |||
3692 | double x, y, z, s, t; | ||
3693 | |||
3694 | s = Math.Cos(angle / 2); | ||
3695 | t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs | ||
3696 | x = axis.x * t; | ||
3697 | y = axis.y * t; | ||
3698 | z = axis.z * t; | ||
3699 | |||
3700 | return new LSL_Rotation(x,y,z,s); | ||
3701 | } | ||
3702 | |||
3703 | |||
3704 | // Xantor 29/apr/2008 | ||
3705 | // converts a Quaternion to X,Y,Z axis rotations | ||
3706 | public LSL_Vector llRot2Axis(LSL_Rotation rot) | ||
3707 | { | ||
3708 | m_host.AddScriptLPS(1); | ||
3709 | double x,y,z; | ||
3710 | |||
3711 | if (rot.s > 1) // normalization needed | ||
3712 | { | ||
3713 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
3714 | rot.z * rot.z + rot.s * rot.s); | ||
3715 | |||
3716 | rot.x /= length; | ||
3717 | rot.y /= length; | ||
3718 | rot.z /= length; | ||
3719 | rot.s /= length; | ||
3720 | |||
3721 | } | ||
3722 | |||
3723 | // double angle = 2 * Math.Acos(rot.s); | ||
3724 | double s = Math.Sqrt(1 - rot.s * rot.s); | ||
3725 | if (s < 0.001) | ||
3726 | { | ||
3727 | x = 1; | ||
3728 | y = z = 0; | ||
3729 | } | ||
3730 | else | ||
3731 | { | ||
3732 | x = rot.x / s; // normalise axis | ||
3733 | y = rot.y / s; | ||
3734 | z = rot.z / s; | ||
3735 | } | ||
3736 | |||
3737 | return new LSL_Vector(x,y,z); | ||
3738 | } | ||
3739 | |||
3740 | |||
3741 | // Returns the angle of a quaternion (see llRot2Axis for the axis) | ||
3742 | public LSL_Float llRot2Angle(LSL_Rotation rot) | ||
3743 | { | ||
3744 | m_host.AddScriptLPS(1); | ||
3745 | |||
3746 | if (rot.s > 1) // normalization needed | ||
3747 | { | ||
3748 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
3749 | rot.z * rot.z + rot.s * rot.s); | ||
3750 | |||
3751 | rot.x /= length; | ||
3752 | rot.y /= length; | ||
3753 | rot.z /= length; | ||
3754 | rot.s /= length; | ||
3755 | } | ||
3756 | |||
3757 | double angle = 2 * Math.Acos(rot.s); | ||
3758 | |||
3759 | return angle; | ||
3760 | } | ||
3761 | |||
3762 | public LSL_Float llAcos(double val) | ||
3763 | { | ||
3764 | m_host.AddScriptLPS(1); | ||
3765 | return (double)Math.Acos(val); | ||
3766 | } | ||
3767 | |||
3768 | public LSL_Float llAsin(double val) | ||
3769 | { | ||
3770 | m_host.AddScriptLPS(1); | ||
3771 | return (double)Math.Asin(val); | ||
3772 | } | ||
3773 | |||
3774 | // Xantor 30/apr/2008 | ||
3775 | public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) | ||
3776 | { | ||
3777 | m_host.AddScriptLPS(1); | ||
3778 | |||
3779 | return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2; | ||
3780 | } | ||
3781 | |||
3782 | public LSL_String llGetInventoryKey(string name) | ||
3783 | { | ||
3784 | m_host.AddScriptLPS(1); | ||
3785 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
3786 | { | ||
3787 | if (inv.Value.Name == name) | ||
3788 | { | ||
3789 | if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) | ||
3790 | { | ||
3791 | return inv.Value.AssetID.ToString(); | ||
3792 | } | ||
3793 | else | ||
3794 | { | ||
3795 | return UUID.Zero.ToString(); | ||
3796 | } | ||
3797 | } | ||
3798 | } | ||
3799 | return UUID.Zero.ToString(); | ||
3800 | } | ||
3801 | |||
3802 | public void llAllowInventoryDrop(int add) | ||
3803 | { | ||
3804 | m_host.AddScriptLPS(1); | ||
3805 | |||
3806 | if (add != 0) | ||
3807 | m_host.ParentGroup.RootPart.AllowedDrop = true; | ||
3808 | else | ||
3809 | m_host.ParentGroup.RootPart.AllowedDrop = false; | ||
3810 | } | ||
3811 | |||
3812 | public LSL_Vector llGetSunDirection() | ||
3813 | { | ||
3814 | m_host.AddScriptLPS(1); | ||
3815 | |||
3816 | LSL_Vector SunDoubleVector3; | ||
3817 | Vector3 SunFloatVector3; | ||
3818 | |||
3819 | // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule | ||
3820 | // have to convert from Vector3 (float) to LSL_Vector (double) | ||
3821 | SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector; | ||
3822 | SunDoubleVector3.x = (double)SunFloatVector3.X; | ||
3823 | SunDoubleVector3.y = (double)SunFloatVector3.Y; | ||
3824 | SunDoubleVector3.z = (double)SunFloatVector3.Z; | ||
3825 | |||
3826 | return SunDoubleVector3; | ||
3827 | } | ||
3828 | |||
3829 | public LSL_Vector llGetTextureOffset(int face) | ||
3830 | { | ||
3831 | m_host.AddScriptLPS(1); | ||
3832 | return GetTextureOffset(m_host, face); | ||
3833 | } | ||
3834 | |||
3835 | private LSL_Vector GetTextureOffset(SceneObjectPart part, int face) | ||
3836 | { | ||
3837 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
3838 | LSL_Vector offset = new LSL_Vector(); | ||
3839 | if (face == ScriptBaseClass.ALL_SIDES) | ||
3840 | { | ||
3841 | face = 0; | ||
3842 | } | ||
3843 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
3844 | { | ||
3845 | offset.x = tex.GetFace((uint)face).OffsetU; | ||
3846 | offset.y = tex.GetFace((uint)face).OffsetV; | ||
3847 | offset.z = 0.0; | ||
3848 | return offset; | ||
3849 | } | ||
3850 | else | ||
3851 | { | ||
3852 | return offset; | ||
3853 | } | ||
3854 | } | ||
3855 | |||
3856 | public LSL_Vector llGetTextureScale(int side) | ||
3857 | { | ||
3858 | m_host.AddScriptLPS(1); | ||
3859 | Primitive.TextureEntry tex = m_host.Shape.Textures; | ||
3860 | LSL_Vector scale; | ||
3861 | if (side == -1) | ||
3862 | { | ||
3863 | side = 0; | ||
3864 | } | ||
3865 | scale.x = tex.GetFace((uint)side).RepeatU; | ||
3866 | scale.y = tex.GetFace((uint)side).RepeatV; | ||
3867 | scale.z = 0.0; | ||
3868 | return scale; | ||
3869 | } | ||
3870 | |||
3871 | public LSL_Float llGetTextureRot(int face) | ||
3872 | { | ||
3873 | m_host.AddScriptLPS(1); | ||
3874 | return GetTextureRot(m_host, face); | ||
3875 | } | ||
3876 | |||
3877 | private LSL_Float GetTextureRot(SceneObjectPart part, int face) | ||
3878 | { | ||
3879 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
3880 | if (face == -1) | ||
3881 | { | ||
3882 | face = 0; | ||
3883 | } | ||
3884 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
3885 | { | ||
3886 | return tex.GetFace((uint)face).Rotation; | ||
3887 | } | ||
3888 | else | ||
3889 | { | ||
3890 | return 0.0; | ||
3891 | } | ||
3892 | } | ||
3893 | |||
3894 | public LSL_Integer llSubStringIndex(string source, string pattern) | ||
3895 | { | ||
3896 | m_host.AddScriptLPS(1); | ||
3897 | return source.IndexOf(pattern); | ||
3898 | } | ||
3899 | |||
3900 | public LSL_String llGetOwnerKey(string id) | ||
3901 | { | ||
3902 | m_host.AddScriptLPS(1); | ||
3903 | UUID key = new UUID(); | ||
3904 | if (UUID.TryParse(id, out key)) | ||
3905 | { | ||
3906 | try | ||
3907 | { | ||
3908 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); | ||
3909 | if (obj == null) | ||
3910 | return id; // the key is for an agent so just return the key | ||
3911 | else | ||
3912 | return obj.OwnerID.ToString(); | ||
3913 | } | ||
3914 | catch (KeyNotFoundException) | ||
3915 | { | ||
3916 | return id; // The Object/Agent not in the region so just return the key | ||
3917 | } | ||
3918 | } | ||
3919 | else | ||
3920 | { | ||
3921 | return UUID.Zero.ToString(); | ||
3922 | } | ||
3923 | } | ||
3924 | |||
3925 | public LSL_Vector llGetCenterOfMass() | ||
3926 | { | ||
3927 | m_host.AddScriptLPS(1); | ||
3928 | NotImplemented("llGetCenterOfMass"); | ||
3929 | return new LSL_Vector(); | ||
3930 | } | ||
3931 | |||
3932 | public LSL_List llListSort(LSL_List src, int stride, int ascending) | ||
3933 | { | ||
3934 | m_host.AddScriptLPS(1); | ||
3935 | |||
3936 | if (stride <= 0) | ||
3937 | { | ||
3938 | stride = 1; | ||
3939 | } | ||
3940 | return src.Sort(stride, ascending); | ||
3941 | } | ||
3942 | |||
3943 | public LSL_Integer llGetListLength(LSL_List src) | ||
3944 | { | ||
3945 | m_host.AddScriptLPS(1); | ||
3946 | |||
3947 | if (src == null) | ||
3948 | { | ||
3949 | return 0; | ||
3950 | } | ||
3951 | else | ||
3952 | { | ||
3953 | return src.Length; | ||
3954 | } | ||
3955 | } | ||
3956 | |||
3957 | public LSL_Integer llList2Integer(LSL_List src, int index) | ||
3958 | { | ||
3959 | m_host.AddScriptLPS(1); | ||
3960 | if (index < 0) | ||
3961 | { | ||
3962 | index = src.Length + index; | ||
3963 | } | ||
3964 | if (index >= src.Length) | ||
3965 | { | ||
3966 | return 0; | ||
3967 | } | ||
3968 | try | ||
3969 | { | ||
3970 | if (src.Data[index] is LSL_Integer) | ||
3971 | return Convert.ToInt32(((LSL_Integer) src.Data[index]).value); | ||
3972 | else if (src.Data[index] is LSL_Float) | ||
3973 | return Convert.ToInt32(((LSL_Float) src.Data[index]).value); | ||
3974 | else if (src.Data[index] is LSL_String) | ||
3975 | return Convert.ToInt32(((LSL_String) src.Data[index]).m_string); | ||
3976 | return Convert.ToInt32(src.Data[index]); | ||
3977 | } | ||
3978 | catch (FormatException) | ||
3979 | { | ||
3980 | return 0; | ||
3981 | } | ||
3982 | } | ||
3983 | |||
3984 | public LSL_Float llList2Float(LSL_List src, int index) | ||
3985 | { | ||
3986 | m_host.AddScriptLPS(1); | ||
3987 | if (index < 0) | ||
3988 | { | ||
3989 | index = src.Length + index; | ||
3990 | } | ||
3991 | if (index >= src.Length) | ||
3992 | { | ||
3993 | return 0.0; | ||
3994 | } | ||
3995 | try | ||
3996 | { | ||
3997 | if (src.Data[index] is LSL_Integer) | ||
3998 | return Convert.ToDouble(((LSL_Integer) src.Data[index]).value); | ||
3999 | else if (src.Data[index] is LSL_Float) | ||
4000 | return Convert.ToDouble(((LSL_Float) src.Data[index]).value); | ||
4001 | else if (src.Data[index] is LSL_String) | ||
4002 | return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); | ||
4003 | return Convert.ToDouble(src.Data[index]); | ||
4004 | } | ||
4005 | catch (FormatException) | ||
4006 | { | ||
4007 | return 0.0; | ||
4008 | } | ||
4009 | } | ||
4010 | |||
4011 | public LSL_String llList2String(LSL_List src, int index) | ||
4012 | { | ||
4013 | m_host.AddScriptLPS(1); | ||
4014 | if (index < 0) | ||
4015 | { | ||
4016 | index = src.Length + index; | ||
4017 | } | ||
4018 | if (index >= src.Length) | ||
4019 | { | ||
4020 | return String.Empty; | ||
4021 | } | ||
4022 | return src.Data[index].ToString(); | ||
4023 | } | ||
4024 | |||
4025 | public LSL_String llList2Key(LSL_List src, int index) | ||
4026 | { | ||
4027 | m_host.AddScriptLPS(1); | ||
4028 | if (index < 0) | ||
4029 | { | ||
4030 | index = src.Length + index; | ||
4031 | } | ||
4032 | if (index >= src.Length) | ||
4033 | { | ||
4034 | return ""; | ||
4035 | } | ||
4036 | return src.Data[index].ToString(); | ||
4037 | } | ||
4038 | |||
4039 | public LSL_Vector llList2Vector(LSL_List src, int index) | ||
4040 | { | ||
4041 | m_host.AddScriptLPS(1); | ||
4042 | if (index < 0) | ||
4043 | { | ||
4044 | index = src.Length + index; | ||
4045 | } | ||
4046 | if (index >= src.Length) | ||
4047 | { | ||
4048 | return new LSL_Vector(0, 0, 0); | ||
4049 | } | ||
4050 | if (src.Data[index].GetType() == typeof(LSL_Vector)) | ||
4051 | { | ||
4052 | return (LSL_Vector)src.Data[index]; | ||
4053 | } | ||
4054 | else | ||
4055 | { | ||
4056 | return new LSL_Vector(src.Data[index].ToString()); | ||
4057 | } | ||
4058 | } | ||
4059 | |||
4060 | public LSL_Rotation llList2Rot(LSL_List src, int index) | ||
4061 | { | ||
4062 | m_host.AddScriptLPS(1); | ||
4063 | if (index < 0) | ||
4064 | { | ||
4065 | index = src.Length + index; | ||
4066 | } | ||
4067 | if (index >= src.Length) | ||
4068 | { | ||
4069 | return new LSL_Rotation(0, 0, 0, 1); | ||
4070 | } | ||
4071 | if (src.Data[index].GetType() == typeof(LSL_Rotation)) | ||
4072 | { | ||
4073 | return (LSL_Rotation)src.Data[index]; | ||
4074 | } | ||
4075 | else | ||
4076 | { | ||
4077 | return new LSL_Rotation(src.Data[index].ToString()); | ||
4078 | } | ||
4079 | } | ||
4080 | |||
4081 | public LSL_List llList2List(LSL_List src, int start, int end) | ||
4082 | { | ||
4083 | m_host.AddScriptLPS(1); | ||
4084 | return src.GetSublist(start, end); | ||
4085 | } | ||
4086 | |||
4087 | public LSL_List llDeleteSubList(LSL_List src, int start, int end) | ||
4088 | { | ||
4089 | return src.DeleteSublist(end, start); | ||
4090 | } | ||
4091 | |||
4092 | public LSL_Integer llGetListEntryType(LSL_List src, int index) | ||
4093 | { | ||
4094 | m_host.AddScriptLPS(1); | ||
4095 | if (index < 0) | ||
4096 | { | ||
4097 | index = src.Length + index; | ||
4098 | } | ||
4099 | if (index >= src.Length) | ||
4100 | { | ||
4101 | return 0; | ||
4102 | } | ||
4103 | |||
4104 | if (src.Data[index] is LSL_Integer || src.Data[index] is Int32) | ||
4105 | return 1; | ||
4106 | if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double) | ||
4107 | return 2; | ||
4108 | if (src.Data[index] is LSL_String || src.Data[index] is String) | ||
4109 | { | ||
4110 | UUID tuuid; | ||
4111 | if (UUID.TryParse(src.Data[index].ToString(), out tuuid)) | ||
4112 | { | ||
4113 | return 4; | ||
4114 | } | ||
4115 | else | ||
4116 | { | ||
4117 | return 3; | ||
4118 | } | ||
4119 | } | ||
4120 | if (src.Data[index] is LSL_Vector) | ||
4121 | return 5; | ||
4122 | if (src.Data[index] is LSL_Rotation) | ||
4123 | return 6; | ||
4124 | if (src.Data[index] is LSL_List) | ||
4125 | return 7; | ||
4126 | return 0; | ||
4127 | |||
4128 | } | ||
4129 | |||
4130 | /// <summary> | ||
4131 | /// Process the supplied list and return the | ||
4132 | /// content of the list formatted as a comma | ||
4133 | /// separated list. There is a space after | ||
4134 | /// each comma. | ||
4135 | /// </summary> | ||
4136 | |||
4137 | public LSL_String llList2CSV(LSL_List src) | ||
4138 | { | ||
4139 | |||
4140 | string ret = String.Empty; | ||
4141 | int x = 0; | ||
4142 | |||
4143 | m_host.AddScriptLPS(1); | ||
4144 | |||
4145 | if (src.Data.Length > 0) | ||
4146 | { | ||
4147 | ret = src.Data[x++].ToString(); | ||
4148 | for (; x < src.Data.Length; x++) | ||
4149 | { | ||
4150 | ret += ", "+src.Data[x].ToString(); | ||
4151 | } | ||
4152 | } | ||
4153 | |||
4154 | return ret; | ||
4155 | } | ||
4156 | |||
4157 | /// <summary> | ||
4158 | /// The supplied string is scanned for commas | ||
4159 | /// and converted into a list. Commas are only | ||
4160 | /// effective if they are encountered outside | ||
4161 | /// of '<' '>' delimiters. Any whitespace | ||
4162 | /// before or after an element is trimmed. | ||
4163 | /// </summary> | ||
4164 | |||
4165 | public LSL_List llCSV2List(string src) | ||
4166 | { | ||
4167 | |||
4168 | LSL_List result = new LSL_List(); | ||
4169 | int parens = 0; | ||
4170 | int start = 0; | ||
4171 | int length = 0; | ||
4172 | |||
4173 | m_host.AddScriptLPS(1); | ||
4174 | |||
4175 | for (int i = 0; i < src.Length; i++) | ||
4176 | { | ||
4177 | switch (src[i]) | ||
4178 | { | ||
4179 | case '<': | ||
4180 | parens++; | ||
4181 | length++; | ||
4182 | break; | ||
4183 | case '>': | ||
4184 | if (parens > 0) | ||
4185 | parens--; | ||
4186 | length++; | ||
4187 | break; | ||
4188 | case ',': | ||
4189 | if (parens == 0) | ||
4190 | { | ||
4191 | result.Add(src.Substring(start,length).Trim()); | ||
4192 | start += length+1; | ||
4193 | length = 0; | ||
4194 | } | ||
4195 | else | ||
4196 | { | ||
4197 | length++; | ||
4198 | } | ||
4199 | break; | ||
4200 | default: | ||
4201 | length++; | ||
4202 | break; | ||
4203 | } | ||
4204 | } | ||
4205 | |||
4206 | result.Add(src.Substring(start,length).Trim()); | ||
4207 | |||
4208 | return result; | ||
4209 | } | ||
4210 | |||
4211 | /// <summary> | ||
4212 | /// Randomizes the list, be arbitrarily reordering | ||
4213 | /// sublists of stride elements. As the stride approaches | ||
4214 | /// the size of the list, the options become very | ||
4215 | /// limited. | ||
4216 | /// </summary> | ||
4217 | /// <remarks> | ||
4218 | /// This could take a while for very large list | ||
4219 | /// sizes. | ||
4220 | /// </remarks> | ||
4221 | |||
4222 | public LSL_List llListRandomize(LSL_List src, int stride) | ||
4223 | { | ||
4224 | LSL_List result; | ||
4225 | Random rand = new Random(); | ||
4226 | |||
4227 | int chunkk; | ||
4228 | int[] chunks; | ||
4229 | |||
4230 | m_host.AddScriptLPS(1); | ||
4231 | |||
4232 | if (stride <= 0) | ||
4233 | { | ||
4234 | stride = 1; | ||
4235 | } | ||
4236 | |||
4237 | // Stride MUST be a factor of the list length | ||
4238 | // If not, then return the src list. This also | ||
4239 | // traps those cases where stride > length. | ||
4240 | |||
4241 | if (src.Length != stride && src.Length%stride == 0) | ||
4242 | { | ||
4243 | chunkk = src.Length/stride; | ||
4244 | |||
4245 | chunks = new int[chunkk]; | ||
4246 | |||
4247 | for (int i = 0; i < chunkk; i++) | ||
4248 | chunks[i] = i; | ||
4249 | |||
4250 | // Knuth shuffle the chunkk index | ||
4251 | for (int i = chunkk - 1; i >= 1; i--) | ||
4252 | { | ||
4253 | // Elect an unrandomized chunk to swap | ||
4254 | int index = rand.Next(i + 1); | ||
4255 | int tmp; | ||
4256 | |||
4257 | // and swap position with first unrandomized chunk | ||
4258 | tmp = chunks[i]; | ||
4259 | chunks[i] = chunks[index]; | ||
4260 | chunks[index] = tmp; | ||
4261 | } | ||
4262 | |||
4263 | // Construct the randomized list | ||
4264 | |||
4265 | result = new LSL_List(); | ||
4266 | |||
4267 | for (int i = 0; i < chunkk; i++) | ||
4268 | { | ||
4269 | for (int j = 0; j < stride; j++) | ||
4270 | { | ||
4271 | result.Add(src.Data[chunks[i]*stride+j]); | ||
4272 | } | ||
4273 | } | ||
4274 | } | ||
4275 | else { | ||
4276 | object[] array = new object[src.Length]; | ||
4277 | Array.Copy(src.Data, 0, array, 0, src.Length); | ||
4278 | result = new LSL_List(array); | ||
4279 | } | ||
4280 | |||
4281 | return result; | ||
4282 | } | ||
4283 | |||
4284 | /// <summary> | ||
4285 | /// Elements in the source list starting with 0 and then | ||
4286 | /// every i+stride. If the stride is negative then the scan | ||
4287 | /// is backwards producing an inverted result. | ||
4288 | /// Only those elements that are also in the specified | ||
4289 | /// range are included in the result. | ||
4290 | /// </summary> | ||
4291 | |||
4292 | public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride) | ||
4293 | { | ||
4294 | |||
4295 | LSL_List result = new LSL_List(); | ||
4296 | int[] si = new int[2]; | ||
4297 | int[] ei = new int[2]; | ||
4298 | bool twopass = false; | ||
4299 | |||
4300 | m_host.AddScriptLPS(1); | ||
4301 | |||
4302 | // First step is always to deal with negative indices | ||
4303 | |||
4304 | if (start < 0) | ||
4305 | start = src.Length+start; | ||
4306 | if (end < 0) | ||
4307 | end = src.Length+end; | ||
4308 | |||
4309 | // Out of bounds indices are OK, just trim them | ||
4310 | // accordingly | ||
4311 | |||
4312 | if (start > src.Length) | ||
4313 | start = src.Length; | ||
4314 | |||
4315 | if (end > src.Length) | ||
4316 | end = src.Length; | ||
4317 | |||
4318 | // There may be one or two ranges to be considered | ||
4319 | |||
4320 | if (start != end) | ||
4321 | { | ||
4322 | |||
4323 | if (start <= end) | ||
4324 | { | ||
4325 | si[0] = start; | ||
4326 | ei[0] = end; | ||
4327 | } | ||
4328 | else | ||
4329 | { | ||
4330 | si[1] = start; | ||
4331 | ei[1] = src.Length; | ||
4332 | si[0] = 0; | ||
4333 | ei[0] = end; | ||
4334 | twopass = true; | ||
4335 | } | ||
4336 | |||
4337 | // The scan always starts from the beginning of the | ||
4338 | // source list, but members are only selected if they | ||
4339 | // fall within the specified sub-range. The specified | ||
4340 | // range values are inclusive. | ||
4341 | // A negative stride reverses the direction of the | ||
4342 | // scan producing an inverted list as a result. | ||
4343 | |||
4344 | if (stride == 0) | ||
4345 | stride = 1; | ||
4346 | |||
4347 | if (stride > 0) | ||
4348 | { | ||
4349 | for (int i = 0; i < src.Length; i += stride) | ||
4350 | { | ||
4351 | if (i<=ei[0] && i>=si[0]) | ||
4352 | result.Add(src.Data[i]); | ||
4353 | if (twopass && i>=si[1] && i<=ei[1]) | ||
4354 | result.Add(src.Data[i]); | ||
4355 | } | ||
4356 | } | ||
4357 | else if (stride < 0) | ||
4358 | { | ||
4359 | for (int i = src.Length - 1; i >= 0; i += stride) | ||
4360 | { | ||
4361 | if (i <= ei[0] && i >= si[0]) | ||
4362 | result.Add(src.Data[i]); | ||
4363 | if (twopass && i >= si[1] && i <= ei[1]) | ||
4364 | result.Add(src.Data[i]); | ||
4365 | } | ||
4366 | } | ||
4367 | } | ||
4368 | |||
4369 | return result; | ||
4370 | } | ||
4371 | |||
4372 | public LSL_Integer llGetRegionAgentCount() | ||
4373 | { | ||
4374 | m_host.AddScriptLPS(1); | ||
4375 | return new LSL_Integer(World.GetAvatars().Count); | ||
4376 | } | ||
4377 | |||
4378 | public LSL_Vector llGetRegionCorner() | ||
4379 | { | ||
4380 | m_host.AddScriptLPS(1); | ||
4381 | return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); | ||
4382 | } | ||
4383 | |||
4384 | /// <summary> | ||
4385 | /// Insert the list identified by <src> into the | ||
4386 | /// list designated by <dest> such that the first | ||
4387 | /// new element has the index specified by <index> | ||
4388 | /// </summary> | ||
4389 | |||
4390 | public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) | ||
4391 | { | ||
4392 | |||
4393 | LSL_List pref = null; | ||
4394 | LSL_List suff = null; | ||
4395 | |||
4396 | m_host.AddScriptLPS(1); | ||
4397 | |||
4398 | if (index < 0) | ||
4399 | { | ||
4400 | index = index+dest.Length; | ||
4401 | if (index < 0) | ||
4402 | { | ||
4403 | index = 0; | ||
4404 | } | ||
4405 | } | ||
4406 | |||
4407 | if (index != 0) | ||
4408 | { | ||
4409 | pref = dest.GetSublist(0,index-1); | ||
4410 | if (index < dest.Length) | ||
4411 | { | ||
4412 | suff = dest.GetSublist(index,-1); | ||
4413 | return pref + src + suff; | ||
4414 | } | ||
4415 | else | ||
4416 | { | ||
4417 | return pref + src; | ||
4418 | } | ||
4419 | } | ||
4420 | else | ||
4421 | { | ||
4422 | if (index < dest.Length) | ||
4423 | { | ||
4424 | suff = dest.GetSublist(index,-1); | ||
4425 | return src + suff; | ||
4426 | } | ||
4427 | else | ||
4428 | { | ||
4429 | return src; | ||
4430 | } | ||
4431 | } | ||
4432 | |||
4433 | } | ||
4434 | |||
4435 | /// <summary> | ||
4436 | /// Returns the index of the first occurrence of test | ||
4437 | /// in src. | ||
4438 | /// </summary> | ||
4439 | |||
4440 | public LSL_Integer llListFindList(LSL_List src, LSL_List test) | ||
4441 | { | ||
4442 | |||
4443 | int index = -1; | ||
4444 | int length = src.Length - test.Length + 1; | ||
4445 | |||
4446 | m_host.AddScriptLPS(1); | ||
4447 | |||
4448 | // If either list is empty, do not match | ||
4449 | |||
4450 | if (src.Length != 0 && test.Length != 0) | ||
4451 | { | ||
4452 | for (int i = 0; i < length; i++) | ||
4453 | { | ||
4454 | if (src.Data[i].Equals(test.Data[0])) | ||
4455 | { | ||
4456 | int j; | ||
4457 | for (j = 1; j < test.Length; j++) | ||
4458 | if (!src.Data[i+j].Equals(test.Data[j])) | ||
4459 | break; | ||
4460 | if (j == test.Length) | ||
4461 | { | ||
4462 | index = i; | ||
4463 | break; | ||
4464 | } | ||
4465 | } | ||
4466 | } | ||
4467 | } | ||
4468 | |||
4469 | return index; | ||
4470 | |||
4471 | } | ||
4472 | |||
4473 | public LSL_String llGetObjectName() | ||
4474 | { | ||
4475 | m_host.AddScriptLPS(1); | ||
4476 | return m_host.Name!=null?m_host.Name:String.Empty; | ||
4477 | } | ||
4478 | |||
4479 | public void llSetObjectName(string name) | ||
4480 | { | ||
4481 | m_host.AddScriptLPS(1); | ||
4482 | m_host.Name = name!=null?name:String.Empty; | ||
4483 | } | ||
4484 | |||
4485 | public LSL_String llGetDate() | ||
4486 | { | ||
4487 | m_host.AddScriptLPS(1); | ||
4488 | DateTime date = DateTime.Now.ToUniversalTime(); | ||
4489 | string result = date.ToString("yyyy-MM-dd"); | ||
4490 | return result; | ||
4491 | } | ||
4492 | |||
4493 | public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir) | ||
4494 | { | ||
4495 | m_host.AddScriptLPS(1); | ||
4496 | NotImplemented("llEdgeOfWorld"); | ||
4497 | return 0; | ||
4498 | } | ||
4499 | |||
4500 | public LSL_Integer llGetAgentInfo(string id) | ||
4501 | { | ||
4502 | m_host.AddScriptLPS(1); | ||
4503 | NotImplemented("llGetAgentInfo"); | ||
4504 | return 0; | ||
4505 | } | ||
4506 | |||
4507 | public void llAdjustSoundVolume(double volume) | ||
4508 | { | ||
4509 | m_host.AddScriptLPS(1); | ||
4510 | m_host.AdjustSoundGain(volume); | ||
4511 | // ScriptSleep(100); | ||
4512 | } | ||
4513 | |||
4514 | public void llSetSoundQueueing(int queue) | ||
4515 | { | ||
4516 | m_host.AddScriptLPS(1); | ||
4517 | NotImplemented("llSetSoundQueueing"); | ||
4518 | } | ||
4519 | |||
4520 | public void llSetSoundRadius(double radius) | ||
4521 | { | ||
4522 | m_host.AddScriptLPS(1); | ||
4523 | m_host.SoundRadius = radius; | ||
4524 | } | ||
4525 | |||
4526 | public LSL_String llKey2Name(string id) | ||
4527 | { | ||
4528 | m_host.AddScriptLPS(1); | ||
4529 | UUID key = new UUID(); | ||
4530 | if (UUID.TryParse(id,out key)) | ||
4531 | { | ||
4532 | ScenePresence presence = World.GetScenePresence(key); | ||
4533 | |||
4534 | if (presence != null) | ||
4535 | { | ||
4536 | return presence.ControllingClient.Name; | ||
4537 | //return presence.Name; | ||
4538 | } | ||
4539 | |||
4540 | if (World.GetSceneObjectPart(key) != null) | ||
4541 | { | ||
4542 | return World.GetSceneObjectPart(key).Name; | ||
4543 | } | ||
4544 | } | ||
4545 | return String.Empty; | ||
4546 | } | ||
4547 | |||
4548 | |||
4549 | |||
4550 | public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) | ||
4551 | { | ||
4552 | m_host.AddScriptLPS(1); | ||
4553 | Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); | ||
4554 | pTexAnim.Flags = (Primitive.TextureAnimMode)mode; | ||
4555 | |||
4556 | //ALL_SIDES | ||
4557 | if (face == ScriptBaseClass.ALL_SIDES) | ||
4558 | face = 255; | ||
4559 | |||
4560 | pTexAnim.Face = (uint)face; | ||
4561 | pTexAnim.Length = (float)length; | ||
4562 | pTexAnim.Rate = (float)rate; | ||
4563 | pTexAnim.SizeX = (uint)sizex; | ||
4564 | pTexAnim.SizeY = (uint)sizey; | ||
4565 | pTexAnim.Start = (float)start; | ||
4566 | |||
4567 | m_host.AddTextureAnimation(pTexAnim); | ||
4568 | m_host.SendFullUpdateToAllClients(); | ||
4569 | m_host.ParentGroup.HasGroupChanged = true; | ||
4570 | } | ||
4571 | |||
4572 | public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, | ||
4573 | LSL_Vector bottom_south_west) | ||
4574 | { | ||
4575 | m_host.AddScriptLPS(1); | ||
4576 | NotImplemented("llTriggerSoundLimited"); | ||
4577 | } | ||
4578 | |||
4579 | public void llEjectFromLand(string pest) | ||
4580 | { | ||
4581 | m_host.AddScriptLPS(1); | ||
4582 | UUID agentId = new UUID(); | ||
4583 | if (UUID.TryParse(pest, out agentId)) | ||
4584 | { | ||
4585 | ScenePresence presence = World.GetScenePresence(agentId); | ||
4586 | if (presence != null) | ||
4587 | { | ||
4588 | // agent must be over the owners land | ||
4589 | if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y)) | ||
4590 | World.TeleportClientHome(agentId, presence.ControllingClient); | ||
4591 | } | ||
4592 | } | ||
4593 | // ScriptSleep(5000); | ||
4594 | } | ||
4595 | |||
4596 | public LSL_List llParseString2List(string str, LSL_List separators, LSL_List spacers) | ||
4597 | { | ||
4598 | m_host.AddScriptLPS(1); | ||
4599 | LSL_List ret = new LSL_List(); | ||
4600 | object[] delimiters = new object[separators.Length + spacers.Length]; | ||
4601 | separators.Data.CopyTo(delimiters, 0); | ||
4602 | spacers.Data.CopyTo(delimiters, separators.Length); | ||
4603 | bool dfound = false; | ||
4604 | do | ||
4605 | { | ||
4606 | dfound = false; | ||
4607 | int cindex = -1; | ||
4608 | string cdeli = ""; | ||
4609 | for (int i = 0; i < delimiters.Length; i++) | ||
4610 | { | ||
4611 | int index = str.IndexOf(delimiters[i].ToString()); | ||
4612 | bool found = index != -1; | ||
4613 | if (found && String.Empty != delimiters[i].ToString()) | ||
4614 | { | ||
4615 | if ((cindex > index) || (cindex == -1)) | ||
4616 | { | ||
4617 | cindex = index; | ||
4618 | cdeli = delimiters[i].ToString(); | ||
4619 | } | ||
4620 | dfound = dfound || found; | ||
4621 | } | ||
4622 | } | ||
4623 | if (cindex != -1) | ||
4624 | { | ||
4625 | if (cindex > 0) | ||
4626 | { | ||
4627 | ret.Add(str.Substring(0, cindex)); | ||
4628 | // Cannot use spacers.Contains() because spacers may be either type String or LSLString | ||
4629 | for (int j = 0; j < spacers.Length; j++) | ||
4630 | { | ||
4631 | if (spacers.Data[j].ToString() == cdeli) | ||
4632 | { | ||
4633 | ret.Add(cdeli); | ||
4634 | break; | ||
4635 | } | ||
4636 | } | ||
4637 | } | ||
4638 | if (cindex == 0 && spacers.Contains(cdeli)) | ||
4639 | { | ||
4640 | ret.Add(cdeli); | ||
4641 | } | ||
4642 | str = str.Substring(cindex + cdeli.Length); | ||
4643 | } | ||
4644 | } while (dfound); | ||
4645 | if (str != "") | ||
4646 | { | ||
4647 | ret.Add(str); | ||
4648 | } | ||
4649 | return ret; | ||
4650 | } | ||
4651 | |||
4652 | public LSL_Integer llOverMyLand(string id) | ||
4653 | { | ||
4654 | m_host.AddScriptLPS(1); | ||
4655 | UUID key = new UUID(); | ||
4656 | if (UUID.TryParse(id,out key)) | ||
4657 | { | ||
4658 | ScenePresence presence = World.GetScenePresence(key); | ||
4659 | if (presence != null) // object is an avatar | ||
4660 | { | ||
4661 | if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y)) | ||
4662 | return 1; | ||
4663 | } | ||
4664 | else // object is not an avatar | ||
4665 | { | ||
4666 | SceneObjectPart obj = World.GetSceneObjectPart(key); | ||
4667 | if (obj != null) | ||
4668 | if (m_host.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y)) | ||
4669 | return 1; | ||
4670 | } | ||
4671 | } | ||
4672 | return 0; | ||
4673 | } | ||
4674 | |||
4675 | public LSL_String llGetLandOwnerAt(LSL_Vector pos) | ||
4676 | { | ||
4677 | m_host.AddScriptLPS(1); | ||
4678 | return World.GetLandOwner((float)pos.x, (float)pos.y).ToString(); | ||
4679 | } | ||
4680 | |||
4681 | public LSL_Vector llGetAgentSize(string id) | ||
4682 | { | ||
4683 | m_host.AddScriptLPS(1); | ||
4684 | ScenePresence avatar = World.GetScenePresence(id); | ||
4685 | LSL_Vector agentSize; | ||
4686 | if (avatar == null) | ||
4687 | { | ||
4688 | agentSize = ScriptBaseClass.ZERO_VECTOR; | ||
4689 | } | ||
4690 | else | ||
4691 | { | ||
4692 | PhysicsVector size = avatar.PhysicsActor.Size; | ||
4693 | agentSize = new LSL_Vector(size.X, size.Y, size.Z); | ||
4694 | } | ||
4695 | return agentSize; | ||
4696 | } | ||
4697 | |||
4698 | public LSL_Integer llSameGroup(string agent) | ||
4699 | { | ||
4700 | m_host.AddScriptLPS(1); | ||
4701 | UUID agentId = new UUID(); | ||
4702 | if (!UUID.TryParse(agent, out agentId)) | ||
4703 | return new LSL_Integer(0); | ||
4704 | ScenePresence presence = World.GetScenePresence(agentId); | ||
4705 | if (presence == null) | ||
4706 | return new LSL_Integer(0); | ||
4707 | IClientAPI client = presence.ControllingClient; | ||
4708 | if (m_host.GroupID == client.ActiveGroupId) | ||
4709 | return new LSL_Integer(1); | ||
4710 | else | ||
4711 | return new LSL_Integer(0); | ||
4712 | } | ||
4713 | |||
4714 | public void llUnSit(string id) | ||
4715 | { | ||
4716 | m_host.AddScriptLPS(1); | ||
4717 | |||
4718 | UUID key = new UUID(); | ||
4719 | if (UUID.TryParse(id, out key)) | ||
4720 | { | ||
4721 | ScenePresence av = World.GetScenePresence(key); | ||
4722 | |||
4723 | if (av != null) | ||
4724 | { | ||
4725 | if (llAvatarOnSitTarget() == id) | ||
4726 | { | ||
4727 | // if the avatar is sitting on this object, then | ||
4728 | // we can unsit them. We don't want random scripts unsitting random people | ||
4729 | // Lets avoid the popcorn avatar scenario. | ||
4730 | av.StandUp(); | ||
4731 | } | ||
4732 | else | ||
4733 | { | ||
4734 | // If the object owner also owns the parcel | ||
4735 | // or | ||
4736 | // if the land is group owned and the object is group owned by the same group | ||
4737 | // or | ||
4738 | // if the object is owned by a person with estate access. | ||
4739 | |||
4740 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y); | ||
4741 | if (parcel != null) | ||
4742 | { | ||
4743 | if (m_host.ObjectOwner == parcel.landData.OwnerID || | ||
4744 | (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.GroupID | ||
4745 | && parcel.landData.IsGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID)) | ||
4746 | { | ||
4747 | av.StandUp(); | ||
4748 | } | ||
4749 | } | ||
4750 | } | ||
4751 | } | ||
4752 | |||
4753 | } | ||
4754 | |||
4755 | } | ||
4756 | |||
4757 | public LSL_Vector llGroundSlope(LSL_Vector offset) | ||
4758 | { | ||
4759 | m_host.AddScriptLPS(1); | ||
4760 | |||
4761 | Vector3 pos = m_host.AbsolutePosition + new Vector3((float)offset.x, | ||
4762 | (float)offset.y, | ||
4763 | (float)offset.z); | ||
4764 | |||
4765 | Vector3 p0 = new Vector3(pos.X, pos.Y, | ||
4766 | (float)llGround( | ||
4767 | new LSL_Vector(pos.X, pos.Y, pos.Z) | ||
4768 | )); | ||
4769 | Vector3 p1 = new Vector3(pos.X + 1, pos.Y, | ||
4770 | (float)llGround( | ||
4771 | new LSL_Vector(pos.X + 1, pos.Y, pos.Z) | ||
4772 | )); | ||
4773 | Vector3 p2 = new Vector3(pos.X, pos.Y + 1, | ||
4774 | (float)llGround( | ||
4775 | new LSL_Vector(pos.X, pos.Y + 1, pos.Z) | ||
4776 | )); | ||
4777 | |||
4778 | Vector3 v0 = new Vector3( | ||
4779 | p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); | ||
4780 | Vector3 v1 = new Vector3( | ||
4781 | p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); | ||
4782 | |||
4783 | v0.Normalize(); | ||
4784 | v1.Normalize(); | ||
4785 | |||
4786 | Vector3 tv = new Vector3(); | ||
4787 | tv.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); | ||
4788 | tv.Y = (v0.Z * v1.X) - (v0.X * v1.Z); | ||
4789 | tv.Z = (v0.X * v1.Y) - (v0.Y * v1.X); | ||
4790 | |||
4791 | return new LSL_Vector(tv.X, tv.Y, tv.Z); | ||
4792 | } | ||
4793 | |||
4794 | public LSL_Vector llGroundNormal(LSL_Vector offset) | ||
4795 | { | ||
4796 | m_host.AddScriptLPS(1); | ||
4797 | LSL_Vector x = llGroundSlope(offset); | ||
4798 | return new LSL_Vector(x.x, x.y, 1.0); | ||
4799 | } | ||
4800 | |||
4801 | public LSL_Vector llGroundContour(LSL_Vector offset) | ||
4802 | { | ||
4803 | m_host.AddScriptLPS(1); | ||
4804 | LSL_Vector x = llGroundSlope(offset); | ||
4805 | return new LSL_Vector(-x.y, x.x, 0.0); | ||
4806 | } | ||
4807 | |||
4808 | public LSL_Integer llGetAttached() | ||
4809 | { | ||
4810 | m_host.AddScriptLPS(1); | ||
4811 | return m_host.ParentGroup.RootPart.AttachmentPoint; | ||
4812 | } | ||
4813 | |||
4814 | public LSL_Integer llGetFreeMemory() | ||
4815 | { | ||
4816 | m_host.AddScriptLPS(1); | ||
4817 | // Make scripts designed for LSO happy | ||
4818 | return 16384; | ||
4819 | } | ||
4820 | |||
4821 | public LSL_String llGetRegionName() | ||
4822 | { | ||
4823 | m_host.AddScriptLPS(1); | ||
4824 | return World.RegionInfo.RegionName; | ||
4825 | } | ||
4826 | |||
4827 | public LSL_Float llGetRegionTimeDilation() | ||
4828 | { | ||
4829 | m_host.AddScriptLPS(1); | ||
4830 | return (double)World.TimeDilation; | ||
4831 | } | ||
4832 | |||
4833 | public LSL_Float llGetRegionFPS() | ||
4834 | { | ||
4835 | m_host.AddScriptLPS(1); | ||
4836 | //TODO: return actual FPS | ||
4837 | return 10.0f; | ||
4838 | } | ||
4839 | |||
4840 | /* particle system rules should be coming into this routine as doubles, that is | ||
4841 | rule[0] should be an integer from this list and rule[1] should be the arg | ||
4842 | for the same integer. wiki.secondlife.com has most of this mapping, but some | ||
4843 | came from http://www.caligari-designs.com/p4u2 | ||
4844 | |||
4845 | We iterate through the list for 'Count' elements, incrementing by two for each | ||
4846 | iteration and set the members of Primitive.ParticleSystem, one at a time. | ||
4847 | */ | ||
4848 | |||
4849 | public enum PrimitiveRule : int | ||
4850 | { | ||
4851 | PSYS_PART_FLAGS = 0, | ||
4852 | PSYS_PART_START_COLOR = 1, | ||
4853 | PSYS_PART_START_ALPHA = 2, | ||
4854 | PSYS_PART_END_COLOR = 3, | ||
4855 | PSYS_PART_END_ALPHA = 4, | ||
4856 | PSYS_PART_START_SCALE = 5, | ||
4857 | PSYS_PART_END_SCALE = 6, | ||
4858 | PSYS_PART_MAX_AGE = 7, | ||
4859 | PSYS_SRC_ACCEL = 8, | ||
4860 | PSYS_SRC_PATTERN = 9, | ||
4861 | PSYS_SRC_TEXTURE = 12, | ||
4862 | PSYS_SRC_BURST_RATE = 13, | ||
4863 | PSYS_SRC_BURST_PART_COUNT = 15, | ||
4864 | PSYS_SRC_BURST_RADIUS = 16, | ||
4865 | PSYS_SRC_BURST_SPEED_MIN = 17, | ||
4866 | PSYS_SRC_BURST_SPEED_MAX = 18, | ||
4867 | PSYS_SRC_MAX_AGE = 19, | ||
4868 | PSYS_SRC_TARGET_KEY = 20, | ||
4869 | PSYS_SRC_OMEGA = 21, | ||
4870 | PSYS_SRC_ANGLE_BEGIN = 22, | ||
4871 | PSYS_SRC_ANGLE_END = 23 | ||
4872 | } | ||
4873 | |||
4874 | internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) | ||
4875 | { | ||
4876 | Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None; | ||
4877 | |||
4878 | return returnval; | ||
4879 | } | ||
4880 | |||
4881 | private Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues() | ||
4882 | { | ||
4883 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(); | ||
4884 | |||
4885 | // TODO find out about the other defaults and add them here | ||
4886 | ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); | ||
4887 | ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); | ||
4888 | ps.PartStartScaleX = 1.0f; | ||
4889 | ps.PartStartScaleY = 1.0f; | ||
4890 | ps.PartEndScaleX = 1.0f; | ||
4891 | ps.PartEndScaleY = 1.0f; | ||
4892 | ps.BurstSpeedMin = 1.0f; | ||
4893 | ps.BurstSpeedMax = 1.0f; | ||
4894 | ps.BurstRate = 0.1f; | ||
4895 | ps.PartMaxAge = 10.0f; | ||
4896 | return ps; | ||
4897 | } | ||
4898 | |||
4899 | public void llParticleSystem(LSL_List rules) | ||
4900 | { | ||
4901 | m_host.AddScriptLPS(1); | ||
4902 | if (rules.Length == 0) | ||
4903 | { | ||
4904 | m_host.RemoveParticleSystem(); | ||
4905 | m_host.ParentGroup.HasGroupChanged = true; | ||
4906 | } | ||
4907 | else | ||
4908 | { | ||
4909 | Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues(); | ||
4910 | LSL_Vector tempv = new LSL_Vector(); | ||
4911 | |||
4912 | float tempf = 0; | ||
4913 | |||
4914 | for (int i = 0; i < rules.Length; i += 2) | ||
4915 | { | ||
4916 | switch ((int)rules.Data[i]) | ||
4917 | { | ||
4918 | case (int)ScriptBaseClass.PSYS_PART_FLAGS: | ||
4919 | prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); | ||
4920 | break; | ||
4921 | |||
4922 | case (int)ScriptBaseClass.PSYS_PART_START_COLOR: | ||
4923 | tempv = rules.GetVector3Item(i + 1); | ||
4924 | prules.PartStartColor.R = (float)tempv.x; | ||
4925 | prules.PartStartColor.G = (float)tempv.y; | ||
4926 | prules.PartStartColor.B = (float)tempv.z; | ||
4927 | break; | ||
4928 | |||
4929 | case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: | ||
4930 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4931 | prules.PartStartColor.A = tempf; | ||
4932 | break; | ||
4933 | |||
4934 | case (int)ScriptBaseClass.PSYS_PART_END_COLOR: | ||
4935 | tempv = rules.GetVector3Item(i + 1); | ||
4936 | prules.PartEndColor.R = (float)tempv.x; | ||
4937 | prules.PartEndColor.G = (float)tempv.y; | ||
4938 | prules.PartEndColor.B = (float)tempv.z; | ||
4939 | break; | ||
4940 | |||
4941 | case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: | ||
4942 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4943 | prules.PartEndColor.A = tempf; | ||
4944 | break; | ||
4945 | |||
4946 | case (int)ScriptBaseClass.PSYS_PART_START_SCALE: | ||
4947 | tempv = rules.GetVector3Item(i + 1); | ||
4948 | prules.PartStartScaleX = (float)tempv.x; | ||
4949 | prules.PartStartScaleY = (float)tempv.y; | ||
4950 | break; | ||
4951 | |||
4952 | case (int)ScriptBaseClass.PSYS_PART_END_SCALE: | ||
4953 | tempv = rules.GetVector3Item(i + 1); | ||
4954 | prules.PartEndScaleX = (float)tempv.x; | ||
4955 | prules.PartEndScaleY = (float)tempv.y; | ||
4956 | break; | ||
4957 | |||
4958 | case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: | ||
4959 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4960 | prules.PartMaxAge = tempf; | ||
4961 | break; | ||
4962 | |||
4963 | case (int)ScriptBaseClass.PSYS_SRC_ACCEL: | ||
4964 | tempv = rules.GetVector3Item(i + 1); | ||
4965 | prules.PartAcceleration.X = (float)tempv.x; | ||
4966 | prules.PartAcceleration.Y = (float)tempv.y; | ||
4967 | prules.PartAcceleration.Z = (float)tempv.z; | ||
4968 | break; | ||
4969 | |||
4970 | case (int)ScriptBaseClass.PSYS_SRC_PATTERN: | ||
4971 | int tmpi = (int)rules.GetLSLIntegerItem(i + 1); | ||
4972 | prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; | ||
4973 | break; | ||
4974 | |||
4975 | case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: | ||
4976 | prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1)); | ||
4977 | break; | ||
4978 | |||
4979 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: | ||
4980 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4981 | prules.BurstRate = (float)tempf; | ||
4982 | break; | ||
4983 | |||
4984 | case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: | ||
4985 | prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); | ||
4986 | break; | ||
4987 | |||
4988 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: | ||
4989 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4990 | prules.BurstRadius = (float)tempf; | ||
4991 | break; | ||
4992 | |||
4993 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: | ||
4994 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4995 | prules.BurstSpeedMin = (float)tempf; | ||
4996 | break; | ||
4997 | |||
4998 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: | ||
4999 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
5000 | prules.BurstSpeedMax = (float)tempf; | ||
5001 | break; | ||
5002 | |||
5003 | case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: | ||
5004 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
5005 | prules.MaxAge = (float)tempf; | ||
5006 | break; | ||
5007 | |||
5008 | case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY: | ||
5009 | UUID key = UUID.Zero; | ||
5010 | if (UUID.TryParse(rules.Data[i + 1].ToString(), out key)) | ||
5011 | { | ||
5012 | prules.Target = key; | ||
5013 | } | ||
5014 | else | ||
5015 | { | ||
5016 | prules.Target = m_host.UUID; | ||
5017 | } | ||
5018 | break; | ||
5019 | |||
5020 | case (int)ScriptBaseClass.PSYS_SRC_OMEGA: | ||
5021 | // AL: This is an assumption, since it is the only thing that would match. | ||
5022 | tempv = rules.GetVector3Item(i + 1); | ||
5023 | prules.AngularVelocity.X = (float)tempv.x; | ||
5024 | prules.AngularVelocity.Y = (float)tempv.y; | ||
5025 | prules.AngularVelocity.Z = (float)tempv.z; | ||
5026 | break; | ||
5027 | |||
5028 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: | ||
5029 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
5030 | prules.InnerAngle = (float)tempf; | ||
5031 | break; | ||
5032 | |||
5033 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: | ||
5034 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
5035 | prules.OuterAngle = (float)tempf; | ||
5036 | break; | ||
5037 | } | ||
5038 | |||
5039 | } | ||
5040 | prules.CRC = 1; | ||
5041 | |||
5042 | m_host.AddNewParticleSystem(prules); | ||
5043 | m_host.ParentGroup.HasGroupChanged = true; | ||
5044 | } | ||
5045 | m_host.SendFullUpdateToAllClients(); | ||
5046 | } | ||
5047 | |||
5048 | public void llGroundRepel(double height, int water, double tau) | ||
5049 | { | ||
5050 | m_host.AddScriptLPS(1); | ||
5051 | NotImplemented("llGroundRepel"); | ||
5052 | } | ||
5053 | |||
5054 | private UUID GetTaskInventoryItem(string name) | ||
5055 | { | ||
5056 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
5057 | { | ||
5058 | if (inv.Value.Name == name) | ||
5059 | return inv.Key; | ||
5060 | } | ||
5061 | return UUID.Zero; | ||
5062 | } | ||
5063 | |||
5064 | public void llGiveInventoryList(string destination, string category, LSL_List inventory) | ||
5065 | { | ||
5066 | m_host.AddScriptLPS(1); | ||
5067 | |||
5068 | UUID destID; | ||
5069 | if (!UUID.TryParse(destination, out destID)) | ||
5070 | return; | ||
5071 | |||
5072 | List<UUID> itemList = new List<UUID>(); | ||
5073 | |||
5074 | foreach (Object item in inventory.Data) | ||
5075 | { | ||
5076 | UUID itemID; | ||
5077 | if (UUID.TryParse(item.ToString(), out itemID)) | ||
5078 | { | ||
5079 | itemList.Add(itemID); | ||
5080 | } | ||
5081 | else | ||
5082 | { | ||
5083 | itemID = GetTaskInventoryItem(item.ToString()); | ||
5084 | if (itemID != UUID.Zero) | ||
5085 | itemList.Add(itemID); | ||
5086 | } | ||
5087 | } | ||
5088 | |||
5089 | if (itemList.Count == 0) | ||
5090 | return; | ||
5091 | |||
5092 | m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList); | ||
5093 | } | ||
5094 | |||
5095 | public void llSetVehicleType(int type) | ||
5096 | { | ||
5097 | m_host.AddScriptLPS(1); | ||
5098 | NotImplemented("llSetVehicleType"); | ||
5099 | } | ||
5100 | |||
5101 | public void llSetVehicledoubleParam(int param, double value) | ||
5102 | { | ||
5103 | m_host.AddScriptLPS(1); | ||
5104 | NotImplemented("llSetVehicledoubleParam"); | ||
5105 | } | ||
5106 | |||
5107 | public void llSetVehicleFloatParam(int param, float value) | ||
5108 | { | ||
5109 | m_host.AddScriptLPS(1); | ||
5110 | NotImplemented("llSetVehicleFloatParam"); | ||
5111 | } | ||
5112 | |||
5113 | public void llSetVehicleVectorParam(int param, LSL_Vector vec) | ||
5114 | { | ||
5115 | m_host.AddScriptLPS(1); | ||
5116 | NotImplemented("llSetVehicleVectorParam"); | ||
5117 | } | ||
5118 | |||
5119 | public void llSetVehicleRotationParam(int param, LSL_Rotation rot) | ||
5120 | { | ||
5121 | m_host.AddScriptLPS(1); | ||
5122 | NotImplemented("llSetVehicleRotationParam"); | ||
5123 | } | ||
5124 | |||
5125 | public void llSetVehicleFlags(int flags) | ||
5126 | { | ||
5127 | m_host.AddScriptLPS(1); | ||
5128 | NotImplemented("llSetVehicleFlags"); | ||
5129 | } | ||
5130 | |||
5131 | public void llRemoveVehicleFlags(int flags) | ||
5132 | { | ||
5133 | m_host.AddScriptLPS(1); | ||
5134 | NotImplemented("llRemoveVehicleFlags"); | ||
5135 | } | ||
5136 | |||
5137 | public void llSitTarget(LSL_Vector offset, LSL_Rotation rot) | ||
5138 | { | ||
5139 | m_host.AddScriptLPS(1); | ||
5140 | // LSL quaternions can normalize to 0, normal Quaternions can't. | ||
5141 | if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) | ||
5142 | rot.z = 1; // ZERO_ROTATION = 0,0,0,1 | ||
5143 | |||
5144 | m_host.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); | ||
5145 | m_host.SitTargetOrientation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); | ||
5146 | } | ||
5147 | |||
5148 | public LSL_String llAvatarOnSitTarget() | ||
5149 | { | ||
5150 | m_host.AddScriptLPS(1); | ||
5151 | return m_host.GetAvatarOnSitTarget().ToString(); | ||
5152 | } | ||
5153 | |||
5154 | public void llAddToLandPassList(string avatar, double hours) | ||
5155 | { | ||
5156 | m_host.AddScriptLPS(1); | ||
5157 | UUID key; | ||
5158 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
5159 | if (land.OwnerID == m_host.OwnerID) | ||
5160 | { | ||
5161 | ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); | ||
5162 | if (UUID.TryParse(avatar, out key)) | ||
5163 | { | ||
5164 | entry.AgentID = key; | ||
5165 | entry.Flags = ParcelManager.AccessList.Access; | ||
5166 | entry.Time = DateTime.Now.AddHours(hours); | ||
5167 | land.ParcelAccessList.Add(entry); | ||
5168 | } | ||
5169 | } | ||
5170 | // ScriptSleep(100); | ||
5171 | } | ||
5172 | |||
5173 | public void llSetTouchText(string text) | ||
5174 | { | ||
5175 | m_host.AddScriptLPS(1); | ||
5176 | m_host.TouchName = text; | ||
5177 | } | ||
5178 | |||
5179 | public void llSetSitText(string text) | ||
5180 | { | ||
5181 | m_host.AddScriptLPS(1); | ||
5182 | m_host.SitName = text; | ||
5183 | } | ||
5184 | |||
5185 | public void llSetCameraEyeOffset(LSL_Vector offset) | ||
5186 | { | ||
5187 | m_host.AddScriptLPS(1); | ||
5188 | m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); | ||
5189 | } | ||
5190 | |||
5191 | public void llSetCameraAtOffset(LSL_Vector offset) | ||
5192 | { | ||
5193 | m_host.AddScriptLPS(1); | ||
5194 | m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); | ||
5195 | } | ||
5196 | |||
5197 | public LSL_String llDumpList2String(LSL_List src, string seperator) | ||
5198 | { | ||
5199 | m_host.AddScriptLPS(1); | ||
5200 | if (src.Length == 0) | ||
5201 | { | ||
5202 | return String.Empty; | ||
5203 | } | ||
5204 | string ret = String.Empty; | ||
5205 | foreach (object o in src.Data) | ||
5206 | { | ||
5207 | ret = ret + o.ToString() + seperator; | ||
5208 | } | ||
5209 | ret = ret.Substring(0, ret.Length - seperator.Length); | ||
5210 | return ret; | ||
5211 | } | ||
5212 | |||
5213 | public LSL_Integer llScriptDanger(LSL_Vector pos) | ||
5214 | { | ||
5215 | m_host.AddScriptLPS(1); | ||
5216 | bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); | ||
5217 | if (result) | ||
5218 | { | ||
5219 | return 1; | ||
5220 | } | ||
5221 | else | ||
5222 | { | ||
5223 | return 0; | ||
5224 | } | ||
5225 | |||
5226 | } | ||
5227 | |||
5228 | public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel) | ||
5229 | { | ||
5230 | m_host.AddScriptLPS(1); | ||
5231 | UUID av = new UUID(); | ||
5232 | if (!UUID.TryParse(avatar,out av)) | ||
5233 | { | ||
5234 | LSLError("First parameter to llDialog needs to be a key"); | ||
5235 | return; | ||
5236 | } | ||
5237 | if (buttons.Length > 12) | ||
5238 | { | ||
5239 | LSLError("No more than 12 buttons can be shown"); | ||
5240 | return; | ||
5241 | } | ||
5242 | string[] buts = new string[buttons.Length]; | ||
5243 | for (int i = 0; i < buttons.Length; i++) | ||
5244 | { | ||
5245 | if (buttons.Data[i].ToString() == String.Empty) | ||
5246 | { | ||
5247 | LSLError("button label cannot be blank"); | ||
5248 | return; | ||
5249 | } | ||
5250 | if (buttons.Data[i].ToString().Length > 24) | ||
5251 | { | ||
5252 | LSLError("button label cannot be longer than 24 characters"); | ||
5253 | return; | ||
5254 | } | ||
5255 | buts[i] = buttons.Data[i].ToString(); | ||
5256 | } | ||
5257 | World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); | ||
5258 | // ScriptSleep(1000); | ||
5259 | } | ||
5260 | |||
5261 | public void llVolumeDetect(int detect) | ||
5262 | { | ||
5263 | m_host.AddScriptLPS(1); | ||
5264 | NotImplemented("llVolumeDetect"); | ||
5265 | } | ||
5266 | |||
5267 | /// <summary> | ||
5268 | /// Reset the named script. The script must be present | ||
5269 | /// in the same prim. | ||
5270 | /// </summary> | ||
5271 | |||
5272 | public void llRemoteLoadScript() | ||
5273 | { | ||
5274 | m_host.AddScriptLPS(1); | ||
5275 | Deprecated("llRemoteLoadScript"); | ||
5276 | // ScriptSleep(3000); | ||
5277 | } | ||
5278 | |||
5279 | public void llSetRemoteScriptAccessPin(int pin) | ||
5280 | { | ||
5281 | m_host.AddScriptLPS(1); | ||
5282 | m_host.ScriptAccessPin = pin; | ||
5283 | } | ||
5284 | |||
5285 | public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) | ||
5286 | { | ||
5287 | m_host.AddScriptLPS(1); | ||
5288 | bool found = false; | ||
5289 | UUID destId = UUID.Zero; | ||
5290 | UUID srcId = UUID.Zero; | ||
5291 | |||
5292 | if (!UUID.TryParse(target, out destId)) | ||
5293 | { | ||
5294 | llSay(0, "Could not parse key " + target); | ||
5295 | return; | ||
5296 | } | ||
5297 | |||
5298 | // target must be a different prim than the one containing the script | ||
5299 | if (m_host.UUID == destId) | ||
5300 | { | ||
5301 | return; | ||
5302 | } | ||
5303 | |||
5304 | // copy the first script found with this inventory name | ||
5305 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
5306 | { | ||
5307 | if (inv.Value.Name == name) | ||
5308 | { | ||
5309 | // make sure the object is a script | ||
5310 | if (10 == inv.Value.Type) | ||
5311 | { | ||
5312 | found = true; | ||
5313 | srcId = inv.Key; | ||
5314 | break; | ||
5315 | } | ||
5316 | } | ||
5317 | } | ||
5318 | |||
5319 | if (!found) | ||
5320 | { | ||
5321 | llSay(0, "Could not find script " + name); | ||
5322 | return; | ||
5323 | } | ||
5324 | |||
5325 | // the rest of the permission checks are done in RezScript, so check the pin there as well | ||
5326 | World.RezScript(srcId, m_host, destId, pin, running, start_param); | ||
5327 | // this will cause the delay even if the script pin or permissions were wrong - seems ok | ||
5328 | ScriptSleep(3000); | ||
5329 | } | ||
5330 | |||
5331 | public void llOpenRemoteDataChannel() | ||
5332 | { | ||
5333 | m_host.AddScriptLPS(1); | ||
5334 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5335 | if (xmlrpcMod.IsEnabled()) | ||
5336 | { | ||
5337 | UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, UUID.Zero); | ||
5338 | object[] resobj = new object[] { new LSL_Integer(1), new LSL_String(channelID.ToString()), new LSL_String(UUID.Zero.ToString()), new LSL_String(String.Empty), new LSL_Integer(0), new LSL_String(String.Empty) }; | ||
5339 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
5340 | "remote_data", resobj, | ||
5341 | new DetectParams[0])); | ||
5342 | } | ||
5343 | // ScriptSleep(1000); | ||
5344 | } | ||
5345 | |||
5346 | public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) | ||
5347 | { | ||
5348 | m_host.AddScriptLPS(1); | ||
5349 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5350 | // ScriptSleep(3000); | ||
5351 | return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString(); | ||
5352 | } | ||
5353 | |||
5354 | public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) | ||
5355 | { | ||
5356 | m_host.AddScriptLPS(1); | ||
5357 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5358 | xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); | ||
5359 | // ScriptSleep(3000); | ||
5360 | } | ||
5361 | |||
5362 | public void llCloseRemoteDataChannel(string channel) | ||
5363 | { | ||
5364 | m_host.AddScriptLPS(1); | ||
5365 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5366 | xmlrpcMod.CloseXMLRPCChannel(channel); | ||
5367 | // ScriptSleep(1000); | ||
5368 | } | ||
5369 | |||
5370 | public LSL_String llMD5String(string src, int nonce) | ||
5371 | { | ||
5372 | m_host.AddScriptLPS(1); | ||
5373 | return Util.Md5Hash(src + ":" + nonce.ToString()); | ||
5374 | } | ||
5375 | |||
5376 | private ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist) | ||
5377 | { | ||
5378 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); | ||
5379 | |||
5380 | if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && | ||
5381 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && | ||
5382 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE && | ||
5383 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE) | ||
5384 | { | ||
5385 | holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT; | ||
5386 | } | ||
5387 | shapeBlock.ProfileCurve = (byte)holeshape; | ||
5388 | if (cut.x < 0f) | ||
5389 | { | ||
5390 | cut.x = 0f; | ||
5391 | } | ||
5392 | if (cut.x > 1f) | ||
5393 | { | ||
5394 | cut.x = 1f; | ||
5395 | } | ||
5396 | if (cut.y < 0f) | ||
5397 | { | ||
5398 | cut.y = 0f; | ||
5399 | } | ||
5400 | if (cut.y > 1f) | ||
5401 | { | ||
5402 | cut.y = 1f; | ||
5403 | } | ||
5404 | if (cut.y - cut.x < 0.05f) | ||
5405 | { | ||
5406 | cut.x = cut.y - 0.05f; | ||
5407 | } | ||
5408 | shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); | ||
5409 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y)); | ||
5410 | if (hollow < 0f) | ||
5411 | { | ||
5412 | hollow = 0f; | ||
5413 | } | ||
5414 | if (hollow > 0.95) | ||
5415 | { | ||
5416 | hollow = 0.95f; | ||
5417 | } | ||
5418 | shapeBlock.ProfileHollow = (ushort)(50000 * hollow); | ||
5419 | if (twist.x < -1.0f) | ||
5420 | { | ||
5421 | twist.x = -1.0f; | ||
5422 | } | ||
5423 | if (twist.x > 1.0f) | ||
5424 | { | ||
5425 | twist.x = 1.0f; | ||
5426 | } | ||
5427 | if (twist.y < -1.0f) | ||
5428 | { | ||
5429 | twist.y = -1.0f; | ||
5430 | } | ||
5431 | if (twist.y > 1.0f) | ||
5432 | { | ||
5433 | twist.y = 1.0f; | ||
5434 | } | ||
5435 | shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); | ||
5436 | shapeBlock.PathTwist = (sbyte)(100 * twist.y); | ||
5437 | |||
5438 | shapeBlock.ObjectLocalID = part.LocalId; | ||
5439 | |||
5440 | // retain pathcurve | ||
5441 | shapeBlock.PathCurve = part.Shape.PathCurve; | ||
5442 | |||
5443 | return shapeBlock; | ||
5444 | } | ||
5445 | |||
5446 | private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge) | ||
5447 | { | ||
5448 | ObjectShapePacket.ObjectDataBlock shapeBlock; | ||
5449 | |||
5450 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); | ||
5451 | |||
5452 | shapeBlock.ProfileCurve += fudge; | ||
5453 | |||
5454 | if (taper_b.x < 0f) | ||
5455 | { | ||
5456 | taper_b.x = 0f; | ||
5457 | } | ||
5458 | if (taper_b.x > 2f) | ||
5459 | { | ||
5460 | taper_b.x = 2f; | ||
5461 | } | ||
5462 | if (taper_b.y < 0f) | ||
5463 | { | ||
5464 | taper_b.y = 0f; | ||
5465 | } | ||
5466 | if (taper_b.y > 2f) | ||
5467 | { | ||
5468 | taper_b.y = 2f; | ||
5469 | } | ||
5470 | shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); | ||
5471 | shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); | ||
5472 | if (topshear.x < -0.5f) | ||
5473 | { | ||
5474 | topshear.x = -0.5f; | ||
5475 | } | ||
5476 | if (topshear.x > 0.5f) | ||
5477 | { | ||
5478 | topshear.x = 0.5f; | ||
5479 | } | ||
5480 | if (topshear.y < -0.5f) | ||
5481 | { | ||
5482 | topshear.y = -0.5f; | ||
5483 | } | ||
5484 | if (topshear.y > 0.5f) | ||
5485 | { | ||
5486 | topshear.y = 0.5f; | ||
5487 | } | ||
5488 | shapeBlock.PathShearX = (byte)(100 * topshear.x); | ||
5489 | shapeBlock.PathShearY = (byte)(100 * topshear.y); | ||
5490 | |||
5491 | part.UpdateShape(shapeBlock); | ||
5492 | } | ||
5493 | |||
5494 | private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge) | ||
5495 | { | ||
5496 | ObjectShapePacket.ObjectDataBlock shapeBlock; | ||
5497 | |||
5498 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); | ||
5499 | |||
5500 | // profile/path swapped for a sphere | ||
5501 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; | ||
5502 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; | ||
5503 | |||
5504 | shapeBlock.ProfileCurve += fudge; | ||
5505 | |||
5506 | shapeBlock.PathScaleX = 100; | ||
5507 | shapeBlock.PathScaleY = 100; | ||
5508 | |||
5509 | if (dimple.x < 0f) | ||
5510 | { | ||
5511 | dimple.x = 0f; | ||
5512 | } | ||
5513 | if (dimple.x > 1f) | ||
5514 | { | ||
5515 | dimple.x = 1f; | ||
5516 | } | ||
5517 | if (dimple.y < 0f) | ||
5518 | { | ||
5519 | dimple.y = 0f; | ||
5520 | } | ||
5521 | if (dimple.y > 1f) | ||
5522 | { | ||
5523 | dimple.y = 1f; | ||
5524 | } | ||
5525 | if (dimple.y - cut.x < 0.05f) | ||
5526 | { | ||
5527 | dimple.x = cut.y - 0.05f; | ||
5528 | } | ||
5529 | shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); | ||
5530 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); | ||
5531 | |||
5532 | part.UpdateShape(shapeBlock); | ||
5533 | } | ||
5534 | |||
5535 | private 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 fudge) | ||
5536 | { | ||
5537 | ObjectShapePacket.ObjectDataBlock shapeBlock; | ||
5538 | |||
5539 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); | ||
5540 | |||
5541 | shapeBlock.ProfileCurve += fudge; | ||
5542 | |||
5543 | // profile/path swapped for a torrus, tube, ring | ||
5544 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; | ||
5545 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; | ||
5546 | |||
5547 | if (holesize.x < 0.05f) | ||
5548 | { | ||
5549 | holesize.x = 0.05f; | ||
5550 | } | ||
5551 | if (holesize.x > 1f) | ||
5552 | { | ||
5553 | holesize.x = 1f; | ||
5554 | } | ||
5555 | if (holesize.y < 0.05f) | ||
5556 | { | ||
5557 | holesize.y = 0.05f; | ||
5558 | } | ||
5559 | if (holesize.y > 0.5f) | ||
5560 | { | ||
5561 | holesize.y = 0.5f; | ||
5562 | } | ||
5563 | shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); | ||
5564 | shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); | ||
5565 | if (topshear.x < -0.5f) | ||
5566 | { | ||
5567 | topshear.x = -0.5f; | ||
5568 | } | ||
5569 | if (topshear.x > 0.5f) | ||
5570 | { | ||
5571 | topshear.x = 0.5f; | ||
5572 | } | ||
5573 | if (topshear.y < -0.5f) | ||
5574 | { | ||
5575 | topshear.y = -0.5f; | ||
5576 | } | ||
5577 | if (topshear.y > 0.5f) | ||
5578 | { | ||
5579 | topshear.y = 0.5f; | ||
5580 | } | ||
5581 | shapeBlock.PathShearX = (byte)(100 * topshear.x); | ||
5582 | shapeBlock.PathShearY = (byte)(100 * topshear.y); | ||
5583 | if (profilecut.x < 0f) | ||
5584 | { | ||
5585 | profilecut.x = 0f; | ||
5586 | } | ||
5587 | if (profilecut.x > 1f) | ||
5588 | { | ||
5589 | profilecut.x = 1f; | ||
5590 | } | ||
5591 | if (profilecut.y < 0f) | ||
5592 | { | ||
5593 | profilecut.y = 0f; | ||
5594 | } | ||
5595 | if (profilecut.y > 1f) | ||
5596 | { | ||
5597 | profilecut.y = 1f; | ||
5598 | } | ||
5599 | if (profilecut.y - cut.x < 0.05f) | ||
5600 | { | ||
5601 | profilecut.x = cut.y - 0.05f; | ||
5602 | } | ||
5603 | shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); | ||
5604 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y)); | ||
5605 | if (taper_a.x < -1f) | ||
5606 | { | ||
5607 | taper_a.x = -1f; | ||
5608 | } | ||
5609 | if (taper_a.x > 1f) | ||
5610 | { | ||
5611 | taper_a.x = 1f; | ||
5612 | } | ||
5613 | if (taper_a.y < -1f) | ||
5614 | { | ||
5615 | taper_a.y = -1f; | ||
5616 | } | ||
5617 | if (taper_a.y > 1f) | ||
5618 | { | ||
5619 | taper_a.y = 1f; | ||
5620 | } | ||
5621 | shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); | ||
5622 | shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); | ||
5623 | if (revolutions < 1f) | ||
5624 | { | ||
5625 | revolutions = 1f; | ||
5626 | } | ||
5627 | if (revolutions > 4f) | ||
5628 | { | ||
5629 | revolutions = 4f; | ||
5630 | } | ||
5631 | shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); | ||
5632 | // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 | ||
5633 | if (radiusoffset < 0f) | ||
5634 | { | ||
5635 | radiusoffset = 0f; | ||
5636 | } | ||
5637 | if (radiusoffset > 1f) | ||
5638 | { | ||
5639 | radiusoffset = 1f; | ||
5640 | } | ||
5641 | shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); | ||
5642 | if (skew < -0.95f) | ||
5643 | { | ||
5644 | skew = -0.95f; | ||
5645 | } | ||
5646 | if (skew > 0.95f) | ||
5647 | { | ||
5648 | skew = 0.95f; | ||
5649 | } | ||
5650 | shapeBlock.PathSkew = (sbyte)(100 * skew); | ||
5651 | |||
5652 | part.UpdateShape(shapeBlock); | ||
5653 | } | ||
5654 | |||
5655 | private void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type) | ||
5656 | { | ||
5657 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); | ||
5658 | UUID sculptId; | ||
5659 | |||
5660 | if (!UUID.TryParse(map, out sculptId)) | ||
5661 | { | ||
5662 | llSay(0, "Could not parse key " + map); | ||
5663 | return; | ||
5664 | } | ||
5665 | |||
5666 | shapeBlock.ObjectLocalID = part.LocalId; | ||
5667 | shapeBlock.PathScaleX = 100; | ||
5668 | shapeBlock.PathScaleY = 150; | ||
5669 | |||
5670 | if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && | ||
5671 | type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && | ||
5672 | type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && | ||
5673 | type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) | ||
5674 | { | ||
5675 | // default | ||
5676 | type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; | ||
5677 | } | ||
5678 | |||
5679 | // retain pathcurve | ||
5680 | shapeBlock.PathCurve = part.Shape.PathCurve; | ||
5681 | |||
5682 | part.Shape.SetSculptData((byte)type, sculptId); | ||
5683 | part.Shape.SculptEntry = true; | ||
5684 | part.UpdateShape(shapeBlock); | ||
5685 | } | ||
5686 | |||
5687 | public void llSetPrimitiveParams(LSL_List rules) | ||
5688 | { | ||
5689 | SetPrimParams(m_host, rules); | ||
5690 | } | ||
5691 | |||
5692 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) | ||
5693 | { | ||
5694 | m_host.AddScriptLPS(1); | ||
5695 | |||
5696 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | ||
5697 | |||
5698 | foreach (SceneObjectPart part in parts) | ||
5699 | SetPrimParams(part, rules); | ||
5700 | } | ||
5701 | |||
5702 | private void SetPrimParams(SceneObjectPart part, LSL_List rules) | ||
5703 | { | ||
5704 | int idx = 0; | ||
5705 | |||
5706 | while (idx < rules.Length) | ||
5707 | { | ||
5708 | int code = rules.GetLSLIntegerItem(idx++); | ||
5709 | |||
5710 | int remain = rules.Length - idx; | ||
5711 | |||
5712 | int face; | ||
5713 | LSL_Vector v; | ||
5714 | |||
5715 | switch (code) | ||
5716 | { | ||
5717 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
5718 | if (remain < 1) | ||
5719 | return; | ||
5720 | |||
5721 | v=rules.GetVector3Item(idx++); | ||
5722 | SetPos(part, v); | ||
5723 | |||
5724 | break; | ||
5725 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
5726 | if (remain < 1) | ||
5727 | return; | ||
5728 | |||
5729 | v=rules.GetVector3Item(idx++); | ||
5730 | SetScale(part, v); | ||
5731 | |||
5732 | break; | ||
5733 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
5734 | if (remain < 1) | ||
5735 | return; | ||
5736 | |||
5737 | LSL_Rotation q = rules.GetQuaternionItem(idx++); | ||
5738 | SetRot(part, q); | ||
5739 | |||
5740 | break; | ||
5741 | |||
5742 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
5743 | if (remain < 3) | ||
5744 | return; | ||
5745 | |||
5746 | code = (int)rules.GetLSLIntegerItem(idx++); | ||
5747 | |||
5748 | remain = rules.Length - idx; | ||
5749 | float hollow; | ||
5750 | LSL_Vector twist; | ||
5751 | LSL_Vector taper_b; | ||
5752 | LSL_Vector topshear; | ||
5753 | float revolutions; | ||
5754 | float radiusoffset; | ||
5755 | float skew; | ||
5756 | LSL_Vector holesize; | ||
5757 | LSL_Vector profilecut; | ||
5758 | |||
5759 | switch (code) | ||
5760 | { | ||
5761 | case (int)ScriptBaseClass.PRIM_TYPE_BOX: | ||
5762 | if (remain < 6) | ||
5763 | return; | ||
5764 | |||
5765 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
5766 | v = rules.GetVector3Item(idx++); // cut | ||
5767 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5768 | twist = rules.GetVector3Item(idx++); | ||
5769 | taper_b = rules.GetVector3Item(idx++); | ||
5770 | topshear = rules.GetVector3Item(idx++); | ||
5771 | |||
5772 | part.Shape.PathCurve = (byte)Extrusion.Straight; | ||
5773 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 1); | ||
5774 | break; | ||
5775 | |||
5776 | case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
5777 | if (remain < 6) | ||
5778 | return; | ||
5779 | |||
5780 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5781 | v = rules.GetVector3Item(idx++); // cut | ||
5782 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5783 | twist = rules.GetVector3Item(idx++); | ||
5784 | taper_b = rules.GetVector3Item(idx++); | ||
5785 | topshear = rules.GetVector3Item(idx++); | ||
5786 | part.Shape.ProfileShape = ProfileShape.Circle; | ||
5787 | part.Shape.PathCurve = (byte)Extrusion.Straight; | ||
5788 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 0); | ||
5789 | break; | ||
5790 | |||
5791 | case (int)ScriptBaseClass.PRIM_TYPE_PRISM: | ||
5792 | if (remain < 6) | ||
5793 | return; | ||
5794 | |||
5795 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5796 | v = rules.GetVector3Item(idx++); //cut | ||
5797 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5798 | twist = rules.GetVector3Item(idx++); | ||
5799 | taper_b = rules.GetVector3Item(idx++); | ||
5800 | topshear = rules.GetVector3Item(idx++); | ||
5801 | part.Shape.PathCurve = (byte)Extrusion.Straight; | ||
5802 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 3); | ||
5803 | break; | ||
5804 | |||
5805 | case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
5806 | if (remain < 5) | ||
5807 | return; | ||
5808 | |||
5809 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5810 | v = rules.GetVector3Item(idx++); // cut | ||
5811 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5812 | twist = rules.GetVector3Item(idx++); | ||
5813 | taper_b = rules.GetVector3Item(idx++); // dimple | ||
5814 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5815 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 5); | ||
5816 | break; | ||
5817 | |||
5818 | case (int)ScriptBaseClass.PRIM_TYPE_TORUS: | ||
5819 | if (remain < 11) | ||
5820 | return; | ||
5821 | |||
5822 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5823 | v = rules.GetVector3Item(idx++); //cut | ||
5824 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5825 | twist = rules.GetVector3Item(idx++); | ||
5826 | holesize = rules.GetVector3Item(idx++); | ||
5827 | topshear = rules.GetVector3Item(idx++); | ||
5828 | profilecut = rules.GetVector3Item(idx++); | ||
5829 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
5830 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
5831 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
5832 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
5833 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5834 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 0); | ||
5835 | break; | ||
5836 | |||
5837 | case (int)ScriptBaseClass.PRIM_TYPE_TUBE: | ||
5838 | if (remain < 11) | ||
5839 | return; | ||
5840 | |||
5841 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5842 | v = rules.GetVector3Item(idx++); //cut | ||
5843 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5844 | twist = rules.GetVector3Item(idx++); | ||
5845 | holesize = rules.GetVector3Item(idx++); | ||
5846 | topshear = rules.GetVector3Item(idx++); | ||
5847 | profilecut = rules.GetVector3Item(idx++); | ||
5848 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
5849 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
5850 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
5851 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
5852 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5853 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 1); | ||
5854 | break; | ||
5855 | |||
5856 | case (int)ScriptBaseClass.PRIM_TYPE_RING: | ||
5857 | if (remain < 11) | ||
5858 | return; | ||
5859 | |||
5860 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5861 | v = rules.GetVector3Item(idx++); //cut | ||
5862 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5863 | twist = rules.GetVector3Item(idx++); | ||
5864 | holesize = rules.GetVector3Item(idx++); | ||
5865 | topshear = rules.GetVector3Item(idx++); | ||
5866 | profilecut = rules.GetVector3Item(idx++); | ||
5867 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
5868 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
5869 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
5870 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
5871 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5872 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 3); | ||
5873 | break; | ||
5874 | |||
5875 | case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
5876 | if (remain < 2) | ||
5877 | return; | ||
5878 | |||
5879 | string map = rules.Data[idx++].ToString(); | ||
5880 | face = (int)rules.GetLSLIntegerItem(idx++); // type | ||
5881 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5882 | SetPrimitiveShapeParams(part, map, face); | ||
5883 | break; | ||
5884 | } | ||
5885 | |||
5886 | break; | ||
5887 | |||
5888 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
5889 | if (remain < 5) | ||
5890 | return; | ||
5891 | |||
5892 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
5893 | string tex=rules.Data[idx++].ToString(); | ||
5894 | LSL_Vector repeats=rules.GetVector3Item(idx++); | ||
5895 | LSL_Vector offsets=rules.GetVector3Item(idx++); | ||
5896 | double rotation=(double)rules.GetLSLFloatItem(idx++); | ||
5897 | |||
5898 | SetTexture(part, tex, face); | ||
5899 | ScaleTexture(part, repeats.x, repeats.y, face); | ||
5900 | OffsetTexture(part, offsets.x, offsets.y, face); | ||
5901 | RotateTexture(part, rotation, face); | ||
5902 | |||
5903 | break; | ||
5904 | |||
5905 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
5906 | if (remain < 3) | ||
5907 | return; | ||
5908 | |||
5909 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
5910 | LSL_Vector color=rules.GetVector3Item(idx++); | ||
5911 | double alpha=(double)rules.GetLSLFloatItem(idx++); | ||
5912 | |||
5913 | SetColor(part, color, face); | ||
5914 | SetAlpha(part, alpha, face); | ||
5915 | |||
5916 | break; | ||
5917 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
5918 | if (remain < 7) | ||
5919 | return; | ||
5920 | |||
5921 | bool flexi = rules.GetLSLIntegerItem(idx++); | ||
5922 | int softness = rules.GetLSLIntegerItem(idx++); | ||
5923 | float gravity = (float)rules.GetLSLFloatItem(idx++); | ||
5924 | float friction = (float)rules.GetLSLFloatItem(idx++); | ||
5925 | float wind = (float)rules.GetLSLFloatItem(idx++); | ||
5926 | float tension = (float)rules.GetLSLFloatItem(idx++); | ||
5927 | LSL_Vector force = rules.GetVector3Item(idx++); | ||
5928 | |||
5929 | SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); | ||
5930 | |||
5931 | break; | ||
5932 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
5933 | if (remain < 5) | ||
5934 | return; | ||
5935 | bool light = rules.GetLSLIntegerItem(idx++); | ||
5936 | LSL_Vector lightcolor = rules.GetVector3Item(idx++); | ||
5937 | float intensity = (float)rules.GetLSLFloatItem(idx++); | ||
5938 | float radius = (float)rules.GetLSLFloatItem(idx++); | ||
5939 | float falloff = (float)rules.GetLSLFloatItem(idx++); | ||
5940 | |||
5941 | SetPointLight(part, light, lightcolor, intensity, radius, falloff); | ||
5942 | |||
5943 | break; | ||
5944 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
5945 | if (remain < 2) | ||
5946 | return; | ||
5947 | face = rules.GetLSLIntegerItem(idx++); | ||
5948 | float glow = (float)rules.GetLSLFloatItem(idx++); | ||
5949 | |||
5950 | SetGlow(part, face, glow); | ||
5951 | |||
5952 | break; | ||
5953 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
5954 | if (remain < 3) | ||
5955 | return; | ||
5956 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
5957 | int shiny = (int)rules.GetLSLIntegerItem(idx++); | ||
5958 | Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++)); | ||
5959 | |||
5960 | SetShiny(part, face, shiny, bump); | ||
5961 | |||
5962 | break; | ||
5963 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
5964 | if (remain < 2) | ||
5965 | return; | ||
5966 | face = rules.GetLSLIntegerItem(idx++); | ||
5967 | bool st = rules.GetLSLIntegerItem(idx++); | ||
5968 | SetFullBright(part, face , st); | ||
5969 | break; | ||
5970 | case (int)ScriptBaseClass.PRIM_MATERIAL: | ||
5971 | if (remain < 1) | ||
5972 | return; | ||
5973 | if (part != null) | ||
5974 | { | ||
5975 | /* Unhandled at this time - sends "Unhandled" message | ||
5976 | will enable when available | ||
5977 | byte material = Convert.ToByte((int)rules.GetLSLIntegerItem(idx++)); | ||
5978 | part.Material = material; | ||
5979 | */ | ||
5980 | return; | ||
5981 | } | ||
5982 | break; | ||
5983 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
5984 | if (remain < 1) | ||
5985 | return; | ||
5986 | |||
5987 | string ph = rules.Data[idx++].ToString(); | ||
5988 | bool phantom; | ||
5989 | |||
5990 | if (ph.Equals("1")) | ||
5991 | phantom = true; | ||
5992 | else | ||
5993 | phantom = false; | ||
5994 | |||
5995 | part.ScriptSetPhantomStatus(phantom); | ||
5996 | part.ScheduleFullUpdate(); | ||
5997 | break; | ||
5998 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
5999 | if (remain < 1) | ||
6000 | return; | ||
6001 | string phy = rules.Data[idx++].ToString(); | ||
6002 | bool physics; | ||
6003 | |||
6004 | if (phy.Equals("1")) | ||
6005 | physics = true; | ||
6006 | else | ||
6007 | physics = false; | ||
6008 | |||
6009 | m_host.ScriptSetPhysicsStatus(physics); | ||
6010 | part.ScheduleFullUpdate(); | ||
6011 | break; | ||
6012 | } | ||
6013 | } | ||
6014 | } | ||
6015 | |||
6016 | public LSL_String llStringToBase64(string str) | ||
6017 | { | ||
6018 | m_host.AddScriptLPS(1); | ||
6019 | try | ||
6020 | { | ||
6021 | byte[] encData_byte = new byte[str.Length]; | ||
6022 | encData_byte = Encoding.UTF8.GetBytes(str); | ||
6023 | string encodedData = Convert.ToBase64String(encData_byte); | ||
6024 | return encodedData; | ||
6025 | } | ||
6026 | catch (Exception e) | ||
6027 | { | ||
6028 | throw new Exception("Error in base64Encode" + e.Message); | ||
6029 | } | ||
6030 | } | ||
6031 | |||
6032 | public LSL_String llBase64ToString(string str) | ||
6033 | { | ||
6034 | m_host.AddScriptLPS(1); | ||
6035 | UTF8Encoding encoder = new UTF8Encoding(); | ||
6036 | Decoder utf8Decode = encoder.GetDecoder(); | ||
6037 | try | ||
6038 | { | ||
6039 | byte[] todecode_byte = Convert.FromBase64String(str); | ||
6040 | int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); | ||
6041 | char[] decoded_char = new char[charCount]; | ||
6042 | utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); | ||
6043 | string result = new String(decoded_char); | ||
6044 | return result; | ||
6045 | } | ||
6046 | catch (Exception e) | ||
6047 | { | ||
6048 | throw new Exception("Error in base64Decode" + e.Message); | ||
6049 | } | ||
6050 | } | ||
6051 | |||
6052 | public void llXorBase64Strings() | ||
6053 | { | ||
6054 | m_host.AddScriptLPS(1); | ||
6055 | Deprecated("llXorBase64Strings"); | ||
6056 | // ScriptSleep(300); | ||
6057 | } | ||
6058 | |||
6059 | public void llRemoteDataSetRegion() | ||
6060 | { | ||
6061 | m_host.AddScriptLPS(1); | ||
6062 | NotImplemented("llRemoteDataSetRegion"); | ||
6063 | } | ||
6064 | |||
6065 | public LSL_Float llLog10(double val) | ||
6066 | { | ||
6067 | m_host.AddScriptLPS(1); | ||
6068 | return (double)Math.Log10(val); | ||
6069 | } | ||
6070 | |||
6071 | public LSL_Float llLog(double val) | ||
6072 | { | ||
6073 | m_host.AddScriptLPS(1); | ||
6074 | return (double)Math.Log(val); | ||
6075 | } | ||
6076 | |||
6077 | public LSL_List llGetAnimationList( string id ) | ||
6078 | { | ||
6079 | m_host.AddScriptLPS(1); | ||
6080 | |||
6081 | LSL_List l = new LSL_List(); | ||
6082 | ScenePresence av = World.GetScenePresence(id); | ||
6083 | if (av == null) | ||
6084 | return l; | ||
6085 | UUID[] anims; | ||
6086 | anims = av.GetAnimationArray(); | ||
6087 | foreach (UUID foo in anims) | ||
6088 | l.Add(foo.ToString()); | ||
6089 | return l; | ||
6090 | } | ||
6091 | |||
6092 | public void llSetParcelMusicURL(string url) | ||
6093 | { | ||
6094 | m_host.AddScriptLPS(1); | ||
6095 | UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
6096 | if (landowner == UUID.Zero) | ||
6097 | { | ||
6098 | return; | ||
6099 | } | ||
6100 | if (landowner != m_host.ObjectOwner) | ||
6101 | { | ||
6102 | return; | ||
6103 | } | ||
6104 | World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); | ||
6105 | // ScriptSleep(2000); | ||
6106 | } | ||
6107 | |||
6108 | public LSL_Vector llGetRootPosition() | ||
6109 | { | ||
6110 | m_host.AddScriptLPS(1); | ||
6111 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z); | ||
6112 | } | ||
6113 | |||
6114 | public LSL_Rotation llGetRootRotation() | ||
6115 | { | ||
6116 | m_host.AddScriptLPS(1); | ||
6117 | return new LSL_Rotation(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W); | ||
6118 | } | ||
6119 | |||
6120 | public LSL_String llGetObjectDesc() | ||
6121 | { | ||
6122 | return m_host.Description!=null?m_host.Description:String.Empty; | ||
6123 | } | ||
6124 | |||
6125 | public void llSetObjectDesc(string desc) | ||
6126 | { | ||
6127 | m_host.AddScriptLPS(1); | ||
6128 | m_host.Description = desc!=null?desc:String.Empty; | ||
6129 | } | ||
6130 | |||
6131 | public LSL_String llGetCreator() | ||
6132 | { | ||
6133 | m_host.AddScriptLPS(1); | ||
6134 | return m_host.ObjectCreator.ToString(); | ||
6135 | } | ||
6136 | |||
6137 | public LSL_String llGetTimestamp() | ||
6138 | { | ||
6139 | m_host.AddScriptLPS(1); | ||
6140 | return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); | ||
6141 | } | ||
6142 | |||
6143 | public void llSetLinkAlpha(int linknumber, double alpha, int face) | ||
6144 | { | ||
6145 | m_host.AddScriptLPS(1); | ||
6146 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); | ||
6147 | if (linknumber > -1) | ||
6148 | { | ||
6149 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
6150 | Color4 texcolor; | ||
6151 | if (face >= 0 && face < GetNumberOfSides(m_host)) | ||
6152 | { | ||
6153 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
6154 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6155 | tex.FaceTextures[face].RGBA = texcolor; | ||
6156 | part.UpdateTexture(tex); | ||
6157 | return; | ||
6158 | } | ||
6159 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
6160 | { | ||
6161 | texcolor = tex.DefaultTexture.RGBA; | ||
6162 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6163 | tex.DefaultTexture.RGBA = texcolor; | ||
6164 | for (uint i = 0; i < GetNumberOfSides(m_host); i++) | ||
6165 | { | ||
6166 | if (tex.FaceTextures[i] != null) | ||
6167 | { | ||
6168 | texcolor = tex.FaceTextures[i].RGBA; | ||
6169 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6170 | tex.FaceTextures[i].RGBA = texcolor; | ||
6171 | } | ||
6172 | } | ||
6173 | texcolor = tex.DefaultTexture.RGBA; | ||
6174 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6175 | tex.DefaultTexture.RGBA = texcolor; | ||
6176 | part.UpdateTexture(tex); | ||
6177 | return; | ||
6178 | } | ||
6179 | return; | ||
6180 | } | ||
6181 | else if (linknumber == -1) | ||
6182 | { | ||
6183 | int num = m_host.ParentGroup.PrimCount; | ||
6184 | for (int w = 0; w < num; w++) | ||
6185 | { | ||
6186 | linknumber = w; | ||
6187 | part = m_host.ParentGroup.GetLinkNumPart(linknumber); | ||
6188 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
6189 | Color4 texcolor; | ||
6190 | if (face > -1) | ||
6191 | { | ||
6192 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
6193 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6194 | tex.FaceTextures[face].RGBA = texcolor; | ||
6195 | part.UpdateTexture(tex); | ||
6196 | } | ||
6197 | else if (face == -1) | ||
6198 | { | ||
6199 | texcolor = tex.DefaultTexture.RGBA; | ||
6200 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6201 | tex.DefaultTexture.RGBA = texcolor; | ||
6202 | for (uint i = 0; i < 32; i++) | ||
6203 | { | ||
6204 | if (tex.FaceTextures[i] != null) | ||
6205 | { | ||
6206 | texcolor = tex.FaceTextures[i].RGBA; | ||
6207 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6208 | tex.FaceTextures[i].RGBA = texcolor; | ||
6209 | } | ||
6210 | } | ||
6211 | texcolor = tex.DefaultTexture.RGBA; | ||
6212 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6213 | tex.DefaultTexture.RGBA = texcolor; | ||
6214 | part.UpdateTexture(tex); | ||
6215 | } | ||
6216 | } | ||
6217 | return; | ||
6218 | } | ||
6219 | } | ||
6220 | |||
6221 | public LSL_Integer llGetNumberOfPrims() | ||
6222 | { | ||
6223 | m_host.AddScriptLPS(1); | ||
6224 | return m_host.ParentGroup.PrimCount; | ||
6225 | } | ||
6226 | |||
6227 | public LSL_List llGetBoundingBox(string obj) | ||
6228 | { | ||
6229 | m_host.AddScriptLPS(1); | ||
6230 | NotImplemented("llGetBoundingBox"); | ||
6231 | return new LSL_List(); | ||
6232 | } | ||
6233 | |||
6234 | public LSL_Vector llGetGeometricCenter() | ||
6235 | { | ||
6236 | return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); | ||
6237 | } | ||
6238 | |||
6239 | public LSL_List llGetPrimitiveParams(LSL_List rules) | ||
6240 | { | ||
6241 | m_host.AddScriptLPS(1); | ||
6242 | |||
6243 | LSL_List res = new LSL_List(); | ||
6244 | int idx=0; | ||
6245 | while (idx < rules.Length) | ||
6246 | { | ||
6247 | int code=(int)rules.GetLSLIntegerItem(idx++); | ||
6248 | int remain=rules.Length-idx; | ||
6249 | |||
6250 | switch (code) | ||
6251 | { | ||
6252 | case (int)ScriptBaseClass.PRIM_MATERIAL: | ||
6253 | res.Add(new LSL_Integer(m_host.Material)); | ||
6254 | break; | ||
6255 | |||
6256 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
6257 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) | ||
6258 | res.Add(new LSL_Integer(1)); | ||
6259 | else | ||
6260 | res.Add(new LSL_Integer(0)); | ||
6261 | break; | ||
6262 | |||
6263 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
6264 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) | ||
6265 | res.Add(new LSL_Integer(1)); | ||
6266 | else | ||
6267 | res.Add(new LSL_Integer(0)); | ||
6268 | break; | ||
6269 | |||
6270 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
6271 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) | ||
6272 | res.Add(new LSL_Integer(1)); | ||
6273 | else | ||
6274 | res.Add(new LSL_Integer(0)); | ||
6275 | break; | ||
6276 | |||
6277 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
6278 | res.Add(new LSL_Vector(m_host.AbsolutePosition.X, | ||
6279 | m_host.AbsolutePosition.Y, | ||
6280 | m_host.AbsolutePosition.Z)); | ||
6281 | break; | ||
6282 | |||
6283 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
6284 | res.Add(new LSL_Vector(m_host.Scale.X, | ||
6285 | m_host.Scale.Y, | ||
6286 | m_host.Scale.Z)); | ||
6287 | break; | ||
6288 | |||
6289 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
6290 | res.Add(new LSL_Rotation(m_host.RotationOffset.X, | ||
6291 | m_host.RotationOffset.Y, | ||
6292 | m_host.RotationOffset.Z, | ||
6293 | m_host.RotationOffset.W)); | ||
6294 | break; | ||
6295 | |||
6296 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
6297 | // implementing box | ||
6298 | PrimitiveBaseShape Shape = m_host.Shape; | ||
6299 | int primType = getScriptPrimType(m_host.Shape); | ||
6300 | res.Add(new LSL_Integer(primType)); | ||
6301 | switch (primType) | ||
6302 | { | ||
6303 | case ScriptBaseClass.PRIM_TYPE_BOX: | ||
6304 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
6305 | case ScriptBaseClass.PRIM_TYPE_PRISM: | ||
6306 | res.Add(new LSL_Integer(Shape.ProfileCurve)); | ||
6307 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | ||
6308 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | ||
6309 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | ||
6310 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); | ||
6311 | res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0)); | ||
6312 | break; | ||
6313 | |||
6314 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
6315 | res.Add(new LSL_Integer(Shape.ProfileCurve)); | ||
6316 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); | ||
6317 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | ||
6318 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | ||
6319 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | ||
6320 | break; | ||
6321 | |||
6322 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
6323 | res.Add(Shape.SculptTexture.ToString()); | ||
6324 | res.Add(new LSL_Integer(Shape.SculptType)); | ||
6325 | break; | ||
6326 | |||
6327 | case ScriptBaseClass.PRIM_TYPE_RING: | ||
6328 | case ScriptBaseClass.PRIM_TYPE_TUBE: | ||
6329 | case ScriptBaseClass.PRIM_TYPE_TORUS: | ||
6330 | // holeshape | ||
6331 | res.Add(new LSL_Integer(Shape.ProfileCurve)); | ||
6332 | |||
6333 | // cut | ||
6334 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); | ||
6335 | |||
6336 | // hollow | ||
6337 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | ||
6338 | |||
6339 | // twist | ||
6340 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | ||
6341 | |||
6342 | // vector holesize | ||
6343 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); | ||
6344 | |||
6345 | // vector topshear | ||
6346 | res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0)); | ||
6347 | |||
6348 | // vector profilecut | ||
6349 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | ||
6350 | |||
6351 | |||
6352 | // vector tapera | ||
6353 | res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); | ||
6354 | |||
6355 | // float revolutions, | ||
6356 | res.Add(new LSL_Float(Shape.PathRevolutions / 50.0)); // needs fixing :( | ||
6357 | |||
6358 | // float radiusoffset, | ||
6359 | res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); | ||
6360 | |||
6361 | // float skew | ||
6362 | res.Add(new LSL_Float(Shape.PathSkew / 100.0)); | ||
6363 | break; | ||
6364 | |||
6365 | } | ||
6366 | break; | ||
6367 | |||
6368 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
6369 | if (remain < 1) | ||
6370 | return res; | ||
6371 | |||
6372 | int face = (int)rules.GetLSLIntegerItem(idx++); | ||
6373 | Primitive.TextureEntry tex = m_host.Shape.Textures; | ||
6374 | if (face == ScriptBaseClass.ALL_SIDES) | ||
6375 | { | ||
6376 | for (face = 0 ; face < GetNumberOfSides(m_host) ; face++) | ||
6377 | { | ||
6378 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | ||
6379 | |||
6380 | res.Add(new LSL_String(texface.TextureID.ToString())); | ||
6381 | res.Add(new LSL_Vector(texface.RepeatU, | ||
6382 | texface.RepeatV, | ||
6383 | 0)); | ||
6384 | res.Add(new LSL_Vector(texface.OffsetU, | ||
6385 | texface.OffsetV, | ||
6386 | 0)); | ||
6387 | res.Add(new LSL_Float(texface.Rotation)); | ||
6388 | } | ||
6389 | } | ||
6390 | else | ||
6391 | { | ||
6392 | if (face >= 0 && face < GetNumberOfSides(m_host)) | ||
6393 | { | ||
6394 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | ||
6395 | |||
6396 | res.Add(new LSL_String(texface.TextureID.ToString())); | ||
6397 | res.Add(new LSL_Vector(texface.RepeatU, | ||
6398 | texface.RepeatV, | ||
6399 | 0)); | ||
6400 | res.Add(new LSL_Vector(texface.OffsetU, | ||
6401 | texface.OffsetV, | ||
6402 | 0)); | ||
6403 | res.Add(new LSL_Float(texface.Rotation)); | ||
6404 | } | ||
6405 | } | ||
6406 | break; | ||
6407 | |||
6408 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
6409 | if (remain < 1) | ||
6410 | return res; | ||
6411 | |||
6412 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6413 | |||
6414 | tex = m_host.Shape.Textures; | ||
6415 | Color4 texcolor; | ||
6416 | if (face == ScriptBaseClass.ALL_SIDES) | ||
6417 | { | ||
6418 | for (face = 0 ; face < GetNumberOfSides(m_host) ; face++) | ||
6419 | { | ||
6420 | texcolor = tex.GetFace((uint)face).RGBA; | ||
6421 | res.Add(new LSL_Vector(texcolor.R, | ||
6422 | texcolor.G, | ||
6423 | texcolor.B)); | ||
6424 | res.Add(new LSL_Float(texcolor.A)); | ||
6425 | } | ||
6426 | } | ||
6427 | else | ||
6428 | { | ||
6429 | texcolor = tex.GetFace((uint)face).RGBA; | ||
6430 | res.Add(new LSL_Vector(texcolor.R, | ||
6431 | texcolor.G, | ||
6432 | texcolor.B)); | ||
6433 | res.Add(new LSL_Float(texcolor.A)); | ||
6434 | } | ||
6435 | break; | ||
6436 | |||
6437 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
6438 | // TODO-------------- | ||
6439 | if (remain < 1) | ||
6440 | return res; | ||
6441 | |||
6442 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6443 | |||
6444 | res.Add(new LSL_Integer(0)); | ||
6445 | res.Add(new LSL_Integer(0)); | ||
6446 | break; | ||
6447 | |||
6448 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
6449 | // TODO-------------- | ||
6450 | if (remain < 1) | ||
6451 | return res; | ||
6452 | |||
6453 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6454 | |||
6455 | res.Add(new LSL_Integer(0)); | ||
6456 | break; | ||
6457 | |||
6458 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
6459 | PrimitiveBaseShape shape = m_host.Shape; | ||
6460 | |||
6461 | if (shape.FlexiEntry) | ||
6462 | res.Add(new LSL_Integer(1)); // active | ||
6463 | else | ||
6464 | res.Add(new LSL_Integer(0)); | ||
6465 | res.Add(new LSL_Integer(shape.FlexiSoftness));// softness | ||
6466 | res.Add(new LSL_Float(shape.FlexiGravity)); // gravity | ||
6467 | res.Add(new LSL_Float(shape.FlexiDrag)); // friction | ||
6468 | res.Add(new LSL_Float(shape.FlexiWind)); // wind | ||
6469 | res.Add(new LSL_Float(shape.FlexiTension)); // tension | ||
6470 | res.Add(new LSL_Vector(shape.FlexiForceX, // force | ||
6471 | shape.FlexiForceY, | ||
6472 | shape.FlexiForceZ)); | ||
6473 | break; | ||
6474 | |||
6475 | case (int)ScriptBaseClass.PRIM_TEXGEN: | ||
6476 | // TODO-------------- | ||
6477 | // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) | ||
6478 | if (remain < 1) | ||
6479 | return res; | ||
6480 | |||
6481 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6482 | |||
6483 | res.Add(new LSL_Integer(0)); | ||
6484 | break; | ||
6485 | |||
6486 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
6487 | shape = m_host.Shape; | ||
6488 | |||
6489 | if (shape.LightEntry) | ||
6490 | res.Add(new LSL_Integer(1)); // active | ||
6491 | else | ||
6492 | res.Add(new LSL_Integer(0)); | ||
6493 | res.Add(new LSL_Vector(shape.LightColorR, // color | ||
6494 | shape.LightColorG, | ||
6495 | shape.LightColorB)); | ||
6496 | res.Add(new LSL_Float(shape.LightIntensity)); // intensity | ||
6497 | res.Add(new LSL_Float(shape.LightRadius)); // radius | ||
6498 | res.Add(new LSL_Float(shape.LightFalloff)); // falloff | ||
6499 | break; | ||
6500 | |||
6501 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
6502 | // TODO-------------- | ||
6503 | if (remain < 1) | ||
6504 | return res; | ||
6505 | |||
6506 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6507 | |||
6508 | res.Add(new LSL_Float(0)); | ||
6509 | break; | ||
6510 | } | ||
6511 | } | ||
6512 | return res; | ||
6513 | } | ||
6514 | |||
6515 | // <remarks> | ||
6516 | // <para> | ||
6517 | // The .NET definition of base 64 is: | ||
6518 | // <list> | ||
6519 | // <item> | ||
6520 | // Significant: A-Z a-z 0-9 + - | ||
6521 | // </item> | ||
6522 | // <item> | ||
6523 | // Whitespace: \t \n \r ' ' | ||
6524 | // </item> | ||
6525 | // <item> | ||
6526 | // Valueless: = | ||
6527 | // </item> | ||
6528 | // <item> | ||
6529 | // End-of-string: \0 or '==' | ||
6530 | // </item> | ||
6531 | // </list> | ||
6532 | // </para> | ||
6533 | // <para> | ||
6534 | // Each point in a base-64 string represents | ||
6535 | // a 6 bit value. A 32-bit integer can be | ||
6536 | // represented using 6 characters (with some | ||
6537 | // redundancy). | ||
6538 | // </para> | ||
6539 | // <para> | ||
6540 | // LSL requires a base64 string to be 8 | ||
6541 | // characters in length. LSL also uses '/' | ||
6542 | // rather than '-' (MIME compliant). | ||
6543 | // </para> | ||
6544 | // <para> | ||
6545 | // RFC 1341 used as a reference (as specified | ||
6546 | // by the SecondLife Wiki). | ||
6547 | // </para> | ||
6548 | // <para> | ||
6549 | // SL do not record any kind of exception for | ||
6550 | // these functions, so the string to integer | ||
6551 | // conversion returns '0' if an invalid | ||
6552 | // character is encountered during conversion. | ||
6553 | // </para> | ||
6554 | // <para> | ||
6555 | // References | ||
6556 | // <list> | ||
6557 | // <item> | ||
6558 | // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64 | ||
6559 | // </item> | ||
6560 | // <item> | ||
6561 | // </item> | ||
6562 | // </list> | ||
6563 | // </para> | ||
6564 | // </remarks> | ||
6565 | |||
6566 | // <summary> | ||
6567 | // Table for converting 6-bit integers into | ||
6568 | // base-64 characters | ||
6569 | // </summary> | ||
6570 | |||
6571 | private static readonly char[] i2ctable = | ||
6572 | { | ||
6573 | 'A','B','C','D','E','F','G','H', | ||
6574 | 'I','J','K','L','M','N','O','P', | ||
6575 | 'Q','R','S','T','U','V','W','X', | ||
6576 | 'Y','Z', | ||
6577 | 'a','b','c','d','e','f','g','h', | ||
6578 | 'i','j','k','l','m','n','o','p', | ||
6579 | 'q','r','s','t','u','v','w','x', | ||
6580 | 'y','z', | ||
6581 | '0','1','2','3','4','5','6','7', | ||
6582 | '8','9', | ||
6583 | '+','/' | ||
6584 | }; | ||
6585 | |||
6586 | // <summary> | ||
6587 | // Table for converting base-64 characters | ||
6588 | // into 6-bit integers. | ||
6589 | // </summary> | ||
6590 | |||
6591 | private static readonly int[] c2itable = | ||
6592 | { | ||
6593 | -1,-1,-1,-1,-1,-1,-1,-1, // 0x | ||
6594 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6595 | -1,-1,-1,-1,-1,-1,-1,-1, // 1x | ||
6596 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6597 | -1,-1,-1,-1,-1,-1,-1,-1, // 2x | ||
6598 | -1,-1,-1,63,-1,-1,-1,64, | ||
6599 | 53,54,55,56,57,58,59,60, // 3x | ||
6600 | 61,62,-1,-1,-1,0,-1,-1, | ||
6601 | -1,1,2,3,4,5,6,7, // 4x | ||
6602 | 8,9,10,11,12,13,14,15, | ||
6603 | 16,17,18,19,20,21,22,23, // 5x | ||
6604 | 24,25,26,-1,-1,-1,-1,-1, | ||
6605 | -1,27,28,29,30,31,32,33, // 6x | ||
6606 | 34,35,36,37,38,39,40,41, | ||
6607 | 42,43,44,45,46,47,48,49, // 7x | ||
6608 | 50,51,52,-1,-1,-1,-1,-1, | ||
6609 | -1,-1,-1,-1,-1,-1,-1,-1, // 8x | ||
6610 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6611 | -1,-1,-1,-1,-1,-1,-1,-1, // 9x | ||
6612 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6613 | -1,-1,-1,-1,-1,-1,-1,-1, // Ax | ||
6614 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6615 | -1,-1,-1,-1,-1,-1,-1,-1, // Bx | ||
6616 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6617 | -1,-1,-1,-1,-1,-1,-1,-1, // Cx | ||
6618 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6619 | -1,-1,-1,-1,-1,-1,-1,-1, // Dx | ||
6620 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6621 | -1,-1,-1,-1,-1,-1,-1,-1, // Ex | ||
6622 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6623 | -1,-1,-1,-1,-1,-1,-1,-1, // Fx | ||
6624 | -1,-1,-1,-1,-1,-1,-1,-1 | ||
6625 | }; | ||
6626 | |||
6627 | // <summary> | ||
6628 | // Converts a 32-bit integer into a Base64 | ||
6629 | // character string. Base64 character strings | ||
6630 | // are always 8 characters long. All iinteger | ||
6631 | // values are acceptable. | ||
6632 | // </summary> | ||
6633 | // <param name="number"> | ||
6634 | // 32-bit integer to be converted. | ||
6635 | // </param> | ||
6636 | // <returns> | ||
6637 | // 8 character string. The 1st six characters | ||
6638 | // contain the encoded number, the last two | ||
6639 | // characters are padded with "=". | ||
6640 | // </returns> | ||
6641 | |||
6642 | public LSL_String llIntegerToBase64(int number) | ||
6643 | { | ||
6644 | // uninitialized string | ||
6645 | |||
6646 | char[] imdt = new char[8]; | ||
6647 | |||
6648 | m_host.AddScriptLPS(1); | ||
6649 | |||
6650 | // Manually unroll the loop | ||
6651 | |||
6652 | imdt[7] = '='; | ||
6653 | imdt[6] = '='; | ||
6654 | imdt[5] = i2ctable[number<<4 & 0x3F]; | ||
6655 | imdt[4] = i2ctable[number>>2 & 0x3F]; | ||
6656 | imdt[3] = i2ctable[number>>8 & 0x3F]; | ||
6657 | imdt[2] = i2ctable[number>>14 & 0x3F]; | ||
6658 | imdt[1] = i2ctable[number>>20 & 0x3F]; | ||
6659 | imdt[0] = i2ctable[number>>26 & 0x3F]; | ||
6660 | |||
6661 | return new string(imdt); | ||
6662 | } | ||
6663 | |||
6664 | // <summary> | ||
6665 | // Converts an eight character base-64 string | ||
6666 | // into a 32-bit integer. | ||
6667 | // </summary> | ||
6668 | // <param name="str"> | ||
6669 | // 8 characters string to be converted. Other | ||
6670 | // length strings return zero. | ||
6671 | // </param> | ||
6672 | // <returns> | ||
6673 | // Returns an integer representing the | ||
6674 | // encoded value providedint he 1st 6 | ||
6675 | // characters of the string. | ||
6676 | // </returns> | ||
6677 | // <remarks> | ||
6678 | // This is coded to behave like LSL's | ||
6679 | // implementation (I think), based upon the | ||
6680 | // information available at the Wiki. | ||
6681 | // If more than 8 characters are supplied, | ||
6682 | // zero is returned. | ||
6683 | // If a NULL string is supplied, zero will | ||
6684 | // be returned. | ||
6685 | // If fewer than 6 characters are supplied, then | ||
6686 | // the answer will reflect a partial | ||
6687 | // accumulation. | ||
6688 | // <para> | ||
6689 | // The 6-bit segments are | ||
6690 | // extracted left-to-right in big-endian mode, | ||
6691 | // which means that segment 6 only contains the | ||
6692 | // two low-order bits of the 32 bit integer as | ||
6693 | // its high order 2 bits. A short string therefore | ||
6694 | // means loss of low-order information. E.g. | ||
6695 | // | ||
6696 | // |<---------------------- 32-bit integer ----------------------->|<-Pad->| | ||
6697 | // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->| | ||
6698 | // |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| | ||
6699 | // |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| | ||
6700 | // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] | | ||
6701 | // | ||
6702 | // </para> | ||
6703 | // </remarks> | ||
6704 | |||
6705 | public LSL_Integer llBase64ToInteger(string str) | ||
6706 | { | ||
6707 | int number = 0; | ||
6708 | int digit; | ||
6709 | |||
6710 | m_host.AddScriptLPS(1); | ||
6711 | |||
6712 | // Require a well-fromed base64 string | ||
6713 | |||
6714 | if (str.Length > 8) | ||
6715 | return 0; | ||
6716 | |||
6717 | // The loop is unrolled in the interests | ||
6718 | // of performance and simple necessity. | ||
6719 | // | ||
6720 | // MUST find 6 digits to be well formed | ||
6721 | // -1 == invalid | ||
6722 | // 0 == padding | ||
6723 | |||
6724 | if ((digit=c2itable[str[0]])<=0) | ||
6725 | { | ||
6726 | return digit<0?(int)0:number; | ||
6727 | } | ||
6728 | number += --digit<<26; | ||
6729 | |||
6730 | if ((digit=c2itable[str[1]])<=0) | ||
6731 | { | ||
6732 | return digit<0?(int)0:number; | ||
6733 | } | ||
6734 | number += --digit<<20; | ||
6735 | |||
6736 | if ((digit=c2itable[str[2]])<=0) | ||
6737 | { | ||
6738 | return digit<0?(int)0:number; | ||
6739 | } | ||
6740 | number += --digit<<14; | ||
6741 | |||
6742 | if ((digit=c2itable[str[3]])<=0) | ||
6743 | { | ||
6744 | return digit<0?(int)0:number; | ||
6745 | } | ||
6746 | number += --digit<<8; | ||
6747 | |||
6748 | if ((digit=c2itable[str[4]])<=0) | ||
6749 | { | ||
6750 | return digit<0?(int)0:number; | ||
6751 | } | ||
6752 | number += --digit<<2; | ||
6753 | |||
6754 | if ((digit=c2itable[str[5]])<=0) | ||
6755 | { | ||
6756 | return digit<0?(int)0:number; | ||
6757 | } | ||
6758 | number += --digit>>4; | ||
6759 | |||
6760 | // ignore trailing padding | ||
6761 | |||
6762 | return number; | ||
6763 | } | ||
6764 | |||
6765 | public LSL_Float llGetGMTclock() | ||
6766 | { | ||
6767 | m_host.AddScriptLPS(1); | ||
6768 | return DateTime.UtcNow.TimeOfDay.TotalSeconds; | ||
6769 | } | ||
6770 | |||
6771 | public LSL_String llGetSimulatorHostname() | ||
6772 | { | ||
6773 | m_host.AddScriptLPS(1); | ||
6774 | return System.Environment.MachineName; | ||
6775 | } | ||
6776 | |||
6777 | public void llSetLocalRot(LSL_Rotation rot) | ||
6778 | { | ||
6779 | m_host.AddScriptLPS(1); | ||
6780 | m_host.RotationOffset = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); | ||
6781 | // ScriptSleep(200); | ||
6782 | } | ||
6783 | |||
6784 | // <summary> | ||
6785 | // Scan the string supplied in 'src' and | ||
6786 | // tokenize it based upon two sets of | ||
6787 | // tokenizers provided in two lists, | ||
6788 | // separators and spacers. | ||
6789 | // </summary> | ||
6790 | // | ||
6791 | // <remarks> | ||
6792 | // Separators demarcate tokens and are | ||
6793 | // elided as they are encountered. Spacers | ||
6794 | // also demarcate tokens, but are themselves | ||
6795 | // retained as tokens. | ||
6796 | // | ||
6797 | // Both separators and spacers may be arbitrarily | ||
6798 | // long strings. i.e. ":::". | ||
6799 | // | ||
6800 | // The function returns an ordered list | ||
6801 | // representing the tokens found in the supplied | ||
6802 | // sources string. If two successive tokenizers | ||
6803 | // are encountered, then a NULL entry is added | ||
6804 | // to the list. | ||
6805 | // | ||
6806 | // It is a precondition that the source and | ||
6807 | // toekizer lisst are non-null. If they are null, | ||
6808 | // then a null pointer exception will be thrown | ||
6809 | // while their lengths are being determined. | ||
6810 | // | ||
6811 | // A small amount of working memoryis required | ||
6812 | // of approximately 8*#tokenizers. | ||
6813 | // | ||
6814 | // There are many ways in which this function | ||
6815 | // can be implemented, this implementation is | ||
6816 | // fairly naive and assumes that when the | ||
6817 | // function is invooked with a short source | ||
6818 | // string and/or short lists of tokenizers, then | ||
6819 | // performance will not be an issue. | ||
6820 | // | ||
6821 | // In order to minimize the perofrmance | ||
6822 | // effects of long strings, or large numbers | ||
6823 | // of tokeizers, the function skips as far as | ||
6824 | // possible whenever a toekenizer is found, | ||
6825 | // and eliminates redundant tokenizers as soon | ||
6826 | // as is possible. | ||
6827 | // | ||
6828 | // The implementation tries to avoid any copying | ||
6829 | // of arrays or other objects. | ||
6830 | // </remarks> | ||
6831 | |||
6832 | public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) | ||
6833 | { | ||
6834 | int beginning = 0; | ||
6835 | int srclen = src.Length; | ||
6836 | int seplen = separators.Length; | ||
6837 | object[] separray = separators.Data; | ||
6838 | int spclen = spacers.Length; | ||
6839 | object[] spcarray = spacers.Data; | ||
6840 | int mlen = seplen+spclen; | ||
6841 | |||
6842 | int[] offset = new int[mlen+1]; | ||
6843 | bool[] active = new bool[mlen]; | ||
6844 | |||
6845 | int best; | ||
6846 | int j; | ||
6847 | |||
6848 | // Initial capacity reduces resize cost | ||
6849 | |||
6850 | LSL_List tokens = new LSL_List(); | ||
6851 | |||
6852 | m_host.AddScriptLPS(1); | ||
6853 | |||
6854 | // All entries are initially valid | ||
6855 | |||
6856 | for (int i = 0; i < mlen; i++) | ||
6857 | active[i] = true; | ||
6858 | |||
6859 | offset[mlen] = srclen; | ||
6860 | |||
6861 | while (beginning < srclen) | ||
6862 | { | ||
6863 | |||
6864 | best = mlen; // as bad as it gets | ||
6865 | |||
6866 | // Scan for separators | ||
6867 | |||
6868 | for (j = 0; j < seplen; j++) | ||
6869 | { | ||
6870 | if (active[j]) | ||
6871 | { | ||
6872 | // scan all of the markers | ||
6873 | if ((offset[j] = src.IndexOf(separray[j].ToString(),beginning)) == -1) | ||
6874 | { | ||
6875 | // not present at all | ||
6876 | active[j] = false; | ||
6877 | } | ||
6878 | else | ||
6879 | { | ||
6880 | // present and correct | ||
6881 | if (offset[j] < offset[best]) | ||
6882 | { | ||
6883 | // closest so far | ||
6884 | best = j; | ||
6885 | if (offset[best] == beginning) | ||
6886 | break; | ||
6887 | } | ||
6888 | } | ||
6889 | } | ||
6890 | } | ||
6891 | |||
6892 | // Scan for spacers | ||
6893 | |||
6894 | if (offset[best] != beginning) | ||
6895 | { | ||
6896 | for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) | ||
6897 | { | ||
6898 | if (active[j]) | ||
6899 | { | ||
6900 | // scan all of the markers | ||
6901 | if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1) | ||
6902 | { | ||
6903 | // not present at all | ||
6904 | active[j] = false; | ||
6905 | } | ||
6906 | else | ||
6907 | { | ||
6908 | // present and correct | ||
6909 | if (offset[j] < offset[best]) | ||
6910 | { | ||
6911 | // closest so far | ||
6912 | best = j; | ||
6913 | } | ||
6914 | } | ||
6915 | } | ||
6916 | } | ||
6917 | } | ||
6918 | |||
6919 | // This is the normal exit from the scanning loop | ||
6920 | |||
6921 | if (best == mlen) | ||
6922 | { | ||
6923 | // no markers were found on this pass | ||
6924 | // so we're pretty much done | ||
6925 | tokens.Add(src.Substring(beginning, srclen - beginning)); | ||
6926 | break; | ||
6927 | } | ||
6928 | |||
6929 | // Otherwise we just add the newly delimited token | ||
6930 | // and recalculate where the search should continue. | ||
6931 | |||
6932 | tokens.Add(src.Substring(beginning,offset[best]-beginning)); | ||
6933 | |||
6934 | if (best < seplen) | ||
6935 | { | ||
6936 | beginning = offset[best] + (separray[best].ToString()).Length; | ||
6937 | } | ||
6938 | else | ||
6939 | { | ||
6940 | beginning = offset[best] + (spcarray[best - seplen].ToString()).Length; | ||
6941 | tokens.Add(spcarray[best - seplen]); | ||
6942 | } | ||
6943 | } | ||
6944 | |||
6945 | // This an awkward an not very intuitive boundary case. If the | ||
6946 | // last substring is a tokenizer, then there is an implied trailing | ||
6947 | // null list entry. Hopefully the single comparison will not be too | ||
6948 | // arduous. Alternatively the 'break' could be replced with a return | ||
6949 | // but that's shabby programming. | ||
6950 | |||
6951 | if (beginning == srclen) | ||
6952 | { | ||
6953 | if (srclen != 0) | ||
6954 | tokens.Add(""); | ||
6955 | } | ||
6956 | |||
6957 | return tokens; | ||
6958 | } | ||
6959 | |||
6960 | public LSL_Integer llGetObjectPermMask(int mask) | ||
6961 | { | ||
6962 | m_host.AddScriptLPS(1); | ||
6963 | |||
6964 | int permmask = 0; | ||
6965 | |||
6966 | if (mask == ScriptBaseClass.MASK_BASE)//0 | ||
6967 | { | ||
6968 | permmask = (int)m_host.BaseMask; | ||
6969 | } | ||
6970 | |||
6971 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 | ||
6972 | { | ||
6973 | permmask = (int)m_host.OwnerMask; | ||
6974 | } | ||
6975 | |||
6976 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 | ||
6977 | { | ||
6978 | permmask = (int)m_host.GroupMask; | ||
6979 | } | ||
6980 | |||
6981 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 | ||
6982 | { | ||
6983 | permmask = (int)m_host.EveryoneMask; | ||
6984 | } | ||
6985 | |||
6986 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 | ||
6987 | { | ||
6988 | permmask = (int)m_host.NextOwnerMask; | ||
6989 | } | ||
6990 | |||
6991 | return permmask; | ||
6992 | } | ||
6993 | |||
6994 | public void llSetObjectPermMask(int mask, int value) | ||
6995 | { | ||
6996 | m_host.AddScriptLPS(1); | ||
6997 | IConfigSource config = new IniConfigSource(Application.iniFilePath); | ||
6998 | if (config.Configs["XEngine"] == null) | ||
6999 | config.AddConfig("XEngine"); | ||
7000 | |||
7001 | if (config.Configs["XEngine"].GetBoolean("AllowGodFunctions", false)) | ||
7002 | { | ||
7003 | if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID)) | ||
7004 | { | ||
7005 | if (mask == ScriptBaseClass.MASK_BASE)//0 | ||
7006 | { | ||
7007 | m_host.BaseMask = (uint)value; | ||
7008 | } | ||
7009 | |||
7010 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 | ||
7011 | { | ||
7012 | m_host.OwnerMask = (uint)value; | ||
7013 | } | ||
7014 | |||
7015 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 | ||
7016 | { | ||
7017 | m_host.GroupMask = (uint)value; | ||
7018 | } | ||
7019 | |||
7020 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 | ||
7021 | { | ||
7022 | m_host.EveryoneMask = (uint)value; | ||
7023 | } | ||
7024 | |||
7025 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 | ||
7026 | { | ||
7027 | m_host.NextOwnerMask = (uint)value; | ||
7028 | } | ||
7029 | } | ||
7030 | } | ||
7031 | } | ||
7032 | |||
7033 | public LSL_Integer llGetInventoryPermMask(string item, int mask) | ||
7034 | { | ||
7035 | m_host.AddScriptLPS(1); | ||
7036 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
7037 | { | ||
7038 | if (inv.Value.Name == item) | ||
7039 | { | ||
7040 | switch (mask) | ||
7041 | { | ||
7042 | case 0: | ||
7043 | return (int)inv.Value.BasePermissions; | ||
7044 | case 1: | ||
7045 | return (int)inv.Value.CurrentPermissions; | ||
7046 | case 2: | ||
7047 | return (int)inv.Value.GroupPermissions; | ||
7048 | case 3: | ||
7049 | return (int)inv.Value.EveryonePermissions; | ||
7050 | case 4: | ||
7051 | return (int)inv.Value.NextPermissions; | ||
7052 | } | ||
7053 | } | ||
7054 | } | ||
7055 | return -1; | ||
7056 | } | ||
7057 | |||
7058 | public void llSetInventoryPermMask(string item, int mask, int value) | ||
7059 | { | ||
7060 | m_host.AddScriptLPS(1); | ||
7061 | NotImplemented("llSetInventoryPermMask"); | ||
7062 | } | ||
7063 | |||
7064 | public LSL_String llGetInventoryCreator(string item) | ||
7065 | { | ||
7066 | m_host.AddScriptLPS(1); | ||
7067 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
7068 | { | ||
7069 | if (inv.Value.Name == item) | ||
7070 | { | ||
7071 | return inv.Value.CreatorID.ToString(); | ||
7072 | } | ||
7073 | } | ||
7074 | llSay(0, "No item name '" + item + "'"); | ||
7075 | return String.Empty; | ||
7076 | } | ||
7077 | |||
7078 | public void llOwnerSay(string msg) | ||
7079 | { | ||
7080 | m_host.AddScriptLPS(1); | ||
7081 | |||
7082 | World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
7083 | // IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
7084 | // wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg); | ||
7085 | } | ||
7086 | |||
7087 | public LSL_String llRequestSimulatorData(string simulator, int data) | ||
7088 | { | ||
7089 | try | ||
7090 | { | ||
7091 | m_host.AddScriptLPS(1); | ||
7092 | |||
7093 | string reply = String.Empty; | ||
7094 | |||
7095 | RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator); | ||
7096 | |||
7097 | switch (data) | ||
7098 | { | ||
7099 | case 5: // DATA_SIM_POS | ||
7100 | if (info == null) | ||
7101 | { | ||
7102 | // ScriptSleep(1000); | ||
7103 | return UUID.Zero.ToString(); | ||
7104 | } | ||
7105 | reply = new LSL_Vector( | ||
7106 | info.RegionLocX * Constants.RegionSize, | ||
7107 | info.RegionLocY * Constants.RegionSize, | ||
7108 | 0).ToString(); | ||
7109 | break; | ||
7110 | case 6: // DATA_SIM_STATUS | ||
7111 | if (info != null) | ||
7112 | reply = "up"; // Duh! | ||
7113 | else | ||
7114 | reply = "unknown"; | ||
7115 | break; | ||
7116 | case 7: // DATA_SIM_RATING | ||
7117 | if (info == null) | ||
7118 | { | ||
7119 | // ScriptSleep(1000); | ||
7120 | return UUID.Zero.ToString(); | ||
7121 | } | ||
7122 | int access = info.RegionSettings.Maturity; | ||
7123 | if (access == 0) | ||
7124 | reply = "PG"; | ||
7125 | else if (access == 1) | ||
7126 | reply = "MATURE"; | ||
7127 | else | ||
7128 | reply = "UNKNOWN"; | ||
7129 | break; | ||
7130 | case 128: // SIM_RELEASE (not LSL conform, valid for OpenSim only) | ||
7131 | reply = m_ScriptEngine.World.GetSimulatorVersion(); | ||
7132 | break; | ||
7133 | default: | ||
7134 | // ScriptSleep(1000); | ||
7135 | return UUID.Zero.ToString(); // Raise no event | ||
7136 | } | ||
7137 | UUID rq = UUID.Random(); | ||
7138 | |||
7139 | UUID tid = AsyncCommands. | ||
7140 | DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString()); | ||
7141 | |||
7142 | AsyncCommands. | ||
7143 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | ||
7144 | |||
7145 | // ScriptSleep(1000); | ||
7146 | return tid.ToString(); | ||
7147 | } | ||
7148 | catch(Exception e) | ||
7149 | { | ||
7150 | Console.WriteLine(e.ToString()); | ||
7151 | return UUID.Zero.ToString(); | ||
7152 | } | ||
7153 | } | ||
7154 | |||
7155 | public void llForceMouselook(int mouselook) | ||
7156 | { | ||
7157 | m_host.AddScriptLPS(1); | ||
7158 | m_host.SetForceMouselook(mouselook != 0); | ||
7159 | } | ||
7160 | |||
7161 | public LSL_Float llGetObjectMass(string id) | ||
7162 | { | ||
7163 | m_host.AddScriptLPS(1); | ||
7164 | UUID key = new UUID(); | ||
7165 | if (UUID.TryParse(id, out key)) | ||
7166 | { | ||
7167 | try | ||
7168 | { | ||
7169 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); | ||
7170 | if (obj != null) | ||
7171 | return (double)obj.GetMass(); | ||
7172 | // the object is null so the key is for an avatar | ||
7173 | ScenePresence avatar = World.GetScenePresence(key); | ||
7174 | if (avatar != null) | ||
7175 | if (avatar.IsChildAgent) | ||
7176 | // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass | ||
7177 | // child agents have a mass of 1.0 | ||
7178 | return 1; | ||
7179 | else | ||
7180 | return (double)avatar.PhysicsActor.Mass; | ||
7181 | } | ||
7182 | catch (KeyNotFoundException) | ||
7183 | { | ||
7184 | return 0; // The Object/Agent not in the region so just return zero | ||
7185 | } | ||
7186 | } | ||
7187 | return 0; | ||
7188 | } | ||
7189 | |||
7190 | /// <summary> | ||
7191 | /// illListReplaceList removes the sub-list defined by the inclusive indices | ||
7192 | /// start and end and inserts the src list in its place. The inclusive | ||
7193 | /// nature of the indices means that at least one element must be deleted | ||
7194 | /// if the indices are within the bounds of the existing list. I.e. 2,2 | ||
7195 | /// will remove the element at index 2 and replace it with the source | ||
7196 | /// list. Both indices may be negative, with the usual interpretation. An | ||
7197 | /// interesting case is where end is lower than start. As these indices | ||
7198 | /// bound the list to be removed, then 0->end, and start->lim are removed | ||
7199 | /// and the source list is added as a suffix. | ||
7200 | /// </summary> | ||
7201 | |||
7202 | public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) | ||
7203 | { | ||
7204 | LSL_List pref = null; | ||
7205 | |||
7206 | m_host.AddScriptLPS(1); | ||
7207 | |||
7208 | // Note that although we have normalized, both | ||
7209 | // indices could still be negative. | ||
7210 | if (start < 0) | ||
7211 | { | ||
7212 | start = start+dest.Length; | ||
7213 | } | ||
7214 | |||
7215 | if (end < 0) | ||
7216 | { | ||
7217 | end = end+dest.Length; | ||
7218 | } | ||
7219 | // The comventional case, remove a sequence starting with | ||
7220 | // start and ending with end. And then insert the source | ||
7221 | // list. | ||
7222 | if (start <= end) | ||
7223 | { | ||
7224 | // If greater than zero, then there is going to be a | ||
7225 | // surviving prefix. Otherwise the inclusive nature | ||
7226 | // of the indices mean that we're going to add the | ||
7227 | // source list as a prefix. | ||
7228 | if (start > 0) | ||
7229 | { | ||
7230 | pref = dest.GetSublist(0,start-1); | ||
7231 | // Only add a suffix if there is something | ||
7232 | // beyond the end index (it's inclusive too). | ||
7233 | if (end + 1 < dest.Length) | ||
7234 | { | ||
7235 | return pref + src + dest.GetSublist(end + 1, -1); | ||
7236 | } | ||
7237 | else | ||
7238 | { | ||
7239 | return pref + src; | ||
7240 | } | ||
7241 | } | ||
7242 | // If start is less than or equal to zero, then | ||
7243 | // the new list is simply a prefix. We still need to | ||
7244 | // figure out any necessary surgery to the destination | ||
7245 | // based upon end. Note that if end exceeds the upper | ||
7246 | // bound in this case, the entire destination list | ||
7247 | // is removed. | ||
7248 | else | ||
7249 | { | ||
7250 | if (end + 1 < dest.Length) | ||
7251 | { | ||
7252 | return src + dest.GetSublist(end + 1, -1); | ||
7253 | } | ||
7254 | else | ||
7255 | { | ||
7256 | return src; | ||
7257 | } | ||
7258 | } | ||
7259 | } | ||
7260 | // Finally, if start > end, we strip away a prefix and | ||
7261 | // a suffix, to leave the list that sits <between> ens | ||
7262 | // and start, and then tag on the src list. AT least | ||
7263 | // that's my interpretation. We can get sublist to do | ||
7264 | // this for us. Note that one, or both of the indices | ||
7265 | // might have been negative. | ||
7266 | else | ||
7267 | { | ||
7268 | return dest.GetSublist(end + 1, start - 1) + src; | ||
7269 | } | ||
7270 | } | ||
7271 | |||
7272 | public void llLoadURL(string avatar_id, string message, string url) | ||
7273 | { | ||
7274 | m_host.AddScriptLPS(1); | ||
7275 | UUID avatarId = new UUID(avatar_id); | ||
7276 | m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, | ||
7277 | url); | ||
7278 | // ScriptSleep(10000); | ||
7279 | } | ||
7280 | |||
7281 | public void llParcelMediaCommandList(LSL_List commandList) | ||
7282 | { | ||
7283 | //TO DO: Implement the missing commands | ||
7284 | //PARCEL_MEDIA_COMMAND_STOP Stop the media stream and go back to the first frame. | ||
7285 | //PARCEL_MEDIA_COMMAND_PAUSE Pause the media stream (stop playing but stay on current frame). | ||
7286 | //PARCEL_MEDIA_COMMAND_PLAY Start the media stream playing from the current frame and stop when the end is reached. | ||
7287 | //PARCEL_MEDIA_COMMAND_LOOP Start the media stream playing from the current frame. When the end is reached, loop to the beginning and continue. | ||
7288 | //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture. | ||
7289 | //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url. | ||
7290 | //PARCEL_MEDIA_COMMAND_TIME float time Move a media stream to a specific time. | ||
7291 | //PARCEL_MEDIA_COMMAND_AGENT key uuid Applies the media command to the specified agent only. | ||
7292 | //PARCEL_MEDIA_COMMAND_UNLOAD Completely unloads the movie and restores the original texture. | ||
7293 | //PARCEL_MEDIA_COMMAND_AUTO_ALIGN integer boolean Sets the parcel option 'Auto scale content'. | ||
7294 | //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later) | ||
7295 | //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later) | ||
7296 | //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later) | ||
7297 | //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) | ||
7298 | m_host.AddScriptLPS(1); | ||
7299 | for (int i = 0; i < commandList.Data.Length; i++) | ||
7300 | { | ||
7301 | switch ((ParcelMediaCommandEnum)commandList.Data[i]) | ||
7302 | { | ||
7303 | case ParcelMediaCommandEnum.Play: | ||
7304 | List<ScenePresence> scenePresencePlayList = World.GetScenePresences(); | ||
7305 | foreach (ScenePresence agent in scenePresencePlayList) | ||
7306 | { | ||
7307 | if (!agent.IsChildAgent) | ||
7308 | { | ||
7309 | agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0); | ||
7310 | } | ||
7311 | } | ||
7312 | break; | ||
7313 | case ParcelMediaCommandEnum.Stop: | ||
7314 | List<ScenePresence> scenePresenceStopList = World.GetScenePresences(); | ||
7315 | foreach (ScenePresence agent in scenePresenceStopList) | ||
7316 | { | ||
7317 | if (!agent.IsChildAgent) | ||
7318 | { | ||
7319 | agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Stop, 0); | ||
7320 | } | ||
7321 | } | ||
7322 | break; | ||
7323 | case ParcelMediaCommandEnum.Pause: | ||
7324 | List<ScenePresence> scenePresencePauseList = World.GetScenePresences(); | ||
7325 | foreach (ScenePresence agent in scenePresencePauseList) | ||
7326 | { | ||
7327 | if (!agent.IsChildAgent) | ||
7328 | { | ||
7329 | agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Pause, 0); | ||
7330 | } | ||
7331 | } | ||
7332 | break; | ||
7333 | |||
7334 | case ParcelMediaCommandEnum.Url: | ||
7335 | if ((i + 1) < commandList.Length) | ||
7336 | { | ||
7337 | if (commandList.Data[i + 1] is string) | ||
7338 | { | ||
7339 | UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
7340 | |||
7341 | if (landowner == UUID.Zero) | ||
7342 | { | ||
7343 | return; | ||
7344 | } | ||
7345 | |||
7346 | if (landowner != m_host.ObjectOwner) | ||
7347 | { | ||
7348 | return; | ||
7349 | } | ||
7350 | |||
7351 | World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, (string)commandList.GetLSLStringItem(i + 1)); | ||
7352 | |||
7353 | List<ScenePresence> scenePresenceList = World.GetScenePresences(); | ||
7354 | LandData landData = World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
7355 | //Send an update of the mediaURL to all the clients that are in the parcel | ||
7356 | foreach (ScenePresence agent in scenePresenceList) | ||
7357 | { | ||
7358 | if (!agent.IsChildAgent) | ||
7359 | { | ||
7360 | //Send parcel media update to the client | ||
7361 | agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, landData.MediaAutoScale, "", landData.Description, 0, 0, 1); | ||
7362 | } | ||
7363 | } | ||
7364 | |||
7365 | } | ||
7366 | i++; | ||
7367 | } | ||
7368 | break; | ||
7369 | default: | ||
7370 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; | ||
7371 | NotImplemented("llParcelMediaCommandList parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType(), commandList.Data[i].ToString()).ToString()); | ||
7372 | break; | ||
7373 | }//end switch | ||
7374 | |||
7375 | } | ||
7376 | // ScriptSleep(2000); | ||
7377 | } | ||
7378 | |||
7379 | public LSL_List llParcelMediaQuery(LSL_List aList) | ||
7380 | { | ||
7381 | m_host.AddScriptLPS(1); | ||
7382 | LSL_List list = new LSL_List(); | ||
7383 | //TO DO: make the implementation for the missing commands | ||
7384 | //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture. | ||
7385 | //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url. | ||
7386 | //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later) | ||
7387 | //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later) | ||
7388 | //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later) | ||
7389 | //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) | ||
7390 | for (int i = 0; i < aList.Data.Length; i++) | ||
7391 | { | ||
7392 | |||
7393 | if (aList.Data[i] != null) | ||
7394 | { | ||
7395 | switch ((ParcelMediaCommandEnum) aList.Data[i]) | ||
7396 | { | ||
7397 | case ParcelMediaCommandEnum.Url: | ||
7398 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); | ||
7399 | break; | ||
7400 | case ParcelMediaCommandEnum.Desc: | ||
7401 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); | ||
7402 | break; | ||
7403 | case ParcelMediaCommandEnum.Texture: | ||
7404 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); | ||
7405 | break; | ||
7406 | default: | ||
7407 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; | ||
7408 | NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); | ||
7409 | break; | ||
7410 | } | ||
7411 | |||
7412 | } | ||
7413 | } | ||
7414 | // ScriptSleep(2000); | ||
7415 | return list; | ||
7416 | } | ||
7417 | |||
7418 | public LSL_Integer llModPow(int a, int b, int c) | ||
7419 | { | ||
7420 | m_host.AddScriptLPS(1); | ||
7421 | Int64 tmp = 0; | ||
7422 | Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); | ||
7423 | // ScriptSleep(1000); | ||
7424 | return Convert.ToInt32(tmp); | ||
7425 | } | ||
7426 | |||
7427 | public LSL_Integer llGetInventoryType(string name) | ||
7428 | { | ||
7429 | m_host.AddScriptLPS(1); | ||
7430 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
7431 | { | ||
7432 | if (inv.Value.Name == name) | ||
7433 | { | ||
7434 | return inv.Value.InvType; | ||
7435 | } | ||
7436 | } | ||
7437 | return -1; | ||
7438 | } | ||
7439 | |||
7440 | public void llSetPayPrice(int price, LSL_List quick_pay_buttons) | ||
7441 | { | ||
7442 | m_host.AddScriptLPS(1); | ||
7443 | |||
7444 | if (quick_pay_buttons.Data.Length < 4) | ||
7445 | { | ||
7446 | LSLError("List must have at least 4 elements"); | ||
7447 | return; | ||
7448 | } | ||
7449 | m_host.ParentGroup.RootPart.PayPrice[0]=price; | ||
7450 | |||
7451 | m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; | ||
7452 | m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; | ||
7453 | m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; | ||
7454 | m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; | ||
7455 | m_host.ParentGroup.HasGroupChanged = true; | ||
7456 | } | ||
7457 | |||
7458 | public LSL_Vector llGetCameraPos() | ||
7459 | { | ||
7460 | m_host.AddScriptLPS(1); | ||
7461 | UUID invItemID=InventorySelf(); | ||
7462 | if (invItemID == UUID.Zero) | ||
7463 | return new LSL_Vector(); | ||
7464 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
7465 | return new LSL_Vector(); | ||
7466 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | ||
7467 | { | ||
7468 | ShoutError("No permissions to track the camera"); | ||
7469 | return new LSL_Vector(); | ||
7470 | } | ||
7471 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | ||
7472 | if (presence != null) | ||
7473 | { | ||
7474 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); | ||
7475 | return pos; | ||
7476 | } | ||
7477 | return new LSL_Vector(); | ||
7478 | } | ||
7479 | |||
7480 | public LSL_Rotation llGetCameraRot() | ||
7481 | { | ||
7482 | m_host.AddScriptLPS(1); | ||
7483 | NotImplemented("llGetCameraRot"); | ||
7484 | return new LSL_Rotation(); | ||
7485 | } | ||
7486 | |||
7487 | public void llSetPrimURL() | ||
7488 | { | ||
7489 | m_host.AddScriptLPS(1); | ||
7490 | NotImplemented("llSetPrimURL"); | ||
7491 | // ScriptSleep(2000); | ||
7492 | } | ||
7493 | |||
7494 | public void llRefreshPrimURL() | ||
7495 | { | ||
7496 | m_host.AddScriptLPS(1); | ||
7497 | NotImplemented("llRefreshPrimURL"); | ||
7498 | // ScriptSleep(20000); | ||
7499 | } | ||
7500 | |||
7501 | public LSL_String llEscapeURL(string url) | ||
7502 | { | ||
7503 | m_host.AddScriptLPS(1); | ||
7504 | try | ||
7505 | { | ||
7506 | return Uri.EscapeUriString(url); | ||
7507 | } | ||
7508 | catch (Exception ex) | ||
7509 | { | ||
7510 | return "llEscapeURL: " + ex.ToString(); | ||
7511 | } | ||
7512 | } | ||
7513 | |||
7514 | public LSL_String llUnescapeURL(string url) | ||
7515 | { | ||
7516 | m_host.AddScriptLPS(1); | ||
7517 | try | ||
7518 | { | ||
7519 | return Uri.UnescapeDataString(url); | ||
7520 | } | ||
7521 | catch (Exception ex) | ||
7522 | { | ||
7523 | return "llUnescapeURL: " + ex.ToString(); | ||
7524 | } | ||
7525 | } | ||
7526 | |||
7527 | public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector look_at) | ||
7528 | { | ||
7529 | m_host.AddScriptLPS(1); | ||
7530 | NotImplemented("llMapDestination"); | ||
7531 | // ScriptSleep(1000); | ||
7532 | } | ||
7533 | |||
7534 | public void llAddToLandBanList(string avatar, double hours) | ||
7535 | { | ||
7536 | m_host.AddScriptLPS(1); | ||
7537 | UUID key; | ||
7538 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7539 | if (land.OwnerID == m_host.OwnerID) | ||
7540 | { | ||
7541 | ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); | ||
7542 | if (UUID.TryParse(avatar, out key)) | ||
7543 | { | ||
7544 | entry.AgentID = key; | ||
7545 | entry.Flags = ParcelManager.AccessList.Ban; | ||
7546 | entry.Time = DateTime.Now.AddHours(hours); | ||
7547 | land.ParcelAccessList.Add(entry); | ||
7548 | } | ||
7549 | } | ||
7550 | // ScriptSleep(100); | ||
7551 | } | ||
7552 | |||
7553 | public void llRemoveFromLandPassList(string avatar) | ||
7554 | { | ||
7555 | m_host.AddScriptLPS(1); | ||
7556 | UUID key; | ||
7557 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7558 | if (land.OwnerID == m_host.OwnerID) | ||
7559 | { | ||
7560 | if (UUID.TryParse(avatar, out key)) | ||
7561 | { | ||
7562 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7563 | { | ||
7564 | if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access) | ||
7565 | { | ||
7566 | land.ParcelAccessList.Remove(entry); | ||
7567 | break; | ||
7568 | } | ||
7569 | } | ||
7570 | } | ||
7571 | } | ||
7572 | // ScriptSleep(100); | ||
7573 | } | ||
7574 | |||
7575 | public void llRemoveFromLandBanList(string avatar) | ||
7576 | { | ||
7577 | m_host.AddScriptLPS(1); | ||
7578 | UUID key; | ||
7579 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7580 | if (land.OwnerID == m_host.OwnerID) | ||
7581 | { | ||
7582 | if (UUID.TryParse(avatar, out key)) | ||
7583 | { | ||
7584 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7585 | { | ||
7586 | if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban) | ||
7587 | { | ||
7588 | land.ParcelAccessList.Remove(entry); | ||
7589 | break; | ||
7590 | } | ||
7591 | } | ||
7592 | } | ||
7593 | } | ||
7594 | // ScriptSleep(100); | ||
7595 | } | ||
7596 | |||
7597 | public void llSetCameraParams(LSL_List rules) | ||
7598 | { | ||
7599 | m_host.AddScriptLPS(1); | ||
7600 | |||
7601 | // our key in the object we are in | ||
7602 | UUID invItemID=InventorySelf(); | ||
7603 | if (invItemID == UUID.Zero) return; | ||
7604 | |||
7605 | // the object we are in | ||
7606 | UUID objectID = m_host.ParentUUID; | ||
7607 | if (objectID == UUID.Zero) return; | ||
7608 | |||
7609 | // we need the permission first, to know which avatar we want to set the camera for | ||
7610 | UUID agentID = m_host.TaskInventory[invItemID].PermsGranter; | ||
7611 | if (agentID == UUID.Zero) return; | ||
7612 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; | ||
7613 | |||
7614 | ScenePresence presence = World.GetScenePresence(agentID); | ||
7615 | |||
7616 | // we are not interested in child-agents | ||
7617 | if (presence.IsChildAgent) return; | ||
7618 | |||
7619 | SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); | ||
7620 | object[] data = rules.Data; | ||
7621 | for (int i = 0; i < data.Length; ++i) { | ||
7622 | int type = Convert.ToInt32(data[i++].ToString()); | ||
7623 | if (i >= data.Length) break; // odd number of entries => ignore the last | ||
7624 | |||
7625 | // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) | ||
7626 | switch (type) { | ||
7627 | case ScriptBaseClass.CAMERA_FOCUS: | ||
7628 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | ||
7629 | case ScriptBaseClass.CAMERA_POSITION: | ||
7630 | LSL_Vector v = (LSL_Vector)data[i]; | ||
7631 | parameters.Add(type + 1, (float)v.x); | ||
7632 | parameters.Add(type + 2, (float)v.y); | ||
7633 | parameters.Add(type + 3, (float)v.z); | ||
7634 | break; | ||
7635 | default: | ||
7636 | // TODO: clean that up as soon as the implicit casts are in | ||
7637 | if (data[i] is LSL_Float) | ||
7638 | parameters.Add(type, (float)((LSL_Float)data[i]).value); | ||
7639 | else if (data[i] is LSL_Integer) | ||
7640 | parameters.Add(type, (float)((LSL_Integer)data[i]).value); | ||
7641 | else parameters.Add(type, Convert.ToSingle(data[i])); | ||
7642 | break; | ||
7643 | } | ||
7644 | } | ||
7645 | if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters); | ||
7646 | } | ||
7647 | |||
7648 | public void llClearCameraParams() | ||
7649 | { | ||
7650 | m_host.AddScriptLPS(1); | ||
7651 | |||
7652 | // our key in the object we are in | ||
7653 | UUID invItemID=InventorySelf(); | ||
7654 | if (invItemID == UUID.Zero) return; | ||
7655 | |||
7656 | // the object we are in | ||
7657 | UUID objectID = m_host.ParentUUID; | ||
7658 | if (objectID == UUID.Zero) return; | ||
7659 | |||
7660 | // we need the permission first, to know which avatar we want to clear the camera for | ||
7661 | UUID agentID = m_host.TaskInventory[invItemID].PermsGranter; | ||
7662 | if (agentID == UUID.Zero) return; | ||
7663 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; | ||
7664 | |||
7665 | ScenePresence presence = World.GetScenePresence(agentID); | ||
7666 | |||
7667 | // we are not interested in child-agents | ||
7668 | if (presence.IsChildAgent) return; | ||
7669 | |||
7670 | presence.ControllingClient.SendClearFollowCamProperties(objectID); | ||
7671 | } | ||
7672 | |||
7673 | public LSL_Float llListStatistics(int operation, LSL_List src) | ||
7674 | { | ||
7675 | m_host.AddScriptLPS(1); | ||
7676 | LSL_List nums = LSL_List.ToDoubleList(src); | ||
7677 | switch (operation) | ||
7678 | { | ||
7679 | case ScriptBaseClass.LIST_STAT_RANGE: | ||
7680 | return nums.Range(); | ||
7681 | case ScriptBaseClass.LIST_STAT_MIN: | ||
7682 | return nums.Min(); | ||
7683 | case ScriptBaseClass.LIST_STAT_MAX: | ||
7684 | return nums.Max(); | ||
7685 | case ScriptBaseClass.LIST_STAT_MEAN: | ||
7686 | return nums.Mean(); | ||
7687 | case ScriptBaseClass.LIST_STAT_MEDIAN: | ||
7688 | return nums.Median(); | ||
7689 | case ScriptBaseClass.LIST_STAT_NUM_COUNT: | ||
7690 | return nums.NumericLength(); | ||
7691 | case ScriptBaseClass.LIST_STAT_STD_DEV: | ||
7692 | return nums.StdDev(); | ||
7693 | case ScriptBaseClass.LIST_STAT_SUM: | ||
7694 | return nums.Sum(); | ||
7695 | case ScriptBaseClass.LIST_STAT_SUM_SQUARES: | ||
7696 | return nums.SumSqrs(); | ||
7697 | case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: | ||
7698 | return nums.GeometricMean(); | ||
7699 | case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: | ||
7700 | return nums.HarmonicMean(); | ||
7701 | default: | ||
7702 | return 0.0; | ||
7703 | } | ||
7704 | } | ||
7705 | |||
7706 | public LSL_Integer llGetUnixTime() | ||
7707 | { | ||
7708 | m_host.AddScriptLPS(1); | ||
7709 | return Util.UnixTimeSinceEpoch(); | ||
7710 | } | ||
7711 | |||
7712 | public LSL_Integer llGetParcelFlags(LSL_Vector pos) | ||
7713 | { | ||
7714 | m_host.AddScriptLPS(1); | ||
7715 | return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.Flags; | ||
7716 | } | ||
7717 | |||
7718 | public LSL_Integer llGetRegionFlags() | ||
7719 | { | ||
7720 | m_host.AddScriptLPS(1); | ||
7721 | IEstateModule estate = World.RequestModuleInterface<IEstateModule>(); | ||
7722 | if (estate == null) | ||
7723 | return 67108864; | ||
7724 | return (int)estate.GetRegionFlags(); | ||
7725 | } | ||
7726 | |||
7727 | public LSL_String llXorBase64StringsCorrect(string str1, string str2) | ||
7728 | { | ||
7729 | m_host.AddScriptLPS(1); | ||
7730 | string ret = String.Empty; | ||
7731 | string src1 = llBase64ToString(str1); | ||
7732 | string src2 = llBase64ToString(str2); | ||
7733 | int c = 0; | ||
7734 | for (int i = 0; i < src1.Length; i++) | ||
7735 | { | ||
7736 | ret += src1[i] ^ src2[c]; | ||
7737 | |||
7738 | c++; | ||
7739 | if (c >= src2.Length) | ||
7740 | c = 0; | ||
7741 | } | ||
7742 | return llStringToBase64(ret); | ||
7743 | } | ||
7744 | |||
7745 | public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) | ||
7746 | { | ||
7747 | // Partial implementation: support for parameter flags needed | ||
7748 | // see http://wiki.secondlife.com/wiki/LlHTTPRequest | ||
7749 | // parameter flags support are implemented in ScriptsHttpRequests.cs | ||
7750 | // in StartHttpRequest | ||
7751 | |||
7752 | m_host.AddScriptLPS(1); | ||
7753 | IHttpRequests httpScriptMod = | ||
7754 | m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); | ||
7755 | List<string> param = new List<string>(); | ||
7756 | foreach (object o in parameters.Data) | ||
7757 | { | ||
7758 | param.Add(o.ToString()); | ||
7759 | } | ||
7760 | |||
7761 | Vector3 position = m_host.AbsolutePosition; | ||
7762 | Vector3 velocity = m_host.Velocity; | ||
7763 | Quaternion rotation = m_host.RotationOffset; | ||
7764 | ScenePresence scenePresence = World.GetScenePresence(m_host.ObjectOwner); | ||
7765 | RegionInfo regionInfo = World.RegionInfo; | ||
7766 | |||
7767 | Dictionary<string, string> httpHeaders = new Dictionary<string, string>(); | ||
7768 | |||
7769 | httpHeaders["X-SecondLife-Shard"] = "OpenSim"; | ||
7770 | httpHeaders["X-SecondLife-Object-Name"] = m_host.Name; | ||
7771 | httpHeaders["X-SecondLife-Object-Key"] = m_itemID.ToString(); | ||
7772 | httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY); | ||
7773 | httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z); | ||
7774 | httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z); | ||
7775 | 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); | ||
7776 | httpHeaders["X-SecondLife-Owner-Name"] = scenePresence == null ? string.Empty : scenePresence.ControllingClient.Name; | ||
7777 | httpHeaders["X-SecondLife-Owner-Key"] = m_host.ObjectOwner.ToString(); | ||
7778 | |||
7779 | UUID reqID = httpScriptMod. | ||
7780 | StartHttpRequest(m_localID, m_itemID, url, param, httpHeaders, body); | ||
7781 | |||
7782 | if (reqID != UUID.Zero) | ||
7783 | return reqID.ToString(); | ||
7784 | else | ||
7785 | return null; | ||
7786 | } | ||
7787 | |||
7788 | public void llResetLandBanList() | ||
7789 | { | ||
7790 | m_host.AddScriptLPS(1); | ||
7791 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7792 | if (land.OwnerID == m_host.OwnerID) | ||
7793 | { | ||
7794 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7795 | { | ||
7796 | if (entry.Flags == ParcelManager.AccessList.Ban) | ||
7797 | { | ||
7798 | land.ParcelAccessList.Remove(entry); | ||
7799 | } | ||
7800 | } | ||
7801 | } | ||
7802 | // ScriptSleep(100); | ||
7803 | } | ||
7804 | |||
7805 | public void llResetLandPassList() | ||
7806 | { | ||
7807 | m_host.AddScriptLPS(1); | ||
7808 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7809 | if (land.OwnerID == m_host.OwnerID) | ||
7810 | { | ||
7811 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7812 | { | ||
7813 | if (entry.Flags == ParcelManager.AccessList.Access) | ||
7814 | { | ||
7815 | land.ParcelAccessList.Remove(entry); | ||
7816 | } | ||
7817 | } | ||
7818 | } | ||
7819 | // ScriptSleep(100); | ||
7820 | } | ||
7821 | |||
7822 | public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) | ||
7823 | { | ||
7824 | m_host.AddScriptLPS(1); | ||
7825 | |||
7826 | LandData land = World.GetLandData((float)pos.x, (float)pos.y); | ||
7827 | |||
7828 | if (land == null) | ||
7829 | { | ||
7830 | return 0; | ||
7831 | } | ||
7832 | |||
7833 | else | ||
7834 | { | ||
7835 | if (sim_wide == 1) | ||
7836 | { | ||
7837 | if (category == 0) | ||
7838 | { | ||
7839 | return land.SimwidePrims; | ||
7840 | } | ||
7841 | |||
7842 | else | ||
7843 | { | ||
7844 | //public int simwideArea = 0; | ||
7845 | return 0; | ||
7846 | } | ||
7847 | } | ||
7848 | |||
7849 | else | ||
7850 | { | ||
7851 | if (category == 0)//Total Prims | ||
7852 | { | ||
7853 | return 0;//land. | ||
7854 | } | ||
7855 | |||
7856 | else if (category == 1)//Owner Prims | ||
7857 | { | ||
7858 | return land.OwnerPrims; | ||
7859 | } | ||
7860 | |||
7861 | else if (category == 2)//Group Prims | ||
7862 | { | ||
7863 | return land.GroupPrims; | ||
7864 | } | ||
7865 | |||
7866 | else if (category == 3)//Other Prims | ||
7867 | { | ||
7868 | return land.OtherPrims; | ||
7869 | } | ||
7870 | |||
7871 | else if (category == 4)//Selected | ||
7872 | { | ||
7873 | return land.SelectedPrims; | ||
7874 | } | ||
7875 | |||
7876 | else if (category == 5)//Temp | ||
7877 | { | ||
7878 | return 0;//land. | ||
7879 | } | ||
7880 | } | ||
7881 | } | ||
7882 | return 0; | ||
7883 | } | ||
7884 | |||
7885 | public LSL_List llGetParcelPrimOwners(LSL_Vector pos) | ||
7886 | { | ||
7887 | m_host.AddScriptLPS(1); | ||
7888 | LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); | ||
7889 | LSL_List ret = new LSL_List(); | ||
7890 | if (land != null) | ||
7891 | { | ||
7892 | foreach (KeyValuePair<UUID, int> d in land.getLandObjectOwners()) | ||
7893 | { | ||
7894 | ret.Add(d.Key.ToString()); | ||
7895 | ret.Add(d.Value); | ||
7896 | } | ||
7897 | } | ||
7898 | // ScriptSleep(2000); | ||
7899 | return ret; | ||
7900 | } | ||
7901 | |||
7902 | public LSL_Integer llGetObjectPrimCount(string object_id) | ||
7903 | { | ||
7904 | m_host.AddScriptLPS(1); | ||
7905 | SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id)); | ||
7906 | if (part == null) | ||
7907 | { | ||
7908 | return 0; | ||
7909 | } | ||
7910 | else | ||
7911 | { | ||
7912 | return part.ParentGroup.Children.Count; | ||
7913 | } | ||
7914 | } | ||
7915 | |||
7916 | public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide) | ||
7917 | { | ||
7918 | m_host.AddScriptLPS(1); | ||
7919 | // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation | ||
7920 | // Which probably will be irrelevent in OpenSim.... | ||
7921 | LandData land = World.GetLandData((float)pos.x, (float)pos.y); | ||
7922 | |||
7923 | float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus; | ||
7924 | |||
7925 | if (land == null) | ||
7926 | { | ||
7927 | return 0; | ||
7928 | } | ||
7929 | |||
7930 | if (sim_wide == 1) | ||
7931 | { | ||
7932 | decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor; | ||
7933 | |||
7934 | return (int)v; | ||
7935 | } | ||
7936 | |||
7937 | else | ||
7938 | { | ||
7939 | decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor; | ||
7940 | |||
7941 | return (int)v; | ||
7942 | } | ||
7943 | |||
7944 | } | ||
7945 | |||
7946 | public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) | ||
7947 | { | ||
7948 | m_host.AddScriptLPS(1); | ||
7949 | LandData land = World.GetLandData((float)pos.x, (float)pos.y); | ||
7950 | if (land == null) | ||
7951 | { | ||
7952 | return new LSL_List(0); | ||
7953 | } | ||
7954 | LSL_List ret = new LSL_List(); | ||
7955 | foreach (object o in param.Data) | ||
7956 | { | ||
7957 | switch (o.ToString()) | ||
7958 | { | ||
7959 | case "0": | ||
7960 | ret = ret + new LSL_List(land.Name); | ||
7961 | break; | ||
7962 | case "1": | ||
7963 | ret = ret + new LSL_List(land.Description); | ||
7964 | break; | ||
7965 | case "2": | ||
7966 | ret = ret + new LSL_List(land.OwnerID.ToString()); | ||
7967 | break; | ||
7968 | case "3": | ||
7969 | ret = ret + new LSL_List(land.GroupID.ToString()); | ||
7970 | break; | ||
7971 | case "4": | ||
7972 | ret = ret + new LSL_List(land.Area); | ||
7973 | break; | ||
7974 | default: | ||
7975 | ret = ret + new LSL_List(0); | ||
7976 | break; | ||
7977 | } | ||
7978 | } | ||
7979 | return ret; | ||
7980 | } | ||
7981 | |||
7982 | public void llSetLinkTexture(int linknumber, string texture, int face) | ||
7983 | { | ||
7984 | m_host.AddScriptLPS(1); | ||
7985 | |||
7986 | if (m_host.ParentGroup == null) | ||
7987 | return; | ||
7988 | |||
7989 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); | ||
7990 | |||
7991 | if (part == null) | ||
7992 | return; | ||
7993 | |||
7994 | SetTexture(part, texture, face); | ||
7995 | // ScriptSleep(200); | ||
7996 | } | ||
7997 | |||
7998 | public LSL_String llStringTrim(string src, int type) | ||
7999 | { | ||
8000 | m_host.AddScriptLPS(1); | ||
8001 | if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } | ||
8002 | if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } | ||
8003 | if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); } | ||
8004 | return src; | ||
8005 | } | ||
8006 | |||
8007 | public LSL_List llGetObjectDetails(string id, LSL_List args) | ||
8008 | { | ||
8009 | m_host.AddScriptLPS(1); | ||
8010 | LSL_List ret = new LSL_List(); | ||
8011 | UUID key = new UUID(); | ||
8012 | if (UUID.TryParse(id, out key)) | ||
8013 | { | ||
8014 | ScenePresence av = World.GetScenePresence(key); | ||
8015 | |||
8016 | if (av != null) | ||
8017 | { | ||
8018 | foreach (object o in args.Data) | ||
8019 | { | ||
8020 | switch (o.ToString()) | ||
8021 | { | ||
8022 | case "1": | ||
8023 | ret.Add(av.Firstname + " " + av.Lastname); | ||
8024 | break; | ||
8025 | case "2": | ||
8026 | ret.Add(""); | ||
8027 | break; | ||
8028 | case "3": | ||
8029 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); | ||
8030 | break; | ||
8031 | case "4": | ||
8032 | ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); | ||
8033 | break; | ||
8034 | case "5": | ||
8035 | ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); | ||
8036 | break; | ||
8037 | case "6": | ||
8038 | ret.Add(id); | ||
8039 | break; | ||
8040 | case "7": | ||
8041 | ret.Add(UUID.Zero.ToString()); | ||
8042 | break; | ||
8043 | case "8": | ||
8044 | ret.Add(UUID.Zero.ToString()); | ||
8045 | break; | ||
8046 | } | ||
8047 | } | ||
8048 | return ret; | ||
8049 | } | ||
8050 | SceneObjectPart obj = World.GetSceneObjectPart(key); | ||
8051 | if (obj != null) | ||
8052 | { | ||
8053 | foreach (object o in args.Data) | ||
8054 | { | ||
8055 | switch (o.ToString()) | ||
8056 | { | ||
8057 | case "1": | ||
8058 | ret.Add(obj.Name); | ||
8059 | break; | ||
8060 | case "2": | ||
8061 | ret.Add(obj.Description); | ||
8062 | break; | ||
8063 | case "3": | ||
8064 | ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); | ||
8065 | break; | ||
8066 | case "4": | ||
8067 | ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); | ||
8068 | break; | ||
8069 | case "5": | ||
8070 | ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); | ||
8071 | break; | ||
8072 | case "6": | ||
8073 | ret.Add(obj.OwnerID.ToString()); | ||
8074 | break; | ||
8075 | case "7": | ||
8076 | ret.Add(obj.GroupID.ToString()); | ||
8077 | break; | ||
8078 | case "8": | ||
8079 | ret.Add(obj.CreatorID.ToString()); | ||
8080 | break; | ||
8081 | } | ||
8082 | } | ||
8083 | return ret; | ||
8084 | } | ||
8085 | } | ||
8086 | return new LSL_List(); | ||
8087 | } | ||
8088 | |||
8089 | |||
8090 | internal UUID ScriptByName(string name) | ||
8091 | { | ||
8092 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
8093 | { | ||
8094 | if (item.Type == 10 && item.Name == name) | ||
8095 | return item.ItemID; | ||
8096 | } | ||
8097 | return UUID.Zero; | ||
8098 | } | ||
8099 | |||
8100 | internal void ShoutError(string msg) | ||
8101 | { | ||
8102 | llShout(ScriptBaseClass.DEBUG_CHANNEL, msg); | ||
8103 | } | ||
8104 | |||
8105 | internal void NotImplemented(string command) | ||
8106 | { | ||
8107 | if (throwErrorOnNotImplemented) | ||
8108 | throw new NotImplementedException("Command not implemented: " + command); | ||
8109 | } | ||
8110 | |||
8111 | internal void Deprecated(string command) | ||
8112 | { | ||
8113 | throw new Exception("Command deprecated: " + command); | ||
8114 | } | ||
8115 | |||
8116 | internal void LSLError(string msg) | ||
8117 | { | ||
8118 | throw new Exception("LSL Runtime Error: " + msg); | ||
8119 | } | ||
8120 | |||
8121 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); | ||
8122 | private void WithNotecard(UUID assetID, AssetRequestCallback cb) | ||
8123 | { | ||
8124 | World.AssetCache.GetAsset(assetID, delegate(UUID i, AssetBase a) { cb(i, a); }, false); | ||
8125 | } | ||
8126 | |||
8127 | public LSL_String llGetNumberOfNotecardLines(string name) | ||
8128 | { | ||
8129 | m_host.AddScriptLPS(1); | ||
8130 | |||
8131 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
8132 | { | ||
8133 | if (item.Type == 7 && item.Name == name) | ||
8134 | { | ||
8135 | UUID tid = AsyncCommands. | ||
8136 | DataserverPlugin.RegisterRequest(m_localID, | ||
8137 | m_itemID, item.AssetID.ToString()); | ||
8138 | if (NotecardCache.IsCached(item.AssetID)) | ||
8139 | { | ||
8140 | AsyncCommands. | ||
8141 | DataserverPlugin.DataserverReply(item.AssetID.ToString(), | ||
8142 | NotecardCache.GetLines(item.AssetID).ToString()); | ||
8143 | // ScriptSleep(100); | ||
8144 | return tid.ToString(); | ||
8145 | } | ||
8146 | WithNotecard(item.AssetID, delegate (UUID id, AssetBase a) | ||
8147 | { | ||
8148 | System.Text.ASCIIEncoding enc = | ||
8149 | new System.Text.ASCIIEncoding(); | ||
8150 | string data = enc.GetString(a.Data); | ||
8151 | //Console.WriteLine(data); | ||
8152 | NotecardCache.Cache(id, data); | ||
8153 | AsyncCommands. | ||
8154 | DataserverPlugin.DataserverReply(id.ToString(), | ||
8155 | NotecardCache.GetLines(id).ToString()); | ||
8156 | }); | ||
8157 | // ScriptSleep(100); | ||
8158 | return tid.ToString(); | ||
8159 | } | ||
8160 | } | ||
8161 | // if we got to here, we didn't find the notecard the script was asking for | ||
8162 | // => complain loudly, as specified by the LSL docs | ||
8163 | ShoutError("Notecard '" + name + "' could not be found."); | ||
8164 | |||
8165 | // ScriptSleep(100); | ||
8166 | return UUID.Zero.ToString(); | ||
8167 | } | ||
8168 | |||
8169 | public LSL_String llGetNotecardLine(string name, int line) | ||
8170 | { | ||
8171 | m_host.AddScriptLPS(1); | ||
8172 | |||
8173 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
8174 | { | ||
8175 | if (item.Type == 7 && item.Name == name) | ||
8176 | { | ||
8177 | UUID tid = AsyncCommands. | ||
8178 | DataserverPlugin.RegisterRequest(m_localID, | ||
8179 | m_itemID, item.AssetID.ToString()); | ||
8180 | |||
8181 | if (NotecardCache.IsCached(item.AssetID)) | ||
8182 | { | ||
8183 | AsyncCommands. | ||
8184 | DataserverPlugin.DataserverReply(item.AssetID.ToString(), | ||
8185 | NotecardCache.GetLine(item.AssetID, line)); | ||
8186 | // ScriptSleep(100); | ||
8187 | return tid.ToString(); | ||
8188 | } | ||
8189 | |||
8190 | WithNotecard(item.AssetID, delegate (UUID id, AssetBase a) | ||
8191 | { | ||
8192 | System.Text.ASCIIEncoding enc = | ||
8193 | new System.Text.ASCIIEncoding(); | ||
8194 | string data = enc.GetString(a.Data); | ||
8195 | //Console.WriteLine(data); | ||
8196 | NotecardCache.Cache(id, data); | ||
8197 | AsyncCommands. | ||
8198 | DataserverPlugin.DataserverReply(id.ToString(), | ||
8199 | NotecardCache.GetLine(id, line)); | ||
8200 | }); | ||
8201 | |||
8202 | // ScriptSleep(100); | ||
8203 | return tid.ToString(); | ||
8204 | } | ||
8205 | } | ||
8206 | |||
8207 | // if we got to here, we didn't find the notecard the script was asking for | ||
8208 | // => complain loudly, as specified by the LSL docs | ||
8209 | ShoutError("Notecard '" + name + "' could not be found."); | ||
8210 | |||
8211 | // ScriptSleep(100); | ||
8212 | return UUID.Zero.ToString(); | ||
8213 | } | ||
8214 | |||
8215 | } | ||
8216 | |||
8217 | public class NotecardCache | ||
8218 | { | ||
8219 | private class Notecard | ||
8220 | { | ||
8221 | public string[] text; | ||
8222 | public DateTime lastRef; | ||
8223 | } | ||
8224 | |||
8225 | private static Dictionary<UUID, Notecard> m_Notecards = | ||
8226 | new Dictionary<UUID, Notecard>(); | ||
8227 | |||
8228 | public static void Cache(UUID assetID, string text) | ||
8229 | { | ||
8230 | CacheCheck(); | ||
8231 | |||
8232 | lock (m_Notecards) | ||
8233 | { | ||
8234 | if (m_Notecards.ContainsKey(assetID)) | ||
8235 | return; | ||
8236 | |||
8237 | Notecard nc = new Notecard(); | ||
8238 | nc.lastRef = DateTime.Now; | ||
8239 | nc.text = ParseText(text.Replace("\r", "").Split('\n')); | ||
8240 | m_Notecards[assetID] = nc; | ||
8241 | } | ||
8242 | } | ||
8243 | |||
8244 | private static string[] ParseText(string[] input) | ||
8245 | { | ||
8246 | int idx = 0; | ||
8247 | int level = 0; | ||
8248 | List<string> output = new List<string>(); | ||
8249 | string[] words; | ||
8250 | |||
8251 | while (idx < input.Length) | ||
8252 | { | ||
8253 | if (input[idx] == "{") | ||
8254 | { | ||
8255 | level++; | ||
8256 | idx++; | ||
8257 | continue; | ||
8258 | } | ||
8259 | |||
8260 | if (input[idx]== "}") | ||
8261 | { | ||
8262 | level--; | ||
8263 | idx++; | ||
8264 | continue; | ||
8265 | } | ||
8266 | |||
8267 | switch (level) | ||
8268 | { | ||
8269 | case 0: | ||
8270 | words = input[idx].Split(' '); // Linden text ver | ||
8271 | // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) | ||
8272 | if (words.Length < 3) | ||
8273 | return new String[0]; | ||
8274 | |||
8275 | int version = int.Parse(words[3]); | ||
8276 | if (version != 2) | ||
8277 | return new String[0]; | ||
8278 | break; | ||
8279 | case 1: | ||
8280 | words = input[idx].Split(' '); | ||
8281 | if (words[0] == "LLEmbeddedItems") | ||
8282 | break; | ||
8283 | if (words[0] == "Text") | ||
8284 | { | ||
8285 | int len = int.Parse(words[2]); | ||
8286 | idx++; | ||
8287 | |||
8288 | int count = -1; | ||
8289 | |||
8290 | while (count < len) | ||
8291 | { | ||
8292 | // int l = input[idx].Length; | ||
8293 | string ln = input[idx]; | ||
8294 | |||
8295 | int need = len-count-1; | ||
8296 | if (ln.Length > need) | ||
8297 | ln = ln.Substring(0, need); | ||
8298 | |||
8299 | output.Add(ln); | ||
8300 | count += ln.Length + 1; | ||
8301 | idx++; | ||
8302 | } | ||
8303 | |||
8304 | return output.ToArray(); | ||
8305 | } | ||
8306 | break; | ||
8307 | case 2: | ||
8308 | words = input[idx].Split(' '); // count | ||
8309 | if (words[0] == "count") | ||
8310 | { | ||
8311 | int c = int.Parse(words[1]); | ||
8312 | if (c > 0) | ||
8313 | return new String[0]; | ||
8314 | break; | ||
8315 | } | ||
8316 | break; | ||
8317 | } | ||
8318 | idx++; | ||
8319 | } | ||
8320 | return output.ToArray(); | ||
8321 | } | ||
8322 | |||
8323 | public static bool IsCached(UUID assetID) | ||
8324 | { | ||
8325 | lock (m_Notecards) | ||
8326 | { | ||
8327 | return m_Notecards.ContainsKey(assetID); | ||
8328 | } | ||
8329 | } | ||
8330 | |||
8331 | public static int GetLines(UUID assetID) | ||
8332 | { | ||
8333 | if (!IsCached(assetID)) | ||
8334 | return -1; | ||
8335 | |||
8336 | lock (m_Notecards) | ||
8337 | { | ||
8338 | m_Notecards[assetID].lastRef = DateTime.Now; | ||
8339 | return m_Notecards[assetID].text.Length; | ||
8340 | } | ||
8341 | } | ||
8342 | |||
8343 | public static string GetLine(UUID assetID, int line) | ||
8344 | { | ||
8345 | if (line < 0) | ||
8346 | return ""; | ||
8347 | |||
8348 | string data; | ||
8349 | |||
8350 | if (!IsCached(assetID)) | ||
8351 | return ""; | ||
8352 | |||
8353 | lock (m_Notecards) | ||
8354 | { | ||
8355 | m_Notecards[assetID].lastRef = DateTime.Now; | ||
8356 | |||
8357 | if (line >= m_Notecards[assetID].text.Length) | ||
8358 | return "\n\n\n"; | ||
8359 | |||
8360 | data = m_Notecards[assetID].text[line]; | ||
8361 | if (data.Length > 255) | ||
8362 | data = data.Substring(0, 255); | ||
8363 | |||
8364 | return data; | ||
8365 | } | ||
8366 | } | ||
8367 | |||
8368 | public static void CacheCheck() | ||
8369 | { | ||
8370 | foreach (UUID key in new List<UUID>(m_Notecards.Keys)) | ||
8371 | { | ||
8372 | Notecard nc = m_Notecards[key]; | ||
8373 | if (nc.lastRef.AddSeconds(30) < DateTime.Now) | ||
8374 | m_Notecards.Remove(key); | ||
180 | } | 8375 | } |
181 | } | 8376 | } |
182 | } | 8377 | } |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs deleted file mode 100644 index 851e43b..0000000 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api_Base.cs +++ /dev/null | |||
@@ -1,8279 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) Contributors, http://opensimulator.org/ | ||
3 | * See CONTRIBUTORS.TXT for a full list of copyright holders. | ||
4 | * | ||
5 | * Redistribution and use in source and binary forms, with or without | ||
6 | * modification, are permitted provided that the following conditions are met: | ||
7 | * * Redistributions of source code must retain the above copyright | ||
8 | * notice, this list of conditions and the following disclaimer. | ||
9 | * * Redistributions in binary form must reproduce the above copyright | ||
10 | * notice, this list of conditions and the following disclaimer in the | ||
11 | * documentation and/or other materials provided with the distribution. | ||
12 | * * Neither the name of the OpenSim Project nor the | ||
13 | * names of its contributors may be used to endorse or promote products | ||
14 | * derived from this software without specific prior written permission. | ||
15 | * | ||
16 | * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY | ||
17 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||
18 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||
19 | * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY | ||
20 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||
21 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||
22 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||
23 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
26 | */ | ||
27 | |||
28 | using System; | ||
29 | using System.Collections; | ||
30 | using System.Collections.Generic; | ||
31 | using System.Runtime.Remoting.Lifetime; | ||
32 | using System.Text; | ||
33 | using System.Threading; | ||
34 | using Nini.Config; | ||
35 | using OpenMetaverse; | ||
36 | using OpenMetaverse.Packets; | ||
37 | using OpenSim; | ||
38 | using OpenSim.Framework; | ||
39 | using OpenSim.Framework.Communications.Cache; | ||
40 | using OpenSim.Region.Environment; | ||
41 | using OpenSim.Region.Interfaces; | ||
42 | using OpenSim.Region.Environment.Interfaces; | ||
43 | using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney; | ||
44 | using OpenSim.Region.Environment.Modules.World.Land; | ||
45 | using OpenSim.Region.Environment.Scenes; | ||
46 | using OpenSim.Region.Physics.Manager; | ||
47 | using OpenSim.Region.ScriptEngine.Shared; | ||
48 | using OpenSim.Region.ScriptEngine.Shared.Api.Plugins; | ||
49 | using OpenSim.Region.ScriptEngine.Shared.ScriptBase; | ||
50 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
51 | using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; | ||
52 | |||
53 | using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; | ||
54 | using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; | ||
55 | using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
56 | using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; | ||
57 | using LSL_Rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; | ||
58 | using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; | ||
59 | using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; | ||
60 | |||
61 | namespace OpenSim.Region.ScriptEngine.Shared.Api | ||
62 | { | ||
63 | /// <summary> | ||
64 | /// Contains all LSL ll-functions. This class will be in Default AppDomain. | ||
65 | /// </summary> | ||
66 | public class LSL_Api_Base : MarshalByRefObject | ||
67 | { | ||
68 | protected IEventReceiver m_ScriptEngine; | ||
69 | protected SceneObjectPart m_host; | ||
70 | protected uint m_localID; | ||
71 | protected UUID m_itemID; | ||
72 | protected bool throwErrorOnNotImplemented = true; | ||
73 | protected AsyncCommandManager AsyncCommands = null; | ||
74 | protected float m_ScriptDelayFactor = 1.0f; | ||
75 | protected float m_ScriptDistanceFactor = 1.0f; | ||
76 | |||
77 | private DateTime m_timer = DateTime.Now; | ||
78 | private bool m_waitingForScriptAnswer=false; | ||
79 | protected void ScriptSleep(int delay) | ||
80 | { | ||
81 | delay = (int)((float)delay * m_ScriptDelayFactor); | ||
82 | if (delay == 0) | ||
83 | return; | ||
84 | System.Threading.Thread.Sleep(delay); | ||
85 | } | ||
86 | |||
87 | public Scene World | ||
88 | { | ||
89 | get { return m_ScriptEngine.World; } | ||
90 | } | ||
91 | |||
92 | private List<SceneObjectPart> GetLinkParts(int linkType) | ||
93 | { | ||
94 | List<SceneObjectPart> ret = new List<SceneObjectPart>(); | ||
95 | ret.Add(m_host); | ||
96 | |||
97 | switch (linkType) | ||
98 | { | ||
99 | case ScriptBaseClass.LINK_SET: | ||
100 | if (m_host.ParentGroup != null) | ||
101 | return new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); | ||
102 | return ret; | ||
103 | |||
104 | case ScriptBaseClass.LINK_ROOT: | ||
105 | if (m_host.ParentGroup != null) | ||
106 | { | ||
107 | ret = new List<SceneObjectPart>(); | ||
108 | ret.Add(m_host.ParentGroup.RootPart); | ||
109 | return ret; | ||
110 | } | ||
111 | return ret; | ||
112 | |||
113 | case ScriptBaseClass.LINK_ALL_OTHERS: | ||
114 | if (m_host.ParentGroup == null) | ||
115 | return new List<SceneObjectPart>(); | ||
116 | ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); | ||
117 | if (ret.Contains(m_host)) | ||
118 | ret.Remove(m_host); | ||
119 | return ret; | ||
120 | |||
121 | case ScriptBaseClass.LINK_ALL_CHILDREN: | ||
122 | if (m_host.ParentGroup == null) | ||
123 | return new List<SceneObjectPart>(); | ||
124 | ret = new List<SceneObjectPart>(m_host.ParentGroup.Children.Values); | ||
125 | if (ret.Contains(m_host.ParentGroup.RootPart)) | ||
126 | ret.Remove(m_host.ParentGroup.RootPart); | ||
127 | return ret; | ||
128 | |||
129 | case ScriptBaseClass.LINK_THIS: | ||
130 | return ret; | ||
131 | |||
132 | default: | ||
133 | if (linkType < 0 || m_host.ParentGroup == null) | ||
134 | return new List<SceneObjectPart>(); | ||
135 | SceneObjectPart target = m_host.ParentGroup.GetLinkNumPart(linkType); | ||
136 | if (target == null) | ||
137 | return new List<SceneObjectPart>(); | ||
138 | ret = new List<SceneObjectPart>(); | ||
139 | ret.Add(target); | ||
140 | return ret; | ||
141 | |||
142 | } | ||
143 | } | ||
144 | |||
145 | private UUID InventorySelf() | ||
146 | { | ||
147 | UUID invItemID = new UUID(); | ||
148 | |||
149 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
150 | { | ||
151 | if (inv.Value.Type == 10 && inv.Value.ItemID == m_itemID) | ||
152 | { | ||
153 | invItemID = inv.Key; | ||
154 | break; | ||
155 | } | ||
156 | } | ||
157 | |||
158 | return invItemID; | ||
159 | } | ||
160 | |||
161 | private UUID InventoryKey(string name, int type) | ||
162 | { | ||
163 | m_host.AddScriptLPS(1); | ||
164 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
165 | { | ||
166 | if (inv.Value.Name == name) | ||
167 | { | ||
168 | if (inv.Value.Type != type) | ||
169 | return UUID.Zero; | ||
170 | |||
171 | return inv.Value.AssetID.ToString(); | ||
172 | } | ||
173 | } | ||
174 | return UUID.Zero; | ||
175 | } | ||
176 | |||
177 | private UUID InventoryKey(string name) | ||
178 | { | ||
179 | m_host.AddScriptLPS(1); | ||
180 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
181 | { | ||
182 | if (inv.Value.Name == name) | ||
183 | { | ||
184 | return inv.Value.AssetID.ToString(); | ||
185 | } | ||
186 | } | ||
187 | return UUID.Zero; | ||
188 | } | ||
189 | |||
190 | |||
191 | /// <summary> | ||
192 | /// accepts a valid UUID, -or- a name of an inventory item. | ||
193 | /// Returns a valid UUID or UUID.Zero if key invalid and item not found | ||
194 | /// in prim inventory. | ||
195 | /// </summary> | ||
196 | /// <param name="k"></param> | ||
197 | /// <returns></returns> | ||
198 | private UUID KeyOrName(string k) | ||
199 | { | ||
200 | UUID key = UUID.Zero; | ||
201 | |||
202 | // if we can parse the string as a key, use it. | ||
203 | if (UUID.TryParse(k, out key)) | ||
204 | { | ||
205 | return key; | ||
206 | } | ||
207 | // else try to locate the name in inventory of object. found returns key, | ||
208 | // not found returns UUID.Zero which will translate to the default particle texture | ||
209 | else | ||
210 | { | ||
211 | return InventoryKey(k); | ||
212 | } | ||
213 | } | ||
214 | |||
215 | //These are the implementations of the various ll-functions used by the LSL scripts. | ||
216 | public LSL_Float llSin(double f) | ||
217 | { | ||
218 | m_host.AddScriptLPS(1); | ||
219 | return (double)Math.Sin(f); | ||
220 | } | ||
221 | |||
222 | public LSL_Float llCos(double f) | ||
223 | { | ||
224 | m_host.AddScriptLPS(1); | ||
225 | return (double)Math.Cos(f); | ||
226 | } | ||
227 | |||
228 | public LSL_Float llTan(double f) | ||
229 | { | ||
230 | m_host.AddScriptLPS(1); | ||
231 | return (double)Math.Tan(f); | ||
232 | } | ||
233 | |||
234 | public LSL_Float llAtan2(double x, double y) | ||
235 | { | ||
236 | m_host.AddScriptLPS(1); | ||
237 | return (double)Math.Atan2(y, x); | ||
238 | } | ||
239 | |||
240 | public LSL_Float llSqrt(double f) | ||
241 | { | ||
242 | m_host.AddScriptLPS(1); | ||
243 | return (double)Math.Sqrt(f); | ||
244 | } | ||
245 | |||
246 | public LSL_Float llPow(double fbase, double fexponent) | ||
247 | { | ||
248 | m_host.AddScriptLPS(1); | ||
249 | return (double)Math.Pow(fbase, fexponent); | ||
250 | } | ||
251 | |||
252 | public LSL_Integer llAbs(int i) | ||
253 | { | ||
254 | m_host.AddScriptLPS(1); | ||
255 | return (int)Math.Abs(i); | ||
256 | } | ||
257 | |||
258 | public LSL_Float llFabs(double f) | ||
259 | { | ||
260 | m_host.AddScriptLPS(1); | ||
261 | return (double)Math.Abs(f); | ||
262 | } | ||
263 | |||
264 | public LSL_Float llFrand(double mag) | ||
265 | { | ||
266 | m_host.AddScriptLPS(1); | ||
267 | lock (Util.RandomClass) | ||
268 | { | ||
269 | return Util.RandomClass.NextDouble() * mag; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | public LSL_Integer llFloor(double f) | ||
274 | { | ||
275 | m_host.AddScriptLPS(1); | ||
276 | return (int)Math.Floor(f); | ||
277 | } | ||
278 | |||
279 | public LSL_Integer llCeil(double f) | ||
280 | { | ||
281 | m_host.AddScriptLPS(1); | ||
282 | return (int)Math.Ceiling(f); | ||
283 | } | ||
284 | |||
285 | // Xantor 01/May/2008 fixed midpointrounding (2.5 becomes 3.0 instead of 2.0, default = ToEven) | ||
286 | public LSL_Integer llRound(double f) | ||
287 | { | ||
288 | m_host.AddScriptLPS(1); | ||
289 | return (int)Math.Round(f, MidpointRounding.AwayFromZero); | ||
290 | } | ||
291 | |||
292 | //This next group are vector operations involving squaring and square root. ckrinke | ||
293 | public LSL_Float llVecMag(LSL_Vector v) | ||
294 | { | ||
295 | m_host.AddScriptLPS(1); | ||
296 | return LSL_Vector.Mag(v); | ||
297 | } | ||
298 | |||
299 | public LSL_Vector llVecNorm(LSL_Vector v) | ||
300 | { | ||
301 | m_host.AddScriptLPS(1); | ||
302 | double mag = LSL_Vector.Mag(v); | ||
303 | LSL_Vector nor = new LSL_Vector(); | ||
304 | nor.x = v.x / mag; | ||
305 | nor.y = v.y / mag; | ||
306 | nor.z = v.z / mag; | ||
307 | return nor; | ||
308 | } | ||
309 | |||
310 | public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) | ||
311 | { | ||
312 | m_host.AddScriptLPS(1); | ||
313 | double dx = a.x - b.x; | ||
314 | double dy = a.y - b.y; | ||
315 | double dz = a.z - b.z; | ||
316 | return Math.Sqrt(dx * dx + dy * dy + dz * dz); | ||
317 | } | ||
318 | |||
319 | //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke | ||
320 | |||
321 | // Utility function for llRot2Euler | ||
322 | |||
323 | // normalize an angle between 0 - 2*PI (0 and 360 degrees) | ||
324 | private double NormalizeAngle(double angle) | ||
325 | { | ||
326 | angle = angle % (Math.PI * 2); | ||
327 | if (angle < 0) angle = angle + Math.PI * 2; | ||
328 | return angle; | ||
329 | } | ||
330 | |||
331 | // Old implementation of llRot2Euler, now normalized | ||
332 | |||
333 | public LSL_Vector llRot2Euler(LSL_Rotation r) | ||
334 | { | ||
335 | m_host.AddScriptLPS(1); | ||
336 | //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke | ||
337 | LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); | ||
338 | double m = (t.x + t.y + t.z + t.s); | ||
339 | if (m == 0) return new LSL_Vector(); | ||
340 | double n = 2 * (r.y * r.s + r.x * r.z); | ||
341 | double p = m * m - n * n; | ||
342 | if (p > 0) | ||
343 | return new LSL_Vector(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))), | ||
344 | NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), | ||
345 | NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)))); | ||
346 | else if (n > 0) | ||
347 | return new LSL_Vector(0.0, Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); | ||
348 | else | ||
349 | return new LSL_Vector(0.0, -Math.PI / 2, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); | ||
350 | } | ||
351 | |||
352 | /* From wiki: | ||
353 | The Euler angle vector (in radians) is converted to a rotation by doing the rotations around the 3 axes | ||
354 | in Z, Y, X order. So llEuler2Rot(<1.0, 2.0, 3.0> * DEG_TO_RAD) generates a rotation by taking the zero rotation, | ||
355 | a vector pointing along the X axis, first rotating it 3 degrees around the global Z axis, then rotating the resulting | ||
356 | vector 2 degrees around the global Y axis, and finally rotating that 1 degree around the global X axis. | ||
357 | */ | ||
358 | |||
359 | /* How we arrived at this llEuler2Rot | ||
360 | * | ||
361 | * Experiment in SL to determine conventions: | ||
362 | * llEuler2Rot(<PI,0,0>)=<1,0,0,0> | ||
363 | * llEuler2Rot(<0,PI,0>)=<0,1,0,0> | ||
364 | * llEuler2Rot(<0,0,PI>)=<0,0,1,0> | ||
365 | * | ||
366 | * Important facts about Quaternions | ||
367 | * - multiplication is non-commutative (a*b != b*a) | ||
368 | * - http://en.wikipedia.org/wiki/Quaternion#Basis_multiplication | ||
369 | * | ||
370 | * Above SL experiment gives (c1,c2,c3,s1,s2,s3 as defined in our llEuler2Rot): | ||
371 | * Qx = c1+i*s1 | ||
372 | * Qy = c2+j*s2; | ||
373 | * Qz = c3+k*s3; | ||
374 | * | ||
375 | * Rotations applied in order (from above) Z, Y, X | ||
376 | * Q = (Qz * Qy) * Qx | ||
377 | * ((c1+i*s1)*(c2+j*s2))*(c3+k*s3) | ||
378 | * (c1*c2+i*s1*c2+j*c1*s2+ij*s1*s2)*(c3+k*s3) | ||
379 | * (c1*c2+i*s1*c2+j*c1*s2+k*s1*s2)*(c3+k*s3) | ||
380 | * 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 | ||
381 | * 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 | ||
382 | * regroup: x=i*(s1*c2*c3+c1*s2*s3) | ||
383 | * y=j*(c1*s2*c3-s1*c2*s3) | ||
384 | * z=k*(s1*s2*c3+c1*c2*s3) | ||
385 | * s= c1*c2*c3-s1*s2*s3 | ||
386 | * | ||
387 | * This implementation agrees with the functions found here: | ||
388 | * http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions | ||
389 | * And with the results in SL. | ||
390 | * | ||
391 | * It's also possible to calculate llEuler2Rot by direct multiplication of | ||
392 | * the Qz, Qy, and Qx vectors (as above - and done in the "accurate" function | ||
393 | * from the wiki). | ||
394 | * Apparently in some cases this is better from a numerical precision perspective? | ||
395 | */ | ||
396 | |||
397 | public LSL_Rotation llEuler2Rot(LSL_Vector v) | ||
398 | { | ||
399 | m_host.AddScriptLPS(1); | ||
400 | |||
401 | double x,y,z,s; | ||
402 | |||
403 | double c1 = Math.Cos(v.x/2.0); | ||
404 | double c2 = Math.Cos(v.y/2.0); | ||
405 | double c3 = Math.Cos(v.z/2.0); | ||
406 | double s1 = Math.Sin(v.x/2.0); | ||
407 | double s2 = Math.Sin(v.y/2.0); | ||
408 | double s3 = Math.Sin(v.z/2.0); | ||
409 | |||
410 | x = s1*c2*c3+c1*s2*s3; | ||
411 | y = c1*s2*c3-s1*c2*s3; | ||
412 | z = s1*s2*c3+c1*c2*s3; | ||
413 | s = c1*c2*c3-s1*s2*s3; | ||
414 | |||
415 | return new LSL_Rotation(x, y, z, s); | ||
416 | } | ||
417 | |||
418 | public LSL_Rotation llAxes2Rot(LSL_Vector fwd, LSL_Vector left, LSL_Vector up) | ||
419 | { | ||
420 | m_host.AddScriptLPS(1); | ||
421 | double x, y, z, s; | ||
422 | int f = 0; | ||
423 | // Important Note: q1=<x,y,z,s> is equal to q2=<-x,-y,-z,-s> | ||
424 | // Computing quaternion x,y,z,s values | ||
425 | x = ((fwd.x - left.y - up.z + 1) / 4); | ||
426 | x *= x; | ||
427 | x = Math.Sqrt(Math.Sqrt(x)); | ||
428 | y = ((1 - up.z) / 2 - x * x); | ||
429 | y *= y; | ||
430 | y = Math.Sqrt(Math.Sqrt(y)); | ||
431 | z = ((1 - left.y) / 2 - x * x); | ||
432 | z *= z; | ||
433 | z = Math.Sqrt(Math.Sqrt(z)); | ||
434 | s = (1 - x * x - y * y - z * z); | ||
435 | s *= s; | ||
436 | s = Math.Sqrt(Math.Sqrt(s)); | ||
437 | |||
438 | // Set f for signs detection | ||
439 | if (fwd.y + left.x >= 0) { f += 1; } | ||
440 | if (fwd.z + up.x >= 0) { f += 2; } | ||
441 | if (left.z - up.y >= 0) { f += 4; } | ||
442 | // Set correct quaternion signs based on f value | ||
443 | if (f == 0) { x = -x; } | ||
444 | if (f == 1) { x = -x; y = -y; } | ||
445 | if (f == 2) { x = -x; z = -z; } | ||
446 | if (f == 3) { s = -s; } | ||
447 | if (f == 4) { x = -x; s = -s; } | ||
448 | if (f == 5) { z = -z; } | ||
449 | if (f == 6) { y = -y; } | ||
450 | |||
451 | LSL_Rotation result = new LSL_Rotation(x, y, z, s); | ||
452 | |||
453 | // a hack to correct a few questionable angles :( | ||
454 | if (llVecDist(llRot2Fwd(result), fwd) > 0.001 || llVecDist(llRot2Left(result), left) > 0.001) | ||
455 | result.s = -s; | ||
456 | |||
457 | return result; | ||
458 | } | ||
459 | |||
460 | public LSL_Vector llRot2Fwd(LSL_Rotation r) | ||
461 | { | ||
462 | m_host.AddScriptLPS(1); | ||
463 | |||
464 | double x, y, z, m; | ||
465 | |||
466 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | ||
467 | // m is always greater than zero | ||
468 | // if m is not equal to 1 then Rotation needs to be normalized | ||
469 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | ||
470 | { | ||
471 | m = 1.0 / Math.Sqrt(m); | ||
472 | r.x *= m; | ||
473 | r.y *= m; | ||
474 | r.z *= m; | ||
475 | r.s *= m; | ||
476 | } | ||
477 | |||
478 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | ||
479 | x = r.x * r.x - r.y * r.y - r.z * r.z + r.s * r.s; | ||
480 | y = 2 * (r.x * r.y + r.z * r.s); | ||
481 | z = 2 * (r.x * r.z - r.y * r.s); | ||
482 | return (new LSL_Vector(x, y, z)); | ||
483 | } | ||
484 | |||
485 | public LSL_Vector llRot2Left(LSL_Rotation r) | ||
486 | { | ||
487 | m_host.AddScriptLPS(1); | ||
488 | |||
489 | double x, y, z, m; | ||
490 | |||
491 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | ||
492 | // m is always greater than zero | ||
493 | // if m is not equal to 1 then Rotation needs to be normalized | ||
494 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | ||
495 | { | ||
496 | m = 1.0 / Math.Sqrt(m); | ||
497 | r.x *= m; | ||
498 | r.y *= m; | ||
499 | r.z *= m; | ||
500 | r.s *= m; | ||
501 | } | ||
502 | |||
503 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | ||
504 | x = 2 * (r.x * r.y - r.z * r.s); | ||
505 | y = -r.x * r.x + r.y * r.y - r.z * r.z + r.s * r.s; | ||
506 | z = 2 * (r.x * r.s + r.y * r.z); | ||
507 | return (new LSL_Vector(x, y, z)); | ||
508 | } | ||
509 | |||
510 | public LSL_Vector llRot2Up(LSL_Rotation r) | ||
511 | { | ||
512 | m_host.AddScriptLPS(1); | ||
513 | double x, y, z, m; | ||
514 | |||
515 | m = r.x * r.x + r.y * r.y + r.z * r.z + r.s * r.s; | ||
516 | // m is always greater than zero | ||
517 | // if m is not equal to 1 then Rotation needs to be normalized | ||
518 | if (Math.Abs(1.0 - m) > 0.000001) // allow a little slop here for calculation precision | ||
519 | { | ||
520 | m = 1.0 / Math.Sqrt(m); | ||
521 | r.x *= m; | ||
522 | r.y *= m; | ||
523 | r.z *= m; | ||
524 | r.s *= m; | ||
525 | } | ||
526 | |||
527 | // Fast Algebric Calculations instead of Vectors & Quaternions Product | ||
528 | x = 2 * (r.x * r.z + r.y * r.s); | ||
529 | y = 2 * (-r.x * r.s + r.y * r.z); | ||
530 | z = -r.x * r.x - r.y * r.y + r.z * r.z + r.s * r.s; | ||
531 | return (new LSL_Vector(x, y, z)); | ||
532 | } | ||
533 | |||
534 | public LSL_Rotation llRotBetween(LSL_Vector a, LSL_Vector b) | ||
535 | { | ||
536 | //A and B should both be normalized | ||
537 | m_host.AddScriptLPS(1); | ||
538 | double dotProduct = LSL_Vector.Dot(a, b); | ||
539 | LSL_Vector crossProduct = LSL_Vector.Cross(a, b); | ||
540 | double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b); | ||
541 | double angle = Math.Acos(dotProduct / magProduct); | ||
542 | LSL_Vector axis = LSL_Vector.Norm(crossProduct); | ||
543 | double s = Math.Sin(angle / 2); | ||
544 | |||
545 | double x = axis.x * s; | ||
546 | double y = axis.y * s; | ||
547 | double z = axis.z * s; | ||
548 | double w = Math.Cos(angle / 2); | ||
549 | |||
550 | if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w)) | ||
551 | return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); | ||
552 | |||
553 | return new LSL_Rotation((float)x, (float)y, (float)z, (float)w); | ||
554 | } | ||
555 | |||
556 | public void llWhisper(int channelID, string text) | ||
557 | { | ||
558 | m_host.AddScriptLPS(1); | ||
559 | |||
560 | if (text.Length > 1023) | ||
561 | text = text.Substring(0, 1023); | ||
562 | |||
563 | World.SimChat(Utils.StringToBytes(text), | ||
564 | ChatTypeEnum.Whisper, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
565 | |||
566 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
567 | wComm.DeliverMessage(ChatTypeEnum.Whisper, channelID, m_host.Name, m_host.UUID, text); | ||
568 | } | ||
569 | |||
570 | public void llSay(int channelID, string text) | ||
571 | { | ||
572 | m_host.AddScriptLPS(1); | ||
573 | |||
574 | if (text.Length > 1023) | ||
575 | text = text.Substring(0, 1023); | ||
576 | |||
577 | World.SimChat(Utils.StringToBytes(text), | ||
578 | ChatTypeEnum.Say, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
579 | |||
580 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
581 | wComm.DeliverMessage(ChatTypeEnum.Say, channelID, m_host.Name, m_host.UUID, text); | ||
582 | } | ||
583 | |||
584 | public void llShout(int channelID, string text) | ||
585 | { | ||
586 | m_host.AddScriptLPS(1); | ||
587 | |||
588 | if (text.Length > 1023) | ||
589 | text = text.Substring(0, 1023); | ||
590 | |||
591 | World.SimChat(Utils.StringToBytes(text), | ||
592 | ChatTypeEnum.Shout, channelID, m_host.AbsolutePosition, m_host.Name, m_host.UUID, true); | ||
593 | |||
594 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
595 | wComm.DeliverMessage(ChatTypeEnum.Shout, channelID, m_host.Name, m_host.UUID, text); | ||
596 | } | ||
597 | |||
598 | public void llRegionSay(int channelID, string text) | ||
599 | { | ||
600 | if (channelID == 0) | ||
601 | { | ||
602 | LSLError("Cannot use llRegionSay() on channel 0"); | ||
603 | return; | ||
604 | } | ||
605 | |||
606 | if (text.Length > 1023) | ||
607 | text = text.Substring(0, 1023); | ||
608 | |||
609 | m_host.AddScriptLPS(1); | ||
610 | |||
611 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
612 | wComm.DeliverMessage(ChatTypeEnum.Region, channelID, m_host.Name, m_host.UUID, text); | ||
613 | } | ||
614 | |||
615 | public LSL_Integer llListen(int channelID, string name, string ID, string msg) | ||
616 | { | ||
617 | m_host.AddScriptLPS(1); | ||
618 | UUID keyID; | ||
619 | UUID.TryParse(ID, out keyID); | ||
620 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
621 | return wComm.Listen(m_localID, m_itemID, m_host.UUID, channelID, name, keyID, msg); | ||
622 | } | ||
623 | |||
624 | public void llListenControl(int number, int active) | ||
625 | { | ||
626 | m_host.AddScriptLPS(1); | ||
627 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
628 | wComm.ListenControl(m_itemID, number, active); | ||
629 | } | ||
630 | |||
631 | public void llListenRemove(int number) | ||
632 | { | ||
633 | m_host.AddScriptLPS(1); | ||
634 | IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
635 | wComm.ListenRemove(m_itemID, number); | ||
636 | } | ||
637 | |||
638 | public void llSensor(string name, string id, int type, double range, double arc) | ||
639 | { | ||
640 | m_host.AddScriptLPS(1); | ||
641 | UUID keyID = UUID.Zero; | ||
642 | UUID.TryParse(id, out keyID); | ||
643 | |||
644 | AsyncCommands.SensorRepeatPlugin.SenseOnce(m_localID, m_itemID, name, keyID, type, range, arc, m_host); | ||
645 | } | ||
646 | |||
647 | public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) | ||
648 | { | ||
649 | m_host.AddScriptLPS(1); | ||
650 | UUID keyID = UUID.Zero; | ||
651 | UUID.TryParse(id, out keyID); | ||
652 | |||
653 | AsyncCommands.SensorRepeatPlugin.SetSenseRepeatEvent(m_localID, m_itemID, name, keyID, type, range, arc, rate, m_host); | ||
654 | } | ||
655 | |||
656 | public void llSensorRemove() | ||
657 | { | ||
658 | m_host.AddScriptLPS(1); | ||
659 | AsyncCommands.SensorRepeatPlugin.UnSetSenseRepeaterEvents(m_localID, m_itemID); | ||
660 | } | ||
661 | |||
662 | public string resolveName(UUID objecUUID) | ||
663 | { | ||
664 | // try avatar username surname | ||
665 | CachedUserInfo profile = World.CommsManager.UserProfileCacheService.GetUserDetails(objecUUID); | ||
666 | if (profile != null && profile.UserProfile != null) | ||
667 | { | ||
668 | string avatarname = profile.UserProfile.FirstName + " " + profile.UserProfile.SurName; | ||
669 | return avatarname; | ||
670 | } | ||
671 | // try an scene object | ||
672 | SceneObjectPart SOP = World.GetSceneObjectPart(objecUUID); | ||
673 | if (SOP != null) | ||
674 | { | ||
675 | string objectname = SOP.Name; | ||
676 | return objectname; | ||
677 | } | ||
678 | |||
679 | EntityBase SensedObject; | ||
680 | lock (World.Entities) | ||
681 | { | ||
682 | World.Entities.TryGetValue(objecUUID, out SensedObject); | ||
683 | } | ||
684 | |||
685 | if (SensedObject == null) | ||
686 | return String.Empty; | ||
687 | return SensedObject.Name; | ||
688 | } | ||
689 | |||
690 | public LSL_String llDetectedName(int number) | ||
691 | { | ||
692 | m_host.AddScriptLPS(1); | ||
693 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
694 | if (d == null) | ||
695 | return String.Empty; | ||
696 | return d.Name; | ||
697 | } | ||
698 | |||
699 | public LSL_String llDetectedKey(int number) | ||
700 | { | ||
701 | m_host.AddScriptLPS(1); | ||
702 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
703 | if (d == null) | ||
704 | return String.Empty; | ||
705 | return d.Key.ToString(); | ||
706 | } | ||
707 | |||
708 | public LSL_String llDetectedOwner(int number) | ||
709 | { | ||
710 | m_host.AddScriptLPS(1); | ||
711 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
712 | if (d == null) | ||
713 | return String.Empty; | ||
714 | return d.Owner.ToString(); | ||
715 | } | ||
716 | |||
717 | public LSL_Integer llDetectedType(int number) | ||
718 | { | ||
719 | m_host.AddScriptLPS(1); | ||
720 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
721 | if (d == null) | ||
722 | return 0; | ||
723 | return new LSL_Integer(d.Type); | ||
724 | } | ||
725 | |||
726 | public LSL_Vector llDetectedPos(int number) | ||
727 | { | ||
728 | m_host.AddScriptLPS(1); | ||
729 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
730 | if (d == null) | ||
731 | return new LSL_Vector(); | ||
732 | return d.Position; | ||
733 | } | ||
734 | |||
735 | public LSL_Vector llDetectedVel(int number) | ||
736 | { | ||
737 | m_host.AddScriptLPS(1); | ||
738 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
739 | if (d == null) | ||
740 | return new LSL_Vector(); | ||
741 | return d.Velocity; | ||
742 | } | ||
743 | |||
744 | public LSL_Vector llDetectedGrab(int number) | ||
745 | { | ||
746 | m_host.AddScriptLPS(1); | ||
747 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
748 | if (parms == null) | ||
749 | return new LSL_Vector(0, 0, 0); | ||
750 | |||
751 | return parms.OffsetPos; | ||
752 | } | ||
753 | |||
754 | public LSL_Rotation llDetectedRot(int number) | ||
755 | { | ||
756 | m_host.AddScriptLPS(1); | ||
757 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
758 | if (d == null) | ||
759 | return new LSL_Rotation(); | ||
760 | return d.Rotation; | ||
761 | } | ||
762 | |||
763 | public LSL_Integer llDetectedGroup(int number) | ||
764 | { | ||
765 | m_host.AddScriptLPS(1); | ||
766 | DetectParams d = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
767 | if (d == null) | ||
768 | return new LSL_Integer(0); | ||
769 | if (m_host.GroupID == d.Group) | ||
770 | return new LSL_Integer(1); | ||
771 | return new LSL_Integer(0); | ||
772 | } | ||
773 | |||
774 | public LSL_Integer llDetectedLinkNumber(int number) | ||
775 | { | ||
776 | m_host.AddScriptLPS(1); | ||
777 | DetectParams parms = m_ScriptEngine.GetDetectParams(m_itemID, number); | ||
778 | if (parms == null) | ||
779 | return new LSL_Integer(0); | ||
780 | |||
781 | return new LSL_Integer(parms.LinkNum); | ||
782 | } | ||
783 | |||
784 | public LSL_Vector llDetectedTouchBinormal(int index) | ||
785 | { | ||
786 | m_host.AddScriptLPS(1); | ||
787 | NotImplemented("llDetectedTouchBinormal"); | ||
788 | return new LSL_Vector(); | ||
789 | } | ||
790 | |||
791 | public LSL_Integer llDetectedTouchFace(int index) | ||
792 | { | ||
793 | m_host.AddScriptLPS(1); | ||
794 | NotImplemented("llDetectedTouchFace"); | ||
795 | return new LSL_Integer(0); | ||
796 | } | ||
797 | |||
798 | public LSL_Vector llDetectedTouchNormal(int index) | ||
799 | { | ||
800 | m_host.AddScriptLPS(1); | ||
801 | NotImplemented("llDetectedTouchNormal"); | ||
802 | return new LSL_Vector(); | ||
803 | } | ||
804 | |||
805 | public LSL_Vector llDetectedTouchPos(int index) | ||
806 | { | ||
807 | m_host.AddScriptLPS(1); | ||
808 | NotImplemented("llDetectedTouchPos"); | ||
809 | return new LSL_Vector(); | ||
810 | } | ||
811 | |||
812 | public LSL_Vector llDetectedTouchST(int index) | ||
813 | { | ||
814 | m_host.AddScriptLPS(1); | ||
815 | NotImplemented("llDetectedTouchST"); | ||
816 | return new LSL_Vector(); | ||
817 | } | ||
818 | |||
819 | public LSL_Vector llDetectedTouchUV(int index) | ||
820 | { | ||
821 | m_host.AddScriptLPS(1); | ||
822 | NotImplemented("llDetectedTouchUV"); | ||
823 | return new LSL_Vector(); | ||
824 | } | ||
825 | |||
826 | public void llDie() | ||
827 | { | ||
828 | m_host.AddScriptLPS(1); | ||
829 | throw new SelfDeleteException(); | ||
830 | } | ||
831 | |||
832 | public LSL_Float llGround(LSL_Vector offset) | ||
833 | { | ||
834 | m_host.AddScriptLPS(1); | ||
835 | int x = (int)(m_host.OffsetPosition.X + offset.x); | ||
836 | int y = (int)(m_host.OffsetPosition.Y + offset.y); | ||
837 | return World.GetLandHeight(x, y); | ||
838 | } | ||
839 | |||
840 | public LSL_Float llCloud(LSL_Vector offset) | ||
841 | { | ||
842 | m_host.AddScriptLPS(1); | ||
843 | return 0; | ||
844 | } | ||
845 | |||
846 | public LSL_Vector llWind(LSL_Vector offset) | ||
847 | { | ||
848 | m_host.AddScriptLPS(1); | ||
849 | return new LSL_Vector(); | ||
850 | } | ||
851 | |||
852 | public void llSetStatus(int status, int value) | ||
853 | { | ||
854 | m_host.AddScriptLPS(1); | ||
855 | |||
856 | int statusrotationaxis = 0; | ||
857 | |||
858 | if ((status & ScriptBaseClass.STATUS_PHYSICS) == ScriptBaseClass.STATUS_PHYSICS) | ||
859 | { | ||
860 | if (value == 1) | ||
861 | { | ||
862 | SceneObjectGroup group = m_host.ParentGroup; | ||
863 | if (group == null) | ||
864 | return; | ||
865 | bool allow = true; | ||
866 | foreach (SceneObjectPart part in group.Children.Values) | ||
867 | { | ||
868 | if (part.Scale.X > World.m_maxPhys || part.Scale.Y > World.m_maxPhys || part.Scale.Z > World.m_maxPhys) | ||
869 | { | ||
870 | allow = false; | ||
871 | break; | ||
872 | } | ||
873 | } | ||
874 | |||
875 | if (!allow) | ||
876 | return; | ||
877 | m_host.ScriptSetPhysicsStatus(true); | ||
878 | } | ||
879 | else | ||
880 | m_host.ScriptSetPhysicsStatus(false); | ||
881 | } | ||
882 | |||
883 | if ((status & ScriptBaseClass.STATUS_PHANTOM) == ScriptBaseClass.STATUS_PHANTOM) | ||
884 | { | ||
885 | if (value == 1) | ||
886 | m_host.ScriptSetPhantomStatus(true); | ||
887 | else | ||
888 | m_host.ScriptSetPhantomStatus(false); | ||
889 | } | ||
890 | |||
891 | if ((status & ScriptBaseClass.STATUS_CAST_SHADOWS) == ScriptBaseClass.STATUS_CAST_SHADOWS) | ||
892 | { | ||
893 | m_host.AddFlag(PrimFlags.CastShadows); | ||
894 | } | ||
895 | |||
896 | if ((status & ScriptBaseClass.STATUS_ROTATE_X) == ScriptBaseClass.STATUS_ROTATE_X) | ||
897 | { | ||
898 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_X; | ||
899 | } | ||
900 | |||
901 | if ((status & ScriptBaseClass.STATUS_ROTATE_Y) == ScriptBaseClass.STATUS_ROTATE_Y) | ||
902 | { | ||
903 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Y; | ||
904 | } | ||
905 | |||
906 | if ((status & ScriptBaseClass.STATUS_ROTATE_Z) == ScriptBaseClass.STATUS_ROTATE_Z) | ||
907 | { | ||
908 | statusrotationaxis |= ScriptBaseClass.STATUS_ROTATE_Z; | ||
909 | } | ||
910 | |||
911 | if ((status & ScriptBaseClass.STATUS_BLOCK_GRAB) == ScriptBaseClass.STATUS_BLOCK_GRAB) | ||
912 | { | ||
913 | NotImplemented("llSetStatus - STATUS_BLOCK_GRAB"); | ||
914 | } | ||
915 | |||
916 | if ((status & ScriptBaseClass.STATUS_DIE_AT_EDGE) == ScriptBaseClass.STATUS_DIE_AT_EDGE) | ||
917 | { | ||
918 | if (value == 1) | ||
919 | m_host.SetDieAtEdge(true); | ||
920 | else | ||
921 | m_host.SetDieAtEdge(false); | ||
922 | } | ||
923 | |||
924 | if ((status & ScriptBaseClass.STATUS_RETURN_AT_EDGE) == ScriptBaseClass.STATUS_RETURN_AT_EDGE) | ||
925 | { | ||
926 | NotImplemented("llSetStatus - STATUS_RETURN_AT_EDGE"); | ||
927 | } | ||
928 | |||
929 | if ((status & ScriptBaseClass.STATUS_SANDBOX) == ScriptBaseClass.STATUS_SANDBOX) | ||
930 | { | ||
931 | NotImplemented("llSetStatus - STATUS_SANDBOX"); | ||
932 | } | ||
933 | |||
934 | if (statusrotationaxis != 0) | ||
935 | { | ||
936 | m_host.SetAxisRotation(statusrotationaxis, value); | ||
937 | } | ||
938 | } | ||
939 | |||
940 | public LSL_Integer llGetStatus(int status) | ||
941 | { | ||
942 | m_host.AddScriptLPS(1); | ||
943 | // Console.WriteLine(m_host.ToString() + " status is " + m_host.GetEffectiveObjectFlags().ToString()); | ||
944 | switch (status) | ||
945 | { | ||
946 | case ScriptBaseClass.STATUS_PHYSICS: | ||
947 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) == (uint)PrimFlags.Physics) | ||
948 | { | ||
949 | return 1; | ||
950 | } | ||
951 | return 0; | ||
952 | |||
953 | case ScriptBaseClass.STATUS_PHANTOM: | ||
954 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) == (uint)PrimFlags.Phantom) | ||
955 | { | ||
956 | return 1; | ||
957 | } | ||
958 | return 0; | ||
959 | |||
960 | case ScriptBaseClass.STATUS_CAST_SHADOWS: | ||
961 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.CastShadows) == (uint)PrimFlags.CastShadows) | ||
962 | { | ||
963 | return 1; | ||
964 | } | ||
965 | return 0; | ||
966 | |||
967 | case ScriptBaseClass.STATUS_BLOCK_GRAB: | ||
968 | NotImplemented("llGetStatus - STATUS_BLOCK_GRAB"); | ||
969 | return 0; | ||
970 | |||
971 | case ScriptBaseClass.STATUS_DIE_AT_EDGE: | ||
972 | if (m_host.GetDieAtEdge()) | ||
973 | return 1; | ||
974 | else | ||
975 | return 0; | ||
976 | |||
977 | case ScriptBaseClass.STATUS_RETURN_AT_EDGE: | ||
978 | NotImplemented("llGetStatus - STATUS_RETURN_AT_EDGE"); | ||
979 | return 0; | ||
980 | |||
981 | case ScriptBaseClass.STATUS_ROTATE_X: | ||
982 | NotImplemented("llGetStatus - STATUS_ROTATE_X"); | ||
983 | return 0; | ||
984 | |||
985 | case ScriptBaseClass.STATUS_ROTATE_Y: | ||
986 | NotImplemented("llGetStatus - STATUS_ROTATE_Y"); | ||
987 | return 0; | ||
988 | |||
989 | case ScriptBaseClass.STATUS_ROTATE_Z: | ||
990 | NotImplemented("llGetStatus - STATUS_ROTATE_Z"); | ||
991 | return 0; | ||
992 | |||
993 | case ScriptBaseClass.STATUS_SANDBOX: | ||
994 | NotImplemented("llGetStatus - STATUS_SANDBOX"); | ||
995 | return 0; | ||
996 | } | ||
997 | return 0; | ||
998 | } | ||
999 | |||
1000 | public void llSetScale(LSL_Vector scale) | ||
1001 | { | ||
1002 | m_host.AddScriptLPS(1); | ||
1003 | SetScale(m_host, scale); | ||
1004 | } | ||
1005 | |||
1006 | private void SetScale(SceneObjectPart part, LSL_Vector scale) | ||
1007 | { | ||
1008 | // TODO: this needs to trigger a persistance save as well | ||
1009 | |||
1010 | if (part == null || part.ParentGroup == null || part.ParentGroup.RootPart == null) | ||
1011 | return; | ||
1012 | |||
1013 | if (part.ParentGroup.RootPart.PhysActor != null && part.ParentGroup.RootPart.PhysActor.IsPhysical) | ||
1014 | { | ||
1015 | if (scale.x > World.m_maxPhys) | ||
1016 | scale.x = World.m_maxPhys; | ||
1017 | if (scale.y > World.m_maxPhys) | ||
1018 | scale.y = World.m_maxPhys; | ||
1019 | if (scale.z > World.m_maxPhys) | ||
1020 | scale.z = World.m_maxPhys; | ||
1021 | } | ||
1022 | if (scale.x > World.m_maxNonphys) | ||
1023 | scale.x = World.m_maxNonphys; | ||
1024 | if (scale.y > World.m_maxNonphys) | ||
1025 | scale.y = World.m_maxNonphys; | ||
1026 | if (scale.z > World.m_maxNonphys) | ||
1027 | scale.z = World.m_maxNonphys; | ||
1028 | Vector3 tmp = part.Scale; | ||
1029 | tmp.X = (float)scale.x; | ||
1030 | tmp.Y = (float)scale.y; | ||
1031 | tmp.Z = (float)scale.z; | ||
1032 | part.Scale = tmp; | ||
1033 | part.SendFullUpdateToAllClients(); | ||
1034 | } | ||
1035 | |||
1036 | public LSL_Vector llGetScale() | ||
1037 | { | ||
1038 | m_host.AddScriptLPS(1); | ||
1039 | return new LSL_Vector(m_host.Scale.X, m_host.Scale.Y, m_host.Scale.Z); | ||
1040 | } | ||
1041 | |||
1042 | public void llSetClickAction(int action) | ||
1043 | { | ||
1044 | m_host.AddScriptLPS(1); | ||
1045 | m_host.ClickAction = (byte)action; | ||
1046 | if (m_host.ParentGroup != null) m_host.ParentGroup.HasGroupChanged = true; | ||
1047 | m_host.ScheduleFullUpdate(); | ||
1048 | return; | ||
1049 | } | ||
1050 | |||
1051 | public void llSetColor(LSL_Vector color, int face) | ||
1052 | { | ||
1053 | m_host.AddScriptLPS(1); | ||
1054 | |||
1055 | SetColor(m_host, color, face); | ||
1056 | } | ||
1057 | |||
1058 | private void SetColor(SceneObjectPart part, LSL_Vector color, int face) | ||
1059 | { | ||
1060 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1061 | Color4 texcolor; | ||
1062 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1063 | { | ||
1064 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
1065 | texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1066 | texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1067 | texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1068 | tex.FaceTextures[face].RGBA = texcolor; | ||
1069 | part.UpdateTexture(tex); | ||
1070 | return; | ||
1071 | } | ||
1072 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1073 | { | ||
1074 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1075 | { | ||
1076 | if (tex.FaceTextures[i] != null) | ||
1077 | { | ||
1078 | texcolor = tex.FaceTextures[i].RGBA; | ||
1079 | texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1080 | texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1081 | texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1082 | tex.FaceTextures[i].RGBA = texcolor; | ||
1083 | } | ||
1084 | texcolor = tex.DefaultTexture.RGBA; | ||
1085 | texcolor.R = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1086 | texcolor.G = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1087 | texcolor.B = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1088 | tex.DefaultTexture.RGBA = texcolor; | ||
1089 | } | ||
1090 | part.UpdateTexture(tex); | ||
1091 | return; | ||
1092 | } | ||
1093 | } | ||
1094 | |||
1095 | public void SetGlow(SceneObjectPart part, int face, float glow) | ||
1096 | { | ||
1097 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1098 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1099 | { | ||
1100 | tex.CreateFace((uint) face); | ||
1101 | tex.FaceTextures[face].Glow = glow; | ||
1102 | part.UpdateTexture(tex); | ||
1103 | return; | ||
1104 | } | ||
1105 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1106 | { | ||
1107 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1108 | { | ||
1109 | if (tex.FaceTextures[i] != null) | ||
1110 | { | ||
1111 | tex.FaceTextures[i].Glow = glow; | ||
1112 | } | ||
1113 | tex.DefaultTexture.Glow = glow; | ||
1114 | } | ||
1115 | part.UpdateTexture(tex); | ||
1116 | return; | ||
1117 | } | ||
1118 | } | ||
1119 | |||
1120 | public void SetShiny(SceneObjectPart part, int face, int shiny, Bumpiness bump) | ||
1121 | { | ||
1122 | |||
1123 | Shininess sval = new Shininess(); | ||
1124 | |||
1125 | switch (shiny) | ||
1126 | { | ||
1127 | case 0: | ||
1128 | sval = Shininess.None; | ||
1129 | break; | ||
1130 | case 1: | ||
1131 | sval = Shininess.Low; | ||
1132 | break; | ||
1133 | case 2: | ||
1134 | sval = Shininess.Medium; | ||
1135 | break; | ||
1136 | case 3: | ||
1137 | sval = Shininess.High; | ||
1138 | break; | ||
1139 | default: | ||
1140 | sval = Shininess.None; | ||
1141 | break; | ||
1142 | } | ||
1143 | |||
1144 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1145 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1146 | { | ||
1147 | tex.CreateFace((uint) face); | ||
1148 | tex.FaceTextures[face].Shiny = sval; | ||
1149 | tex.FaceTextures[face].Bump = bump; | ||
1150 | part.UpdateTexture(tex); | ||
1151 | return; | ||
1152 | } | ||
1153 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1154 | { | ||
1155 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1156 | { | ||
1157 | if (tex.FaceTextures[i] != null) | ||
1158 | { | ||
1159 | tex.FaceTextures[i].Shiny = sval; | ||
1160 | tex.FaceTextures[i].Bump = bump;; | ||
1161 | } | ||
1162 | tex.DefaultTexture.Shiny = sval; | ||
1163 | tex.DefaultTexture.Bump = bump; | ||
1164 | } | ||
1165 | part.UpdateTexture(tex); | ||
1166 | return; | ||
1167 | } | ||
1168 | } | ||
1169 | |||
1170 | public void SetFullBright(SceneObjectPart part, int face, bool bright) | ||
1171 | { | ||
1172 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1173 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1174 | { | ||
1175 | tex.CreateFace((uint) face); | ||
1176 | tex.FaceTextures[face].Fullbright = bright; | ||
1177 | part.UpdateTexture(tex); | ||
1178 | return; | ||
1179 | } | ||
1180 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1181 | { | ||
1182 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1183 | { | ||
1184 | if (tex.FaceTextures[i] != null) | ||
1185 | { | ||
1186 | tex.FaceTextures[i].Fullbright = bright; | ||
1187 | } | ||
1188 | } | ||
1189 | tex.DefaultTexture.Fullbright = bright; | ||
1190 | part.UpdateTexture(tex); | ||
1191 | return; | ||
1192 | } | ||
1193 | } | ||
1194 | |||
1195 | public LSL_Float llGetAlpha(int face) | ||
1196 | { | ||
1197 | m_host.AddScriptLPS(1); | ||
1198 | |||
1199 | return GetAlpha(m_host, face); | ||
1200 | } | ||
1201 | |||
1202 | private LSL_Float GetAlpha(SceneObjectPart part, int face) | ||
1203 | { | ||
1204 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1205 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1206 | { | ||
1207 | int i; | ||
1208 | double sum = 0.0; | ||
1209 | for (i = 0 ; i < GetNumberOfSides(part) ; i++) | ||
1210 | sum += (double)tex.GetFace((uint)i).RGBA.A; | ||
1211 | return sum; | ||
1212 | } | ||
1213 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1214 | { | ||
1215 | return (double)tex.GetFace((uint)face).RGBA.A; | ||
1216 | } | ||
1217 | return 0.0; | ||
1218 | } | ||
1219 | |||
1220 | public void llSetAlpha(double alpha, int face) | ||
1221 | { | ||
1222 | m_host.AddScriptLPS(1); | ||
1223 | |||
1224 | SetAlpha(m_host, alpha, face); | ||
1225 | } | ||
1226 | |||
1227 | private void SetAlpha(SceneObjectPart part, double alpha, int face) | ||
1228 | { | ||
1229 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1230 | Color4 texcolor; | ||
1231 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1232 | { | ||
1233 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
1234 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
1235 | tex.FaceTextures[face].RGBA = texcolor; | ||
1236 | part.UpdateTexture(tex); | ||
1237 | return; | ||
1238 | } | ||
1239 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1240 | { | ||
1241 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1242 | { | ||
1243 | if (tex.FaceTextures[i] != null) | ||
1244 | { | ||
1245 | texcolor = tex.FaceTextures[i].RGBA; | ||
1246 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
1247 | tex.FaceTextures[i].RGBA = texcolor; | ||
1248 | } | ||
1249 | } | ||
1250 | texcolor = tex.DefaultTexture.RGBA; | ||
1251 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
1252 | tex.DefaultTexture.RGBA = texcolor; | ||
1253 | part.UpdateTexture(tex); | ||
1254 | return; | ||
1255 | } | ||
1256 | } | ||
1257 | |||
1258 | /// <summary> | ||
1259 | /// Set flexi parameters of a part. | ||
1260 | /// | ||
1261 | /// FIXME: Much of this code should probably be within the part itself. | ||
1262 | /// </summary> | ||
1263 | /// <param name="part"></param> | ||
1264 | /// <param name="flexi"></param> | ||
1265 | /// <param name="softness"></param> | ||
1266 | /// <param name="gravity"></param> | ||
1267 | /// <param name="friction"></param> | ||
1268 | /// <param name="wind"></param> | ||
1269 | /// <param name="tension"></param> | ||
1270 | /// <param name="Force"></param> | ||
1271 | private void SetFlexi(SceneObjectPart part, bool flexi, int softness, float gravity, float friction, | ||
1272 | float wind, float tension, LSL_Vector Force) | ||
1273 | { | ||
1274 | if (part == null) | ||
1275 | return; | ||
1276 | |||
1277 | bool needs_fakedelete = false; | ||
1278 | if (flexi) | ||
1279 | { | ||
1280 | if (!part.Shape.FlexiEntry) | ||
1281 | { | ||
1282 | needs_fakedelete = true; | ||
1283 | } | ||
1284 | part.Shape.FlexiEntry = true; // this setting flexi true isn't working, but the below parameters do | ||
1285 | // work once the prim is already flexi | ||
1286 | part.Shape.FlexiSoftness = softness; | ||
1287 | part.Shape.FlexiGravity = gravity; | ||
1288 | part.Shape.FlexiDrag = friction; | ||
1289 | part.Shape.FlexiWind = wind; | ||
1290 | part.Shape.FlexiTension = tension; | ||
1291 | part.Shape.FlexiForceX = (float)Force.x; | ||
1292 | part.Shape.FlexiForceY = (float)Force.y; | ||
1293 | part.Shape.FlexiForceZ = (float)Force.z; | ||
1294 | part.Shape.PathCurve = 0x80; | ||
1295 | |||
1296 | } | ||
1297 | else | ||
1298 | { | ||
1299 | if (part.Shape.FlexiEntry) | ||
1300 | { | ||
1301 | needs_fakedelete = true; | ||
1302 | } | ||
1303 | part.Shape.FlexiEntry = false; | ||
1304 | } | ||
1305 | |||
1306 | needs_fakedelete = false; | ||
1307 | if (needs_fakedelete) | ||
1308 | { | ||
1309 | if (part.ParentGroup != null) | ||
1310 | { | ||
1311 | part.ParentGroup.FakeDeleteGroup(); | ||
1312 | } | ||
1313 | } | ||
1314 | |||
1315 | part.ParentGroup.HasGroupChanged = true; | ||
1316 | part.ScheduleFullUpdate(); | ||
1317 | } | ||
1318 | |||
1319 | /// <summary> | ||
1320 | /// Set a light point on a part | ||
1321 | /// | ||
1322 | /// FIXME: Much of this code should probably be in SceneObjectGroup | ||
1323 | /// </summary> | ||
1324 | /// <param name="part"></param> | ||
1325 | /// <param name="light"></param> | ||
1326 | /// <param name="color"></param> | ||
1327 | /// <param name="intensity"></param> | ||
1328 | /// <param name="radius"></param> | ||
1329 | /// <param name="falloff"></param> | ||
1330 | private void SetPointLight(SceneObjectPart part, bool light, LSL_Vector color, float intensity, float radius, float falloff) | ||
1331 | { | ||
1332 | if (part == null) | ||
1333 | return; | ||
1334 | |||
1335 | if (light) | ||
1336 | { | ||
1337 | part.Shape.LightEntry = true; | ||
1338 | part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); | ||
1339 | part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); | ||
1340 | part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); | ||
1341 | part.Shape.LightIntensity = intensity; | ||
1342 | part.Shape.LightRadius = radius; | ||
1343 | part.Shape.LightFalloff = falloff; | ||
1344 | } | ||
1345 | else | ||
1346 | { | ||
1347 | part.Shape.LightEntry = false; | ||
1348 | } | ||
1349 | |||
1350 | part.ParentGroup.HasGroupChanged = true; | ||
1351 | part.ScheduleFullUpdate(); | ||
1352 | } | ||
1353 | |||
1354 | public LSL_Vector llGetColor(int face) | ||
1355 | { | ||
1356 | m_host.AddScriptLPS(1); | ||
1357 | return GetColor(m_host, face); | ||
1358 | } | ||
1359 | |||
1360 | private LSL_Vector GetColor(SceneObjectPart part, int face) | ||
1361 | { | ||
1362 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1363 | Color4 texcolor; | ||
1364 | LSL_Vector rgb = new LSL_Vector(); | ||
1365 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1366 | { | ||
1367 | int i; | ||
1368 | |||
1369 | for (i = 0 ; i < GetNumberOfSides(part) ; i++) | ||
1370 | { | ||
1371 | texcolor = tex.GetFace((uint)i).RGBA; | ||
1372 | rgb.x += texcolor.R; | ||
1373 | rgb.y += texcolor.G; | ||
1374 | rgb.z += texcolor.B; | ||
1375 | } | ||
1376 | |||
1377 | rgb.x /= (float)GetNumberOfSides(part); | ||
1378 | rgb.y /= (float)GetNumberOfSides(part); | ||
1379 | rgb.z /= (float)GetNumberOfSides(part); | ||
1380 | |||
1381 | return rgb; | ||
1382 | } | ||
1383 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1384 | { | ||
1385 | texcolor = tex.GetFace((uint)face).RGBA; | ||
1386 | rgb.x = texcolor.R; | ||
1387 | rgb.y = texcolor.G; | ||
1388 | rgb.z = texcolor.B; | ||
1389 | return rgb; | ||
1390 | } | ||
1391 | else | ||
1392 | { | ||
1393 | return new LSL_Vector(); | ||
1394 | } | ||
1395 | } | ||
1396 | |||
1397 | public void llSetTexture(string texture, int face) | ||
1398 | { | ||
1399 | m_host.AddScriptLPS(1); | ||
1400 | SetTexture(m_host, texture, face); | ||
1401 | // ScriptSleep(200); | ||
1402 | } | ||
1403 | |||
1404 | private void SetTexture(SceneObjectPart part, string texture, int face) | ||
1405 | { | ||
1406 | UUID textureID=new UUID(); | ||
1407 | |||
1408 | if (!UUID.TryParse(texture, out textureID)) | ||
1409 | { | ||
1410 | textureID=InventoryKey(texture, (int)AssetType.Texture); | ||
1411 | } | ||
1412 | |||
1413 | if (textureID == UUID.Zero) | ||
1414 | return; | ||
1415 | |||
1416 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1417 | |||
1418 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1419 | { | ||
1420 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1421 | texface.TextureID = textureID; | ||
1422 | tex.FaceTextures[face] = texface; | ||
1423 | part.UpdateTexture(tex); | ||
1424 | return; | ||
1425 | } | ||
1426 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
1427 | { | ||
1428 | for (uint i = 0; i < GetNumberOfSides(part); i++) | ||
1429 | { | ||
1430 | if (tex.FaceTextures[i] != null) | ||
1431 | { | ||
1432 | tex.FaceTextures[i].TextureID = textureID; | ||
1433 | } | ||
1434 | } | ||
1435 | tex.DefaultTexture.TextureID = textureID; | ||
1436 | part.UpdateTexture(tex); | ||
1437 | return; | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | public void llScaleTexture(double u, double v, int face) | ||
1442 | { | ||
1443 | m_host.AddScriptLPS(1); | ||
1444 | |||
1445 | ScaleTexture(m_host, u, v, face); | ||
1446 | // ScriptSleep(200); | ||
1447 | } | ||
1448 | |||
1449 | private void ScaleTexture(SceneObjectPart part, double u, double v, int face) | ||
1450 | { | ||
1451 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1452 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1453 | { | ||
1454 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1455 | texface.RepeatU = (float)u; | ||
1456 | texface.RepeatV = (float)v; | ||
1457 | tex.FaceTextures[face] = texface; | ||
1458 | part.UpdateTexture(tex); | ||
1459 | return; | ||
1460 | } | ||
1461 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1462 | { | ||
1463 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1464 | { | ||
1465 | if (tex.FaceTextures[i] != null) | ||
1466 | { | ||
1467 | tex.FaceTextures[i].RepeatU = (float)u; | ||
1468 | tex.FaceTextures[i].RepeatV = (float)v; | ||
1469 | } | ||
1470 | } | ||
1471 | tex.DefaultTexture.RepeatU = (float)u; | ||
1472 | tex.DefaultTexture.RepeatV = (float)v; | ||
1473 | part.UpdateTexture(tex); | ||
1474 | return; | ||
1475 | } | ||
1476 | } | ||
1477 | |||
1478 | public void llOffsetTexture(double u, double v, int face) | ||
1479 | { | ||
1480 | m_host.AddScriptLPS(1); | ||
1481 | OffsetTexture(m_host, u, v, face); | ||
1482 | // ScriptSleep(200); | ||
1483 | } | ||
1484 | |||
1485 | private void OffsetTexture(SceneObjectPart part, double u, double v, int face) | ||
1486 | { | ||
1487 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1488 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1489 | { | ||
1490 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1491 | texface.OffsetU = (float)u; | ||
1492 | texface.OffsetV = (float)v; | ||
1493 | tex.FaceTextures[face] = texface; | ||
1494 | part.UpdateTexture(tex); | ||
1495 | return; | ||
1496 | } | ||
1497 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1498 | { | ||
1499 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1500 | { | ||
1501 | if (tex.FaceTextures[i] != null) | ||
1502 | { | ||
1503 | tex.FaceTextures[i].OffsetU = (float)u; | ||
1504 | tex.FaceTextures[i].OffsetV = (float)v; | ||
1505 | } | ||
1506 | } | ||
1507 | tex.DefaultTexture.OffsetU = (float)u; | ||
1508 | tex.DefaultTexture.OffsetV = (float)v; | ||
1509 | part.UpdateTexture(tex); | ||
1510 | return; | ||
1511 | } | ||
1512 | } | ||
1513 | |||
1514 | public void llRotateTexture(double rotation, int face) | ||
1515 | { | ||
1516 | m_host.AddScriptLPS(1); | ||
1517 | RotateTexture(m_host, rotation, face); | ||
1518 | // ScriptSleep(200); | ||
1519 | } | ||
1520 | |||
1521 | private void RotateTexture(SceneObjectPart part, double rotation, int face) | ||
1522 | { | ||
1523 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1524 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1525 | { | ||
1526 | Primitive.TextureEntryFace texface = tex.CreateFace((uint)face); | ||
1527 | texface.Rotation = (float)rotation; | ||
1528 | tex.FaceTextures[face] = texface; | ||
1529 | part.UpdateTexture(tex); | ||
1530 | return; | ||
1531 | } | ||
1532 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1533 | { | ||
1534 | for (int i = 0; i < GetNumberOfSides(part); i++) | ||
1535 | { | ||
1536 | if (tex.FaceTextures[i] != null) | ||
1537 | { | ||
1538 | tex.FaceTextures[i].Rotation = (float)rotation; | ||
1539 | } | ||
1540 | } | ||
1541 | tex.DefaultTexture.Rotation = (float)rotation; | ||
1542 | part.UpdateTexture(tex); | ||
1543 | return; | ||
1544 | } | ||
1545 | } | ||
1546 | |||
1547 | public LSL_String llGetTexture(int face) | ||
1548 | { | ||
1549 | m_host.AddScriptLPS(1); | ||
1550 | return GetTexture(m_host, face); | ||
1551 | } | ||
1552 | |||
1553 | private LSL_String GetTexture(SceneObjectPart part, int face) | ||
1554 | { | ||
1555 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
1556 | if (face == ScriptBaseClass.ALL_SIDES) | ||
1557 | { | ||
1558 | face = 0; | ||
1559 | } | ||
1560 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
1561 | { | ||
1562 | Primitive.TextureEntryFace texface; | ||
1563 | texface = tex.GetFace((uint)face); | ||
1564 | return texface.TextureID.ToString(); | ||
1565 | } | ||
1566 | else | ||
1567 | { | ||
1568 | return String.Empty; | ||
1569 | } | ||
1570 | } | ||
1571 | |||
1572 | public void llSetPos(LSL_Vector pos) | ||
1573 | { | ||
1574 | m_host.AddScriptLPS(1); | ||
1575 | |||
1576 | SetPos(m_host, pos); | ||
1577 | |||
1578 | ScriptSleep(200); | ||
1579 | } | ||
1580 | |||
1581 | private void SetPos(SceneObjectPart part, LSL_Vector targetPos) | ||
1582 | { | ||
1583 | // Capped movemment if distance > 10m (http://wiki.secondlife.com/wiki/LlSetPos) | ||
1584 | LSL_Vector currentPos = llGetLocalPos(); | ||
1585 | if (llVecDist(currentPos, targetPos) > 10.0f * m_ScriptDistanceFactor) | ||
1586 | { | ||
1587 | targetPos = currentPos + m_ScriptDistanceFactor * 10.0f * llVecNorm(targetPos - currentPos); | ||
1588 | } | ||
1589 | |||
1590 | if (part.ParentID != 0) | ||
1591 | { | ||
1592 | part.UpdateOffSet(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z)); | ||
1593 | } | ||
1594 | else | ||
1595 | { | ||
1596 | part.UpdateGroupPosition(new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z)); | ||
1597 | } | ||
1598 | } | ||
1599 | |||
1600 | public LSL_Vector llGetPos() | ||
1601 | { | ||
1602 | m_host.AddScriptLPS(1); | ||
1603 | return new LSL_Vector(m_host.AbsolutePosition.X, | ||
1604 | m_host.AbsolutePosition.Y, | ||
1605 | m_host.AbsolutePosition.Z); | ||
1606 | } | ||
1607 | |||
1608 | public LSL_Vector llGetLocalPos() | ||
1609 | { | ||
1610 | m_host.AddScriptLPS(1); | ||
1611 | if (m_host.ParentID != 0) | ||
1612 | { | ||
1613 | return new LSL_Vector(m_host.OffsetPosition.X, | ||
1614 | m_host.OffsetPosition.Y, | ||
1615 | m_host.OffsetPosition.Z); | ||
1616 | } | ||
1617 | else | ||
1618 | { | ||
1619 | return new LSL_Vector(m_host.AbsolutePosition.X, | ||
1620 | m_host.AbsolutePosition.Y, | ||
1621 | m_host.AbsolutePosition.Z); | ||
1622 | } | ||
1623 | } | ||
1624 | |||
1625 | public void llSetRot(LSL_Rotation rot) | ||
1626 | { | ||
1627 | m_host.AddScriptLPS(1); | ||
1628 | |||
1629 | SetRot(m_host, rot); | ||
1630 | |||
1631 | ScriptSleep(200); | ||
1632 | } | ||
1633 | |||
1634 | private void SetRot(SceneObjectPart part, LSL_Rotation rot) | ||
1635 | { | ||
1636 | part.UpdateRotation(new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s)); | ||
1637 | // Update rotation does not move the object in the physics scene if it's a linkset. | ||
1638 | part.ParentGroup.AbsolutePosition = part.ParentGroup.AbsolutePosition; | ||
1639 | } | ||
1640 | |||
1641 | public LSL_Rotation llGetRot() | ||
1642 | { | ||
1643 | m_host.AddScriptLPS(1); | ||
1644 | Quaternion q = m_host.RotationOffset; | ||
1645 | return new LSL_Rotation(q.X, q.Y, q.Z, q.W); | ||
1646 | } | ||
1647 | |||
1648 | public LSL_Rotation llGetLocalRot() | ||
1649 | { | ||
1650 | m_host.AddScriptLPS(1); | ||
1651 | return new LSL_Rotation(m_host.RotationOffset.X, m_host.RotationOffset.Y, m_host.RotationOffset.Z, m_host.RotationOffset.W); | ||
1652 | } | ||
1653 | |||
1654 | public void llSetForce(LSL_Vector force, int local) | ||
1655 | { | ||
1656 | m_host.AddScriptLPS(1); | ||
1657 | |||
1658 | if (m_host.ParentGroup != null) | ||
1659 | { | ||
1660 | if (m_host.ParentGroup.RootPart != null) | ||
1661 | { | ||
1662 | if (local != 0) | ||
1663 | force *= llGetRot(); | ||
1664 | |||
1665 | m_host.ParentGroup.RootPart.SetForce(new PhysicsVector((float)force.x, (float)force.y, (float)force.z)); | ||
1666 | } | ||
1667 | } | ||
1668 | } | ||
1669 | |||
1670 | public LSL_Vector llGetForce() | ||
1671 | { | ||
1672 | LSL_Vector force = new LSL_Vector(0.0, 0.0, 0.0); | ||
1673 | |||
1674 | m_host.AddScriptLPS(1); | ||
1675 | |||
1676 | if (m_host.ParentGroup != null) | ||
1677 | { | ||
1678 | if (m_host.ParentGroup.RootPart != null) | ||
1679 | { | ||
1680 | PhysicsVector tmpForce = m_host.ParentGroup.RootPart.GetForce(); | ||
1681 | force.x = tmpForce.X; | ||
1682 | force.y = tmpForce.Y; | ||
1683 | force.z = tmpForce.Z; | ||
1684 | } | ||
1685 | } | ||
1686 | |||
1687 | return force; | ||
1688 | } | ||
1689 | |||
1690 | public LSL_Integer llTarget(LSL_Vector position, double range) | ||
1691 | { | ||
1692 | m_host.AddScriptLPS(1); | ||
1693 | return m_host.registerTargetWaypoint(new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); | ||
1694 | } | ||
1695 | |||
1696 | public void llTargetRemove(int number) | ||
1697 | { | ||
1698 | m_host.AddScriptLPS(1); | ||
1699 | m_host.unregisterTargetWaypoint(number); | ||
1700 | } | ||
1701 | |||
1702 | public LSL_Integer llRotTarget(LSL_Rotation rot, double error) | ||
1703 | { | ||
1704 | m_host.AddScriptLPS(1); | ||
1705 | NotImplemented("llRotTarget"); | ||
1706 | return 0; | ||
1707 | } | ||
1708 | |||
1709 | public void llRotTargetRemove(int number) | ||
1710 | { | ||
1711 | m_host.AddScriptLPS(1); | ||
1712 | NotImplemented("llRotTargetRemove"); | ||
1713 | } | ||
1714 | |||
1715 | public void llMoveToTarget(LSL_Vector target, double tau) | ||
1716 | { | ||
1717 | m_host.AddScriptLPS(1); | ||
1718 | m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); | ||
1719 | } | ||
1720 | |||
1721 | public void llStopMoveToTarget() | ||
1722 | { | ||
1723 | m_host.AddScriptLPS(1); | ||
1724 | m_host.StopMoveToTarget(); | ||
1725 | } | ||
1726 | |||
1727 | public void llApplyImpulse(LSL_Vector force, int local) | ||
1728 | { | ||
1729 | m_host.AddScriptLPS(1); | ||
1730 | //No energy force yet | ||
1731 | |||
1732 | if (force.x > 20000) | ||
1733 | force.x = 20000; | ||
1734 | if (force.y > 20000) | ||
1735 | force.y = 20000; | ||
1736 | if (force.z > 20000) | ||
1737 | force.z = 20000; | ||
1738 | |||
1739 | m_host.ApplyImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); | ||
1740 | } | ||
1741 | |||
1742 | public void llApplyRotationalImpulse(LSL_Vector force, int local) | ||
1743 | { | ||
1744 | m_host.AddScriptLPS(1); | ||
1745 | NotImplemented("llApplyRotationalImpulse"); | ||
1746 | } | ||
1747 | |||
1748 | public void llSetTorque(LSL_Vector torque, int local) | ||
1749 | { | ||
1750 | m_host.AddScriptLPS(1); | ||
1751 | NotImplemented("llSetTorque"); | ||
1752 | } | ||
1753 | |||
1754 | public LSL_Vector llGetTorque() | ||
1755 | { | ||
1756 | m_host.AddScriptLPS(1); | ||
1757 | NotImplemented("llGetTorque"); | ||
1758 | return new LSL_Vector(); | ||
1759 | } | ||
1760 | |||
1761 | public void llSetForceAndTorque(LSL_Vector force, LSL_Vector torque, int local) | ||
1762 | { | ||
1763 | m_host.AddScriptLPS(1); | ||
1764 | NotImplemented("llSetForceAndTorque"); | ||
1765 | } | ||
1766 | |||
1767 | public LSL_Vector llGetVel() | ||
1768 | { | ||
1769 | m_host.AddScriptLPS(1); | ||
1770 | return new LSL_Vector(m_host.Velocity.X, m_host.Velocity.Y, m_host.Velocity.Z); | ||
1771 | } | ||
1772 | |||
1773 | public LSL_Vector llGetAccel() | ||
1774 | { | ||
1775 | m_host.AddScriptLPS(1); | ||
1776 | return new LSL_Vector(m_host.Acceleration.X, m_host.Acceleration.Y, m_host.Acceleration.Z); | ||
1777 | } | ||
1778 | |||
1779 | public LSL_Vector llGetOmega() | ||
1780 | { | ||
1781 | m_host.AddScriptLPS(1); | ||
1782 | return new LSL_Vector(m_host.RotationalVelocity.X, m_host.RotationalVelocity.Y, m_host.RotationalVelocity.Z); | ||
1783 | } | ||
1784 | |||
1785 | public LSL_Float llGetTimeOfDay() | ||
1786 | { | ||
1787 | m_host.AddScriptLPS(1); | ||
1788 | return (double)(((DateTime.Now.TimeOfDay.TotalMilliseconds / 1000) % (3600 * 4)) * World.TimeDilation); | ||
1789 | } | ||
1790 | |||
1791 | public LSL_Float llGetWallclock() | ||
1792 | { | ||
1793 | m_host.AddScriptLPS(1); | ||
1794 | return DateTime.Now.TimeOfDay.TotalSeconds; | ||
1795 | } | ||
1796 | |||
1797 | public LSL_Float llGetTime() | ||
1798 | { | ||
1799 | m_host.AddScriptLPS(1); | ||
1800 | TimeSpan ScriptTime = DateTime.Now - m_timer; | ||
1801 | return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation); | ||
1802 | } | ||
1803 | |||
1804 | public void llResetTime() | ||
1805 | { | ||
1806 | m_host.AddScriptLPS(1); | ||
1807 | m_timer = DateTime.Now; | ||
1808 | } | ||
1809 | |||
1810 | public LSL_Float llGetAndResetTime() | ||
1811 | { | ||
1812 | m_host.AddScriptLPS(1); | ||
1813 | TimeSpan ScriptTime = DateTime.Now - m_timer; | ||
1814 | m_timer = DateTime.Now; | ||
1815 | return (double)((ScriptTime.TotalMilliseconds / 1000)*World.TimeDilation); | ||
1816 | } | ||
1817 | |||
1818 | public void llSound() | ||
1819 | { | ||
1820 | m_host.AddScriptLPS(1); | ||
1821 | // This function has been deprecated | ||
1822 | // see http://www.lslwiki.net/lslwiki/wakka.php?wakka=llSound | ||
1823 | Deprecated("llSound"); | ||
1824 | } | ||
1825 | |||
1826 | // Xantor 20080528 PlaySound updated so it accepts an objectinventory name -or- a key to a sound | ||
1827 | // 20080530 Updated to remove code duplication | ||
1828 | public void llPlaySound(string sound, double volume) | ||
1829 | { | ||
1830 | m_host.AddScriptLPS(1); | ||
1831 | |||
1832 | // send the sound, once, to all clients in range | ||
1833 | m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0); | ||
1834 | } | ||
1835 | |||
1836 | // Xantor 20080528 we should do this differently. | ||
1837 | // 1) apply the sound to the object | ||
1838 | // 2) schedule full update | ||
1839 | // just sending the sound out once doesn't work so well when other avatars come in view later on | ||
1840 | // or when the prim gets moved, changed, sat on, whatever | ||
1841 | // see large number of mantises (mantes?) | ||
1842 | // 20080530 Updated to remove code duplication | ||
1843 | // 20080530 Stop sound if there is one, otherwise volume only changes don't work | ||
1844 | public void llLoopSound(string sound, double volume) | ||
1845 | { | ||
1846 | m_host.AddScriptLPS(1); | ||
1847 | |||
1848 | if (m_host.Sound != UUID.Zero) | ||
1849 | llStopSound(); | ||
1850 | |||
1851 | m_host.Sound = KeyOrName(sound); | ||
1852 | m_host.SoundGain = volume; | ||
1853 | m_host.SoundFlags = 1; // looping | ||
1854 | m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? | ||
1855 | |||
1856 | m_host.ScheduleFullUpdate(); | ||
1857 | m_host.SendFullUpdateToAllClients(); | ||
1858 | } | ||
1859 | |||
1860 | public void llLoopSoundMaster(string sound, double volume) | ||
1861 | { | ||
1862 | m_host.AddScriptLPS(1); | ||
1863 | NotImplemented("llLoopSoundMaster"); | ||
1864 | } | ||
1865 | |||
1866 | public void llLoopSoundSlave(string sound, double volume) | ||
1867 | { | ||
1868 | m_host.AddScriptLPS(1); | ||
1869 | NotImplemented("llLoopSoundSlave"); | ||
1870 | } | ||
1871 | |||
1872 | public void llPlaySoundSlave(string sound, double volume) | ||
1873 | { | ||
1874 | m_host.AddScriptLPS(1); | ||
1875 | NotImplemented("llPlaySoundSlave"); | ||
1876 | } | ||
1877 | |||
1878 | public void llTriggerSound(string sound, double volume) | ||
1879 | { | ||
1880 | m_host.AddScriptLPS(1); | ||
1881 | // send the sound, once, to all clients in range | ||
1882 | m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0); | ||
1883 | } | ||
1884 | |||
1885 | // Xantor 20080528: Clear prim data of sound instead | ||
1886 | public void llStopSound() | ||
1887 | { | ||
1888 | m_host.AddScriptLPS(1); | ||
1889 | |||
1890 | m_host.Sound = UUID.Zero; | ||
1891 | m_host.SoundGain = 0; | ||
1892 | m_host.SoundFlags = 0; | ||
1893 | m_host.SoundRadius = 0; | ||
1894 | |||
1895 | m_host.ScheduleFullUpdate(); | ||
1896 | m_host.SendFullUpdateToAllClients(); | ||
1897 | |||
1898 | // m_host.SendSound(UUID.Zero.ToString(), 1.0, false, 2); | ||
1899 | } | ||
1900 | |||
1901 | public void llPreloadSound(string sound) | ||
1902 | { | ||
1903 | m_host.AddScriptLPS(1); | ||
1904 | m_host.PreloadSound(sound); | ||
1905 | // ScriptSleep(1000); | ||
1906 | } | ||
1907 | |||
1908 | /// <summary> | ||
1909 | /// Return a portion of the designated string bounded by | ||
1910 | /// inclusive indices (start and end). As usual, the negative | ||
1911 | /// indices, and the tolerance for out-of-bound values, makes | ||
1912 | /// this more complicated than it might otherwise seem. | ||
1913 | /// </summary> | ||
1914 | |||
1915 | public LSL_String llGetSubString(string src, int start, int end) | ||
1916 | { | ||
1917 | |||
1918 | m_host.AddScriptLPS(1); | ||
1919 | |||
1920 | // Normalize indices (if negative). | ||
1921 | // After normlaization they may still be | ||
1922 | // negative, but that is now relative to | ||
1923 | // the start, rather than the end, of the | ||
1924 | // sequence. | ||
1925 | |||
1926 | if (start < 0) | ||
1927 | { | ||
1928 | start = src.Length+start; | ||
1929 | } | ||
1930 | if (end < 0) | ||
1931 | { | ||
1932 | end = src.Length+end; | ||
1933 | } | ||
1934 | |||
1935 | // Conventional substring | ||
1936 | if (start <= end) | ||
1937 | { | ||
1938 | // Implies both bounds are out-of-range. | ||
1939 | if (end < 0 || start >= src.Length) | ||
1940 | { | ||
1941 | return String.Empty; | ||
1942 | } | ||
1943 | // If end is positive, then it directly | ||
1944 | // corresponds to the lengt of the substring | ||
1945 | // needed (plus one of course). BUT, it | ||
1946 | // must be within bounds. | ||
1947 | if (end >= src.Length) | ||
1948 | { | ||
1949 | end = src.Length-1; | ||
1950 | } | ||
1951 | |||
1952 | if (start < 0) | ||
1953 | { | ||
1954 | return src.Substring(0,end+1); | ||
1955 | } | ||
1956 | // Both indices are positive | ||
1957 | return src.Substring(start, (end+1) - start); | ||
1958 | } | ||
1959 | |||
1960 | // Inverted substring (end < start) | ||
1961 | else | ||
1962 | { | ||
1963 | // Implies both indices are below the | ||
1964 | // lower bound. In the inverted case, that | ||
1965 | // means the entire string will be returned | ||
1966 | // unchanged. | ||
1967 | if (start < 0) | ||
1968 | { | ||
1969 | return src; | ||
1970 | } | ||
1971 | // If both indices are greater than the upper | ||
1972 | // bound the result may seem initially counter | ||
1973 | // intuitive. | ||
1974 | if (end >= src.Length) | ||
1975 | { | ||
1976 | return src; | ||
1977 | } | ||
1978 | |||
1979 | if (end < 0) | ||
1980 | { | ||
1981 | if (start < src.Length) | ||
1982 | { | ||
1983 | return src.Substring(start); | ||
1984 | } | ||
1985 | else | ||
1986 | { | ||
1987 | return String.Empty; | ||
1988 | } | ||
1989 | } | ||
1990 | else | ||
1991 | { | ||
1992 | if (start < src.Length) | ||
1993 | { | ||
1994 | return src.Substring(0,end+1) + src.Substring(start); | ||
1995 | } | ||
1996 | else | ||
1997 | { | ||
1998 | return src.Substring(0,end+1); | ||
1999 | } | ||
2000 | } | ||
2001 | } | ||
2002 | } | ||
2003 | |||
2004 | /// <summary> | ||
2005 | /// Delete substring removes the specified substring bounded | ||
2006 | /// by the inclusive indices start and end. Indices may be | ||
2007 | /// negative (indicating end-relative) and may be inverted, | ||
2008 | /// i.e. end < start. | ||
2009 | /// </summary> | ||
2010 | |||
2011 | public LSL_String llDeleteSubString(string src, int start, int end) | ||
2012 | { | ||
2013 | |||
2014 | m_host.AddScriptLPS(1); | ||
2015 | |||
2016 | // Normalize indices (if negative). | ||
2017 | // After normlaization they may still be | ||
2018 | // negative, but that is now relative to | ||
2019 | // the start, rather than the end, of the | ||
2020 | // sequence. | ||
2021 | if (start < 0) | ||
2022 | { | ||
2023 | start = src.Length+start; | ||
2024 | } | ||
2025 | if (end < 0) | ||
2026 | { | ||
2027 | end = src.Length+end; | ||
2028 | } | ||
2029 | // Conventionally delimited substring | ||
2030 | if (start <= end) | ||
2031 | { | ||
2032 | // If both bounds are outside of the existing | ||
2033 | // string, then return unchanges. | ||
2034 | if (end < 0 || start >= src.Length) | ||
2035 | { | ||
2036 | return src; | ||
2037 | } | ||
2038 | // At least one bound is in-range, so we | ||
2039 | // need to clip the out-of-bound argument. | ||
2040 | if (start < 0) | ||
2041 | { | ||
2042 | start = 0; | ||
2043 | } | ||
2044 | |||
2045 | if (end >= src.Length) | ||
2046 | { | ||
2047 | end = src.Length-1; | ||
2048 | } | ||
2049 | |||
2050 | return src.Remove(start,end-start+1); | ||
2051 | } | ||
2052 | // Inverted substring | ||
2053 | else | ||
2054 | { | ||
2055 | // In this case, out of bounds means that | ||
2056 | // the existing string is part of the cut. | ||
2057 | if (start < 0 || end >= src.Length) | ||
2058 | { | ||
2059 | return String.Empty; | ||
2060 | } | ||
2061 | |||
2062 | if (end > 0) | ||
2063 | { | ||
2064 | if (start < src.Length) | ||
2065 | { | ||
2066 | return src.Remove(start).Remove(0,end+1); | ||
2067 | } | ||
2068 | else | ||
2069 | { | ||
2070 | return src.Remove(0,end+1); | ||
2071 | } | ||
2072 | } | ||
2073 | else | ||
2074 | { | ||
2075 | if (start < src.Length) | ||
2076 | { | ||
2077 | return src.Remove(start); | ||
2078 | } | ||
2079 | else | ||
2080 | { | ||
2081 | return src; | ||
2082 | } | ||
2083 | } | ||
2084 | } | ||
2085 | } | ||
2086 | |||
2087 | /// <summary> | ||
2088 | /// Insert string inserts the specified string identified by src | ||
2089 | /// at the index indicated by index. Index may be negative, in | ||
2090 | /// which case it is end-relative. The index may exceed either | ||
2091 | /// string bound, with the result being a concatenation. | ||
2092 | /// </summary> | ||
2093 | |||
2094 | public LSL_String llInsertString(string dest, int index, string src) | ||
2095 | { | ||
2096 | |||
2097 | m_host.AddScriptLPS(1); | ||
2098 | |||
2099 | // Normalize indices (if negative). | ||
2100 | // After normlaization they may still be | ||
2101 | // negative, but that is now relative to | ||
2102 | // the start, rather than the end, of the | ||
2103 | // sequence. | ||
2104 | if (index < 0) | ||
2105 | { | ||
2106 | index = dest.Length+index; | ||
2107 | |||
2108 | // Negative now means it is less than the lower | ||
2109 | // bound of the string. | ||
2110 | |||
2111 | if (index < 0) | ||
2112 | { | ||
2113 | return src+dest; | ||
2114 | } | ||
2115 | |||
2116 | } | ||
2117 | |||
2118 | if (index >= dest.Length) | ||
2119 | { | ||
2120 | return dest+src; | ||
2121 | } | ||
2122 | |||
2123 | // The index is in bounds. | ||
2124 | // In this case the index refers to the index that will | ||
2125 | // be assigned to the first character of the inserted string. | ||
2126 | // So unlike the other string operations, we do not add one | ||
2127 | // to get the correct string length. | ||
2128 | return dest.Substring(0,index)+src+dest.Substring(index); | ||
2129 | |||
2130 | } | ||
2131 | |||
2132 | public LSL_String llToUpper(string src) | ||
2133 | { | ||
2134 | m_host.AddScriptLPS(1); | ||
2135 | return src.ToUpper(); | ||
2136 | } | ||
2137 | |||
2138 | public LSL_String llToLower(string src) | ||
2139 | { | ||
2140 | m_host.AddScriptLPS(1); | ||
2141 | return src.ToLower(); | ||
2142 | } | ||
2143 | |||
2144 | public LSL_Integer llGiveMoney(string destination, int amount) | ||
2145 | { | ||
2146 | UUID invItemID=InventorySelf(); | ||
2147 | if (invItemID == UUID.Zero) | ||
2148 | return 0; | ||
2149 | |||
2150 | m_host.AddScriptLPS(1); | ||
2151 | |||
2152 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
2153 | return 0; | ||
2154 | |||
2155 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_DEBIT) == 0) | ||
2156 | { | ||
2157 | LSLError("No permissions to give money"); | ||
2158 | return 0; | ||
2159 | } | ||
2160 | |||
2161 | UUID toID=new UUID(); | ||
2162 | |||
2163 | if (!UUID.TryParse(destination, out toID)) | ||
2164 | { | ||
2165 | LSLError("Bad key in llGiveMoney"); | ||
2166 | return 0; | ||
2167 | } | ||
2168 | |||
2169 | IMoneyModule money=World.RequestModuleInterface<IMoneyModule>(); | ||
2170 | |||
2171 | if (money == null) | ||
2172 | { | ||
2173 | NotImplemented("llGiveMoney"); | ||
2174 | return 0; | ||
2175 | } | ||
2176 | |||
2177 | bool result=money.ObjectGiveMoney(m_host.ParentGroup.RootPart.UUID, m_host.ParentGroup.RootPart.OwnerID, toID, amount); | ||
2178 | |||
2179 | if (result) | ||
2180 | return 1; | ||
2181 | |||
2182 | return 0; | ||
2183 | } | ||
2184 | |||
2185 | public void llMakeExplosion() | ||
2186 | { | ||
2187 | m_host.AddScriptLPS(1); | ||
2188 | Deprecated("llMakeExplosion"); | ||
2189 | // ScriptSleep(100); | ||
2190 | } | ||
2191 | |||
2192 | public void llMakeFountain() | ||
2193 | { | ||
2194 | m_host.AddScriptLPS(1); | ||
2195 | Deprecated("llMakeFountain"); | ||
2196 | // ScriptSleep(100); | ||
2197 | } | ||
2198 | |||
2199 | public void llMakeSmoke() | ||
2200 | { | ||
2201 | m_host.AddScriptLPS(1); | ||
2202 | Deprecated("llMakeSmoke"); | ||
2203 | // ScriptSleep(100); | ||
2204 | } | ||
2205 | |||
2206 | public void llMakeFire() | ||
2207 | { | ||
2208 | m_host.AddScriptLPS(1); | ||
2209 | Deprecated("llMakeFire"); | ||
2210 | // ScriptSleep(100); | ||
2211 | } | ||
2212 | |||
2213 | public void llRezAtRoot(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | ||
2214 | { | ||
2215 | m_host.AddScriptLPS(1); | ||
2216 | |||
2217 | if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) | ||
2218 | return; | ||
2219 | float dist = (float)llVecDist(llGetPos(), pos); | ||
2220 | |||
2221 | if (dist > m_ScriptDistanceFactor * 10.0f) | ||
2222 | return; | ||
2223 | |||
2224 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
2225 | { | ||
2226 | if (inv.Value.Name == inventory) | ||
2227 | { | ||
2228 | // make sure we're an object. | ||
2229 | if (inv.Value.InvType != (int)InventoryType.Object) | ||
2230 | { | ||
2231 | llSay(0, "Unable to create requested object. Object is missing from database."); | ||
2232 | return; | ||
2233 | } | ||
2234 | |||
2235 | Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); | ||
2236 | |||
2237 | // test if we're further away then 10m | ||
2238 | if (Util.GetDistanceTo(llpos, m_host.AbsolutePosition) > 10) | ||
2239 | return; // wiki says, if it's further away then 10m, silently fail. | ||
2240 | |||
2241 | Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); | ||
2242 | |||
2243 | // need the magnitude later | ||
2244 | float velmag = (float)Util.GetMagnitude(llvel); | ||
2245 | |||
2246 | SceneObjectGroup new_group = World.RezObject(m_host, inv.Value, llpos, new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), llvel, param); | ||
2247 | |||
2248 | // If either of these are null, then there was an unknown error. | ||
2249 | if (new_group == null) | ||
2250 | continue; | ||
2251 | if (new_group.RootPart == null) | ||
2252 | continue; | ||
2253 | |||
2254 | // objects rezzed with this method are die_at_edge by default. | ||
2255 | new_group.RootPart.SetDieAtEdge(true); | ||
2256 | |||
2257 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2258 | "object_rez", new Object[] { | ||
2259 | new LSL_String( | ||
2260 | new_group.RootPart.UUID.ToString()) }, | ||
2261 | new DetectParams[0])); | ||
2262 | |||
2263 | float groupmass = new_group.GetMass(); | ||
2264 | |||
2265 | //Recoil. | ||
2266 | llApplyImpulse(new LSL_Vector(llvel.X * groupmass, llvel.Y * groupmass, llvel.Z * groupmass), 0); | ||
2267 | // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) | ||
2268 | ScriptSleep((int)((groupmass * velmag) / 10)); | ||
2269 | // ScriptSleep(100); | ||
2270 | return; | ||
2271 | } | ||
2272 | } | ||
2273 | llSay(0, "Could not find object " + inventory); | ||
2274 | } | ||
2275 | |||
2276 | public void llRezObject(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param) | ||
2277 | { | ||
2278 | llRezAtRoot(inventory, pos, vel, rot, param); | ||
2279 | } | ||
2280 | |||
2281 | public void llLookAt(LSL_Vector target, double strength, double damping) | ||
2282 | { | ||
2283 | m_host.AddScriptLPS(1); | ||
2284 | NotImplemented("llLookAt"); | ||
2285 | } | ||
2286 | |||
2287 | public void llStopLookAt() | ||
2288 | { | ||
2289 | m_host.AddScriptLPS(1); | ||
2290 | NotImplemented("llStopLookAt"); | ||
2291 | } | ||
2292 | |||
2293 | public void llSetTimerEvent(double sec) | ||
2294 | { | ||
2295 | m_host.AddScriptLPS(1); | ||
2296 | // Setting timer repeat | ||
2297 | AsyncCommands.TimerPlugin.SetTimerEvent(m_localID, m_itemID, sec); | ||
2298 | } | ||
2299 | |||
2300 | public void llSleep(double sec) | ||
2301 | { | ||
2302 | m_host.AddScriptLPS(1); | ||
2303 | Thread.Sleep((int)(sec * 1000)); | ||
2304 | } | ||
2305 | |||
2306 | public LSL_Float llGetMass() | ||
2307 | { | ||
2308 | m_host.AddScriptLPS(1); | ||
2309 | return m_host.GetMass(); | ||
2310 | } | ||
2311 | |||
2312 | public void llCollisionFilter(string name, string id, int accept) | ||
2313 | { | ||
2314 | m_host.AddScriptLPS(1); | ||
2315 | NotImplemented("llCollisionFilter"); | ||
2316 | } | ||
2317 | |||
2318 | public void llTakeControls(int controls, int accept, int pass_on) | ||
2319 | { | ||
2320 | if (!m_host.TaskInventory.ContainsKey(InventorySelf())) | ||
2321 | { | ||
2322 | return; | ||
2323 | } | ||
2324 | |||
2325 | if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero) | ||
2326 | { | ||
2327 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); | ||
2328 | |||
2329 | if (presence != null) | ||
2330 | { | ||
2331 | if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) | ||
2332 | { | ||
2333 | presence.RegisterControlEventsToScript(controls, accept, pass_on, m_localID, m_itemID); | ||
2334 | |||
2335 | } | ||
2336 | } | ||
2337 | } | ||
2338 | |||
2339 | m_host.AddScriptLPS(1); | ||
2340 | } | ||
2341 | |||
2342 | public void llReleaseControls() | ||
2343 | { | ||
2344 | m_host.AddScriptLPS(1); | ||
2345 | |||
2346 | if (!m_host.TaskInventory.ContainsKey(InventorySelf())) | ||
2347 | { | ||
2348 | return; | ||
2349 | } | ||
2350 | |||
2351 | if (m_host.TaskInventory[InventorySelf()].PermsGranter != UUID.Zero) | ||
2352 | { | ||
2353 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[InventorySelf()].PermsGranter); | ||
2354 | |||
2355 | if (presence != null) | ||
2356 | { | ||
2357 | if ((m_host.TaskInventory[InventorySelf()].PermsMask & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) != 0) | ||
2358 | { | ||
2359 | // Unregister controls from Presence | ||
2360 | presence.UnRegisterControlEventsToScript(m_localID, m_itemID); | ||
2361 | // Remove Take Control permission. | ||
2362 | m_host.TaskInventory[InventorySelf()].PermsMask &= ~ScriptBaseClass.PERMISSION_TAKE_CONTROLS; | ||
2363 | } | ||
2364 | } | ||
2365 | } | ||
2366 | } | ||
2367 | |||
2368 | public void llAttachToAvatar(int attachment) | ||
2369 | { | ||
2370 | m_host.AddScriptLPS(1); | ||
2371 | NotImplemented("llAttachToAvatar"); | ||
2372 | } | ||
2373 | |||
2374 | public void llDetachFromAvatar() | ||
2375 | { | ||
2376 | m_host.AddScriptLPS(1); | ||
2377 | NotImplemented("llDetachFromAvatar"); | ||
2378 | } | ||
2379 | |||
2380 | public void llTakeCamera(string avatar) | ||
2381 | { | ||
2382 | m_host.AddScriptLPS(1); | ||
2383 | Deprecated("llTakeCamera"); | ||
2384 | } | ||
2385 | |||
2386 | public void llReleaseCamera(string avatar) | ||
2387 | { | ||
2388 | m_host.AddScriptLPS(1); | ||
2389 | Deprecated("llReleaseCamera"); | ||
2390 | } | ||
2391 | |||
2392 | public LSL_String llGetOwner() | ||
2393 | { | ||
2394 | m_host.AddScriptLPS(1); | ||
2395 | |||
2396 | return m_host.ObjectOwner.ToString(); | ||
2397 | } | ||
2398 | |||
2399 | public void llInstantMessage(string user, string message) | ||
2400 | { | ||
2401 | m_host.AddScriptLPS(1); | ||
2402 | |||
2403 | // We may be able to use ClientView.SendInstantMessage here, but we need a client instance. | ||
2404 | // InstantMessageModule.OnInstantMessage searches through a list of scenes for a client matching the toAgent, | ||
2405 | // but I don't think we have a list of scenes available from here. | ||
2406 | // (We also don't want to duplicate the code in OnInstantMessage if we can avoid it.) | ||
2407 | |||
2408 | // user is a UUID | ||
2409 | |||
2410 | // TODO: figure out values for client, fromSession, and imSessionID | ||
2411 | // client.SendInstantMessage(m_host.UUID, fromSession, message, user, imSessionID, m_host.Name, AgentManager.InstantMessageDialog.MessageFromAgent, (uint)Util.UnixTimeSinceEpoch()); | ||
2412 | UUID friendTransactionID = UUID.Random(); | ||
2413 | |||
2414 | //m_pendingFriendRequests.Add(friendTransactionID, fromAgentID); | ||
2415 | |||
2416 | GridInstantMessage msg = new GridInstantMessage(); | ||
2417 | msg.fromAgentID = new Guid(m_host.UUID.ToString()); // fromAgentID.Guid; | ||
2418 | msg.fromAgentSession = new Guid(friendTransactionID.ToString());// fromAgentSession.UUID; | ||
2419 | msg.toAgentID = new Guid(user); // toAgentID.Guid; | ||
2420 | msg.imSessionID = new Guid(friendTransactionID.ToString()); // This is the item we're mucking with here | ||
2421 | // Console.WriteLine("[Scripting IM]: From:" + msg.fromAgentID.ToString() + " To: " + msg.toAgentID.ToString() + " Session:" + msg.imSessionID.ToString() + " Message:" + message); | ||
2422 | // Console.WriteLine("[Scripting IM]: Filling Session: " + msg.imSessionID.ToString()); | ||
2423 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch();// timestamp; | ||
2424 | //if (client != null) | ||
2425 | //{ | ||
2426 | msg.fromAgentName = m_host.Name;//client.FirstName + " " + client.LastName;// fromAgentName; | ||
2427 | //} | ||
2428 | //else | ||
2429 | //{ | ||
2430 | // msg.fromAgentName = "(hippos)";// Added for posterity. This means that we can't figure out who sent it | ||
2431 | //} | ||
2432 | msg.message = message; | ||
2433 | msg.dialog = (byte)19; // messgage from script ??? // dialog; | ||
2434 | msg.fromGroup = false;// fromGroup; | ||
2435 | msg.offline = (byte)0; //offline; | ||
2436 | msg.ParentEstateID = 0; //ParentEstateID; | ||
2437 | msg.Position = Vector3.Zero;// new Vector3(m_host.AbsolutePosition); | ||
2438 | msg.RegionID = World.RegionInfo.RegionID.Guid;//RegionID.Guid; | ||
2439 | msg.binaryBucket = new byte[0];// binaryBucket; | ||
2440 | World.TriggerGridInstantMessage(msg, InstantMessageReceiver.IMModule); | ||
2441 | // ScriptSleep(2000); | ||
2442 | } | ||
2443 | |||
2444 | public void llEmail(string address, string subject, string message) | ||
2445 | { | ||
2446 | m_host.AddScriptLPS(1); | ||
2447 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | ||
2448 | if (emailModule == null) | ||
2449 | return; | ||
2450 | |||
2451 | emailModule.SendEmail(m_host.UUID, address, subject, message); | ||
2452 | // ScriptSleep(20000); | ||
2453 | } | ||
2454 | |||
2455 | public void llGetNextEmail(string address, string subject) | ||
2456 | { | ||
2457 | m_host.AddScriptLPS(1); | ||
2458 | IEmailModule emailModule = m_ScriptEngine.World.RequestModuleInterface<IEmailModule>(); | ||
2459 | if (emailModule == null) | ||
2460 | return; | ||
2461 | Email email; | ||
2462 | |||
2463 | email = emailModule.GetNextEmail(m_host.UUID, address, subject); | ||
2464 | |||
2465 | if (email == null) | ||
2466 | return; | ||
2467 | |||
2468 | m_ScriptEngine.PostObjectEvent(m_host.LocalId, | ||
2469 | new EventParams("email", | ||
2470 | new Object[] { | ||
2471 | new LSL_String(email.time), | ||
2472 | new LSL_String(email.sender), | ||
2473 | new LSL_String(email.subject), | ||
2474 | new LSL_String(email.message), | ||
2475 | new LSL_Integer(email.numLeft)}, | ||
2476 | new DetectParams[0])); | ||
2477 | |||
2478 | } | ||
2479 | |||
2480 | public LSL_String llGetKey() | ||
2481 | { | ||
2482 | m_host.AddScriptLPS(1); | ||
2483 | return m_host.UUID.ToString(); | ||
2484 | } | ||
2485 | |||
2486 | public void llSetBuoyancy(double buoyancy) | ||
2487 | { | ||
2488 | m_host.AddScriptLPS(1); | ||
2489 | if (m_host.ParentGroup != null) | ||
2490 | { | ||
2491 | if (m_host.ParentGroup.RootPart != null) | ||
2492 | { | ||
2493 | m_host.ParentGroup.RootPart.SetBuoyancy((float)buoyancy); | ||
2494 | } | ||
2495 | } | ||
2496 | } | ||
2497 | |||
2498 | |||
2499 | |||
2500 | public void llSetHoverHeight(double height, int water, double tau) | ||
2501 | { | ||
2502 | m_host.AddScriptLPS(1); | ||
2503 | NotImplemented("llSetHoverHeight"); | ||
2504 | } | ||
2505 | |||
2506 | public void llStopHover() | ||
2507 | { | ||
2508 | m_host.AddScriptLPS(1); | ||
2509 | NotImplemented("llStopHover"); | ||
2510 | } | ||
2511 | |||
2512 | public void llMinEventDelay(double delay) | ||
2513 | { | ||
2514 | m_host.AddScriptLPS(1); | ||
2515 | NotImplemented("llMinEventDelay"); | ||
2516 | } | ||
2517 | |||
2518 | public void llSoundPreload() | ||
2519 | { | ||
2520 | m_host.AddScriptLPS(1); | ||
2521 | Deprecated("llSoundPreload"); | ||
2522 | } | ||
2523 | |||
2524 | public void llRotLookAt(LSL_Rotation target, double strength, double damping) | ||
2525 | { | ||
2526 | m_host.AddScriptLPS(1); | ||
2527 | NotImplemented("llRotLookAt"); | ||
2528 | } | ||
2529 | |||
2530 | public LSL_Integer llStringLength(string str) | ||
2531 | { | ||
2532 | m_host.AddScriptLPS(1); | ||
2533 | if (str.Length > 0) | ||
2534 | { | ||
2535 | return str.Length; | ||
2536 | } | ||
2537 | else | ||
2538 | { | ||
2539 | return 0; | ||
2540 | } | ||
2541 | } | ||
2542 | |||
2543 | public void llStartAnimation(string anim) | ||
2544 | { | ||
2545 | m_host.AddScriptLPS(1); | ||
2546 | |||
2547 | UUID invItemID=InventorySelf(); | ||
2548 | if (invItemID == UUID.Zero) | ||
2549 | return; | ||
2550 | |||
2551 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
2552 | return; | ||
2553 | |||
2554 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) | ||
2555 | { | ||
2556 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); | ||
2557 | |||
2558 | if (presence != null) | ||
2559 | { | ||
2560 | // Do NOT try to parse UUID, animations cannot be triggered by ID | ||
2561 | UUID animID=InventoryKey(anim, (int)AssetType.Animation); | ||
2562 | if (animID == UUID.Zero) | ||
2563 | presence.AddAnimation(anim); | ||
2564 | else | ||
2565 | presence.AddAnimation(animID); | ||
2566 | } | ||
2567 | } | ||
2568 | } | ||
2569 | |||
2570 | public void llStopAnimation(string anim) | ||
2571 | { | ||
2572 | m_host.AddScriptLPS(1); | ||
2573 | |||
2574 | UUID invItemID=InventorySelf(); | ||
2575 | if (invItemID == UUID.Zero) | ||
2576 | return; | ||
2577 | |||
2578 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
2579 | return; | ||
2580 | |||
2581 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION) != 0) | ||
2582 | { | ||
2583 | UUID animID = new UUID(); | ||
2584 | |||
2585 | if (!UUID.TryParse(anim, out animID)) | ||
2586 | { | ||
2587 | animID=InventoryKey(anim); | ||
2588 | } | ||
2589 | |||
2590 | ScenePresence presence = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter); | ||
2591 | |||
2592 | if (presence != null) | ||
2593 | { | ||
2594 | if (animID == UUID.Zero) | ||
2595 | presence.RemoveAnimation(anim); | ||
2596 | else | ||
2597 | presence.RemoveAnimation(animID); | ||
2598 | } | ||
2599 | } | ||
2600 | } | ||
2601 | |||
2602 | public void llPointAt() | ||
2603 | { | ||
2604 | m_host.AddScriptLPS(1); | ||
2605 | NotImplemented("llPointAt"); | ||
2606 | } | ||
2607 | |||
2608 | public void llStopPointAt() | ||
2609 | { | ||
2610 | m_host.AddScriptLPS(1); | ||
2611 | NotImplemented("llStopPointAt"); | ||
2612 | } | ||
2613 | |||
2614 | public void llTargetOmega(LSL_Vector axis, double spinrate, double gain) | ||
2615 | { | ||
2616 | m_host.AddScriptLPS(1); | ||
2617 | m_host.RotationalVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); | ||
2618 | m_host.AngularVelocity = new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate)); | ||
2619 | m_host.ScheduleTerseUpdate(); | ||
2620 | m_host.SendTerseUpdateToAllClients(); | ||
2621 | m_host.ParentGroup.HasGroupChanged = true; | ||
2622 | } | ||
2623 | |||
2624 | public LSL_Integer llGetStartParameter() | ||
2625 | { | ||
2626 | m_host.AddScriptLPS(1); | ||
2627 | return m_ScriptEngine.GetStartParameter(m_itemID); | ||
2628 | } | ||
2629 | |||
2630 | public void llGodLikeRezObject(string inventory, LSL_Vector pos) | ||
2631 | { | ||
2632 | m_host.AddScriptLPS(1); | ||
2633 | NotImplemented("llGodLikeRezObject"); | ||
2634 | } | ||
2635 | |||
2636 | public void llRequestPermissions(string agent, int perm) | ||
2637 | { | ||
2638 | UUID agentID=new UUID(); | ||
2639 | |||
2640 | if (!UUID.TryParse(agent, out agentID)) | ||
2641 | return; | ||
2642 | |||
2643 | UUID invItemID=InventorySelf(); | ||
2644 | |||
2645 | if (invItemID == UUID.Zero) | ||
2646 | return; // Not in a prim? How?? | ||
2647 | |||
2648 | if (agentID == UUID.Zero || perm == 0) // Releasing permissions | ||
2649 | { | ||
2650 | llReleaseControls(); | ||
2651 | |||
2652 | m_host.TaskInventory[invItemID].PermsGranter=UUID.Zero; | ||
2653 | m_host.TaskInventory[invItemID].PermsMask=0; | ||
2654 | |||
2655 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2656 | "run_time_permissions", new Object[] { | ||
2657 | new LSL_Integer(0) }, | ||
2658 | new DetectParams[0])); | ||
2659 | |||
2660 | return; | ||
2661 | } | ||
2662 | |||
2663 | if ( m_host.TaskInventory[invItemID].PermsGranter != agentID || (perm & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) | ||
2664 | llReleaseControls(); | ||
2665 | |||
2666 | m_host.AddScriptLPS(1); | ||
2667 | |||
2668 | if (m_host.ParentGroup.RootPart.IsAttachment && agent == m_host.ParentGroup.RootPart.AttachedAvatar) | ||
2669 | { | ||
2670 | // When attached, certain permissions are implicit if requested from owner | ||
2671 | int implicitPerms = ScriptBaseClass.PERMISSION_TAKE_CONTROLS | | ||
2672 | ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | ||
2673 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | | ||
2674 | ScriptBaseClass.PERMISSION_ATTACH; | ||
2675 | |||
2676 | if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms | ||
2677 | { | ||
2678 | m_host.TaskInventory[invItemID].PermsGranter=agentID; | ||
2679 | m_host.TaskInventory[invItemID].PermsMask=perm; | ||
2680 | |||
2681 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2682 | "run_time_permissions", new Object[] { | ||
2683 | new LSL_Integer(perm) }, | ||
2684 | new DetectParams[0])); | ||
2685 | |||
2686 | return; | ||
2687 | } | ||
2688 | } | ||
2689 | else if (m_host.SitTargetAvatar == agentID) // Sitting avatar | ||
2690 | { | ||
2691 | // When agent is sitting, certain permissions are implicit if requested from sitting agent | ||
2692 | int implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | | ||
2693 | ScriptBaseClass.PERMISSION_CONTROL_CAMERA | | ||
2694 | ScriptBaseClass.PERMISSION_TRACK_CAMERA; | ||
2695 | |||
2696 | if ((perm & (~implicitPerms)) == 0) // Requested only implicit perms | ||
2697 | { | ||
2698 | m_host.TaskInventory[invItemID].PermsGranter=agentID; | ||
2699 | m_host.TaskInventory[invItemID].PermsMask=perm; | ||
2700 | |||
2701 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2702 | "run_time_permissions", new Object[] { | ||
2703 | new LSL_Integer(perm) }, | ||
2704 | new DetectParams[0])); | ||
2705 | |||
2706 | return; | ||
2707 | } | ||
2708 | } | ||
2709 | |||
2710 | ScenePresence presence = World.GetScenePresence(agentID); | ||
2711 | |||
2712 | if (presence != null) | ||
2713 | { | ||
2714 | string ownerName=resolveName(m_host.ParentGroup.RootPart.OwnerID); | ||
2715 | if (ownerName == String.Empty) | ||
2716 | ownerName="(hippos)"; | ||
2717 | |||
2718 | if (!m_waitingForScriptAnswer) | ||
2719 | { | ||
2720 | m_host.TaskInventory[invItemID].PermsGranter=agentID; | ||
2721 | m_host.TaskInventory[invItemID].PermsMask=0; | ||
2722 | presence.ControllingClient.OnScriptAnswer+=handleScriptAnswer; | ||
2723 | m_waitingForScriptAnswer=true; | ||
2724 | } | ||
2725 | |||
2726 | presence.ControllingClient.SendScriptQuestion(m_host.UUID, m_host.ParentGroup.RootPart.Name, ownerName, invItemID, perm); | ||
2727 | return; | ||
2728 | } | ||
2729 | |||
2730 | // Requested agent is not in range, refuse perms | ||
2731 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2732 | "run_time_permissions", new Object[] { | ||
2733 | new LSL_Integer(0) }, | ||
2734 | new DetectParams[0])); | ||
2735 | } | ||
2736 | |||
2737 | void handleScriptAnswer(IClientAPI client, UUID taskID, UUID itemID, int answer) | ||
2738 | { | ||
2739 | if (taskID != m_host.UUID) | ||
2740 | return; | ||
2741 | |||
2742 | UUID invItemID=InventorySelf(); | ||
2743 | |||
2744 | if (invItemID == UUID.Zero) | ||
2745 | return; | ||
2746 | |||
2747 | client.OnScriptAnswer-=handleScriptAnswer; | ||
2748 | m_waitingForScriptAnswer=false; | ||
2749 | |||
2750 | if ((answer & ScriptBaseClass.PERMISSION_TAKE_CONTROLS) == 0) | ||
2751 | llReleaseControls(); | ||
2752 | |||
2753 | m_host.TaskInventory[invItemID].PermsMask=answer; | ||
2754 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
2755 | "run_time_permissions", new Object[] { | ||
2756 | new LSL_Integer(answer) }, | ||
2757 | new DetectParams[0])); | ||
2758 | } | ||
2759 | |||
2760 | public LSL_String llGetPermissionsKey() | ||
2761 | { | ||
2762 | m_host.AddScriptLPS(1); | ||
2763 | |||
2764 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
2765 | { | ||
2766 | if (item.Type == 10 && item.ItemID == m_itemID) | ||
2767 | { | ||
2768 | return item.PermsGranter.ToString(); | ||
2769 | } | ||
2770 | } | ||
2771 | |||
2772 | return UUID.Zero.ToString(); | ||
2773 | } | ||
2774 | |||
2775 | public LSL_Integer llGetPermissions() | ||
2776 | { | ||
2777 | m_host.AddScriptLPS(1); | ||
2778 | |||
2779 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
2780 | { | ||
2781 | if (item.Type == 10 && item.ItemID == m_itemID) | ||
2782 | { | ||
2783 | return item.PermsMask; | ||
2784 | } | ||
2785 | } | ||
2786 | |||
2787 | return 0; | ||
2788 | } | ||
2789 | |||
2790 | public LSL_Integer llGetLinkNumber() | ||
2791 | { | ||
2792 | m_host.AddScriptLPS(1); | ||
2793 | |||
2794 | if (m_host.ParentGroup.Children.Count > 1) | ||
2795 | { | ||
2796 | return m_host.LinkNum; | ||
2797 | } | ||
2798 | else | ||
2799 | { | ||
2800 | return 0; | ||
2801 | } | ||
2802 | } | ||
2803 | |||
2804 | public void llSetLinkColor(int linknumber, LSL_Vector color, int face) | ||
2805 | { | ||
2806 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | ||
2807 | |||
2808 | foreach (SceneObjectPart part in parts) | ||
2809 | SetColor(part, color, face); | ||
2810 | } | ||
2811 | |||
2812 | public void llCreateLink(string target, int parent) | ||
2813 | { | ||
2814 | m_host.AddScriptLPS(1); | ||
2815 | UUID invItemID = InventorySelf(); | ||
2816 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0) { | ||
2817 | ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); | ||
2818 | return; | ||
2819 | } | ||
2820 | IClientAPI client = World.GetScenePresence(m_host.TaskInventory[invItemID].PermsGranter).ControllingClient; | ||
2821 | SceneObjectPart targetPart = World.GetSceneObjectPart(target); | ||
2822 | SceneObjectGroup parentPrim = null, childPrim = null; | ||
2823 | if (targetPart != null) | ||
2824 | { | ||
2825 | if (parent != 0) { | ||
2826 | parentPrim = m_host.ParentGroup; | ||
2827 | childPrim = targetPart.ParentGroup; | ||
2828 | } | ||
2829 | else | ||
2830 | { | ||
2831 | parentPrim = targetPart.ParentGroup; | ||
2832 | childPrim = m_host.ParentGroup; | ||
2833 | } | ||
2834 | // byte uf = childPrim.RootPart.UpdateFlag; | ||
2835 | childPrim.RootPart.UpdateFlag = 0; | ||
2836 | parentPrim.LinkToGroup(childPrim); | ||
2837 | // if (uf != (Byte)0) | ||
2838 | // parent.RootPart.UpdateFlag = uf; | ||
2839 | } | ||
2840 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
2841 | parentPrim.RootPart.AddFlag(PrimFlags.CreateSelected); | ||
2842 | parentPrim.HasGroupChanged = true; | ||
2843 | parentPrim.ScheduleGroupForFullUpdate(); | ||
2844 | parentPrim.GetProperties(client); | ||
2845 | |||
2846 | ScriptSleep(1000); | ||
2847 | } | ||
2848 | |||
2849 | public void llBreakLink(int linknum) | ||
2850 | { | ||
2851 | m_host.AddScriptLPS(1); | ||
2852 | UUID invItemID = InventorySelf(); | ||
2853 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CHANGE_LINKS) == 0) | ||
2854 | { | ||
2855 | ShoutError("Script trying to link but PERMISSION_CHANGE_LINKS permission not set!"); | ||
2856 | return; | ||
2857 | } | ||
2858 | if (linknum < ScriptBaseClass.LINK_THIS) | ||
2859 | return; | ||
2860 | SceneObjectGroup parentPrim = m_host.ParentGroup; | ||
2861 | SceneObjectPart childPrim = null; | ||
2862 | switch (linknum) | ||
2863 | { | ||
2864 | case ScriptBaseClass.LINK_ROOT: | ||
2865 | break; | ||
2866 | case ScriptBaseClass.LINK_SET: | ||
2867 | case ScriptBaseClass.LINK_ALL_OTHERS: | ||
2868 | case ScriptBaseClass.LINK_ALL_CHILDREN: | ||
2869 | case ScriptBaseClass.LINK_THIS: | ||
2870 | foreach (SceneObjectPart part in parentPrim.Children.Values) | ||
2871 | { | ||
2872 | if (part.UUID != m_host.UUID) | ||
2873 | { | ||
2874 | childPrim = part; | ||
2875 | break; | ||
2876 | } | ||
2877 | } | ||
2878 | break; | ||
2879 | default: | ||
2880 | childPrim = parentPrim.GetLinkNumPart(linknum); | ||
2881 | if (childPrim.UUID == m_host.UUID) | ||
2882 | childPrim = null; | ||
2883 | break; | ||
2884 | } | ||
2885 | if (linknum == ScriptBaseClass.LINK_ROOT) | ||
2886 | { | ||
2887 | // Restructuring Multiple Prims. | ||
2888 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); | ||
2889 | parts.Remove(parentPrim.RootPart); | ||
2890 | foreach (SceneObjectPart part in parts) | ||
2891 | { | ||
2892 | parentPrim.DelinkFromGroup(part.LocalId, true); | ||
2893 | } | ||
2894 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
2895 | if (parts.Count > 0) { | ||
2896 | SceneObjectPart newRoot = parts[0]; | ||
2897 | parts.Remove(newRoot); | ||
2898 | foreach (SceneObjectPart part in parts) | ||
2899 | { | ||
2900 | part.UpdateFlag = 0; | ||
2901 | newRoot.ParentGroup.LinkToGroup(part.ParentGroup); | ||
2902 | } | ||
2903 | } | ||
2904 | } | ||
2905 | else | ||
2906 | { | ||
2907 | if (childPrim == null) | ||
2908 | return; | ||
2909 | parentPrim.DelinkFromGroup(childPrim.LocalId, true); | ||
2910 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
2911 | } | ||
2912 | } | ||
2913 | |||
2914 | public void llBreakAllLinks() | ||
2915 | { | ||
2916 | m_host.AddScriptLPS(1); | ||
2917 | SceneObjectGroup parentPrim = m_host.ParentGroup; | ||
2918 | List<SceneObjectPart> parts = new List<SceneObjectPart>(parentPrim.Children.Values); | ||
2919 | parts.Remove(parentPrim.RootPart); | ||
2920 | foreach (SceneObjectPart part in parts) | ||
2921 | { | ||
2922 | parentPrim.DelinkFromGroup(part.LocalId, true); | ||
2923 | parentPrim.TriggerScriptChangedEvent(Changed.LINK); | ||
2924 | } | ||
2925 | } | ||
2926 | |||
2927 | public LSL_String llGetLinkKey(int linknum) | ||
2928 | { | ||
2929 | m_host.AddScriptLPS(1); | ||
2930 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); | ||
2931 | if (part != null) | ||
2932 | { | ||
2933 | return part.UUID.ToString(); | ||
2934 | } | ||
2935 | else | ||
2936 | { | ||
2937 | return UUID.Zero.ToString(); | ||
2938 | } | ||
2939 | } | ||
2940 | |||
2941 | public LSL_String llGetLinkName(int linknum) | ||
2942 | { | ||
2943 | m_host.AddScriptLPS(1); | ||
2944 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknum); | ||
2945 | if (part != null) | ||
2946 | { | ||
2947 | return part.Name; | ||
2948 | } | ||
2949 | else | ||
2950 | { | ||
2951 | return ""; | ||
2952 | } | ||
2953 | } | ||
2954 | |||
2955 | public LSL_Integer llGetInventoryNumber(int type) | ||
2956 | { | ||
2957 | m_host.AddScriptLPS(1); | ||
2958 | int count = 0; | ||
2959 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
2960 | { | ||
2961 | if (inv.Value.Type == type || type == -1) | ||
2962 | { | ||
2963 | count = count + 1; | ||
2964 | } | ||
2965 | } | ||
2966 | return count; | ||
2967 | } | ||
2968 | |||
2969 | public LSL_String llGetInventoryName(int type, int number) | ||
2970 | { | ||
2971 | m_host.AddScriptLPS(1); | ||
2972 | ArrayList keys = new ArrayList(); | ||
2973 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
2974 | { | ||
2975 | if (inv.Value.Type == type || type == -1) | ||
2976 | { | ||
2977 | keys.Add(inv.Value.Name); | ||
2978 | } | ||
2979 | } | ||
2980 | if (keys.Count == 0) | ||
2981 | { | ||
2982 | return String.Empty; | ||
2983 | } | ||
2984 | keys.Sort(); | ||
2985 | if (keys.Count > number) | ||
2986 | { | ||
2987 | return (string)keys[number]; | ||
2988 | } | ||
2989 | return String.Empty; | ||
2990 | } | ||
2991 | |||
2992 | public LSL_Float llGetEnergy() | ||
2993 | { | ||
2994 | m_host.AddScriptLPS(1); | ||
2995 | // TODO: figure out real energy value | ||
2996 | return 1.0f; | ||
2997 | } | ||
2998 | |||
2999 | public void llGiveInventory(string destination, string inventory) | ||
3000 | { | ||
3001 | m_host.AddScriptLPS(1); | ||
3002 | bool found = false; | ||
3003 | UUID destId = UUID.Zero; | ||
3004 | UUID objId = UUID.Zero; | ||
3005 | |||
3006 | if (!UUID.TryParse(destination, out destId)) | ||
3007 | { | ||
3008 | llSay(0, "Could not parse key " + destination); | ||
3009 | return; | ||
3010 | } | ||
3011 | |||
3012 | // move the first object found with this inventory name | ||
3013 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
3014 | { | ||
3015 | if (inv.Value.Name == inventory) | ||
3016 | { | ||
3017 | found = true; | ||
3018 | objId = inv.Key; | ||
3019 | break; | ||
3020 | } | ||
3021 | } | ||
3022 | |||
3023 | if (!found) | ||
3024 | { | ||
3025 | llSay(0, String.Format("Could not find object '{0}'", inventory)); | ||
3026 | throw new Exception(String.Format("The inventory object '{0}' could not be found", inventory)); | ||
3027 | } | ||
3028 | |||
3029 | // check if destination is an avatar | ||
3030 | if (World.GetScenePresence(destId) != null) | ||
3031 | { | ||
3032 | // destination is an avatar | ||
3033 | World.MoveTaskInventoryItem(destId, null, m_host, objId); | ||
3034 | } | ||
3035 | else | ||
3036 | { | ||
3037 | // destination is an object | ||
3038 | World.MoveTaskInventoryItem(destId, m_host, objId); | ||
3039 | } | ||
3040 | // ScriptSleep(3000); | ||
3041 | } | ||
3042 | |||
3043 | public void llRemoveInventory(string name) | ||
3044 | { | ||
3045 | m_host.AddScriptLPS(1); | ||
3046 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3047 | { | ||
3048 | if (item.Name == name) | ||
3049 | { | ||
3050 | m_host.RemoveInventoryItem(item.ItemID); | ||
3051 | return; | ||
3052 | } | ||
3053 | } | ||
3054 | } | ||
3055 | |||
3056 | public void llSetText(string text, LSL_Vector color, double alpha) | ||
3057 | { | ||
3058 | m_host.AddScriptLPS(1); | ||
3059 | Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), | ||
3060 | Util.Clip((float)color.y, 0.0f, 1.0f), | ||
3061 | Util.Clip((float)color.z, 0.0f, 1.0f)); | ||
3062 | m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); | ||
3063 | m_host.ParentGroup.HasGroupChanged = true; | ||
3064 | } | ||
3065 | |||
3066 | public LSL_Float llWater(LSL_Vector offset) | ||
3067 | { | ||
3068 | m_host.AddScriptLPS(1); | ||
3069 | return World.RegionInfo.RegionSettings.WaterHeight; | ||
3070 | } | ||
3071 | |||
3072 | public void llPassTouches(int pass) | ||
3073 | { | ||
3074 | m_host.AddScriptLPS(1); | ||
3075 | NotImplemented("llPassTouches"); | ||
3076 | } | ||
3077 | |||
3078 | public LSL_String llRequestAgentData(string id, int data) | ||
3079 | { | ||
3080 | m_host.AddScriptLPS(1); | ||
3081 | |||
3082 | UserProfileData userProfile = | ||
3083 | World.CommsManager.UserService.GetUserProfile(id); | ||
3084 | |||
3085 | UserAgentData userAgent = | ||
3086 | World.CommsManager.UserService.GetAgentByUUID(id); | ||
3087 | |||
3088 | if (userProfile == null || userAgent == null) | ||
3089 | return UUID.Zero.ToString(); | ||
3090 | |||
3091 | string reply = String.Empty; | ||
3092 | |||
3093 | switch (data) | ||
3094 | { | ||
3095 | case 1: // DATA_ONLINE (0|1) | ||
3096 | // TODO: implement fetching of this information | ||
3097 | if (userProfile.CurrentAgent.AgentOnline) | ||
3098 | reply = "1"; | ||
3099 | else | ||
3100 | reply = "0"; | ||
3101 | break; | ||
3102 | case 2: // DATA_NAME (First Last) | ||
3103 | reply = userProfile.FirstName + " " + userProfile.SurName; | ||
3104 | break; | ||
3105 | case 3: // DATA_BORN (YYYY-MM-DD) | ||
3106 | DateTime born = new DateTime(1970, 1, 1, 0, 0, 0, 0); | ||
3107 | born = born.AddSeconds(userProfile.Created); | ||
3108 | reply = born.ToString("yyyy-MM-dd"); | ||
3109 | break; | ||
3110 | case 4: // DATA_RATING (0,0,0,0,0,0) | ||
3111 | reply = "0,0,0,0,0,0"; | ||
3112 | break; | ||
3113 | case 8: // DATA_PAYINFO (0|1|2|3) | ||
3114 | reply = "0"; | ||
3115 | break; | ||
3116 | default: | ||
3117 | return UUID.Zero.ToString(); // Raise no event | ||
3118 | } | ||
3119 | |||
3120 | UUID rq = UUID.Random(); | ||
3121 | |||
3122 | UUID tid = AsyncCommands. | ||
3123 | DataserverPlugin.RegisterRequest(m_localID, | ||
3124 | m_itemID, rq.ToString()); | ||
3125 | |||
3126 | AsyncCommands. | ||
3127 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | ||
3128 | |||
3129 | // ScriptSleep(100); | ||
3130 | return tid.ToString(); | ||
3131 | } | ||
3132 | |||
3133 | public LSL_String llRequestInventoryData(string name) | ||
3134 | { | ||
3135 | m_host.AddScriptLPS(1); | ||
3136 | |||
3137 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3138 | { | ||
3139 | if (item.Type == 3 && item.Name == name) | ||
3140 | { | ||
3141 | UUID tid = AsyncCommands. | ||
3142 | DataserverPlugin.RegisterRequest(m_localID, | ||
3143 | m_itemID, item.AssetID.ToString()); | ||
3144 | |||
3145 | Vector3 region = new Vector3( | ||
3146 | World.RegionInfo.RegionLocX * Constants.RegionSize, | ||
3147 | World.RegionInfo.RegionLocY * Constants.RegionSize, | ||
3148 | 0); | ||
3149 | |||
3150 | World.AssetCache.GetAsset(item.AssetID, | ||
3151 | delegate(UUID i, AssetBase a) | ||
3152 | { | ||
3153 | AssetLandmark lm = new AssetLandmark(a); | ||
3154 | |||
3155 | float rx = (uint)(lm.RegionHandle >> 32); | ||
3156 | float ry = (uint)lm.RegionHandle; | ||
3157 | region = lm.Position + new Vector3(rx, ry, 0) - region; | ||
3158 | |||
3159 | string reply = region.ToString(); | ||
3160 | AsyncCommands. | ||
3161 | DataserverPlugin.DataserverReply(i.ToString(), | ||
3162 | reply); | ||
3163 | }, false); | ||
3164 | |||
3165 | // ScriptSleep(1000); | ||
3166 | return tid.ToString(); | ||
3167 | } | ||
3168 | } | ||
3169 | // ScriptSleep(1000); | ||
3170 | return String.Empty; | ||
3171 | } | ||
3172 | |||
3173 | public void llSetDamage(double damage) | ||
3174 | { | ||
3175 | m_host.AddScriptLPS(1); | ||
3176 | NotImplemented("llSetDamage"); | ||
3177 | } | ||
3178 | |||
3179 | public void llTeleportAgentHome(string agent) | ||
3180 | { | ||
3181 | m_host.AddScriptLPS(1); | ||
3182 | UUID agentId = new UUID(); | ||
3183 | if (UUID.TryParse(agent, out agentId)) | ||
3184 | { | ||
3185 | ScenePresence presence = World.GetScenePresence(agentId); | ||
3186 | if (presence != null) | ||
3187 | { | ||
3188 | // agent must be over the owners land | ||
3189 | if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y)) | ||
3190 | World.TeleportClientHome(agentId, presence.ControllingClient); | ||
3191 | } | ||
3192 | } | ||
3193 | // ScriptSleep(5000); | ||
3194 | } | ||
3195 | |||
3196 | public void llTextBox(string avatar, string message, int chat_channel) | ||
3197 | { | ||
3198 | m_host.AddScriptLPS(1); | ||
3199 | NotImplemented("llTextBox"); | ||
3200 | } | ||
3201 | |||
3202 | public void llModifyLand(int action, int brush) | ||
3203 | { | ||
3204 | m_host.AddScriptLPS(1); | ||
3205 | World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new Vector3(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, 0)); | ||
3206 | } | ||
3207 | |||
3208 | public void llCollisionSound(string impact_sound, double impact_volume) | ||
3209 | { | ||
3210 | m_host.AddScriptLPS(1); | ||
3211 | NotImplemented("llCollisionSound"); | ||
3212 | } | ||
3213 | |||
3214 | public void llCollisionSprite(string impact_sprite) | ||
3215 | { | ||
3216 | m_host.AddScriptLPS(1); | ||
3217 | NotImplemented("llCollisionSprite"); | ||
3218 | } | ||
3219 | |||
3220 | public LSL_String llGetAnimation(string id) | ||
3221 | { | ||
3222 | m_host.AddScriptLPS(1); | ||
3223 | NotImplemented("llGetAnimation"); | ||
3224 | return String.Empty; | ||
3225 | } | ||
3226 | |||
3227 | public void llMessageLinked(int linknum, int num, string msg, string id) | ||
3228 | { | ||
3229 | |||
3230 | m_host.AddScriptLPS(1); | ||
3231 | |||
3232 | // uint partLocalID; | ||
3233 | UUID partItemID; | ||
3234 | |||
3235 | switch ((int)linknum) | ||
3236 | { | ||
3237 | |||
3238 | case (int)ScriptBaseClass.LINK_ROOT: | ||
3239 | |||
3240 | SceneObjectPart part = m_host.ParentGroup.RootPart; | ||
3241 | |||
3242 | foreach (TaskInventoryItem item in part.TaskInventory.Values) | ||
3243 | { | ||
3244 | if (item.Type == 10) | ||
3245 | { | ||
3246 | // partLocalID = part.LocalId; | ||
3247 | partItemID = item.ItemID; | ||
3248 | |||
3249 | object[] resobj = new object[] | ||
3250 | { | ||
3251 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3252 | }; | ||
3253 | |||
3254 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3255 | new EventParams("link_message", | ||
3256 | resobj, new DetectParams[0])); | ||
3257 | } | ||
3258 | } | ||
3259 | |||
3260 | break; | ||
3261 | |||
3262 | case (int)ScriptBaseClass.LINK_SET: | ||
3263 | |||
3264 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3265 | { | ||
3266 | |||
3267 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3268 | { | ||
3269 | if (item.Type == 10) | ||
3270 | { | ||
3271 | // partLocalID = partInst.LocalId; | ||
3272 | partItemID = item.ItemID; | ||
3273 | Object[] resobj = new object[] | ||
3274 | { | ||
3275 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3276 | }; | ||
3277 | |||
3278 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3279 | new EventParams("link_message", | ||
3280 | resobj, new DetectParams[0])); | ||
3281 | } | ||
3282 | } | ||
3283 | } | ||
3284 | |||
3285 | break; | ||
3286 | |||
3287 | case (int)ScriptBaseClass.LINK_ALL_OTHERS: | ||
3288 | |||
3289 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3290 | { | ||
3291 | |||
3292 | if (partInst.LocalId != m_host.LocalId) | ||
3293 | { | ||
3294 | |||
3295 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3296 | { | ||
3297 | if (item.Type == 10) | ||
3298 | { | ||
3299 | // partLocalID = partInst.LocalId; | ||
3300 | partItemID = item.ItemID; | ||
3301 | Object[] resobj = new object[] | ||
3302 | { | ||
3303 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3304 | }; | ||
3305 | |||
3306 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3307 | new EventParams("link_message", | ||
3308 | resobj, new DetectParams[0])); | ||
3309 | } | ||
3310 | } | ||
3311 | |||
3312 | } | ||
3313 | } | ||
3314 | |||
3315 | break; | ||
3316 | |||
3317 | case (int)ScriptBaseClass.LINK_ALL_CHILDREN: | ||
3318 | |||
3319 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3320 | { | ||
3321 | |||
3322 | if (partInst.LocalId != m_host.ParentGroup.RootPart.LocalId) | ||
3323 | { | ||
3324 | |||
3325 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3326 | { | ||
3327 | if (item.Type == 10) | ||
3328 | { | ||
3329 | // partLocalID = partInst.LocalId; | ||
3330 | partItemID = item.ItemID; | ||
3331 | Object[] resobj = new object[] | ||
3332 | { | ||
3333 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3334 | }; | ||
3335 | |||
3336 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3337 | new EventParams("link_message", | ||
3338 | resobj, new DetectParams[0])); | ||
3339 | } | ||
3340 | } | ||
3341 | |||
3342 | } | ||
3343 | } | ||
3344 | |||
3345 | break; | ||
3346 | |||
3347 | case (int)ScriptBaseClass.LINK_THIS: | ||
3348 | |||
3349 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3350 | { | ||
3351 | if (item.Type == 10) | ||
3352 | { | ||
3353 | partItemID = item.ItemID; | ||
3354 | |||
3355 | object[] resobj = new object[] | ||
3356 | { | ||
3357 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3358 | }; | ||
3359 | |||
3360 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3361 | new EventParams("link_message", | ||
3362 | resobj, new DetectParams[0])); | ||
3363 | } | ||
3364 | } | ||
3365 | |||
3366 | break; | ||
3367 | |||
3368 | default: | ||
3369 | |||
3370 | foreach (SceneObjectPart partInst in m_host.ParentGroup.GetParts()) | ||
3371 | { | ||
3372 | |||
3373 | if ((partInst.LinkNum) == linknum) | ||
3374 | { | ||
3375 | |||
3376 | foreach (TaskInventoryItem item in partInst.TaskInventory.Values) | ||
3377 | { | ||
3378 | if (item.Type == 10) | ||
3379 | { | ||
3380 | // partLocalID = partInst.LocalId; | ||
3381 | partItemID = item.ItemID; | ||
3382 | Object[] resObjDef = new object[] | ||
3383 | { | ||
3384 | new LSL_Integer(m_host.LinkNum), new LSL_Integer(num), new LSL_String(msg), new LSL_String(id) | ||
3385 | }; | ||
3386 | |||
3387 | m_ScriptEngine.PostScriptEvent(partItemID, | ||
3388 | new EventParams("link_message", | ||
3389 | resObjDef, new DetectParams[0])); | ||
3390 | } | ||
3391 | } | ||
3392 | |||
3393 | } | ||
3394 | } | ||
3395 | |||
3396 | break; | ||
3397 | |||
3398 | } | ||
3399 | |||
3400 | } | ||
3401 | |||
3402 | public void llPushObject(string target, LSL_Vector impulse, LSL_Vector ang_impulse, int local) | ||
3403 | { | ||
3404 | m_host.AddScriptLPS(1); | ||
3405 | SceneObjectPart targ = World.GetSceneObjectPart(target); | ||
3406 | if (targ == null) | ||
3407 | return; | ||
3408 | targ.ApplyImpulse(new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z), local != 0); | ||
3409 | } | ||
3410 | |||
3411 | public void llPassCollisions(int pass) | ||
3412 | { | ||
3413 | m_host.AddScriptLPS(1); | ||
3414 | NotImplemented("llPassCollisions"); | ||
3415 | } | ||
3416 | |||
3417 | public LSL_String llGetScriptName() | ||
3418 | { | ||
3419 | |||
3420 | string result = String.Empty; | ||
3421 | |||
3422 | m_host.AddScriptLPS(1); | ||
3423 | |||
3424 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
3425 | { | ||
3426 | if (item.Type == 10 && item.ItemID == m_itemID) | ||
3427 | { | ||
3428 | result = item.Name!=null?item.Name:String.Empty; | ||
3429 | break; | ||
3430 | } | ||
3431 | } | ||
3432 | |||
3433 | return result; | ||
3434 | |||
3435 | } | ||
3436 | |||
3437 | // this function to understand which shape it is (taken from meshmerizer) | ||
3438 | // quite useful can be used by meshmerizer to have a centralized point of understanding the shape | ||
3439 | // except that it refers to scripting constants | ||
3440 | private int getScriptPrimType(PrimitiveBaseShape primShape) | ||
3441 | { | ||
3442 | if (primShape.SculptEntry) | ||
3443 | return ScriptBaseClass.PRIM_TYPE_SCULPT; | ||
3444 | if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) | ||
3445 | { | ||
3446 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
3447 | return ScriptBaseClass.PRIM_TYPE_BOX; | ||
3448 | else if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
3449 | return ScriptBaseClass.PRIM_TYPE_TUBE; | ||
3450 | } | ||
3451 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) | ||
3452 | { | ||
3453 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
3454 | return ScriptBaseClass.PRIM_TYPE_CYLINDER; | ||
3455 | // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits | ||
3456 | else if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
3457 | return ScriptBaseClass.PRIM_TYPE_TORUS; | ||
3458 | } | ||
3459 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) | ||
3460 | { | ||
3461 | if (primShape.PathCurve == (byte)Extrusion.Curve1 || primShape.PathCurve == (byte)Extrusion.Curve2) | ||
3462 | return ScriptBaseClass.PRIM_TYPE_SPHERE; | ||
3463 | } | ||
3464 | else if ((primShape.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) | ||
3465 | { | ||
3466 | if (primShape.PathCurve == (byte)Extrusion.Straight) | ||
3467 | return ScriptBaseClass.PRIM_TYPE_PRISM; | ||
3468 | else if (primShape.PathCurve == (byte)Extrusion.Curve1) | ||
3469 | return ScriptBaseClass.PRIM_TYPE_RING; | ||
3470 | } | ||
3471 | return ScriptBaseClass.PRIM_TYPE_BOX; | ||
3472 | } | ||
3473 | |||
3474 | // Helper functions to understand if object has cut, hollow, dimple, and other affecting number of faces | ||
3475 | private void hasCutHollowDimpleProfileCut(int primType, PrimitiveBaseShape shape, out bool hasCut, out bool hasHollow, | ||
3476 | out bool hasDimple, out bool hasProfileCut) | ||
3477 | { | ||
3478 | if (primType == ScriptBaseClass.PRIM_TYPE_BOX | ||
3479 | || | ||
3480 | primType == ScriptBaseClass.PRIM_TYPE_CYLINDER | ||
3481 | || | ||
3482 | primType == ScriptBaseClass.PRIM_TYPE_PRISM) | ||
3483 | |||
3484 | hasCut = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); | ||
3485 | else | ||
3486 | hasCut = (shape.PathBegin > 0) || (shape.PathEnd > 0); | ||
3487 | |||
3488 | hasHollow = shape.ProfileHollow > 0; | ||
3489 | hasDimple = (shape.ProfileBegin > 0) || (shape.ProfileEnd > 0); // taken from llSetPrimitiveParms | ||
3490 | hasProfileCut = hasDimple; // is it the same thing? | ||
3491 | |||
3492 | } | ||
3493 | |||
3494 | public LSL_Integer llGetNumberOfSides() | ||
3495 | { | ||
3496 | m_host.AddScriptLPS(1); | ||
3497 | |||
3498 | return GetNumberOfSides(m_host); | ||
3499 | } | ||
3500 | |||
3501 | private int GetNumberOfSides(SceneObjectPart part) | ||
3502 | { | ||
3503 | int ret = 0; | ||
3504 | bool hasCut; | ||
3505 | bool hasHollow; | ||
3506 | bool hasDimple; | ||
3507 | bool hasProfileCut; | ||
3508 | |||
3509 | int primType = getScriptPrimType(part.Shape); | ||
3510 | hasCutHollowDimpleProfileCut(primType, part.Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut); | ||
3511 | |||
3512 | switch (primType) | ||
3513 | { | ||
3514 | case ScriptBaseClass.PRIM_TYPE_BOX: | ||
3515 | ret = 6; | ||
3516 | if (hasCut) ret += 2; | ||
3517 | if (hasHollow) ret += 1; | ||
3518 | break; | ||
3519 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
3520 | ret = 3; | ||
3521 | if (hasCut) ret += 2; | ||
3522 | if (hasHollow) ret += 1; | ||
3523 | break; | ||
3524 | case ScriptBaseClass.PRIM_TYPE_PRISM: | ||
3525 | ret = 5; | ||
3526 | if (hasCut) ret += 2; | ||
3527 | if (hasHollow) ret += 1; | ||
3528 | break; | ||
3529 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
3530 | ret = 1; | ||
3531 | if (hasCut) ret += 2; | ||
3532 | if (hasDimple) ret += 2; | ||
3533 | if (hasHollow) ret += 3; // Emulate lsl on secondlife (according to documentation it should have added only +1) | ||
3534 | break; | ||
3535 | case ScriptBaseClass.PRIM_TYPE_TORUS: | ||
3536 | ret = 1; | ||
3537 | if (hasCut) ret += 2; | ||
3538 | if (hasProfileCut) ret += 2; | ||
3539 | if (hasHollow) ret += 1; | ||
3540 | break; | ||
3541 | case ScriptBaseClass.PRIM_TYPE_TUBE: | ||
3542 | ret = 4; | ||
3543 | if (hasCut) ret += 2; | ||
3544 | if (hasProfileCut) ret += 2; | ||
3545 | if (hasHollow) ret += 1; | ||
3546 | break; | ||
3547 | case ScriptBaseClass.PRIM_TYPE_RING: | ||
3548 | ret = 3; | ||
3549 | if (hasCut) ret += 2; | ||
3550 | if (hasProfileCut) ret += 2; | ||
3551 | if (hasHollow) ret += 1; | ||
3552 | break; | ||
3553 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
3554 | ret = 1; | ||
3555 | break; | ||
3556 | } | ||
3557 | return ret; | ||
3558 | } | ||
3559 | |||
3560 | |||
3561 | /* The new / changed functions were tested with the following LSL script: | ||
3562 | |||
3563 | default | ||
3564 | { | ||
3565 | state_entry() | ||
3566 | { | ||
3567 | rotation rot = llEuler2Rot(<0,70,0> * DEG_TO_RAD); | ||
3568 | |||
3569 | llOwnerSay("to get here, we rotate over: "+ (string) llRot2Axis(rot)); | ||
3570 | llOwnerSay("and we rotate for: "+ (llRot2Angle(rot) * RAD_TO_DEG)); | ||
3571 | |||
3572 | // convert back and forth between quaternion <-> vector and angle | ||
3573 | |||
3574 | rotation newrot = llAxisAngle2Rot(llRot2Axis(rot),llRot2Angle(rot)); | ||
3575 | |||
3576 | llOwnerSay("Old rotation was: "+(string) rot); | ||
3577 | llOwnerSay("re-converted rotation is: "+(string) newrot); | ||
3578 | |||
3579 | llSetRot(rot); // to check the parameters in the prim | ||
3580 | } | ||
3581 | } | ||
3582 | */ | ||
3583 | |||
3584 | |||
3585 | |||
3586 | // Xantor 29/apr/2008 | ||
3587 | // Returns rotation described by rotating angle radians about axis. | ||
3588 | // q = cos(a/2) + i (x * sin(a/2)) + j (y * sin(a/2)) + k (z * sin(a/2)) | ||
3589 | public LSL_Rotation llAxisAngle2Rot(LSL_Vector axis, double angle) | ||
3590 | { | ||
3591 | m_host.AddScriptLPS(1); | ||
3592 | |||
3593 | double x, y, z, s, t; | ||
3594 | |||
3595 | s = Math.Cos(angle / 2); | ||
3596 | t = Math.Sin(angle / 2); // temp value to avoid 2 more sin() calcs | ||
3597 | x = axis.x * t; | ||
3598 | y = axis.y * t; | ||
3599 | z = axis.z * t; | ||
3600 | |||
3601 | return new LSL_Rotation(x,y,z,s); | ||
3602 | } | ||
3603 | |||
3604 | |||
3605 | // Xantor 29/apr/2008 | ||
3606 | // converts a Quaternion to X,Y,Z axis rotations | ||
3607 | public LSL_Vector llRot2Axis(LSL_Rotation rot) | ||
3608 | { | ||
3609 | m_host.AddScriptLPS(1); | ||
3610 | double x,y,z; | ||
3611 | |||
3612 | if (rot.s > 1) // normalization needed | ||
3613 | { | ||
3614 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
3615 | rot.z * rot.z + rot.s * rot.s); | ||
3616 | |||
3617 | rot.x /= length; | ||
3618 | rot.y /= length; | ||
3619 | rot.z /= length; | ||
3620 | rot.s /= length; | ||
3621 | |||
3622 | } | ||
3623 | |||
3624 | // double angle = 2 * Math.Acos(rot.s); | ||
3625 | double s = Math.Sqrt(1 - rot.s * rot.s); | ||
3626 | if (s < 0.001) | ||
3627 | { | ||
3628 | x = 1; | ||
3629 | y = z = 0; | ||
3630 | } | ||
3631 | else | ||
3632 | { | ||
3633 | x = rot.x / s; // normalise axis | ||
3634 | y = rot.y / s; | ||
3635 | z = rot.z / s; | ||
3636 | } | ||
3637 | |||
3638 | return new LSL_Vector(x,y,z); | ||
3639 | } | ||
3640 | |||
3641 | |||
3642 | // Returns the angle of a quaternion (see llRot2Axis for the axis) | ||
3643 | public LSL_Float llRot2Angle(LSL_Rotation rot) | ||
3644 | { | ||
3645 | m_host.AddScriptLPS(1); | ||
3646 | |||
3647 | if (rot.s > 1) // normalization needed | ||
3648 | { | ||
3649 | double length = Math.Sqrt(rot.x * rot.x + rot.y * rot.y + | ||
3650 | rot.z * rot.z + rot.s * rot.s); | ||
3651 | |||
3652 | rot.x /= length; | ||
3653 | rot.y /= length; | ||
3654 | rot.z /= length; | ||
3655 | rot.s /= length; | ||
3656 | } | ||
3657 | |||
3658 | double angle = 2 * Math.Acos(rot.s); | ||
3659 | |||
3660 | return angle; | ||
3661 | } | ||
3662 | |||
3663 | public LSL_Float llAcos(double val) | ||
3664 | { | ||
3665 | m_host.AddScriptLPS(1); | ||
3666 | return (double)Math.Acos(val); | ||
3667 | } | ||
3668 | |||
3669 | public LSL_Float llAsin(double val) | ||
3670 | { | ||
3671 | m_host.AddScriptLPS(1); | ||
3672 | return (double)Math.Asin(val); | ||
3673 | } | ||
3674 | |||
3675 | // Xantor 30/apr/2008 | ||
3676 | public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) | ||
3677 | { | ||
3678 | m_host.AddScriptLPS(1); | ||
3679 | |||
3680 | return (double) Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2; | ||
3681 | } | ||
3682 | |||
3683 | public LSL_String llGetInventoryKey(string name) | ||
3684 | { | ||
3685 | m_host.AddScriptLPS(1); | ||
3686 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
3687 | { | ||
3688 | if (inv.Value.Name == name) | ||
3689 | { | ||
3690 | if ((inv.Value.CurrentPermissions & (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) == (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify)) | ||
3691 | { | ||
3692 | return inv.Value.AssetID.ToString(); | ||
3693 | } | ||
3694 | else | ||
3695 | { | ||
3696 | return UUID.Zero.ToString(); | ||
3697 | } | ||
3698 | } | ||
3699 | } | ||
3700 | return UUID.Zero.ToString(); | ||
3701 | } | ||
3702 | |||
3703 | public void llAllowInventoryDrop(int add) | ||
3704 | { | ||
3705 | m_host.AddScriptLPS(1); | ||
3706 | |||
3707 | if (add != 0) | ||
3708 | m_host.ParentGroup.RootPart.AllowedDrop = true; | ||
3709 | else | ||
3710 | m_host.ParentGroup.RootPart.AllowedDrop = false; | ||
3711 | } | ||
3712 | |||
3713 | public LSL_Vector llGetSunDirection() | ||
3714 | { | ||
3715 | m_host.AddScriptLPS(1); | ||
3716 | |||
3717 | LSL_Vector SunDoubleVector3; | ||
3718 | Vector3 SunFloatVector3; | ||
3719 | |||
3720 | // sunPosition estate setting is set in OpenSim.Region.Environment.Modules.SunModule | ||
3721 | // have to convert from Vector3 (float) to LSL_Vector (double) | ||
3722 | SunFloatVector3 = World.RegionInfo.RegionSettings.SunVector; | ||
3723 | SunDoubleVector3.x = (double)SunFloatVector3.X; | ||
3724 | SunDoubleVector3.y = (double)SunFloatVector3.Y; | ||
3725 | SunDoubleVector3.z = (double)SunFloatVector3.Z; | ||
3726 | |||
3727 | return SunDoubleVector3; | ||
3728 | } | ||
3729 | |||
3730 | public LSL_Vector llGetTextureOffset(int face) | ||
3731 | { | ||
3732 | m_host.AddScriptLPS(1); | ||
3733 | return GetTextureOffset(m_host, face); | ||
3734 | } | ||
3735 | |||
3736 | private LSL_Vector GetTextureOffset(SceneObjectPart part, int face) | ||
3737 | { | ||
3738 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
3739 | LSL_Vector offset = new LSL_Vector(); | ||
3740 | if (face == ScriptBaseClass.ALL_SIDES) | ||
3741 | { | ||
3742 | face = 0; | ||
3743 | } | ||
3744 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
3745 | { | ||
3746 | offset.x = tex.GetFace((uint)face).OffsetU; | ||
3747 | offset.y = tex.GetFace((uint)face).OffsetV; | ||
3748 | offset.z = 0.0; | ||
3749 | return offset; | ||
3750 | } | ||
3751 | else | ||
3752 | { | ||
3753 | return offset; | ||
3754 | } | ||
3755 | } | ||
3756 | |||
3757 | public LSL_Vector llGetTextureScale(int side) | ||
3758 | { | ||
3759 | m_host.AddScriptLPS(1); | ||
3760 | Primitive.TextureEntry tex = m_host.Shape.Textures; | ||
3761 | LSL_Vector scale; | ||
3762 | if (side == -1) | ||
3763 | { | ||
3764 | side = 0; | ||
3765 | } | ||
3766 | scale.x = tex.GetFace((uint)side).RepeatU; | ||
3767 | scale.y = tex.GetFace((uint)side).RepeatV; | ||
3768 | scale.z = 0.0; | ||
3769 | return scale; | ||
3770 | } | ||
3771 | |||
3772 | public LSL_Float llGetTextureRot(int face) | ||
3773 | { | ||
3774 | m_host.AddScriptLPS(1); | ||
3775 | return GetTextureRot(m_host, face); | ||
3776 | } | ||
3777 | |||
3778 | private LSL_Float GetTextureRot(SceneObjectPart part, int face) | ||
3779 | { | ||
3780 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
3781 | if (face == -1) | ||
3782 | { | ||
3783 | face = 0; | ||
3784 | } | ||
3785 | if (face >= 0 && face < GetNumberOfSides(part)) | ||
3786 | { | ||
3787 | return tex.GetFace((uint)face).Rotation; | ||
3788 | } | ||
3789 | else | ||
3790 | { | ||
3791 | return 0.0; | ||
3792 | } | ||
3793 | } | ||
3794 | |||
3795 | public LSL_Integer llSubStringIndex(string source, string pattern) | ||
3796 | { | ||
3797 | m_host.AddScriptLPS(1); | ||
3798 | return source.IndexOf(pattern); | ||
3799 | } | ||
3800 | |||
3801 | public LSL_String llGetOwnerKey(string id) | ||
3802 | { | ||
3803 | m_host.AddScriptLPS(1); | ||
3804 | UUID key = new UUID(); | ||
3805 | if (UUID.TryParse(id, out key)) | ||
3806 | { | ||
3807 | try | ||
3808 | { | ||
3809 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); | ||
3810 | if (obj == null) | ||
3811 | return id; // the key is for an agent so just return the key | ||
3812 | else | ||
3813 | return obj.OwnerID.ToString(); | ||
3814 | } | ||
3815 | catch (KeyNotFoundException) | ||
3816 | { | ||
3817 | return id; // The Object/Agent not in the region so just return the key | ||
3818 | } | ||
3819 | } | ||
3820 | else | ||
3821 | { | ||
3822 | return UUID.Zero.ToString(); | ||
3823 | } | ||
3824 | } | ||
3825 | |||
3826 | public LSL_Vector llGetCenterOfMass() | ||
3827 | { | ||
3828 | m_host.AddScriptLPS(1); | ||
3829 | NotImplemented("llGetCenterOfMass"); | ||
3830 | return new LSL_Vector(); | ||
3831 | } | ||
3832 | |||
3833 | public LSL_List llListSort(LSL_List src, int stride, int ascending) | ||
3834 | { | ||
3835 | m_host.AddScriptLPS(1); | ||
3836 | |||
3837 | if (stride <= 0) | ||
3838 | { | ||
3839 | stride = 1; | ||
3840 | } | ||
3841 | return src.Sort(stride, ascending); | ||
3842 | } | ||
3843 | |||
3844 | public LSL_Integer llGetListLength(LSL_List src) | ||
3845 | { | ||
3846 | m_host.AddScriptLPS(1); | ||
3847 | |||
3848 | if (src == null) | ||
3849 | { | ||
3850 | return 0; | ||
3851 | } | ||
3852 | else | ||
3853 | { | ||
3854 | return src.Length; | ||
3855 | } | ||
3856 | } | ||
3857 | |||
3858 | public LSL_Integer llList2Integer(LSL_List src, int index) | ||
3859 | { | ||
3860 | m_host.AddScriptLPS(1); | ||
3861 | if (index < 0) | ||
3862 | { | ||
3863 | index = src.Length + index; | ||
3864 | } | ||
3865 | if (index >= src.Length) | ||
3866 | { | ||
3867 | return 0; | ||
3868 | } | ||
3869 | try | ||
3870 | { | ||
3871 | if (src.Data[index] is LSL_Integer) | ||
3872 | return Convert.ToInt32(((LSL_Integer) src.Data[index]).value); | ||
3873 | else if (src.Data[index] is LSL_Float) | ||
3874 | return Convert.ToInt32(((LSL_Float) src.Data[index]).value); | ||
3875 | else if (src.Data[index] is LSL_String) | ||
3876 | return Convert.ToInt32(((LSL_String) src.Data[index]).m_string); | ||
3877 | return Convert.ToInt32(src.Data[index]); | ||
3878 | } | ||
3879 | catch (FormatException) | ||
3880 | { | ||
3881 | return 0; | ||
3882 | } | ||
3883 | } | ||
3884 | |||
3885 | public LSL_Float llList2Float(LSL_List src, int index) | ||
3886 | { | ||
3887 | m_host.AddScriptLPS(1); | ||
3888 | if (index < 0) | ||
3889 | { | ||
3890 | index = src.Length + index; | ||
3891 | } | ||
3892 | if (index >= src.Length) | ||
3893 | { | ||
3894 | return 0.0; | ||
3895 | } | ||
3896 | try | ||
3897 | { | ||
3898 | if (src.Data[index] is LSL_Integer) | ||
3899 | return Convert.ToDouble(((LSL_Integer) src.Data[index]).value); | ||
3900 | else if (src.Data[index] is LSL_Float) | ||
3901 | return Convert.ToDouble(((LSL_Float) src.Data[index]).value); | ||
3902 | else if (src.Data[index] is LSL_String) | ||
3903 | return Convert.ToDouble(((LSL_String) src.Data[index]).m_string); | ||
3904 | return Convert.ToDouble(src.Data[index]); | ||
3905 | } | ||
3906 | catch (FormatException) | ||
3907 | { | ||
3908 | return 0.0; | ||
3909 | } | ||
3910 | } | ||
3911 | |||
3912 | public LSL_String llList2String(LSL_List src, int index) | ||
3913 | { | ||
3914 | m_host.AddScriptLPS(1); | ||
3915 | if (index < 0) | ||
3916 | { | ||
3917 | index = src.Length + index; | ||
3918 | } | ||
3919 | if (index >= src.Length) | ||
3920 | { | ||
3921 | return String.Empty; | ||
3922 | } | ||
3923 | return src.Data[index].ToString(); | ||
3924 | } | ||
3925 | |||
3926 | public LSL_String llList2Key(LSL_List src, int index) | ||
3927 | { | ||
3928 | m_host.AddScriptLPS(1); | ||
3929 | if (index < 0) | ||
3930 | { | ||
3931 | index = src.Length + index; | ||
3932 | } | ||
3933 | if (index >= src.Length) | ||
3934 | { | ||
3935 | return ""; | ||
3936 | } | ||
3937 | return src.Data[index].ToString(); | ||
3938 | } | ||
3939 | |||
3940 | public LSL_Vector llList2Vector(LSL_List src, int index) | ||
3941 | { | ||
3942 | m_host.AddScriptLPS(1); | ||
3943 | if (index < 0) | ||
3944 | { | ||
3945 | index = src.Length + index; | ||
3946 | } | ||
3947 | if (index >= src.Length) | ||
3948 | { | ||
3949 | return new LSL_Vector(0, 0, 0); | ||
3950 | } | ||
3951 | if (src.Data[index].GetType() == typeof(LSL_Vector)) | ||
3952 | { | ||
3953 | return (LSL_Vector)src.Data[index]; | ||
3954 | } | ||
3955 | else | ||
3956 | { | ||
3957 | return new LSL_Vector(src.Data[index].ToString()); | ||
3958 | } | ||
3959 | } | ||
3960 | |||
3961 | public LSL_Rotation llList2Rot(LSL_List src, int index) | ||
3962 | { | ||
3963 | m_host.AddScriptLPS(1); | ||
3964 | if (index < 0) | ||
3965 | { | ||
3966 | index = src.Length + index; | ||
3967 | } | ||
3968 | if (index >= src.Length) | ||
3969 | { | ||
3970 | return new LSL_Rotation(0, 0, 0, 1); | ||
3971 | } | ||
3972 | if (src.Data[index].GetType() == typeof(LSL_Rotation)) | ||
3973 | { | ||
3974 | return (LSL_Rotation)src.Data[index]; | ||
3975 | } | ||
3976 | else | ||
3977 | { | ||
3978 | return new LSL_Rotation(src.Data[index].ToString()); | ||
3979 | } | ||
3980 | } | ||
3981 | |||
3982 | public LSL_List llList2List(LSL_List src, int start, int end) | ||
3983 | { | ||
3984 | m_host.AddScriptLPS(1); | ||
3985 | return src.GetSublist(start, end); | ||
3986 | } | ||
3987 | |||
3988 | public LSL_List llDeleteSubList(LSL_List src, int start, int end) | ||
3989 | { | ||
3990 | return src.DeleteSublist(end, start); | ||
3991 | } | ||
3992 | |||
3993 | public LSL_Integer llGetListEntryType(LSL_List src, int index) | ||
3994 | { | ||
3995 | m_host.AddScriptLPS(1); | ||
3996 | if (index < 0) | ||
3997 | { | ||
3998 | index = src.Length + index; | ||
3999 | } | ||
4000 | if (index >= src.Length) | ||
4001 | { | ||
4002 | return 0; | ||
4003 | } | ||
4004 | |||
4005 | if (src.Data[index] is LSL_Integer || src.Data[index] is Int32) | ||
4006 | return 1; | ||
4007 | if (src.Data[index] is LSL_Float || src.Data[index] is Single || src.Data[index] is Double) | ||
4008 | return 2; | ||
4009 | if (src.Data[index] is LSL_String || src.Data[index] is String) | ||
4010 | { | ||
4011 | UUID tuuid; | ||
4012 | if (UUID.TryParse(src.Data[index].ToString(), out tuuid)) | ||
4013 | { | ||
4014 | return 4; | ||
4015 | } | ||
4016 | else | ||
4017 | { | ||
4018 | return 3; | ||
4019 | } | ||
4020 | } | ||
4021 | if (src.Data[index] is LSL_Vector) | ||
4022 | return 5; | ||
4023 | if (src.Data[index] is LSL_Rotation) | ||
4024 | return 6; | ||
4025 | if (src.Data[index] is LSL_List) | ||
4026 | return 7; | ||
4027 | return 0; | ||
4028 | |||
4029 | } | ||
4030 | |||
4031 | /// <summary> | ||
4032 | /// Process the supplied list and return the | ||
4033 | /// content of the list formatted as a comma | ||
4034 | /// separated list. There is a space after | ||
4035 | /// each comma. | ||
4036 | /// </summary> | ||
4037 | |||
4038 | public LSL_String llList2CSV(LSL_List src) | ||
4039 | { | ||
4040 | |||
4041 | string ret = String.Empty; | ||
4042 | int x = 0; | ||
4043 | |||
4044 | m_host.AddScriptLPS(1); | ||
4045 | |||
4046 | if (src.Data.Length > 0) | ||
4047 | { | ||
4048 | ret = src.Data[x++].ToString(); | ||
4049 | for (; x < src.Data.Length; x++) | ||
4050 | { | ||
4051 | ret += ", "+src.Data[x].ToString(); | ||
4052 | } | ||
4053 | } | ||
4054 | |||
4055 | return ret; | ||
4056 | } | ||
4057 | |||
4058 | /// <summary> | ||
4059 | /// The supplied string is scanned for commas | ||
4060 | /// and converted into a list. Commas are only | ||
4061 | /// effective if they are encountered outside | ||
4062 | /// of '<' '>' delimiters. Any whitespace | ||
4063 | /// before or after an element is trimmed. | ||
4064 | /// </summary> | ||
4065 | |||
4066 | public LSL_List llCSV2List(string src) | ||
4067 | { | ||
4068 | |||
4069 | LSL_List result = new LSL_List(); | ||
4070 | int parens = 0; | ||
4071 | int start = 0; | ||
4072 | int length = 0; | ||
4073 | |||
4074 | m_host.AddScriptLPS(1); | ||
4075 | |||
4076 | for (int i = 0; i < src.Length; i++) | ||
4077 | { | ||
4078 | switch (src[i]) | ||
4079 | { | ||
4080 | case '<': | ||
4081 | parens++; | ||
4082 | length++; | ||
4083 | break; | ||
4084 | case '>': | ||
4085 | if (parens > 0) | ||
4086 | parens--; | ||
4087 | length++; | ||
4088 | break; | ||
4089 | case ',': | ||
4090 | if (parens == 0) | ||
4091 | { | ||
4092 | result.Add(src.Substring(start,length).Trim()); | ||
4093 | start += length+1; | ||
4094 | length = 0; | ||
4095 | } | ||
4096 | else | ||
4097 | { | ||
4098 | length++; | ||
4099 | } | ||
4100 | break; | ||
4101 | default: | ||
4102 | length++; | ||
4103 | break; | ||
4104 | } | ||
4105 | } | ||
4106 | |||
4107 | result.Add(src.Substring(start,length).Trim()); | ||
4108 | |||
4109 | return result; | ||
4110 | } | ||
4111 | |||
4112 | /// <summary> | ||
4113 | /// Randomizes the list, be arbitrarily reordering | ||
4114 | /// sublists of stride elements. As the stride approaches | ||
4115 | /// the size of the list, the options become very | ||
4116 | /// limited. | ||
4117 | /// </summary> | ||
4118 | /// <remarks> | ||
4119 | /// This could take a while for very large list | ||
4120 | /// sizes. | ||
4121 | /// </remarks> | ||
4122 | |||
4123 | public LSL_List llListRandomize(LSL_List src, int stride) | ||
4124 | { | ||
4125 | LSL_List result; | ||
4126 | Random rand = new Random(); | ||
4127 | |||
4128 | int chunkk; | ||
4129 | int[] chunks; | ||
4130 | |||
4131 | m_host.AddScriptLPS(1); | ||
4132 | |||
4133 | if (stride <= 0) | ||
4134 | { | ||
4135 | stride = 1; | ||
4136 | } | ||
4137 | |||
4138 | // Stride MUST be a factor of the list length | ||
4139 | // If not, then return the src list. This also | ||
4140 | // traps those cases where stride > length. | ||
4141 | |||
4142 | if (src.Length != stride && src.Length%stride == 0) | ||
4143 | { | ||
4144 | chunkk = src.Length/stride; | ||
4145 | |||
4146 | chunks = new int[chunkk]; | ||
4147 | |||
4148 | for (int i = 0; i < chunkk; i++) | ||
4149 | chunks[i] = i; | ||
4150 | |||
4151 | // Knuth shuffle the chunkk index | ||
4152 | for (int i = chunkk - 1; i >= 1; i--) | ||
4153 | { | ||
4154 | // Elect an unrandomized chunk to swap | ||
4155 | int index = rand.Next(i + 1); | ||
4156 | int tmp; | ||
4157 | |||
4158 | // and swap position with first unrandomized chunk | ||
4159 | tmp = chunks[i]; | ||
4160 | chunks[i] = chunks[index]; | ||
4161 | chunks[index] = tmp; | ||
4162 | } | ||
4163 | |||
4164 | // Construct the randomized list | ||
4165 | |||
4166 | result = new LSL_List(); | ||
4167 | |||
4168 | for (int i = 0; i < chunkk; i++) | ||
4169 | { | ||
4170 | for (int j = 0; j < stride; j++) | ||
4171 | { | ||
4172 | result.Add(src.Data[chunks[i]*stride+j]); | ||
4173 | } | ||
4174 | } | ||
4175 | } | ||
4176 | else { | ||
4177 | object[] array = new object[src.Length]; | ||
4178 | Array.Copy(src.Data, 0, array, 0, src.Length); | ||
4179 | result = new LSL_List(array); | ||
4180 | } | ||
4181 | |||
4182 | return result; | ||
4183 | } | ||
4184 | |||
4185 | /// <summary> | ||
4186 | /// Elements in the source list starting with 0 and then | ||
4187 | /// every i+stride. If the stride is negative then the scan | ||
4188 | /// is backwards producing an inverted result. | ||
4189 | /// Only those elements that are also in the specified | ||
4190 | /// range are included in the result. | ||
4191 | /// </summary> | ||
4192 | |||
4193 | public LSL_List llList2ListStrided(LSL_List src, int start, int end, int stride) | ||
4194 | { | ||
4195 | |||
4196 | LSL_List result = new LSL_List(); | ||
4197 | int[] si = new int[2]; | ||
4198 | int[] ei = new int[2]; | ||
4199 | bool twopass = false; | ||
4200 | |||
4201 | m_host.AddScriptLPS(1); | ||
4202 | |||
4203 | // First step is always to deal with negative indices | ||
4204 | |||
4205 | if (start < 0) | ||
4206 | start = src.Length+start; | ||
4207 | if (end < 0) | ||
4208 | end = src.Length+end; | ||
4209 | |||
4210 | // Out of bounds indices are OK, just trim them | ||
4211 | // accordingly | ||
4212 | |||
4213 | if (start > src.Length) | ||
4214 | start = src.Length; | ||
4215 | |||
4216 | if (end > src.Length) | ||
4217 | end = src.Length; | ||
4218 | |||
4219 | // There may be one or two ranges to be considered | ||
4220 | |||
4221 | if (start != end) | ||
4222 | { | ||
4223 | |||
4224 | if (start <= end) | ||
4225 | { | ||
4226 | si[0] = start; | ||
4227 | ei[0] = end; | ||
4228 | } | ||
4229 | else | ||
4230 | { | ||
4231 | si[1] = start; | ||
4232 | ei[1] = src.Length; | ||
4233 | si[0] = 0; | ||
4234 | ei[0] = end; | ||
4235 | twopass = true; | ||
4236 | } | ||
4237 | |||
4238 | // The scan always starts from the beginning of the | ||
4239 | // source list, but members are only selected if they | ||
4240 | // fall within the specified sub-range. The specified | ||
4241 | // range values are inclusive. | ||
4242 | // A negative stride reverses the direction of the | ||
4243 | // scan producing an inverted list as a result. | ||
4244 | |||
4245 | if (stride == 0) | ||
4246 | stride = 1; | ||
4247 | |||
4248 | if (stride > 0) | ||
4249 | { | ||
4250 | for (int i = 0; i < src.Length; i += stride) | ||
4251 | { | ||
4252 | if (i<=ei[0] && i>=si[0]) | ||
4253 | result.Add(src.Data[i]); | ||
4254 | if (twopass && i>=si[1] && i<=ei[1]) | ||
4255 | result.Add(src.Data[i]); | ||
4256 | } | ||
4257 | } | ||
4258 | else if (stride < 0) | ||
4259 | { | ||
4260 | for (int i = src.Length - 1; i >= 0; i += stride) | ||
4261 | { | ||
4262 | if (i <= ei[0] && i >= si[0]) | ||
4263 | result.Add(src.Data[i]); | ||
4264 | if (twopass && i >= si[1] && i <= ei[1]) | ||
4265 | result.Add(src.Data[i]); | ||
4266 | } | ||
4267 | } | ||
4268 | } | ||
4269 | |||
4270 | return result; | ||
4271 | } | ||
4272 | |||
4273 | public LSL_Integer llGetRegionAgentCount() | ||
4274 | { | ||
4275 | m_host.AddScriptLPS(1); | ||
4276 | return new LSL_Integer(World.GetAvatars().Count); | ||
4277 | } | ||
4278 | |||
4279 | public LSL_Vector llGetRegionCorner() | ||
4280 | { | ||
4281 | m_host.AddScriptLPS(1); | ||
4282 | return new LSL_Vector(World.RegionInfo.RegionLocX * Constants.RegionSize, World.RegionInfo.RegionLocY * Constants.RegionSize, 0); | ||
4283 | } | ||
4284 | |||
4285 | /// <summary> | ||
4286 | /// Insert the list identified by <src> into the | ||
4287 | /// list designated by <dest> such that the first | ||
4288 | /// new element has the index specified by <index> | ||
4289 | /// </summary> | ||
4290 | |||
4291 | public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) | ||
4292 | { | ||
4293 | |||
4294 | LSL_List pref = null; | ||
4295 | LSL_List suff = null; | ||
4296 | |||
4297 | m_host.AddScriptLPS(1); | ||
4298 | |||
4299 | if (index < 0) | ||
4300 | { | ||
4301 | index = index+dest.Length; | ||
4302 | if (index < 0) | ||
4303 | { | ||
4304 | index = 0; | ||
4305 | } | ||
4306 | } | ||
4307 | |||
4308 | if (index != 0) | ||
4309 | { | ||
4310 | pref = dest.GetSublist(0,index-1); | ||
4311 | if (index < dest.Length) | ||
4312 | { | ||
4313 | suff = dest.GetSublist(index,-1); | ||
4314 | return pref + src + suff; | ||
4315 | } | ||
4316 | else | ||
4317 | { | ||
4318 | return pref + src; | ||
4319 | } | ||
4320 | } | ||
4321 | else | ||
4322 | { | ||
4323 | if (index < dest.Length) | ||
4324 | { | ||
4325 | suff = dest.GetSublist(index,-1); | ||
4326 | return src + suff; | ||
4327 | } | ||
4328 | else | ||
4329 | { | ||
4330 | return src; | ||
4331 | } | ||
4332 | } | ||
4333 | |||
4334 | } | ||
4335 | |||
4336 | /// <summary> | ||
4337 | /// Returns the index of the first occurrence of test | ||
4338 | /// in src. | ||
4339 | /// </summary> | ||
4340 | |||
4341 | public LSL_Integer llListFindList(LSL_List src, LSL_List test) | ||
4342 | { | ||
4343 | |||
4344 | int index = -1; | ||
4345 | int length = src.Length - test.Length + 1; | ||
4346 | |||
4347 | m_host.AddScriptLPS(1); | ||
4348 | |||
4349 | // If either list is empty, do not match | ||
4350 | |||
4351 | if (src.Length != 0 && test.Length != 0) | ||
4352 | { | ||
4353 | for (int i = 0; i < length; i++) | ||
4354 | { | ||
4355 | if (src.Data[i].Equals(test.Data[0])) | ||
4356 | { | ||
4357 | int j; | ||
4358 | for (j = 1; j < test.Length; j++) | ||
4359 | if (!src.Data[i+j].Equals(test.Data[j])) | ||
4360 | break; | ||
4361 | if (j == test.Length) | ||
4362 | { | ||
4363 | index = i; | ||
4364 | break; | ||
4365 | } | ||
4366 | } | ||
4367 | } | ||
4368 | } | ||
4369 | |||
4370 | return index; | ||
4371 | |||
4372 | } | ||
4373 | |||
4374 | public LSL_String llGetObjectName() | ||
4375 | { | ||
4376 | m_host.AddScriptLPS(1); | ||
4377 | return m_host.Name!=null?m_host.Name:String.Empty; | ||
4378 | } | ||
4379 | |||
4380 | public void llSetObjectName(string name) | ||
4381 | { | ||
4382 | m_host.AddScriptLPS(1); | ||
4383 | m_host.Name = name!=null?name:String.Empty; | ||
4384 | } | ||
4385 | |||
4386 | public LSL_String llGetDate() | ||
4387 | { | ||
4388 | m_host.AddScriptLPS(1); | ||
4389 | DateTime date = DateTime.Now.ToUniversalTime(); | ||
4390 | string result = date.ToString("yyyy-MM-dd"); | ||
4391 | return result; | ||
4392 | } | ||
4393 | |||
4394 | public LSL_Integer llEdgeOfWorld(LSL_Vector pos, LSL_Vector dir) | ||
4395 | { | ||
4396 | m_host.AddScriptLPS(1); | ||
4397 | NotImplemented("llEdgeOfWorld"); | ||
4398 | return 0; | ||
4399 | } | ||
4400 | |||
4401 | public LSL_Integer llGetAgentInfo(string id) | ||
4402 | { | ||
4403 | m_host.AddScriptLPS(1); | ||
4404 | NotImplemented("llGetAgentInfo"); | ||
4405 | return 0; | ||
4406 | } | ||
4407 | |||
4408 | public void llAdjustSoundVolume(double volume) | ||
4409 | { | ||
4410 | m_host.AddScriptLPS(1); | ||
4411 | m_host.AdjustSoundGain(volume); | ||
4412 | // ScriptSleep(100); | ||
4413 | } | ||
4414 | |||
4415 | public void llSetSoundQueueing(int queue) | ||
4416 | { | ||
4417 | m_host.AddScriptLPS(1); | ||
4418 | NotImplemented("llSetSoundQueueing"); | ||
4419 | } | ||
4420 | |||
4421 | public void llSetSoundRadius(double radius) | ||
4422 | { | ||
4423 | m_host.AddScriptLPS(1); | ||
4424 | m_host.SoundRadius = radius; | ||
4425 | } | ||
4426 | |||
4427 | public LSL_String llKey2Name(string id) | ||
4428 | { | ||
4429 | m_host.AddScriptLPS(1); | ||
4430 | UUID key = new UUID(); | ||
4431 | if (UUID.TryParse(id,out key)) | ||
4432 | { | ||
4433 | ScenePresence presence = World.GetScenePresence(key); | ||
4434 | |||
4435 | if (presence != null) | ||
4436 | { | ||
4437 | return presence.ControllingClient.Name; | ||
4438 | //return presence.Name; | ||
4439 | } | ||
4440 | |||
4441 | if (World.GetSceneObjectPart(key) != null) | ||
4442 | { | ||
4443 | return World.GetSceneObjectPart(key).Name; | ||
4444 | } | ||
4445 | } | ||
4446 | return String.Empty; | ||
4447 | } | ||
4448 | |||
4449 | |||
4450 | |||
4451 | public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) | ||
4452 | { | ||
4453 | m_host.AddScriptLPS(1); | ||
4454 | Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); | ||
4455 | pTexAnim.Flags = (Primitive.TextureAnimMode)mode; | ||
4456 | |||
4457 | //ALL_SIDES | ||
4458 | if (face == ScriptBaseClass.ALL_SIDES) | ||
4459 | face = 255; | ||
4460 | |||
4461 | pTexAnim.Face = (uint)face; | ||
4462 | pTexAnim.Length = (float)length; | ||
4463 | pTexAnim.Rate = (float)rate; | ||
4464 | pTexAnim.SizeX = (uint)sizex; | ||
4465 | pTexAnim.SizeY = (uint)sizey; | ||
4466 | pTexAnim.Start = (float)start; | ||
4467 | |||
4468 | m_host.AddTextureAnimation(pTexAnim); | ||
4469 | m_host.SendFullUpdateToAllClients(); | ||
4470 | m_host.ParentGroup.HasGroupChanged = true; | ||
4471 | } | ||
4472 | |||
4473 | public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, | ||
4474 | LSL_Vector bottom_south_west) | ||
4475 | { | ||
4476 | m_host.AddScriptLPS(1); | ||
4477 | NotImplemented("llTriggerSoundLimited"); | ||
4478 | } | ||
4479 | |||
4480 | public void llEjectFromLand(string pest) | ||
4481 | { | ||
4482 | m_host.AddScriptLPS(1); | ||
4483 | UUID agentId = new UUID(); | ||
4484 | if (UUID.TryParse(pest, out agentId)) | ||
4485 | { | ||
4486 | ScenePresence presence = World.GetScenePresence(agentId); | ||
4487 | if (presence != null) | ||
4488 | { | ||
4489 | // agent must be over the owners land | ||
4490 | if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y)) | ||
4491 | World.TeleportClientHome(agentId, presence.ControllingClient); | ||
4492 | } | ||
4493 | } | ||
4494 | // ScriptSleep(5000); | ||
4495 | } | ||
4496 | |||
4497 | public LSL_List llParseString2List(string str, LSL_List separators, LSL_List spacers) | ||
4498 | { | ||
4499 | m_host.AddScriptLPS(1); | ||
4500 | LSL_List ret = new LSL_List(); | ||
4501 | object[] delimiters = new object[separators.Length + spacers.Length]; | ||
4502 | separators.Data.CopyTo(delimiters, 0); | ||
4503 | spacers.Data.CopyTo(delimiters, separators.Length); | ||
4504 | bool dfound = false; | ||
4505 | do | ||
4506 | { | ||
4507 | dfound = false; | ||
4508 | int cindex = -1; | ||
4509 | string cdeli = ""; | ||
4510 | for (int i = 0; i < delimiters.Length; i++) | ||
4511 | { | ||
4512 | int index = str.IndexOf(delimiters[i].ToString()); | ||
4513 | bool found = index != -1; | ||
4514 | if (found && String.Empty != delimiters[i].ToString()) | ||
4515 | { | ||
4516 | if ((cindex > index) || (cindex == -1)) | ||
4517 | { | ||
4518 | cindex = index; | ||
4519 | cdeli = delimiters[i].ToString(); | ||
4520 | } | ||
4521 | dfound = dfound || found; | ||
4522 | } | ||
4523 | } | ||
4524 | if (cindex != -1) | ||
4525 | { | ||
4526 | if (cindex > 0) | ||
4527 | { | ||
4528 | ret.Add(str.Substring(0, cindex)); | ||
4529 | // Cannot use spacers.Contains() because spacers may be either type String or LSLString | ||
4530 | for (int j = 0; j < spacers.Length; j++) | ||
4531 | { | ||
4532 | if (spacers.Data[j].ToString() == cdeli) | ||
4533 | { | ||
4534 | ret.Add(cdeli); | ||
4535 | break; | ||
4536 | } | ||
4537 | } | ||
4538 | } | ||
4539 | if (cindex == 0 && spacers.Contains(cdeli)) | ||
4540 | { | ||
4541 | ret.Add(cdeli); | ||
4542 | } | ||
4543 | str = str.Substring(cindex + cdeli.Length); | ||
4544 | } | ||
4545 | } while (dfound); | ||
4546 | if (str != "") | ||
4547 | { | ||
4548 | ret.Add(str); | ||
4549 | } | ||
4550 | return ret; | ||
4551 | } | ||
4552 | |||
4553 | public LSL_Integer llOverMyLand(string id) | ||
4554 | { | ||
4555 | m_host.AddScriptLPS(1); | ||
4556 | UUID key = new UUID(); | ||
4557 | if (UUID.TryParse(id,out key)) | ||
4558 | { | ||
4559 | ScenePresence presence = World.GetScenePresence(key); | ||
4560 | if (presence != null) // object is an avatar | ||
4561 | { | ||
4562 | if (m_host.OwnerID == World.GetLandOwner(presence.AbsolutePosition.X, presence.AbsolutePosition.Y)) | ||
4563 | return 1; | ||
4564 | } | ||
4565 | else // object is not an avatar | ||
4566 | { | ||
4567 | SceneObjectPart obj = World.GetSceneObjectPart(key); | ||
4568 | if (obj != null) | ||
4569 | if (m_host.OwnerID == World.GetLandOwner(obj.AbsolutePosition.X, obj.AbsolutePosition.Y)) | ||
4570 | return 1; | ||
4571 | } | ||
4572 | } | ||
4573 | return 0; | ||
4574 | } | ||
4575 | |||
4576 | public LSL_String llGetLandOwnerAt(LSL_Vector pos) | ||
4577 | { | ||
4578 | m_host.AddScriptLPS(1); | ||
4579 | return World.GetLandOwner((float)pos.x, (float)pos.y).ToString(); | ||
4580 | } | ||
4581 | |||
4582 | public LSL_Vector llGetAgentSize(string id) | ||
4583 | { | ||
4584 | m_host.AddScriptLPS(1); | ||
4585 | ScenePresence avatar = World.GetScenePresence(id); | ||
4586 | LSL_Vector agentSize; | ||
4587 | if (avatar == null) | ||
4588 | { | ||
4589 | agentSize = ScriptBaseClass.ZERO_VECTOR; | ||
4590 | } | ||
4591 | else | ||
4592 | { | ||
4593 | PhysicsVector size = avatar.PhysicsActor.Size; | ||
4594 | agentSize = new LSL_Vector(size.X, size.Y, size.Z); | ||
4595 | } | ||
4596 | return agentSize; | ||
4597 | } | ||
4598 | |||
4599 | public LSL_Integer llSameGroup(string agent) | ||
4600 | { | ||
4601 | m_host.AddScriptLPS(1); | ||
4602 | UUID agentId = new UUID(); | ||
4603 | if (!UUID.TryParse(agent, out agentId)) | ||
4604 | return new LSL_Integer(0); | ||
4605 | ScenePresence presence = World.GetScenePresence(agentId); | ||
4606 | if (presence == null) | ||
4607 | return new LSL_Integer(0); | ||
4608 | IClientAPI client = presence.ControllingClient; | ||
4609 | if (m_host.GroupID == client.ActiveGroupId) | ||
4610 | return new LSL_Integer(1); | ||
4611 | else | ||
4612 | return new LSL_Integer(0); | ||
4613 | } | ||
4614 | |||
4615 | public void llUnSit(string id) | ||
4616 | { | ||
4617 | m_host.AddScriptLPS(1); | ||
4618 | |||
4619 | UUID key = new UUID(); | ||
4620 | if (UUID.TryParse(id, out key)) | ||
4621 | { | ||
4622 | ScenePresence av = World.GetScenePresence(key); | ||
4623 | |||
4624 | if (av != null) | ||
4625 | { | ||
4626 | if (llAvatarOnSitTarget() == id) | ||
4627 | { | ||
4628 | // if the avatar is sitting on this object, then | ||
4629 | // we can unsit them. We don't want random scripts unsitting random people | ||
4630 | // Lets avoid the popcorn avatar scenario. | ||
4631 | av.StandUp(); | ||
4632 | } | ||
4633 | else | ||
4634 | { | ||
4635 | // If the object owner also owns the parcel | ||
4636 | // or | ||
4637 | // if the land is group owned and the object is group owned by the same group | ||
4638 | // or | ||
4639 | // if the object is owned by a person with estate access. | ||
4640 | |||
4641 | ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y); | ||
4642 | if (parcel != null) | ||
4643 | { | ||
4644 | if (m_host.ObjectOwner == parcel.landData.OwnerID || | ||
4645 | (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.landData.GroupID | ||
4646 | && parcel.landData.IsGroupOwned) || World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID)) | ||
4647 | { | ||
4648 | av.StandUp(); | ||
4649 | } | ||
4650 | } | ||
4651 | } | ||
4652 | } | ||
4653 | |||
4654 | } | ||
4655 | |||
4656 | } | ||
4657 | |||
4658 | public LSL_Vector llGroundSlope(LSL_Vector offset) | ||
4659 | { | ||
4660 | m_host.AddScriptLPS(1); | ||
4661 | |||
4662 | Vector3 pos = m_host.AbsolutePosition + new Vector3((float)offset.x, | ||
4663 | (float)offset.y, | ||
4664 | (float)offset.z); | ||
4665 | |||
4666 | Vector3 p0 = new Vector3(pos.X, pos.Y, | ||
4667 | (float)llGround( | ||
4668 | new LSL_Vector(pos.X, pos.Y, pos.Z) | ||
4669 | )); | ||
4670 | Vector3 p1 = new Vector3(pos.X + 1, pos.Y, | ||
4671 | (float)llGround( | ||
4672 | new LSL_Vector(pos.X + 1, pos.Y, pos.Z) | ||
4673 | )); | ||
4674 | Vector3 p2 = new Vector3(pos.X, pos.Y + 1, | ||
4675 | (float)llGround( | ||
4676 | new LSL_Vector(pos.X, pos.Y + 1, pos.Z) | ||
4677 | )); | ||
4678 | |||
4679 | Vector3 v0 = new Vector3( | ||
4680 | p1.X - p0.X, p1.Y - p0.Y, p1.Z - p0.Z); | ||
4681 | Vector3 v1 = new Vector3( | ||
4682 | p2.X - p1.X, p2.Y - p1.Y, p2.Z - p1.Z); | ||
4683 | |||
4684 | v0.Normalize(); | ||
4685 | v1.Normalize(); | ||
4686 | |||
4687 | Vector3 tv = new Vector3(); | ||
4688 | tv.X = (v0.Y * v1.Z) - (v0.Z * v1.Y); | ||
4689 | tv.Y = (v0.Z * v1.X) - (v0.X * v1.Z); | ||
4690 | tv.Z = (v0.X * v1.Y) - (v0.Y * v1.X); | ||
4691 | |||
4692 | return new LSL_Vector(tv.X, tv.Y, tv.Z); | ||
4693 | } | ||
4694 | |||
4695 | public LSL_Vector llGroundNormal(LSL_Vector offset) | ||
4696 | { | ||
4697 | m_host.AddScriptLPS(1); | ||
4698 | LSL_Vector x = llGroundSlope(offset); | ||
4699 | return new LSL_Vector(x.x, x.y, 1.0); | ||
4700 | } | ||
4701 | |||
4702 | public LSL_Vector llGroundContour(LSL_Vector offset) | ||
4703 | { | ||
4704 | m_host.AddScriptLPS(1); | ||
4705 | LSL_Vector x = llGroundSlope(offset); | ||
4706 | return new LSL_Vector(-x.y, x.x, 0.0); | ||
4707 | } | ||
4708 | |||
4709 | public LSL_Integer llGetAttached() | ||
4710 | { | ||
4711 | m_host.AddScriptLPS(1); | ||
4712 | return m_host.ParentGroup.RootPart.AttachmentPoint; | ||
4713 | } | ||
4714 | |||
4715 | public LSL_Integer llGetFreeMemory() | ||
4716 | { | ||
4717 | m_host.AddScriptLPS(1); | ||
4718 | // Make scripts designed for LSO happy | ||
4719 | return 16384; | ||
4720 | } | ||
4721 | |||
4722 | public LSL_String llGetRegionName() | ||
4723 | { | ||
4724 | m_host.AddScriptLPS(1); | ||
4725 | return World.RegionInfo.RegionName; | ||
4726 | } | ||
4727 | |||
4728 | public LSL_Float llGetRegionTimeDilation() | ||
4729 | { | ||
4730 | m_host.AddScriptLPS(1); | ||
4731 | return (double)World.TimeDilation; | ||
4732 | } | ||
4733 | |||
4734 | public LSL_Float llGetRegionFPS() | ||
4735 | { | ||
4736 | m_host.AddScriptLPS(1); | ||
4737 | //TODO: return actual FPS | ||
4738 | return 10.0f; | ||
4739 | } | ||
4740 | |||
4741 | /* particle system rules should be coming into this routine as doubles, that is | ||
4742 | rule[0] should be an integer from this list and rule[1] should be the arg | ||
4743 | for the same integer. wiki.secondlife.com has most of this mapping, but some | ||
4744 | came from http://www.caligari-designs.com/p4u2 | ||
4745 | |||
4746 | We iterate through the list for 'Count' elements, incrementing by two for each | ||
4747 | iteration and set the members of Primitive.ParticleSystem, one at a time. | ||
4748 | */ | ||
4749 | |||
4750 | public enum PrimitiveRule : int | ||
4751 | { | ||
4752 | PSYS_PART_FLAGS = 0, | ||
4753 | PSYS_PART_START_COLOR = 1, | ||
4754 | PSYS_PART_START_ALPHA = 2, | ||
4755 | PSYS_PART_END_COLOR = 3, | ||
4756 | PSYS_PART_END_ALPHA = 4, | ||
4757 | PSYS_PART_START_SCALE = 5, | ||
4758 | PSYS_PART_END_SCALE = 6, | ||
4759 | PSYS_PART_MAX_AGE = 7, | ||
4760 | PSYS_SRC_ACCEL = 8, | ||
4761 | PSYS_SRC_PATTERN = 9, | ||
4762 | PSYS_SRC_TEXTURE = 12, | ||
4763 | PSYS_SRC_BURST_RATE = 13, | ||
4764 | PSYS_SRC_BURST_PART_COUNT = 15, | ||
4765 | PSYS_SRC_BURST_RADIUS = 16, | ||
4766 | PSYS_SRC_BURST_SPEED_MIN = 17, | ||
4767 | PSYS_SRC_BURST_SPEED_MAX = 18, | ||
4768 | PSYS_SRC_MAX_AGE = 19, | ||
4769 | PSYS_SRC_TARGET_KEY = 20, | ||
4770 | PSYS_SRC_OMEGA = 21, | ||
4771 | PSYS_SRC_ANGLE_BEGIN = 22, | ||
4772 | PSYS_SRC_ANGLE_END = 23 | ||
4773 | } | ||
4774 | |||
4775 | internal Primitive.ParticleSystem.ParticleDataFlags ConvertUINTtoFlags(uint flags) | ||
4776 | { | ||
4777 | Primitive.ParticleSystem.ParticleDataFlags returnval = Primitive.ParticleSystem.ParticleDataFlags.None; | ||
4778 | |||
4779 | return returnval; | ||
4780 | } | ||
4781 | |||
4782 | private Primitive.ParticleSystem getNewParticleSystemWithSLDefaultValues() | ||
4783 | { | ||
4784 | Primitive.ParticleSystem ps = new Primitive.ParticleSystem(); | ||
4785 | |||
4786 | // TODO find out about the other defaults and add them here | ||
4787 | ps.PartStartColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); | ||
4788 | ps.PartEndColor = new Color4(1.0f, 1.0f, 1.0f, 1.0f); | ||
4789 | ps.PartStartScaleX = 1.0f; | ||
4790 | ps.PartStartScaleY = 1.0f; | ||
4791 | ps.PartEndScaleX = 1.0f; | ||
4792 | ps.PartEndScaleY = 1.0f; | ||
4793 | ps.BurstSpeedMin = 1.0f; | ||
4794 | ps.BurstSpeedMax = 1.0f; | ||
4795 | ps.BurstRate = 0.1f; | ||
4796 | ps.PartMaxAge = 10.0f; | ||
4797 | return ps; | ||
4798 | } | ||
4799 | |||
4800 | public void llParticleSystem(LSL_List rules) | ||
4801 | { | ||
4802 | m_host.AddScriptLPS(1); | ||
4803 | if (rules.Length == 0) | ||
4804 | { | ||
4805 | m_host.RemoveParticleSystem(); | ||
4806 | m_host.ParentGroup.HasGroupChanged = true; | ||
4807 | } | ||
4808 | else | ||
4809 | { | ||
4810 | Primitive.ParticleSystem prules = getNewParticleSystemWithSLDefaultValues(); | ||
4811 | LSL_Vector tempv = new LSL_Vector(); | ||
4812 | |||
4813 | float tempf = 0; | ||
4814 | |||
4815 | for (int i = 0; i < rules.Length; i += 2) | ||
4816 | { | ||
4817 | switch ((int)rules.Data[i]) | ||
4818 | { | ||
4819 | case (int)ScriptBaseClass.PSYS_PART_FLAGS: | ||
4820 | prules.PartDataFlags = (Primitive.ParticleSystem.ParticleDataFlags)(uint)rules.GetLSLIntegerItem(i + 1); | ||
4821 | break; | ||
4822 | |||
4823 | case (int)ScriptBaseClass.PSYS_PART_START_COLOR: | ||
4824 | tempv = rules.GetVector3Item(i + 1); | ||
4825 | prules.PartStartColor.R = (float)tempv.x; | ||
4826 | prules.PartStartColor.G = (float)tempv.y; | ||
4827 | prules.PartStartColor.B = (float)tempv.z; | ||
4828 | break; | ||
4829 | |||
4830 | case (int)ScriptBaseClass.PSYS_PART_START_ALPHA: | ||
4831 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4832 | prules.PartStartColor.A = tempf; | ||
4833 | break; | ||
4834 | |||
4835 | case (int)ScriptBaseClass.PSYS_PART_END_COLOR: | ||
4836 | tempv = rules.GetVector3Item(i + 1); | ||
4837 | prules.PartEndColor.R = (float)tempv.x; | ||
4838 | prules.PartEndColor.G = (float)tempv.y; | ||
4839 | prules.PartEndColor.B = (float)tempv.z; | ||
4840 | break; | ||
4841 | |||
4842 | case (int)ScriptBaseClass.PSYS_PART_END_ALPHA: | ||
4843 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4844 | prules.PartEndColor.A = tempf; | ||
4845 | break; | ||
4846 | |||
4847 | case (int)ScriptBaseClass.PSYS_PART_START_SCALE: | ||
4848 | tempv = rules.GetVector3Item(i + 1); | ||
4849 | prules.PartStartScaleX = (float)tempv.x; | ||
4850 | prules.PartStartScaleY = (float)tempv.y; | ||
4851 | break; | ||
4852 | |||
4853 | case (int)ScriptBaseClass.PSYS_PART_END_SCALE: | ||
4854 | tempv = rules.GetVector3Item(i + 1); | ||
4855 | prules.PartEndScaleX = (float)tempv.x; | ||
4856 | prules.PartEndScaleY = (float)tempv.y; | ||
4857 | break; | ||
4858 | |||
4859 | case (int)ScriptBaseClass.PSYS_PART_MAX_AGE: | ||
4860 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4861 | prules.PartMaxAge = tempf; | ||
4862 | break; | ||
4863 | |||
4864 | case (int)ScriptBaseClass.PSYS_SRC_ACCEL: | ||
4865 | tempv = rules.GetVector3Item(i + 1); | ||
4866 | prules.PartAcceleration.X = (float)tempv.x; | ||
4867 | prules.PartAcceleration.Y = (float)tempv.y; | ||
4868 | prules.PartAcceleration.Z = (float)tempv.z; | ||
4869 | break; | ||
4870 | |||
4871 | case (int)ScriptBaseClass.PSYS_SRC_PATTERN: | ||
4872 | int tmpi = (int)rules.GetLSLIntegerItem(i + 1); | ||
4873 | prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; | ||
4874 | break; | ||
4875 | |||
4876 | case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: | ||
4877 | prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1)); | ||
4878 | break; | ||
4879 | |||
4880 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RATE: | ||
4881 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4882 | prules.BurstRate = (float)tempf; | ||
4883 | break; | ||
4884 | |||
4885 | case (int)ScriptBaseClass.PSYS_SRC_BURST_PART_COUNT: | ||
4886 | prules.BurstPartCount = (byte)(int)rules.GetLSLIntegerItem(i + 1); | ||
4887 | break; | ||
4888 | |||
4889 | case (int)ScriptBaseClass.PSYS_SRC_BURST_RADIUS: | ||
4890 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4891 | prules.BurstRadius = (float)tempf; | ||
4892 | break; | ||
4893 | |||
4894 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MIN: | ||
4895 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4896 | prules.BurstSpeedMin = (float)tempf; | ||
4897 | break; | ||
4898 | |||
4899 | case (int)ScriptBaseClass.PSYS_SRC_BURST_SPEED_MAX: | ||
4900 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4901 | prules.BurstSpeedMax = (float)tempf; | ||
4902 | break; | ||
4903 | |||
4904 | case (int)ScriptBaseClass.PSYS_SRC_MAX_AGE: | ||
4905 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4906 | prules.MaxAge = (float)tempf; | ||
4907 | break; | ||
4908 | |||
4909 | case (int)ScriptBaseClass.PSYS_SRC_TARGET_KEY: | ||
4910 | UUID key = UUID.Zero; | ||
4911 | if (UUID.TryParse(rules.Data[i + 1].ToString(), out key)) | ||
4912 | { | ||
4913 | prules.Target = key; | ||
4914 | } | ||
4915 | else | ||
4916 | { | ||
4917 | prules.Target = m_host.UUID; | ||
4918 | } | ||
4919 | break; | ||
4920 | |||
4921 | case (int)ScriptBaseClass.PSYS_SRC_OMEGA: | ||
4922 | // AL: This is an assumption, since it is the only thing that would match. | ||
4923 | tempv = rules.GetVector3Item(i + 1); | ||
4924 | prules.AngularVelocity.X = (float)tempv.x; | ||
4925 | prules.AngularVelocity.Y = (float)tempv.y; | ||
4926 | prules.AngularVelocity.Z = (float)tempv.z; | ||
4927 | break; | ||
4928 | |||
4929 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: | ||
4930 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4931 | prules.InnerAngle = (float)tempf; | ||
4932 | break; | ||
4933 | |||
4934 | case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: | ||
4935 | tempf = (float)rules.GetLSLFloatItem(i + 1); | ||
4936 | prules.OuterAngle = (float)tempf; | ||
4937 | break; | ||
4938 | } | ||
4939 | |||
4940 | } | ||
4941 | prules.CRC = 1; | ||
4942 | |||
4943 | m_host.AddNewParticleSystem(prules); | ||
4944 | m_host.ParentGroup.HasGroupChanged = true; | ||
4945 | } | ||
4946 | m_host.SendFullUpdateToAllClients(); | ||
4947 | } | ||
4948 | |||
4949 | public void llGroundRepel(double height, int water, double tau) | ||
4950 | { | ||
4951 | m_host.AddScriptLPS(1); | ||
4952 | NotImplemented("llGroundRepel"); | ||
4953 | } | ||
4954 | |||
4955 | private UUID GetTaskInventoryItem(string name) | ||
4956 | { | ||
4957 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
4958 | { | ||
4959 | if (inv.Value.Name == name) | ||
4960 | return inv.Key; | ||
4961 | } | ||
4962 | return UUID.Zero; | ||
4963 | } | ||
4964 | |||
4965 | public void llGiveInventoryList(string destination, string category, LSL_List inventory) | ||
4966 | { | ||
4967 | m_host.AddScriptLPS(1); | ||
4968 | |||
4969 | UUID destID; | ||
4970 | if (!UUID.TryParse(destination, out destID)) | ||
4971 | return; | ||
4972 | |||
4973 | List<UUID> itemList = new List<UUID>(); | ||
4974 | |||
4975 | foreach (Object item in inventory.Data) | ||
4976 | { | ||
4977 | UUID itemID; | ||
4978 | if (UUID.TryParse(item.ToString(), out itemID)) | ||
4979 | { | ||
4980 | itemList.Add(itemID); | ||
4981 | } | ||
4982 | else | ||
4983 | { | ||
4984 | itemID = GetTaskInventoryItem(item.ToString()); | ||
4985 | if (itemID != UUID.Zero) | ||
4986 | itemList.Add(itemID); | ||
4987 | } | ||
4988 | } | ||
4989 | |||
4990 | if (itemList.Count == 0) | ||
4991 | return; | ||
4992 | |||
4993 | m_ScriptEngine.World.MoveTaskInventoryItems(destID, category, m_host, itemList); | ||
4994 | } | ||
4995 | |||
4996 | public void llSetVehicleType(int type) | ||
4997 | { | ||
4998 | m_host.AddScriptLPS(1); | ||
4999 | NotImplemented("llSetVehicleType"); | ||
5000 | } | ||
5001 | |||
5002 | public void llSetVehicledoubleParam(int param, double value) | ||
5003 | { | ||
5004 | m_host.AddScriptLPS(1); | ||
5005 | NotImplemented("llSetVehicledoubleParam"); | ||
5006 | } | ||
5007 | |||
5008 | public void llSetVehicleFloatParam(int param, float value) | ||
5009 | { | ||
5010 | m_host.AddScriptLPS(1); | ||
5011 | NotImplemented("llSetVehicleFloatParam"); | ||
5012 | } | ||
5013 | |||
5014 | public void llSetVehicleVectorParam(int param, LSL_Vector vec) | ||
5015 | { | ||
5016 | m_host.AddScriptLPS(1); | ||
5017 | NotImplemented("llSetVehicleVectorParam"); | ||
5018 | } | ||
5019 | |||
5020 | public void llSetVehicleRotationParam(int param, LSL_Rotation rot) | ||
5021 | { | ||
5022 | m_host.AddScriptLPS(1); | ||
5023 | NotImplemented("llSetVehicleRotationParam"); | ||
5024 | } | ||
5025 | |||
5026 | public void llSetVehicleFlags(int flags) | ||
5027 | { | ||
5028 | m_host.AddScriptLPS(1); | ||
5029 | NotImplemented("llSetVehicleFlags"); | ||
5030 | } | ||
5031 | |||
5032 | public void llRemoveVehicleFlags(int flags) | ||
5033 | { | ||
5034 | m_host.AddScriptLPS(1); | ||
5035 | NotImplemented("llRemoveVehicleFlags"); | ||
5036 | } | ||
5037 | |||
5038 | public void llSitTarget(LSL_Vector offset, LSL_Rotation rot) | ||
5039 | { | ||
5040 | m_host.AddScriptLPS(1); | ||
5041 | // LSL quaternions can normalize to 0, normal Quaternions can't. | ||
5042 | if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) | ||
5043 | rot.z = 1; // ZERO_ROTATION = 0,0,0,1 | ||
5044 | |||
5045 | m_host.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); | ||
5046 | m_host.SitTargetOrientation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); | ||
5047 | } | ||
5048 | |||
5049 | public LSL_String llAvatarOnSitTarget() | ||
5050 | { | ||
5051 | m_host.AddScriptLPS(1); | ||
5052 | return m_host.GetAvatarOnSitTarget().ToString(); | ||
5053 | } | ||
5054 | |||
5055 | public void llAddToLandPassList(string avatar, double hours) | ||
5056 | { | ||
5057 | m_host.AddScriptLPS(1); | ||
5058 | UUID key; | ||
5059 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
5060 | if (land.OwnerID == m_host.OwnerID) | ||
5061 | { | ||
5062 | ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); | ||
5063 | if (UUID.TryParse(avatar, out key)) | ||
5064 | { | ||
5065 | entry.AgentID = key; | ||
5066 | entry.Flags = ParcelManager.AccessList.Access; | ||
5067 | entry.Time = DateTime.Now.AddHours(hours); | ||
5068 | land.ParcelAccessList.Add(entry); | ||
5069 | } | ||
5070 | } | ||
5071 | // ScriptSleep(100); | ||
5072 | } | ||
5073 | |||
5074 | public void llSetTouchText(string text) | ||
5075 | { | ||
5076 | m_host.AddScriptLPS(1); | ||
5077 | m_host.TouchName = text; | ||
5078 | } | ||
5079 | |||
5080 | public void llSetSitText(string text) | ||
5081 | { | ||
5082 | m_host.AddScriptLPS(1); | ||
5083 | m_host.SitName = text; | ||
5084 | } | ||
5085 | |||
5086 | public void llSetCameraEyeOffset(LSL_Vector offset) | ||
5087 | { | ||
5088 | m_host.AddScriptLPS(1); | ||
5089 | m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); | ||
5090 | } | ||
5091 | |||
5092 | public void llSetCameraAtOffset(LSL_Vector offset) | ||
5093 | { | ||
5094 | m_host.AddScriptLPS(1); | ||
5095 | m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); | ||
5096 | } | ||
5097 | |||
5098 | public LSL_String llDumpList2String(LSL_List src, string seperator) | ||
5099 | { | ||
5100 | m_host.AddScriptLPS(1); | ||
5101 | if (src.Length == 0) | ||
5102 | { | ||
5103 | return String.Empty; | ||
5104 | } | ||
5105 | string ret = String.Empty; | ||
5106 | foreach (object o in src.Data) | ||
5107 | { | ||
5108 | ret = ret + o.ToString() + seperator; | ||
5109 | } | ||
5110 | ret = ret.Substring(0, ret.Length - seperator.Length); | ||
5111 | return ret; | ||
5112 | } | ||
5113 | |||
5114 | public LSL_Integer llScriptDanger(LSL_Vector pos) | ||
5115 | { | ||
5116 | m_host.AddScriptLPS(1); | ||
5117 | bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); | ||
5118 | if (result) | ||
5119 | { | ||
5120 | return 1; | ||
5121 | } | ||
5122 | else | ||
5123 | { | ||
5124 | return 0; | ||
5125 | } | ||
5126 | |||
5127 | } | ||
5128 | |||
5129 | public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel) | ||
5130 | { | ||
5131 | m_host.AddScriptLPS(1); | ||
5132 | UUID av = new UUID(); | ||
5133 | if (!UUID.TryParse(avatar,out av)) | ||
5134 | { | ||
5135 | LSLError("First parameter to llDialog needs to be a key"); | ||
5136 | return; | ||
5137 | } | ||
5138 | if (buttons.Length > 12) | ||
5139 | { | ||
5140 | LSLError("No more than 12 buttons can be shown"); | ||
5141 | return; | ||
5142 | } | ||
5143 | string[] buts = new string[buttons.Length]; | ||
5144 | for (int i = 0; i < buttons.Length; i++) | ||
5145 | { | ||
5146 | if (buttons.Data[i].ToString() == String.Empty) | ||
5147 | { | ||
5148 | LSLError("button label cannot be blank"); | ||
5149 | return; | ||
5150 | } | ||
5151 | if (buttons.Data[i].ToString().Length > 24) | ||
5152 | { | ||
5153 | LSLError("button label cannot be longer than 24 characters"); | ||
5154 | return; | ||
5155 | } | ||
5156 | buts[i] = buttons.Data[i].ToString(); | ||
5157 | } | ||
5158 | World.SendDialogToUser(av, m_host.Name, m_host.UUID, m_host.OwnerID, message, new UUID("00000000-0000-2222-3333-100000001000"), chat_channel, buts); | ||
5159 | // ScriptSleep(1000); | ||
5160 | } | ||
5161 | |||
5162 | public void llVolumeDetect(int detect) | ||
5163 | { | ||
5164 | m_host.AddScriptLPS(1); | ||
5165 | NotImplemented("llVolumeDetect"); | ||
5166 | } | ||
5167 | |||
5168 | /// <summary> | ||
5169 | /// Reset the named script. The script must be present | ||
5170 | /// in the same prim. | ||
5171 | /// </summary> | ||
5172 | |||
5173 | public void llRemoteLoadScript() | ||
5174 | { | ||
5175 | m_host.AddScriptLPS(1); | ||
5176 | Deprecated("llRemoteLoadScript"); | ||
5177 | // ScriptSleep(3000); | ||
5178 | } | ||
5179 | |||
5180 | public void llSetRemoteScriptAccessPin(int pin) | ||
5181 | { | ||
5182 | m_host.AddScriptLPS(1); | ||
5183 | m_host.ScriptAccessPin = pin; | ||
5184 | } | ||
5185 | |||
5186 | public void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param) | ||
5187 | { | ||
5188 | m_host.AddScriptLPS(1); | ||
5189 | bool found = false; | ||
5190 | UUID destId = UUID.Zero; | ||
5191 | UUID srcId = UUID.Zero; | ||
5192 | |||
5193 | if (!UUID.TryParse(target, out destId)) | ||
5194 | { | ||
5195 | llSay(0, "Could not parse key " + target); | ||
5196 | return; | ||
5197 | } | ||
5198 | |||
5199 | // target must be a different prim than the one containing the script | ||
5200 | if (m_host.UUID == destId) | ||
5201 | { | ||
5202 | return; | ||
5203 | } | ||
5204 | |||
5205 | // copy the first script found with this inventory name | ||
5206 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
5207 | { | ||
5208 | if (inv.Value.Name == name) | ||
5209 | { | ||
5210 | // make sure the object is a script | ||
5211 | if (10 == inv.Value.Type) | ||
5212 | { | ||
5213 | found = true; | ||
5214 | srcId = inv.Key; | ||
5215 | break; | ||
5216 | } | ||
5217 | } | ||
5218 | } | ||
5219 | |||
5220 | if (!found) | ||
5221 | { | ||
5222 | llSay(0, "Could not find script " + name); | ||
5223 | return; | ||
5224 | } | ||
5225 | |||
5226 | // the rest of the permission checks are done in RezScript, so check the pin there as well | ||
5227 | World.RezScript(srcId, m_host, destId, pin, running, start_param); | ||
5228 | // this will cause the delay even if the script pin or permissions were wrong - seems ok | ||
5229 | ScriptSleep(3000); | ||
5230 | } | ||
5231 | |||
5232 | public void llOpenRemoteDataChannel() | ||
5233 | { | ||
5234 | m_host.AddScriptLPS(1); | ||
5235 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5236 | if (xmlrpcMod.IsEnabled()) | ||
5237 | { | ||
5238 | UUID channelID = xmlrpcMod.OpenXMLRPCChannel(m_localID, m_itemID, UUID.Zero); | ||
5239 | object[] resobj = new object[] { new LSL_Integer(1), new LSL_String(channelID.ToString()), new LSL_String(UUID.Zero.ToString()), new LSL_String(String.Empty), new LSL_Integer(0), new LSL_String(String.Empty) }; | ||
5240 | m_ScriptEngine.PostScriptEvent(m_itemID, new EventParams( | ||
5241 | "remote_data", resobj, | ||
5242 | new DetectParams[0])); | ||
5243 | } | ||
5244 | // ScriptSleep(1000); | ||
5245 | } | ||
5246 | |||
5247 | public LSL_String llSendRemoteData(string channel, string dest, int idata, string sdata) | ||
5248 | { | ||
5249 | m_host.AddScriptLPS(1); | ||
5250 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5251 | // ScriptSleep(3000); | ||
5252 | return (xmlrpcMod.SendRemoteData(m_localID, m_itemID, channel, dest, idata, sdata)).ToString(); | ||
5253 | } | ||
5254 | |||
5255 | public void llRemoteDataReply(string channel, string message_id, string sdata, int idata) | ||
5256 | { | ||
5257 | m_host.AddScriptLPS(1); | ||
5258 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5259 | xmlrpcMod.RemoteDataReply(channel, message_id, sdata, idata); | ||
5260 | // ScriptSleep(3000); | ||
5261 | } | ||
5262 | |||
5263 | public void llCloseRemoteDataChannel(string channel) | ||
5264 | { | ||
5265 | m_host.AddScriptLPS(1); | ||
5266 | IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); | ||
5267 | xmlrpcMod.CloseXMLRPCChannel(channel); | ||
5268 | // ScriptSleep(1000); | ||
5269 | } | ||
5270 | |||
5271 | public LSL_String llMD5String(string src, int nonce) | ||
5272 | { | ||
5273 | m_host.AddScriptLPS(1); | ||
5274 | return Util.Md5Hash(src + ":" + nonce.ToString()); | ||
5275 | } | ||
5276 | |||
5277 | private ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist) | ||
5278 | { | ||
5279 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); | ||
5280 | |||
5281 | if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && | ||
5282 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_CIRCLE && | ||
5283 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_SQUARE && | ||
5284 | holeshape != (int)ScriptBaseClass.PRIM_HOLE_TRIANGLE) | ||
5285 | { | ||
5286 | holeshape = (int)ScriptBaseClass.PRIM_HOLE_DEFAULT; | ||
5287 | } | ||
5288 | shapeBlock.ProfileCurve = (byte)holeshape; | ||
5289 | if (cut.x < 0f) | ||
5290 | { | ||
5291 | cut.x = 0f; | ||
5292 | } | ||
5293 | if (cut.x > 1f) | ||
5294 | { | ||
5295 | cut.x = 1f; | ||
5296 | } | ||
5297 | if (cut.y < 0f) | ||
5298 | { | ||
5299 | cut.y = 0f; | ||
5300 | } | ||
5301 | if (cut.y > 1f) | ||
5302 | { | ||
5303 | cut.y = 1f; | ||
5304 | } | ||
5305 | if (cut.y - cut.x < 0.05f) | ||
5306 | { | ||
5307 | cut.x = cut.y - 0.05f; | ||
5308 | } | ||
5309 | shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); | ||
5310 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y)); | ||
5311 | if (hollow < 0f) | ||
5312 | { | ||
5313 | hollow = 0f; | ||
5314 | } | ||
5315 | if (hollow > 0.95) | ||
5316 | { | ||
5317 | hollow = 0.95f; | ||
5318 | } | ||
5319 | shapeBlock.ProfileHollow = (ushort)(50000 * hollow); | ||
5320 | if (twist.x < -1.0f) | ||
5321 | { | ||
5322 | twist.x = -1.0f; | ||
5323 | } | ||
5324 | if (twist.x > 1.0f) | ||
5325 | { | ||
5326 | twist.x = 1.0f; | ||
5327 | } | ||
5328 | if (twist.y < -1.0f) | ||
5329 | { | ||
5330 | twist.y = -1.0f; | ||
5331 | } | ||
5332 | if (twist.y > 1.0f) | ||
5333 | { | ||
5334 | twist.y = 1.0f; | ||
5335 | } | ||
5336 | shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); | ||
5337 | shapeBlock.PathTwist = (sbyte)(100 * twist.y); | ||
5338 | |||
5339 | shapeBlock.ObjectLocalID = part.LocalId; | ||
5340 | |||
5341 | // retain pathcurve | ||
5342 | shapeBlock.PathCurve = part.Shape.PathCurve; | ||
5343 | |||
5344 | return shapeBlock; | ||
5345 | } | ||
5346 | |||
5347 | private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte fudge) | ||
5348 | { | ||
5349 | ObjectShapePacket.ObjectDataBlock shapeBlock; | ||
5350 | |||
5351 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); | ||
5352 | |||
5353 | shapeBlock.ProfileCurve += fudge; | ||
5354 | |||
5355 | if (taper_b.x < 0f) | ||
5356 | { | ||
5357 | taper_b.x = 0f; | ||
5358 | } | ||
5359 | if (taper_b.x > 2f) | ||
5360 | { | ||
5361 | taper_b.x = 2f; | ||
5362 | } | ||
5363 | if (taper_b.y < 0f) | ||
5364 | { | ||
5365 | taper_b.y = 0f; | ||
5366 | } | ||
5367 | if (taper_b.y > 2f) | ||
5368 | { | ||
5369 | taper_b.y = 2f; | ||
5370 | } | ||
5371 | shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); | ||
5372 | shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); | ||
5373 | if (topshear.x < -0.5f) | ||
5374 | { | ||
5375 | topshear.x = -0.5f; | ||
5376 | } | ||
5377 | if (topshear.x > 0.5f) | ||
5378 | { | ||
5379 | topshear.x = 0.5f; | ||
5380 | } | ||
5381 | if (topshear.y < -0.5f) | ||
5382 | { | ||
5383 | topshear.y = -0.5f; | ||
5384 | } | ||
5385 | if (topshear.y > 0.5f) | ||
5386 | { | ||
5387 | topshear.y = 0.5f; | ||
5388 | } | ||
5389 | shapeBlock.PathShearX = (byte)(100 * topshear.x); | ||
5390 | shapeBlock.PathShearY = (byte)(100 * topshear.y); | ||
5391 | |||
5392 | part.UpdateShape(shapeBlock); | ||
5393 | } | ||
5394 | |||
5395 | private void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector dimple, byte fudge) | ||
5396 | { | ||
5397 | ObjectShapePacket.ObjectDataBlock shapeBlock; | ||
5398 | |||
5399 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); | ||
5400 | |||
5401 | // profile/path swapped for a sphere | ||
5402 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; | ||
5403 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; | ||
5404 | |||
5405 | shapeBlock.ProfileCurve += fudge; | ||
5406 | |||
5407 | shapeBlock.PathScaleX = 100; | ||
5408 | shapeBlock.PathScaleY = 100; | ||
5409 | |||
5410 | if (dimple.x < 0f) | ||
5411 | { | ||
5412 | dimple.x = 0f; | ||
5413 | } | ||
5414 | if (dimple.x > 1f) | ||
5415 | { | ||
5416 | dimple.x = 1f; | ||
5417 | } | ||
5418 | if (dimple.y < 0f) | ||
5419 | { | ||
5420 | dimple.y = 0f; | ||
5421 | } | ||
5422 | if (dimple.y > 1f) | ||
5423 | { | ||
5424 | dimple.y = 1f; | ||
5425 | } | ||
5426 | if (dimple.y - cut.x < 0.05f) | ||
5427 | { | ||
5428 | dimple.x = cut.y - 0.05f; | ||
5429 | } | ||
5430 | shapeBlock.ProfileBegin = (ushort)(50000 * dimple.x); | ||
5431 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - dimple.y)); | ||
5432 | |||
5433 | part.UpdateShape(shapeBlock); | ||
5434 | } | ||
5435 | |||
5436 | private 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 fudge) | ||
5437 | { | ||
5438 | ObjectShapePacket.ObjectDataBlock shapeBlock; | ||
5439 | |||
5440 | shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist); | ||
5441 | |||
5442 | shapeBlock.ProfileCurve += fudge; | ||
5443 | |||
5444 | // profile/path swapped for a torrus, tube, ring | ||
5445 | shapeBlock.PathBegin = shapeBlock.ProfileBegin; | ||
5446 | shapeBlock.PathEnd = shapeBlock.ProfileEnd; | ||
5447 | |||
5448 | if (holesize.x < 0.05f) | ||
5449 | { | ||
5450 | holesize.x = 0.05f; | ||
5451 | } | ||
5452 | if (holesize.x > 1f) | ||
5453 | { | ||
5454 | holesize.x = 1f; | ||
5455 | } | ||
5456 | if (holesize.y < 0.05f) | ||
5457 | { | ||
5458 | holesize.y = 0.05f; | ||
5459 | } | ||
5460 | if (holesize.y > 0.5f) | ||
5461 | { | ||
5462 | holesize.y = 0.5f; | ||
5463 | } | ||
5464 | shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); | ||
5465 | shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); | ||
5466 | if (topshear.x < -0.5f) | ||
5467 | { | ||
5468 | topshear.x = -0.5f; | ||
5469 | } | ||
5470 | if (topshear.x > 0.5f) | ||
5471 | { | ||
5472 | topshear.x = 0.5f; | ||
5473 | } | ||
5474 | if (topshear.y < -0.5f) | ||
5475 | { | ||
5476 | topshear.y = -0.5f; | ||
5477 | } | ||
5478 | if (topshear.y > 0.5f) | ||
5479 | { | ||
5480 | topshear.y = 0.5f; | ||
5481 | } | ||
5482 | shapeBlock.PathShearX = (byte)(100 * topshear.x); | ||
5483 | shapeBlock.PathShearY = (byte)(100 * topshear.y); | ||
5484 | if (profilecut.x < 0f) | ||
5485 | { | ||
5486 | profilecut.x = 0f; | ||
5487 | } | ||
5488 | if (profilecut.x > 1f) | ||
5489 | { | ||
5490 | profilecut.x = 1f; | ||
5491 | } | ||
5492 | if (profilecut.y < 0f) | ||
5493 | { | ||
5494 | profilecut.y = 0f; | ||
5495 | } | ||
5496 | if (profilecut.y > 1f) | ||
5497 | { | ||
5498 | profilecut.y = 1f; | ||
5499 | } | ||
5500 | if (profilecut.y - cut.x < 0.05f) | ||
5501 | { | ||
5502 | profilecut.x = cut.y - 0.05f; | ||
5503 | } | ||
5504 | shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); | ||
5505 | shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y)); | ||
5506 | if (taper_a.x < -1f) | ||
5507 | { | ||
5508 | taper_a.x = -1f; | ||
5509 | } | ||
5510 | if (taper_a.x > 1f) | ||
5511 | { | ||
5512 | taper_a.x = 1f; | ||
5513 | } | ||
5514 | if (taper_a.y < -1f) | ||
5515 | { | ||
5516 | taper_a.y = -1f; | ||
5517 | } | ||
5518 | if (taper_a.y > 1f) | ||
5519 | { | ||
5520 | taper_a.y = 1f; | ||
5521 | } | ||
5522 | shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); | ||
5523 | shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); | ||
5524 | if (revolutions < 1f) | ||
5525 | { | ||
5526 | revolutions = 1f; | ||
5527 | } | ||
5528 | if (revolutions > 4f) | ||
5529 | { | ||
5530 | revolutions = 4f; | ||
5531 | } | ||
5532 | shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); | ||
5533 | // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 | ||
5534 | if (radiusoffset < 0f) | ||
5535 | { | ||
5536 | radiusoffset = 0f; | ||
5537 | } | ||
5538 | if (radiusoffset > 1f) | ||
5539 | { | ||
5540 | radiusoffset = 1f; | ||
5541 | } | ||
5542 | shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); | ||
5543 | if (skew < -0.95f) | ||
5544 | { | ||
5545 | skew = -0.95f; | ||
5546 | } | ||
5547 | if (skew > 0.95f) | ||
5548 | { | ||
5549 | skew = 0.95f; | ||
5550 | } | ||
5551 | shapeBlock.PathSkew = (sbyte)(100 * skew); | ||
5552 | |||
5553 | part.UpdateShape(shapeBlock); | ||
5554 | } | ||
5555 | |||
5556 | private void SetPrimitiveShapeParams(SceneObjectPart part, string map, int type) | ||
5557 | { | ||
5558 | ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); | ||
5559 | UUID sculptId; | ||
5560 | |||
5561 | if (!UUID.TryParse(map, out sculptId)) | ||
5562 | { | ||
5563 | llSay(0, "Could not parse key " + map); | ||
5564 | return; | ||
5565 | } | ||
5566 | |||
5567 | shapeBlock.ObjectLocalID = part.LocalId; | ||
5568 | shapeBlock.PathScaleX = 100; | ||
5569 | shapeBlock.PathScaleY = 150; | ||
5570 | |||
5571 | if (type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_CYLINDER && | ||
5572 | type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_PLANE && | ||
5573 | type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE && | ||
5574 | type != (int)ScriptBaseClass.PRIM_SCULPT_TYPE_TORUS) | ||
5575 | { | ||
5576 | // default | ||
5577 | type = (int)ScriptBaseClass.PRIM_SCULPT_TYPE_SPHERE; | ||
5578 | } | ||
5579 | |||
5580 | // retain pathcurve | ||
5581 | shapeBlock.PathCurve = part.Shape.PathCurve; | ||
5582 | |||
5583 | part.Shape.SetSculptData((byte)type, sculptId); | ||
5584 | part.Shape.SculptEntry = true; | ||
5585 | part.UpdateShape(shapeBlock); | ||
5586 | } | ||
5587 | |||
5588 | public void llSetPrimitiveParams(LSL_List rules) | ||
5589 | { | ||
5590 | SetPrimParams(m_host, rules); | ||
5591 | } | ||
5592 | |||
5593 | public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) | ||
5594 | { | ||
5595 | m_host.AddScriptLPS(1); | ||
5596 | |||
5597 | List<SceneObjectPart> parts = GetLinkParts(linknumber); | ||
5598 | |||
5599 | foreach (SceneObjectPart part in parts) | ||
5600 | SetPrimParams(part, rules); | ||
5601 | } | ||
5602 | |||
5603 | private void SetPrimParams(SceneObjectPart part, LSL_List rules) | ||
5604 | { | ||
5605 | int idx = 0; | ||
5606 | |||
5607 | while (idx < rules.Length) | ||
5608 | { | ||
5609 | int code = rules.GetLSLIntegerItem(idx++); | ||
5610 | |||
5611 | int remain = rules.Length - idx; | ||
5612 | |||
5613 | int face; | ||
5614 | LSL_Vector v; | ||
5615 | |||
5616 | switch (code) | ||
5617 | { | ||
5618 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
5619 | if (remain < 1) | ||
5620 | return; | ||
5621 | |||
5622 | v=rules.GetVector3Item(idx++); | ||
5623 | SetPos(part, v); | ||
5624 | |||
5625 | break; | ||
5626 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
5627 | if (remain < 1) | ||
5628 | return; | ||
5629 | |||
5630 | v=rules.GetVector3Item(idx++); | ||
5631 | SetScale(part, v); | ||
5632 | |||
5633 | break; | ||
5634 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
5635 | if (remain < 1) | ||
5636 | return; | ||
5637 | |||
5638 | LSL_Rotation q = rules.GetQuaternionItem(idx++); | ||
5639 | SetRot(part, q); | ||
5640 | |||
5641 | break; | ||
5642 | |||
5643 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
5644 | if (remain < 3) | ||
5645 | return; | ||
5646 | |||
5647 | code = (int)rules.GetLSLIntegerItem(idx++); | ||
5648 | |||
5649 | remain = rules.Length - idx; | ||
5650 | float hollow; | ||
5651 | LSL_Vector twist; | ||
5652 | LSL_Vector taper_b; | ||
5653 | LSL_Vector topshear; | ||
5654 | float revolutions; | ||
5655 | float radiusoffset; | ||
5656 | float skew; | ||
5657 | LSL_Vector holesize; | ||
5658 | LSL_Vector profilecut; | ||
5659 | |||
5660 | switch (code) | ||
5661 | { | ||
5662 | case (int)ScriptBaseClass.PRIM_TYPE_BOX: | ||
5663 | if (remain < 6) | ||
5664 | return; | ||
5665 | |||
5666 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
5667 | v = rules.GetVector3Item(idx++); // cut | ||
5668 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5669 | twist = rules.GetVector3Item(idx++); | ||
5670 | taper_b = rules.GetVector3Item(idx++); | ||
5671 | topshear = rules.GetVector3Item(idx++); | ||
5672 | |||
5673 | part.Shape.PathCurve = (byte)Extrusion.Straight; | ||
5674 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 1); | ||
5675 | break; | ||
5676 | |||
5677 | case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
5678 | if (remain < 6) | ||
5679 | return; | ||
5680 | |||
5681 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5682 | v = rules.GetVector3Item(idx++); // cut | ||
5683 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5684 | twist = rules.GetVector3Item(idx++); | ||
5685 | taper_b = rules.GetVector3Item(idx++); | ||
5686 | topshear = rules.GetVector3Item(idx++); | ||
5687 | part.Shape.ProfileShape = ProfileShape.Circle; | ||
5688 | part.Shape.PathCurve = (byte)Extrusion.Straight; | ||
5689 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 0); | ||
5690 | break; | ||
5691 | |||
5692 | case (int)ScriptBaseClass.PRIM_TYPE_PRISM: | ||
5693 | if (remain < 6) | ||
5694 | return; | ||
5695 | |||
5696 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5697 | v = rules.GetVector3Item(idx++); //cut | ||
5698 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5699 | twist = rules.GetVector3Item(idx++); | ||
5700 | taper_b = rules.GetVector3Item(idx++); | ||
5701 | topshear = rules.GetVector3Item(idx++); | ||
5702 | part.Shape.PathCurve = (byte)Extrusion.Straight; | ||
5703 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, topshear, 3); | ||
5704 | break; | ||
5705 | |||
5706 | case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
5707 | if (remain < 5) | ||
5708 | return; | ||
5709 | |||
5710 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5711 | v = rules.GetVector3Item(idx++); // cut | ||
5712 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5713 | twist = rules.GetVector3Item(idx++); | ||
5714 | taper_b = rules.GetVector3Item(idx++); // dimple | ||
5715 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5716 | SetPrimitiveShapeParams(part, face, v, hollow, twist, taper_b, 5); | ||
5717 | break; | ||
5718 | |||
5719 | case (int)ScriptBaseClass.PRIM_TYPE_TORUS: | ||
5720 | if (remain < 11) | ||
5721 | return; | ||
5722 | |||
5723 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5724 | v = rules.GetVector3Item(idx++); //cut | ||
5725 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5726 | twist = rules.GetVector3Item(idx++); | ||
5727 | holesize = rules.GetVector3Item(idx++); | ||
5728 | topshear = rules.GetVector3Item(idx++); | ||
5729 | profilecut = rules.GetVector3Item(idx++); | ||
5730 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
5731 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
5732 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
5733 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
5734 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5735 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 0); | ||
5736 | break; | ||
5737 | |||
5738 | case (int)ScriptBaseClass.PRIM_TYPE_TUBE: | ||
5739 | if (remain < 11) | ||
5740 | return; | ||
5741 | |||
5742 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5743 | v = rules.GetVector3Item(idx++); //cut | ||
5744 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5745 | twist = rules.GetVector3Item(idx++); | ||
5746 | holesize = rules.GetVector3Item(idx++); | ||
5747 | topshear = rules.GetVector3Item(idx++); | ||
5748 | profilecut = rules.GetVector3Item(idx++); | ||
5749 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
5750 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
5751 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
5752 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
5753 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5754 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 1); | ||
5755 | break; | ||
5756 | |||
5757 | case (int)ScriptBaseClass.PRIM_TYPE_RING: | ||
5758 | if (remain < 11) | ||
5759 | return; | ||
5760 | |||
5761 | face = (int)rules.GetLSLIntegerItem(idx++); // holeshape | ||
5762 | v = rules.GetVector3Item(idx++); //cut | ||
5763 | hollow = (float)rules.GetLSLFloatItem(idx++); | ||
5764 | twist = rules.GetVector3Item(idx++); | ||
5765 | holesize = rules.GetVector3Item(idx++); | ||
5766 | topshear = rules.GetVector3Item(idx++); | ||
5767 | profilecut = rules.GetVector3Item(idx++); | ||
5768 | taper_b = rules.GetVector3Item(idx++); // taper_a | ||
5769 | revolutions = (float)rules.GetLSLFloatItem(idx++); | ||
5770 | radiusoffset = (float)rules.GetLSLFloatItem(idx++); | ||
5771 | skew = (float)rules.GetLSLFloatItem(idx++); | ||
5772 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5773 | SetPrimitiveShapeParams(part, face, v, hollow, twist, holesize, topshear, profilecut, taper_b, revolutions, radiusoffset, skew, 3); | ||
5774 | break; | ||
5775 | |||
5776 | case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
5777 | if (remain < 2) | ||
5778 | return; | ||
5779 | |||
5780 | string map = rules.Data[idx++].ToString(); | ||
5781 | face = (int)rules.GetLSLIntegerItem(idx++); // type | ||
5782 | part.Shape.PathCurve = (byte)Extrusion.Curve1; | ||
5783 | SetPrimitiveShapeParams(part, map, face); | ||
5784 | break; | ||
5785 | } | ||
5786 | |||
5787 | break; | ||
5788 | |||
5789 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
5790 | if (remain < 5) | ||
5791 | return; | ||
5792 | |||
5793 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
5794 | string tex=rules.Data[idx++].ToString(); | ||
5795 | LSL_Vector repeats=rules.GetVector3Item(idx++); | ||
5796 | LSL_Vector offsets=rules.GetVector3Item(idx++); | ||
5797 | double rotation=(double)rules.GetLSLFloatItem(idx++); | ||
5798 | |||
5799 | SetTexture(part, tex, face); | ||
5800 | ScaleTexture(part, repeats.x, repeats.y, face); | ||
5801 | OffsetTexture(part, offsets.x, offsets.y, face); | ||
5802 | RotateTexture(part, rotation, face); | ||
5803 | |||
5804 | break; | ||
5805 | |||
5806 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
5807 | if (remain < 3) | ||
5808 | return; | ||
5809 | |||
5810 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
5811 | LSL_Vector color=rules.GetVector3Item(idx++); | ||
5812 | double alpha=(double)rules.GetLSLFloatItem(idx++); | ||
5813 | |||
5814 | SetColor(part, color, face); | ||
5815 | SetAlpha(part, alpha, face); | ||
5816 | |||
5817 | break; | ||
5818 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
5819 | if (remain < 7) | ||
5820 | return; | ||
5821 | |||
5822 | bool flexi = rules.GetLSLIntegerItem(idx++); | ||
5823 | int softness = rules.GetLSLIntegerItem(idx++); | ||
5824 | float gravity = (float)rules.GetLSLFloatItem(idx++); | ||
5825 | float friction = (float)rules.GetLSLFloatItem(idx++); | ||
5826 | float wind = (float)rules.GetLSLFloatItem(idx++); | ||
5827 | float tension = (float)rules.GetLSLFloatItem(idx++); | ||
5828 | LSL_Vector force = rules.GetVector3Item(idx++); | ||
5829 | |||
5830 | SetFlexi(part, flexi, softness, gravity, friction, wind, tension, force); | ||
5831 | |||
5832 | break; | ||
5833 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
5834 | if (remain < 5) | ||
5835 | return; | ||
5836 | bool light = rules.GetLSLIntegerItem(idx++); | ||
5837 | LSL_Vector lightcolor = rules.GetVector3Item(idx++); | ||
5838 | float intensity = (float)rules.GetLSLFloatItem(idx++); | ||
5839 | float radius = (float)rules.GetLSLFloatItem(idx++); | ||
5840 | float falloff = (float)rules.GetLSLFloatItem(idx++); | ||
5841 | |||
5842 | SetPointLight(part, light, lightcolor, intensity, radius, falloff); | ||
5843 | |||
5844 | break; | ||
5845 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
5846 | if (remain < 2) | ||
5847 | return; | ||
5848 | face = rules.GetLSLIntegerItem(idx++); | ||
5849 | float glow = (float)rules.GetLSLFloatItem(idx++); | ||
5850 | |||
5851 | SetGlow(part, face, glow); | ||
5852 | |||
5853 | break; | ||
5854 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
5855 | if (remain < 3) | ||
5856 | return; | ||
5857 | face = (int)rules.GetLSLIntegerItem(idx++); | ||
5858 | int shiny = (int)rules.GetLSLIntegerItem(idx++); | ||
5859 | Bumpiness bump = (Bumpiness)Convert.ToByte((int)rules.GetLSLIntegerItem(idx++)); | ||
5860 | |||
5861 | SetShiny(part, face, shiny, bump); | ||
5862 | |||
5863 | break; | ||
5864 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
5865 | if (remain < 2) | ||
5866 | return; | ||
5867 | face = rules.GetLSLIntegerItem(idx++); | ||
5868 | bool st = rules.GetLSLIntegerItem(idx++); | ||
5869 | SetFullBright(part, face , st); | ||
5870 | break; | ||
5871 | case (int)ScriptBaseClass.PRIM_MATERIAL: | ||
5872 | if (remain < 1) | ||
5873 | return; | ||
5874 | if (part != null) | ||
5875 | { | ||
5876 | /* Unhandled at this time - sends "Unhandled" message | ||
5877 | will enable when available | ||
5878 | byte material = Convert.ToByte((int)rules.GetLSLIntegerItem(idx++)); | ||
5879 | part.Material = material; | ||
5880 | */ | ||
5881 | return; | ||
5882 | } | ||
5883 | break; | ||
5884 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
5885 | if (remain < 1) | ||
5886 | return; | ||
5887 | |||
5888 | string ph = rules.Data[idx++].ToString(); | ||
5889 | bool phantom; | ||
5890 | |||
5891 | if (ph.Equals("1")) | ||
5892 | phantom = true; | ||
5893 | else | ||
5894 | phantom = false; | ||
5895 | |||
5896 | part.ScriptSetPhantomStatus(phantom); | ||
5897 | part.ScheduleFullUpdate(); | ||
5898 | break; | ||
5899 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
5900 | if (remain < 1) | ||
5901 | return; | ||
5902 | string phy = rules.Data[idx++].ToString(); | ||
5903 | bool physics; | ||
5904 | |||
5905 | if (phy.Equals("1")) | ||
5906 | physics = true; | ||
5907 | else | ||
5908 | physics = false; | ||
5909 | |||
5910 | m_host.ScriptSetPhysicsStatus(physics); | ||
5911 | part.ScheduleFullUpdate(); | ||
5912 | break; | ||
5913 | } | ||
5914 | } | ||
5915 | } | ||
5916 | |||
5917 | public LSL_String llStringToBase64(string str) | ||
5918 | { | ||
5919 | m_host.AddScriptLPS(1); | ||
5920 | try | ||
5921 | { | ||
5922 | byte[] encData_byte = new byte[str.Length]; | ||
5923 | encData_byte = Encoding.UTF8.GetBytes(str); | ||
5924 | string encodedData = Convert.ToBase64String(encData_byte); | ||
5925 | return encodedData; | ||
5926 | } | ||
5927 | catch (Exception e) | ||
5928 | { | ||
5929 | throw new Exception("Error in base64Encode" + e.Message); | ||
5930 | } | ||
5931 | } | ||
5932 | |||
5933 | public LSL_String llBase64ToString(string str) | ||
5934 | { | ||
5935 | m_host.AddScriptLPS(1); | ||
5936 | UTF8Encoding encoder = new UTF8Encoding(); | ||
5937 | Decoder utf8Decode = encoder.GetDecoder(); | ||
5938 | try | ||
5939 | { | ||
5940 | byte[] todecode_byte = Convert.FromBase64String(str); | ||
5941 | int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length); | ||
5942 | char[] decoded_char = new char[charCount]; | ||
5943 | utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0); | ||
5944 | string result = new String(decoded_char); | ||
5945 | return result; | ||
5946 | } | ||
5947 | catch (Exception e) | ||
5948 | { | ||
5949 | throw new Exception("Error in base64Decode" + e.Message); | ||
5950 | } | ||
5951 | } | ||
5952 | |||
5953 | public void llXorBase64Strings() | ||
5954 | { | ||
5955 | m_host.AddScriptLPS(1); | ||
5956 | Deprecated("llXorBase64Strings"); | ||
5957 | // ScriptSleep(300); | ||
5958 | } | ||
5959 | |||
5960 | public void llRemoteDataSetRegion() | ||
5961 | { | ||
5962 | m_host.AddScriptLPS(1); | ||
5963 | NotImplemented("llRemoteDataSetRegion"); | ||
5964 | } | ||
5965 | |||
5966 | public LSL_Float llLog10(double val) | ||
5967 | { | ||
5968 | m_host.AddScriptLPS(1); | ||
5969 | return (double)Math.Log10(val); | ||
5970 | } | ||
5971 | |||
5972 | public LSL_Float llLog(double val) | ||
5973 | { | ||
5974 | m_host.AddScriptLPS(1); | ||
5975 | return (double)Math.Log(val); | ||
5976 | } | ||
5977 | |||
5978 | public LSL_List llGetAnimationList( string id ) | ||
5979 | { | ||
5980 | m_host.AddScriptLPS(1); | ||
5981 | |||
5982 | LSL_List l = new LSL_List(); | ||
5983 | ScenePresence av = World.GetScenePresence(id); | ||
5984 | if (av == null) | ||
5985 | return l; | ||
5986 | UUID[] anims; | ||
5987 | anims = av.GetAnimationArray(); | ||
5988 | foreach (UUID foo in anims) | ||
5989 | l.Add(foo.ToString()); | ||
5990 | return l; | ||
5991 | } | ||
5992 | |||
5993 | public void llSetParcelMusicURL(string url) | ||
5994 | { | ||
5995 | m_host.AddScriptLPS(1); | ||
5996 | UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
5997 | if (landowner == UUID.Zero) | ||
5998 | { | ||
5999 | return; | ||
6000 | } | ||
6001 | if (landowner != m_host.ObjectOwner) | ||
6002 | { | ||
6003 | return; | ||
6004 | } | ||
6005 | World.SetLandMusicURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url); | ||
6006 | // ScriptSleep(2000); | ||
6007 | } | ||
6008 | |||
6009 | public LSL_Vector llGetRootPosition() | ||
6010 | { | ||
6011 | m_host.AddScriptLPS(1); | ||
6012 | return new LSL_Vector(m_host.ParentGroup.AbsolutePosition.X, m_host.ParentGroup.AbsolutePosition.Y, m_host.ParentGroup.AbsolutePosition.Z); | ||
6013 | } | ||
6014 | |||
6015 | public LSL_Rotation llGetRootRotation() | ||
6016 | { | ||
6017 | m_host.AddScriptLPS(1); | ||
6018 | return new LSL_Rotation(m_host.ParentGroup.GroupRotation.X, m_host.ParentGroup.GroupRotation.Y, m_host.ParentGroup.GroupRotation.Z, m_host.ParentGroup.GroupRotation.W); | ||
6019 | } | ||
6020 | |||
6021 | public LSL_String llGetObjectDesc() | ||
6022 | { | ||
6023 | return m_host.Description!=null?m_host.Description:String.Empty; | ||
6024 | } | ||
6025 | |||
6026 | public void llSetObjectDesc(string desc) | ||
6027 | { | ||
6028 | m_host.AddScriptLPS(1); | ||
6029 | m_host.Description = desc!=null?desc:String.Empty; | ||
6030 | } | ||
6031 | |||
6032 | public LSL_String llGetCreator() | ||
6033 | { | ||
6034 | m_host.AddScriptLPS(1); | ||
6035 | return m_host.ObjectCreator.ToString(); | ||
6036 | } | ||
6037 | |||
6038 | public LSL_String llGetTimestamp() | ||
6039 | { | ||
6040 | m_host.AddScriptLPS(1); | ||
6041 | return DateTime.Now.ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ss.fffffffZ"); | ||
6042 | } | ||
6043 | |||
6044 | public void llSetLinkAlpha(int linknumber, double alpha, int face) | ||
6045 | { | ||
6046 | m_host.AddScriptLPS(1); | ||
6047 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); | ||
6048 | if (linknumber > -1) | ||
6049 | { | ||
6050 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
6051 | Color4 texcolor; | ||
6052 | if (face >= 0 && face < GetNumberOfSides(m_host)) | ||
6053 | { | ||
6054 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
6055 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6056 | tex.FaceTextures[face].RGBA = texcolor; | ||
6057 | part.UpdateTexture(tex); | ||
6058 | return; | ||
6059 | } | ||
6060 | else if (face == ScriptBaseClass.ALL_SIDES) | ||
6061 | { | ||
6062 | texcolor = tex.DefaultTexture.RGBA; | ||
6063 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6064 | tex.DefaultTexture.RGBA = texcolor; | ||
6065 | for (uint i = 0; i < GetNumberOfSides(m_host); i++) | ||
6066 | { | ||
6067 | if (tex.FaceTextures[i] != null) | ||
6068 | { | ||
6069 | texcolor = tex.FaceTextures[i].RGBA; | ||
6070 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6071 | tex.FaceTextures[i].RGBA = texcolor; | ||
6072 | } | ||
6073 | } | ||
6074 | texcolor = tex.DefaultTexture.RGBA; | ||
6075 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6076 | tex.DefaultTexture.RGBA = texcolor; | ||
6077 | part.UpdateTexture(tex); | ||
6078 | return; | ||
6079 | } | ||
6080 | return; | ||
6081 | } | ||
6082 | else if (linknumber == -1) | ||
6083 | { | ||
6084 | int num = m_host.ParentGroup.PrimCount; | ||
6085 | for (int w = 0; w < num; w++) | ||
6086 | { | ||
6087 | linknumber = w; | ||
6088 | part = m_host.ParentGroup.GetLinkNumPart(linknumber); | ||
6089 | Primitive.TextureEntry tex = part.Shape.Textures; | ||
6090 | Color4 texcolor; | ||
6091 | if (face > -1) | ||
6092 | { | ||
6093 | texcolor = tex.CreateFace((uint)face).RGBA; | ||
6094 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6095 | tex.FaceTextures[face].RGBA = texcolor; | ||
6096 | part.UpdateTexture(tex); | ||
6097 | } | ||
6098 | else if (face == -1) | ||
6099 | { | ||
6100 | texcolor = tex.DefaultTexture.RGBA; | ||
6101 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6102 | tex.DefaultTexture.RGBA = texcolor; | ||
6103 | for (uint i = 0; i < 32; i++) | ||
6104 | { | ||
6105 | if (tex.FaceTextures[i] != null) | ||
6106 | { | ||
6107 | texcolor = tex.FaceTextures[i].RGBA; | ||
6108 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6109 | tex.FaceTextures[i].RGBA = texcolor; | ||
6110 | } | ||
6111 | } | ||
6112 | texcolor = tex.DefaultTexture.RGBA; | ||
6113 | texcolor.A = Util.Clip((float)alpha, 0.0f, 1.0f); | ||
6114 | tex.DefaultTexture.RGBA = texcolor; | ||
6115 | part.UpdateTexture(tex); | ||
6116 | } | ||
6117 | } | ||
6118 | return; | ||
6119 | } | ||
6120 | } | ||
6121 | |||
6122 | public LSL_Integer llGetNumberOfPrims() | ||
6123 | { | ||
6124 | m_host.AddScriptLPS(1); | ||
6125 | return m_host.ParentGroup.PrimCount; | ||
6126 | } | ||
6127 | |||
6128 | public LSL_List llGetBoundingBox(string obj) | ||
6129 | { | ||
6130 | m_host.AddScriptLPS(1); | ||
6131 | NotImplemented("llGetBoundingBox"); | ||
6132 | return new LSL_List(); | ||
6133 | } | ||
6134 | |||
6135 | public LSL_Vector llGetGeometricCenter() | ||
6136 | { | ||
6137 | return new LSL_Vector(m_host.GetGeometricCenter().X, m_host.GetGeometricCenter().Y, m_host.GetGeometricCenter().Z); | ||
6138 | } | ||
6139 | |||
6140 | public LSL_List llGetPrimitiveParams(LSL_List rules) | ||
6141 | { | ||
6142 | m_host.AddScriptLPS(1); | ||
6143 | |||
6144 | LSL_List res = new LSL_List(); | ||
6145 | int idx=0; | ||
6146 | while (idx < rules.Length) | ||
6147 | { | ||
6148 | int code=(int)rules.GetLSLIntegerItem(idx++); | ||
6149 | int remain=rules.Length-idx; | ||
6150 | |||
6151 | switch (code) | ||
6152 | { | ||
6153 | case (int)ScriptBaseClass.PRIM_MATERIAL: | ||
6154 | res.Add(new LSL_Integer(m_host.Material)); | ||
6155 | break; | ||
6156 | |||
6157 | case (int)ScriptBaseClass.PRIM_PHYSICS: | ||
6158 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Physics) != 0) | ||
6159 | res.Add(new LSL_Integer(1)); | ||
6160 | else | ||
6161 | res.Add(new LSL_Integer(0)); | ||
6162 | break; | ||
6163 | |||
6164 | case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: | ||
6165 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.TemporaryOnRez) != 0) | ||
6166 | res.Add(new LSL_Integer(1)); | ||
6167 | else | ||
6168 | res.Add(new LSL_Integer(0)); | ||
6169 | break; | ||
6170 | |||
6171 | case (int)ScriptBaseClass.PRIM_PHANTOM: | ||
6172 | if ((m_host.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0) | ||
6173 | res.Add(new LSL_Integer(1)); | ||
6174 | else | ||
6175 | res.Add(new LSL_Integer(0)); | ||
6176 | break; | ||
6177 | |||
6178 | case (int)ScriptBaseClass.PRIM_POSITION: | ||
6179 | res.Add(new LSL_Vector(m_host.AbsolutePosition.X, | ||
6180 | m_host.AbsolutePosition.Y, | ||
6181 | m_host.AbsolutePosition.Z)); | ||
6182 | break; | ||
6183 | |||
6184 | case (int)ScriptBaseClass.PRIM_SIZE: | ||
6185 | res.Add(new LSL_Vector(m_host.Scale.X, | ||
6186 | m_host.Scale.Y, | ||
6187 | m_host.Scale.Z)); | ||
6188 | break; | ||
6189 | |||
6190 | case (int)ScriptBaseClass.PRIM_ROTATION: | ||
6191 | res.Add(new LSL_Rotation(m_host.RotationOffset.X, | ||
6192 | m_host.RotationOffset.Y, | ||
6193 | m_host.RotationOffset.Z, | ||
6194 | m_host.RotationOffset.W)); | ||
6195 | break; | ||
6196 | |||
6197 | case (int)ScriptBaseClass.PRIM_TYPE: | ||
6198 | // implementing box | ||
6199 | PrimitiveBaseShape Shape = m_host.Shape; | ||
6200 | int primType = getScriptPrimType(m_host.Shape); | ||
6201 | res.Add(new LSL_Integer(primType)); | ||
6202 | switch (primType) | ||
6203 | { | ||
6204 | case ScriptBaseClass.PRIM_TYPE_BOX: | ||
6205 | case ScriptBaseClass.PRIM_TYPE_CYLINDER: | ||
6206 | case ScriptBaseClass.PRIM_TYPE_PRISM: | ||
6207 | res.Add(new LSL_Integer(Shape.ProfileCurve)); | ||
6208 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | ||
6209 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | ||
6210 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | ||
6211 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); | ||
6212 | res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0)); | ||
6213 | break; | ||
6214 | |||
6215 | case ScriptBaseClass.PRIM_TYPE_SPHERE: | ||
6216 | res.Add(new LSL_Integer(Shape.ProfileCurve)); | ||
6217 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); | ||
6218 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | ||
6219 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | ||
6220 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | ||
6221 | break; | ||
6222 | |||
6223 | case ScriptBaseClass.PRIM_TYPE_SCULPT: | ||
6224 | res.Add(Shape.SculptTexture.ToString()); | ||
6225 | res.Add(new LSL_Integer(Shape.SculptType)); | ||
6226 | break; | ||
6227 | |||
6228 | case ScriptBaseClass.PRIM_TYPE_RING: | ||
6229 | case ScriptBaseClass.PRIM_TYPE_TUBE: | ||
6230 | case ScriptBaseClass.PRIM_TYPE_TORUS: | ||
6231 | // holeshape | ||
6232 | res.Add(new LSL_Integer(Shape.ProfileCurve)); | ||
6233 | |||
6234 | // cut | ||
6235 | res.Add(new LSL_Vector(Shape.PathBegin / 50000.0, 1 - Shape.PathEnd / 50000.0, 0)); | ||
6236 | |||
6237 | // hollow | ||
6238 | res.Add(new LSL_Float(Shape.ProfileHollow / 50000.0)); | ||
6239 | |||
6240 | // twist | ||
6241 | res.Add(new LSL_Vector(Shape.PathTwistBegin / 100.0, Shape.PathTwist / 100.0, 0)); | ||
6242 | |||
6243 | // vector holesize | ||
6244 | res.Add(new LSL_Vector(1 - (Shape.PathScaleX / 100.0 - 1), 1 - (Shape.PathScaleY / 100.0 - 1), 0)); | ||
6245 | |||
6246 | // vector topshear | ||
6247 | res.Add(new LSL_Vector(Shape.PathShearX / 100.0, Shape.PathShearY / 100.0, 0)); | ||
6248 | |||
6249 | // vector profilecut | ||
6250 | res.Add(new LSL_Vector(Shape.ProfileBegin / 50000.0, 1 - Shape.ProfileEnd / 50000.0, 0)); | ||
6251 | |||
6252 | |||
6253 | // vector tapera | ||
6254 | res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); | ||
6255 | |||
6256 | // float revolutions, | ||
6257 | res.Add(new LSL_Float(Shape.PathRevolutions / 50.0)); // needs fixing :( | ||
6258 | |||
6259 | // float radiusoffset, | ||
6260 | res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); | ||
6261 | |||
6262 | // float skew | ||
6263 | res.Add(new LSL_Float(Shape.PathSkew / 100.0)); | ||
6264 | break; | ||
6265 | |||
6266 | } | ||
6267 | break; | ||
6268 | |||
6269 | case (int)ScriptBaseClass.PRIM_TEXTURE: | ||
6270 | if (remain < 1) | ||
6271 | return res; | ||
6272 | |||
6273 | int face = (int)rules.GetLSLIntegerItem(idx++); | ||
6274 | Primitive.TextureEntry tex = m_host.Shape.Textures; | ||
6275 | if (face == ScriptBaseClass.ALL_SIDES) | ||
6276 | { | ||
6277 | for (face = 0 ; face < GetNumberOfSides(m_host) ; face++) | ||
6278 | { | ||
6279 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | ||
6280 | |||
6281 | res.Add(new LSL_String(texface.TextureID.ToString())); | ||
6282 | res.Add(new LSL_Vector(texface.RepeatU, | ||
6283 | texface.RepeatV, | ||
6284 | 0)); | ||
6285 | res.Add(new LSL_Vector(texface.OffsetU, | ||
6286 | texface.OffsetV, | ||
6287 | 0)); | ||
6288 | res.Add(new LSL_Float(texface.Rotation)); | ||
6289 | } | ||
6290 | } | ||
6291 | else | ||
6292 | { | ||
6293 | if (face >= 0 && face < GetNumberOfSides(m_host)) | ||
6294 | { | ||
6295 | Primitive.TextureEntryFace texface = tex.GetFace((uint)face); | ||
6296 | |||
6297 | res.Add(new LSL_String(texface.TextureID.ToString())); | ||
6298 | res.Add(new LSL_Vector(texface.RepeatU, | ||
6299 | texface.RepeatV, | ||
6300 | 0)); | ||
6301 | res.Add(new LSL_Vector(texface.OffsetU, | ||
6302 | texface.OffsetV, | ||
6303 | 0)); | ||
6304 | res.Add(new LSL_Float(texface.Rotation)); | ||
6305 | } | ||
6306 | } | ||
6307 | break; | ||
6308 | |||
6309 | case (int)ScriptBaseClass.PRIM_COLOR: | ||
6310 | if (remain < 1) | ||
6311 | return res; | ||
6312 | |||
6313 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6314 | |||
6315 | tex = m_host.Shape.Textures; | ||
6316 | Color4 texcolor; | ||
6317 | if (face == ScriptBaseClass.ALL_SIDES) | ||
6318 | { | ||
6319 | for (face = 0 ; face < GetNumberOfSides(m_host) ; face++) | ||
6320 | { | ||
6321 | texcolor = tex.GetFace((uint)face).RGBA; | ||
6322 | res.Add(new LSL_Vector(texcolor.R, | ||
6323 | texcolor.G, | ||
6324 | texcolor.B)); | ||
6325 | res.Add(new LSL_Float(texcolor.A)); | ||
6326 | } | ||
6327 | } | ||
6328 | else | ||
6329 | { | ||
6330 | texcolor = tex.GetFace((uint)face).RGBA; | ||
6331 | res.Add(new LSL_Vector(texcolor.R, | ||
6332 | texcolor.G, | ||
6333 | texcolor.B)); | ||
6334 | res.Add(new LSL_Float(texcolor.A)); | ||
6335 | } | ||
6336 | break; | ||
6337 | |||
6338 | case (int)ScriptBaseClass.PRIM_BUMP_SHINY: | ||
6339 | // TODO-------------- | ||
6340 | if (remain < 1) | ||
6341 | return res; | ||
6342 | |||
6343 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6344 | |||
6345 | res.Add(new LSL_Integer(0)); | ||
6346 | res.Add(new LSL_Integer(0)); | ||
6347 | break; | ||
6348 | |||
6349 | case (int)ScriptBaseClass.PRIM_FULLBRIGHT: | ||
6350 | // TODO-------------- | ||
6351 | if (remain < 1) | ||
6352 | return res; | ||
6353 | |||
6354 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6355 | |||
6356 | res.Add(new LSL_Integer(0)); | ||
6357 | break; | ||
6358 | |||
6359 | case (int)ScriptBaseClass.PRIM_FLEXIBLE: | ||
6360 | PrimitiveBaseShape shape = m_host.Shape; | ||
6361 | |||
6362 | if (shape.FlexiEntry) | ||
6363 | res.Add(new LSL_Integer(1)); // active | ||
6364 | else | ||
6365 | res.Add(new LSL_Integer(0)); | ||
6366 | res.Add(new LSL_Integer(shape.FlexiSoftness));// softness | ||
6367 | res.Add(new LSL_Float(shape.FlexiGravity)); // gravity | ||
6368 | res.Add(new LSL_Float(shape.FlexiDrag)); // friction | ||
6369 | res.Add(new LSL_Float(shape.FlexiWind)); // wind | ||
6370 | res.Add(new LSL_Float(shape.FlexiTension)); // tension | ||
6371 | res.Add(new LSL_Vector(shape.FlexiForceX, // force | ||
6372 | shape.FlexiForceY, | ||
6373 | shape.FlexiForceZ)); | ||
6374 | break; | ||
6375 | |||
6376 | case (int)ScriptBaseClass.PRIM_TEXGEN: | ||
6377 | // TODO-------------- | ||
6378 | // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) | ||
6379 | if (remain < 1) | ||
6380 | return res; | ||
6381 | |||
6382 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6383 | |||
6384 | res.Add(new LSL_Integer(0)); | ||
6385 | break; | ||
6386 | |||
6387 | case (int)ScriptBaseClass.PRIM_POINT_LIGHT: | ||
6388 | shape = m_host.Shape; | ||
6389 | |||
6390 | if (shape.LightEntry) | ||
6391 | res.Add(new LSL_Integer(1)); // active | ||
6392 | else | ||
6393 | res.Add(new LSL_Integer(0)); | ||
6394 | res.Add(new LSL_Vector(shape.LightColorR, // color | ||
6395 | shape.LightColorG, | ||
6396 | shape.LightColorB)); | ||
6397 | res.Add(new LSL_Float(shape.LightIntensity)); // intensity | ||
6398 | res.Add(new LSL_Float(shape.LightRadius)); // radius | ||
6399 | res.Add(new LSL_Float(shape.LightFalloff)); // falloff | ||
6400 | break; | ||
6401 | |||
6402 | case (int)ScriptBaseClass.PRIM_GLOW: | ||
6403 | // TODO-------------- | ||
6404 | if (remain < 1) | ||
6405 | return res; | ||
6406 | |||
6407 | face=(int)rules.GetLSLIntegerItem(idx++); | ||
6408 | |||
6409 | res.Add(new LSL_Float(0)); | ||
6410 | break; | ||
6411 | } | ||
6412 | } | ||
6413 | return res; | ||
6414 | } | ||
6415 | |||
6416 | // <remarks> | ||
6417 | // <para> | ||
6418 | // The .NET definition of base 64 is: | ||
6419 | // <list> | ||
6420 | // <item> | ||
6421 | // Significant: A-Z a-z 0-9 + - | ||
6422 | // </item> | ||
6423 | // <item> | ||
6424 | // Whitespace: \t \n \r ' ' | ||
6425 | // </item> | ||
6426 | // <item> | ||
6427 | // Valueless: = | ||
6428 | // </item> | ||
6429 | // <item> | ||
6430 | // End-of-string: \0 or '==' | ||
6431 | // </item> | ||
6432 | // </list> | ||
6433 | // </para> | ||
6434 | // <para> | ||
6435 | // Each point in a base-64 string represents | ||
6436 | // a 6 bit value. A 32-bit integer can be | ||
6437 | // represented using 6 characters (with some | ||
6438 | // redundancy). | ||
6439 | // </para> | ||
6440 | // <para> | ||
6441 | // LSL requires a base64 string to be 8 | ||
6442 | // characters in length. LSL also uses '/' | ||
6443 | // rather than '-' (MIME compliant). | ||
6444 | // </para> | ||
6445 | // <para> | ||
6446 | // RFC 1341 used as a reference (as specified | ||
6447 | // by the SecondLife Wiki). | ||
6448 | // </para> | ||
6449 | // <para> | ||
6450 | // SL do not record any kind of exception for | ||
6451 | // these functions, so the string to integer | ||
6452 | // conversion returns '0' if an invalid | ||
6453 | // character is encountered during conversion. | ||
6454 | // </para> | ||
6455 | // <para> | ||
6456 | // References | ||
6457 | // <list> | ||
6458 | // <item> | ||
6459 | // http://lslwiki.net/lslwiki/wakka.php?wakka=Base64 | ||
6460 | // </item> | ||
6461 | // <item> | ||
6462 | // </item> | ||
6463 | // </list> | ||
6464 | // </para> | ||
6465 | // </remarks> | ||
6466 | |||
6467 | // <summary> | ||
6468 | // Table for converting 6-bit integers into | ||
6469 | // base-64 characters | ||
6470 | // </summary> | ||
6471 | |||
6472 | private static readonly char[] i2ctable = | ||
6473 | { | ||
6474 | 'A','B','C','D','E','F','G','H', | ||
6475 | 'I','J','K','L','M','N','O','P', | ||
6476 | 'Q','R','S','T','U','V','W','X', | ||
6477 | 'Y','Z', | ||
6478 | 'a','b','c','d','e','f','g','h', | ||
6479 | 'i','j','k','l','m','n','o','p', | ||
6480 | 'q','r','s','t','u','v','w','x', | ||
6481 | 'y','z', | ||
6482 | '0','1','2','3','4','5','6','7', | ||
6483 | '8','9', | ||
6484 | '+','/' | ||
6485 | }; | ||
6486 | |||
6487 | // <summary> | ||
6488 | // Table for converting base-64 characters | ||
6489 | // into 6-bit integers. | ||
6490 | // </summary> | ||
6491 | |||
6492 | private static readonly int[] c2itable = | ||
6493 | { | ||
6494 | -1,-1,-1,-1,-1,-1,-1,-1, // 0x | ||
6495 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6496 | -1,-1,-1,-1,-1,-1,-1,-1, // 1x | ||
6497 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6498 | -1,-1,-1,-1,-1,-1,-1,-1, // 2x | ||
6499 | -1,-1,-1,63,-1,-1,-1,64, | ||
6500 | 53,54,55,56,57,58,59,60, // 3x | ||
6501 | 61,62,-1,-1,-1,0,-1,-1, | ||
6502 | -1,1,2,3,4,5,6,7, // 4x | ||
6503 | 8,9,10,11,12,13,14,15, | ||
6504 | 16,17,18,19,20,21,22,23, // 5x | ||
6505 | 24,25,26,-1,-1,-1,-1,-1, | ||
6506 | -1,27,28,29,30,31,32,33, // 6x | ||
6507 | 34,35,36,37,38,39,40,41, | ||
6508 | 42,43,44,45,46,47,48,49, // 7x | ||
6509 | 50,51,52,-1,-1,-1,-1,-1, | ||
6510 | -1,-1,-1,-1,-1,-1,-1,-1, // 8x | ||
6511 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6512 | -1,-1,-1,-1,-1,-1,-1,-1, // 9x | ||
6513 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6514 | -1,-1,-1,-1,-1,-1,-1,-1, // Ax | ||
6515 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6516 | -1,-1,-1,-1,-1,-1,-1,-1, // Bx | ||
6517 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6518 | -1,-1,-1,-1,-1,-1,-1,-1, // Cx | ||
6519 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6520 | -1,-1,-1,-1,-1,-1,-1,-1, // Dx | ||
6521 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6522 | -1,-1,-1,-1,-1,-1,-1,-1, // Ex | ||
6523 | -1,-1,-1,-1,-1,-1,-1,-1, | ||
6524 | -1,-1,-1,-1,-1,-1,-1,-1, // Fx | ||
6525 | -1,-1,-1,-1,-1,-1,-1,-1 | ||
6526 | }; | ||
6527 | |||
6528 | // <summary> | ||
6529 | // Converts a 32-bit integer into a Base64 | ||
6530 | // character string. Base64 character strings | ||
6531 | // are always 8 characters long. All iinteger | ||
6532 | // values are acceptable. | ||
6533 | // </summary> | ||
6534 | // <param name="number"> | ||
6535 | // 32-bit integer to be converted. | ||
6536 | // </param> | ||
6537 | // <returns> | ||
6538 | // 8 character string. The 1st six characters | ||
6539 | // contain the encoded number, the last two | ||
6540 | // characters are padded with "=". | ||
6541 | // </returns> | ||
6542 | |||
6543 | public LSL_String llIntegerToBase64(int number) | ||
6544 | { | ||
6545 | // uninitialized string | ||
6546 | |||
6547 | char[] imdt = new char[8]; | ||
6548 | |||
6549 | m_host.AddScriptLPS(1); | ||
6550 | |||
6551 | // Manually unroll the loop | ||
6552 | |||
6553 | imdt[7] = '='; | ||
6554 | imdt[6] = '='; | ||
6555 | imdt[5] = i2ctable[number<<4 & 0x3F]; | ||
6556 | imdt[4] = i2ctable[number>>2 & 0x3F]; | ||
6557 | imdt[3] = i2ctable[number>>8 & 0x3F]; | ||
6558 | imdt[2] = i2ctable[number>>14 & 0x3F]; | ||
6559 | imdt[1] = i2ctable[number>>20 & 0x3F]; | ||
6560 | imdt[0] = i2ctable[number>>26 & 0x3F]; | ||
6561 | |||
6562 | return new string(imdt); | ||
6563 | } | ||
6564 | |||
6565 | // <summary> | ||
6566 | // Converts an eight character base-64 string | ||
6567 | // into a 32-bit integer. | ||
6568 | // </summary> | ||
6569 | // <param name="str"> | ||
6570 | // 8 characters string to be converted. Other | ||
6571 | // length strings return zero. | ||
6572 | // </param> | ||
6573 | // <returns> | ||
6574 | // Returns an integer representing the | ||
6575 | // encoded value providedint he 1st 6 | ||
6576 | // characters of the string. | ||
6577 | // </returns> | ||
6578 | // <remarks> | ||
6579 | // This is coded to behave like LSL's | ||
6580 | // implementation (I think), based upon the | ||
6581 | // information available at the Wiki. | ||
6582 | // If more than 8 characters are supplied, | ||
6583 | // zero is returned. | ||
6584 | // If a NULL string is supplied, zero will | ||
6585 | // be returned. | ||
6586 | // If fewer than 6 characters are supplied, then | ||
6587 | // the answer will reflect a partial | ||
6588 | // accumulation. | ||
6589 | // <para> | ||
6590 | // The 6-bit segments are | ||
6591 | // extracted left-to-right in big-endian mode, | ||
6592 | // which means that segment 6 only contains the | ||
6593 | // two low-order bits of the 32 bit integer as | ||
6594 | // its high order 2 bits. A short string therefore | ||
6595 | // means loss of low-order information. E.g. | ||
6596 | // | ||
6597 | // |<---------------------- 32-bit integer ----------------------->|<-Pad->| | ||
6598 | // |<--Byte 0----->|<--Byte 1----->|<--Byte 2----->|<--Byte 3----->|<-Pad->| | ||
6599 | // |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| | ||
6600 | // |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| | ||
6601 | // | str[0] | str[1] | str[2] | str[3] | str[4] | str[6] | | ||
6602 | // | ||
6603 | // </para> | ||
6604 | // </remarks> | ||
6605 | |||
6606 | public LSL_Integer llBase64ToInteger(string str) | ||
6607 | { | ||
6608 | int number = 0; | ||
6609 | int digit; | ||
6610 | |||
6611 | m_host.AddScriptLPS(1); | ||
6612 | |||
6613 | // Require a well-fromed base64 string | ||
6614 | |||
6615 | if (str.Length > 8) | ||
6616 | return 0; | ||
6617 | |||
6618 | // The loop is unrolled in the interests | ||
6619 | // of performance and simple necessity. | ||
6620 | // | ||
6621 | // MUST find 6 digits to be well formed | ||
6622 | // -1 == invalid | ||
6623 | // 0 == padding | ||
6624 | |||
6625 | if ((digit=c2itable[str[0]])<=0) | ||
6626 | { | ||
6627 | return digit<0?(int)0:number; | ||
6628 | } | ||
6629 | number += --digit<<26; | ||
6630 | |||
6631 | if ((digit=c2itable[str[1]])<=0) | ||
6632 | { | ||
6633 | return digit<0?(int)0:number; | ||
6634 | } | ||
6635 | number += --digit<<20; | ||
6636 | |||
6637 | if ((digit=c2itable[str[2]])<=0) | ||
6638 | { | ||
6639 | return digit<0?(int)0:number; | ||
6640 | } | ||
6641 | number += --digit<<14; | ||
6642 | |||
6643 | if ((digit=c2itable[str[3]])<=0) | ||
6644 | { | ||
6645 | return digit<0?(int)0:number; | ||
6646 | } | ||
6647 | number += --digit<<8; | ||
6648 | |||
6649 | if ((digit=c2itable[str[4]])<=0) | ||
6650 | { | ||
6651 | return digit<0?(int)0:number; | ||
6652 | } | ||
6653 | number += --digit<<2; | ||
6654 | |||
6655 | if ((digit=c2itable[str[5]])<=0) | ||
6656 | { | ||
6657 | return digit<0?(int)0:number; | ||
6658 | } | ||
6659 | number += --digit>>4; | ||
6660 | |||
6661 | // ignore trailing padding | ||
6662 | |||
6663 | return number; | ||
6664 | } | ||
6665 | |||
6666 | public LSL_Float llGetGMTclock() | ||
6667 | { | ||
6668 | m_host.AddScriptLPS(1); | ||
6669 | return DateTime.UtcNow.TimeOfDay.TotalSeconds; | ||
6670 | } | ||
6671 | |||
6672 | public LSL_String llGetSimulatorHostname() | ||
6673 | { | ||
6674 | m_host.AddScriptLPS(1); | ||
6675 | return System.Environment.MachineName; | ||
6676 | } | ||
6677 | |||
6678 | public void llSetLocalRot(LSL_Rotation rot) | ||
6679 | { | ||
6680 | m_host.AddScriptLPS(1); | ||
6681 | m_host.RotationOffset = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); | ||
6682 | // ScriptSleep(200); | ||
6683 | } | ||
6684 | |||
6685 | // <summary> | ||
6686 | // Scan the string supplied in 'src' and | ||
6687 | // tokenize it based upon two sets of | ||
6688 | // tokenizers provided in two lists, | ||
6689 | // separators and spacers. | ||
6690 | // </summary> | ||
6691 | // | ||
6692 | // <remarks> | ||
6693 | // Separators demarcate tokens and are | ||
6694 | // elided as they are encountered. Spacers | ||
6695 | // also demarcate tokens, but are themselves | ||
6696 | // retained as tokens. | ||
6697 | // | ||
6698 | // Both separators and spacers may be arbitrarily | ||
6699 | // long strings. i.e. ":::". | ||
6700 | // | ||
6701 | // The function returns an ordered list | ||
6702 | // representing the tokens found in the supplied | ||
6703 | // sources string. If two successive tokenizers | ||
6704 | // are encountered, then a NULL entry is added | ||
6705 | // to the list. | ||
6706 | // | ||
6707 | // It is a precondition that the source and | ||
6708 | // toekizer lisst are non-null. If they are null, | ||
6709 | // then a null pointer exception will be thrown | ||
6710 | // while their lengths are being determined. | ||
6711 | // | ||
6712 | // A small amount of working memoryis required | ||
6713 | // of approximately 8*#tokenizers. | ||
6714 | // | ||
6715 | // There are many ways in which this function | ||
6716 | // can be implemented, this implementation is | ||
6717 | // fairly naive and assumes that when the | ||
6718 | // function is invooked with a short source | ||
6719 | // string and/or short lists of tokenizers, then | ||
6720 | // performance will not be an issue. | ||
6721 | // | ||
6722 | // In order to minimize the perofrmance | ||
6723 | // effects of long strings, or large numbers | ||
6724 | // of tokeizers, the function skips as far as | ||
6725 | // possible whenever a toekenizer is found, | ||
6726 | // and eliminates redundant tokenizers as soon | ||
6727 | // as is possible. | ||
6728 | // | ||
6729 | // The implementation tries to avoid any copying | ||
6730 | // of arrays or other objects. | ||
6731 | // </remarks> | ||
6732 | |||
6733 | public LSL_List llParseStringKeepNulls(string src, LSL_List separators, LSL_List spacers) | ||
6734 | { | ||
6735 | int beginning = 0; | ||
6736 | int srclen = src.Length; | ||
6737 | int seplen = separators.Length; | ||
6738 | object[] separray = separators.Data; | ||
6739 | int spclen = spacers.Length; | ||
6740 | object[] spcarray = spacers.Data; | ||
6741 | int mlen = seplen+spclen; | ||
6742 | |||
6743 | int[] offset = new int[mlen+1]; | ||
6744 | bool[] active = new bool[mlen]; | ||
6745 | |||
6746 | int best; | ||
6747 | int j; | ||
6748 | |||
6749 | // Initial capacity reduces resize cost | ||
6750 | |||
6751 | LSL_List tokens = new LSL_List(); | ||
6752 | |||
6753 | m_host.AddScriptLPS(1); | ||
6754 | |||
6755 | // All entries are initially valid | ||
6756 | |||
6757 | for (int i = 0; i < mlen; i++) | ||
6758 | active[i] = true; | ||
6759 | |||
6760 | offset[mlen] = srclen; | ||
6761 | |||
6762 | while (beginning < srclen) | ||
6763 | { | ||
6764 | |||
6765 | best = mlen; // as bad as it gets | ||
6766 | |||
6767 | // Scan for separators | ||
6768 | |||
6769 | for (j = 0; j < seplen; j++) | ||
6770 | { | ||
6771 | if (active[j]) | ||
6772 | { | ||
6773 | // scan all of the markers | ||
6774 | if ((offset[j] = src.IndexOf(separray[j].ToString(),beginning)) == -1) | ||
6775 | { | ||
6776 | // not present at all | ||
6777 | active[j] = false; | ||
6778 | } | ||
6779 | else | ||
6780 | { | ||
6781 | // present and correct | ||
6782 | if (offset[j] < offset[best]) | ||
6783 | { | ||
6784 | // closest so far | ||
6785 | best = j; | ||
6786 | if (offset[best] == beginning) | ||
6787 | break; | ||
6788 | } | ||
6789 | } | ||
6790 | } | ||
6791 | } | ||
6792 | |||
6793 | // Scan for spacers | ||
6794 | |||
6795 | if (offset[best] != beginning) | ||
6796 | { | ||
6797 | for (j = seplen; (j < mlen) && (offset[best] > beginning); j++) | ||
6798 | { | ||
6799 | if (active[j]) | ||
6800 | { | ||
6801 | // scan all of the markers | ||
6802 | if ((offset[j] = src.IndexOf(spcarray[j-seplen].ToString(), beginning)) == -1) | ||
6803 | { | ||
6804 | // not present at all | ||
6805 | active[j] = false; | ||
6806 | } | ||
6807 | else | ||
6808 | { | ||
6809 | // present and correct | ||
6810 | if (offset[j] < offset[best]) | ||
6811 | { | ||
6812 | // closest so far | ||
6813 | best = j; | ||
6814 | } | ||
6815 | } | ||
6816 | } | ||
6817 | } | ||
6818 | } | ||
6819 | |||
6820 | // This is the normal exit from the scanning loop | ||
6821 | |||
6822 | if (best == mlen) | ||
6823 | { | ||
6824 | // no markers were found on this pass | ||
6825 | // so we're pretty much done | ||
6826 | tokens.Add(src.Substring(beginning, srclen - beginning)); | ||
6827 | break; | ||
6828 | } | ||
6829 | |||
6830 | // Otherwise we just add the newly delimited token | ||
6831 | // and recalculate where the search should continue. | ||
6832 | |||
6833 | tokens.Add(src.Substring(beginning,offset[best]-beginning)); | ||
6834 | |||
6835 | if (best < seplen) | ||
6836 | { | ||
6837 | beginning = offset[best] + (separray[best].ToString()).Length; | ||
6838 | } | ||
6839 | else | ||
6840 | { | ||
6841 | beginning = offset[best] + (spcarray[best - seplen].ToString()).Length; | ||
6842 | tokens.Add(spcarray[best - seplen]); | ||
6843 | } | ||
6844 | } | ||
6845 | |||
6846 | // This an awkward an not very intuitive boundary case. If the | ||
6847 | // last substring is a tokenizer, then there is an implied trailing | ||
6848 | // null list entry. Hopefully the single comparison will not be too | ||
6849 | // arduous. Alternatively the 'break' could be replced with a return | ||
6850 | // but that's shabby programming. | ||
6851 | |||
6852 | if (beginning == srclen) | ||
6853 | { | ||
6854 | if (srclen != 0) | ||
6855 | tokens.Add(""); | ||
6856 | } | ||
6857 | |||
6858 | return tokens; | ||
6859 | } | ||
6860 | |||
6861 | public LSL_Integer llGetObjectPermMask(int mask) | ||
6862 | { | ||
6863 | m_host.AddScriptLPS(1); | ||
6864 | |||
6865 | int permmask = 0; | ||
6866 | |||
6867 | if (mask == ScriptBaseClass.MASK_BASE)//0 | ||
6868 | { | ||
6869 | permmask = (int)m_host.BaseMask; | ||
6870 | } | ||
6871 | |||
6872 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 | ||
6873 | { | ||
6874 | permmask = (int)m_host.OwnerMask; | ||
6875 | } | ||
6876 | |||
6877 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 | ||
6878 | { | ||
6879 | permmask = (int)m_host.GroupMask; | ||
6880 | } | ||
6881 | |||
6882 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 | ||
6883 | { | ||
6884 | permmask = (int)m_host.EveryoneMask; | ||
6885 | } | ||
6886 | |||
6887 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 | ||
6888 | { | ||
6889 | permmask = (int)m_host.NextOwnerMask; | ||
6890 | } | ||
6891 | |||
6892 | return permmask; | ||
6893 | } | ||
6894 | |||
6895 | public void llSetObjectPermMask(int mask, int value) | ||
6896 | { | ||
6897 | m_host.AddScriptLPS(1); | ||
6898 | IConfigSource config = new IniConfigSource(Application.iniFilePath); | ||
6899 | if (config.Configs["XEngine"] == null) | ||
6900 | config.AddConfig("XEngine"); | ||
6901 | |||
6902 | if (config.Configs["XEngine"].GetBoolean("AllowGodFunctions", false)) | ||
6903 | { | ||
6904 | if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID)) | ||
6905 | { | ||
6906 | if (mask == ScriptBaseClass.MASK_BASE)//0 | ||
6907 | { | ||
6908 | m_host.BaseMask = (uint)value; | ||
6909 | } | ||
6910 | |||
6911 | else if (mask == ScriptBaseClass.MASK_OWNER)//1 | ||
6912 | { | ||
6913 | m_host.OwnerMask = (uint)value; | ||
6914 | } | ||
6915 | |||
6916 | else if (mask == ScriptBaseClass.MASK_GROUP)//2 | ||
6917 | { | ||
6918 | m_host.GroupMask = (uint)value; | ||
6919 | } | ||
6920 | |||
6921 | else if (mask == ScriptBaseClass.MASK_EVERYONE)//3 | ||
6922 | { | ||
6923 | m_host.EveryoneMask = (uint)value; | ||
6924 | } | ||
6925 | |||
6926 | else if (mask == ScriptBaseClass.MASK_NEXT)//4 | ||
6927 | { | ||
6928 | m_host.NextOwnerMask = (uint)value; | ||
6929 | } | ||
6930 | } | ||
6931 | } | ||
6932 | } | ||
6933 | |||
6934 | public LSL_Integer llGetInventoryPermMask(string item, int mask) | ||
6935 | { | ||
6936 | m_host.AddScriptLPS(1); | ||
6937 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
6938 | { | ||
6939 | if (inv.Value.Name == item) | ||
6940 | { | ||
6941 | switch (mask) | ||
6942 | { | ||
6943 | case 0: | ||
6944 | return (int)inv.Value.BasePermissions; | ||
6945 | case 1: | ||
6946 | return (int)inv.Value.CurrentPermissions; | ||
6947 | case 2: | ||
6948 | return (int)inv.Value.GroupPermissions; | ||
6949 | case 3: | ||
6950 | return (int)inv.Value.EveryonePermissions; | ||
6951 | case 4: | ||
6952 | return (int)inv.Value.NextPermissions; | ||
6953 | } | ||
6954 | } | ||
6955 | } | ||
6956 | return -1; | ||
6957 | } | ||
6958 | |||
6959 | public void llSetInventoryPermMask(string item, int mask, int value) | ||
6960 | { | ||
6961 | m_host.AddScriptLPS(1); | ||
6962 | NotImplemented("llSetInventoryPermMask"); | ||
6963 | } | ||
6964 | |||
6965 | public LSL_String llGetInventoryCreator(string item) | ||
6966 | { | ||
6967 | m_host.AddScriptLPS(1); | ||
6968 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
6969 | { | ||
6970 | if (inv.Value.Name == item) | ||
6971 | { | ||
6972 | return inv.Value.CreatorID.ToString(); | ||
6973 | } | ||
6974 | } | ||
6975 | llSay(0, "No item name '" + item + "'"); | ||
6976 | return String.Empty; | ||
6977 | } | ||
6978 | |||
6979 | public void llOwnerSay(string msg) | ||
6980 | { | ||
6981 | m_host.AddScriptLPS(1); | ||
6982 | |||
6983 | World.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, m_host.AbsolutePosition, m_host.Name, m_host.UUID, false); | ||
6984 | // IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>(); | ||
6985 | // wComm.DeliverMessage(ChatTypeEnum.Owner, 0, m_host.Name, m_host.UUID, msg); | ||
6986 | } | ||
6987 | |||
6988 | public LSL_String llRequestSimulatorData(string simulator, int data) | ||
6989 | { | ||
6990 | try | ||
6991 | { | ||
6992 | m_host.AddScriptLPS(1); | ||
6993 | |||
6994 | string reply = String.Empty; | ||
6995 | |||
6996 | RegionInfo info = m_ScriptEngine.World.RequestClosestRegion(simulator); | ||
6997 | |||
6998 | switch (data) | ||
6999 | { | ||
7000 | case 5: // DATA_SIM_POS | ||
7001 | if (info == null) | ||
7002 | { | ||
7003 | // ScriptSleep(1000); | ||
7004 | return UUID.Zero.ToString(); | ||
7005 | } | ||
7006 | reply = new LSL_Vector( | ||
7007 | info.RegionLocX * Constants.RegionSize, | ||
7008 | info.RegionLocY * Constants.RegionSize, | ||
7009 | 0).ToString(); | ||
7010 | break; | ||
7011 | case 6: // DATA_SIM_STATUS | ||
7012 | if (info != null) | ||
7013 | reply = "up"; // Duh! | ||
7014 | else | ||
7015 | reply = "unknown"; | ||
7016 | break; | ||
7017 | case 7: // DATA_SIM_RATING | ||
7018 | if (info == null) | ||
7019 | { | ||
7020 | // ScriptSleep(1000); | ||
7021 | return UUID.Zero.ToString(); | ||
7022 | } | ||
7023 | int access = info.RegionSettings.Maturity; | ||
7024 | if (access == 0) | ||
7025 | reply = "PG"; | ||
7026 | else if (access == 1) | ||
7027 | reply = "MATURE"; | ||
7028 | else | ||
7029 | reply = "UNKNOWN"; | ||
7030 | break; | ||
7031 | case 128: // SIM_RELEASE (not LSL conform, valid for OpenSim only) | ||
7032 | reply = m_ScriptEngine.World.GetSimulatorVersion(); | ||
7033 | break; | ||
7034 | default: | ||
7035 | // ScriptSleep(1000); | ||
7036 | return UUID.Zero.ToString(); // Raise no event | ||
7037 | } | ||
7038 | UUID rq = UUID.Random(); | ||
7039 | |||
7040 | UUID tid = AsyncCommands. | ||
7041 | DataserverPlugin.RegisterRequest(m_localID, m_itemID, rq.ToString()); | ||
7042 | |||
7043 | AsyncCommands. | ||
7044 | DataserverPlugin.DataserverReply(rq.ToString(), reply); | ||
7045 | |||
7046 | // ScriptSleep(1000); | ||
7047 | return tid.ToString(); | ||
7048 | } | ||
7049 | catch(Exception e) | ||
7050 | { | ||
7051 | Console.WriteLine(e.ToString()); | ||
7052 | return UUID.Zero.ToString(); | ||
7053 | } | ||
7054 | } | ||
7055 | |||
7056 | public void llForceMouselook(int mouselook) | ||
7057 | { | ||
7058 | m_host.AddScriptLPS(1); | ||
7059 | m_host.SetForceMouselook(mouselook != 0); | ||
7060 | } | ||
7061 | |||
7062 | public LSL_Float llGetObjectMass(string id) | ||
7063 | { | ||
7064 | m_host.AddScriptLPS(1); | ||
7065 | UUID key = new UUID(); | ||
7066 | if (UUID.TryParse(id, out key)) | ||
7067 | { | ||
7068 | try | ||
7069 | { | ||
7070 | SceneObjectPart obj = World.GetSceneObjectPart(World.Entities[key].LocalId); | ||
7071 | if (obj != null) | ||
7072 | return (double)obj.GetMass(); | ||
7073 | // the object is null so the key is for an avatar | ||
7074 | ScenePresence avatar = World.GetScenePresence(key); | ||
7075 | if (avatar != null) | ||
7076 | if (avatar.IsChildAgent) | ||
7077 | // reference http://www.lslwiki.net/lslwiki/wakka.php?wakka=llGetObjectMass | ||
7078 | // child agents have a mass of 1.0 | ||
7079 | return 1; | ||
7080 | else | ||
7081 | return (double)avatar.PhysicsActor.Mass; | ||
7082 | } | ||
7083 | catch (KeyNotFoundException) | ||
7084 | { | ||
7085 | return 0; // The Object/Agent not in the region so just return zero | ||
7086 | } | ||
7087 | } | ||
7088 | return 0; | ||
7089 | } | ||
7090 | |||
7091 | /// <summary> | ||
7092 | /// illListReplaceList removes the sub-list defined by the inclusive indices | ||
7093 | /// start and end and inserts the src list in its place. The inclusive | ||
7094 | /// nature of the indices means that at least one element must be deleted | ||
7095 | /// if the indices are within the bounds of the existing list. I.e. 2,2 | ||
7096 | /// will remove the element at index 2 and replace it with the source | ||
7097 | /// list. Both indices may be negative, with the usual interpretation. An | ||
7098 | /// interesting case is where end is lower than start. As these indices | ||
7099 | /// bound the list to be removed, then 0->end, and start->lim are removed | ||
7100 | /// and the source list is added as a suffix. | ||
7101 | /// </summary> | ||
7102 | |||
7103 | public LSL_List llListReplaceList(LSL_List dest, LSL_List src, int start, int end) | ||
7104 | { | ||
7105 | LSL_List pref = null; | ||
7106 | |||
7107 | m_host.AddScriptLPS(1); | ||
7108 | |||
7109 | // Note that although we have normalized, both | ||
7110 | // indices could still be negative. | ||
7111 | if (start < 0) | ||
7112 | { | ||
7113 | start = start+dest.Length; | ||
7114 | } | ||
7115 | |||
7116 | if (end < 0) | ||
7117 | { | ||
7118 | end = end+dest.Length; | ||
7119 | } | ||
7120 | // The comventional case, remove a sequence starting with | ||
7121 | // start and ending with end. And then insert the source | ||
7122 | // list. | ||
7123 | if (start <= end) | ||
7124 | { | ||
7125 | // If greater than zero, then there is going to be a | ||
7126 | // surviving prefix. Otherwise the inclusive nature | ||
7127 | // of the indices mean that we're going to add the | ||
7128 | // source list as a prefix. | ||
7129 | if (start > 0) | ||
7130 | { | ||
7131 | pref = dest.GetSublist(0,start-1); | ||
7132 | // Only add a suffix if there is something | ||
7133 | // beyond the end index (it's inclusive too). | ||
7134 | if (end + 1 < dest.Length) | ||
7135 | { | ||
7136 | return pref + src + dest.GetSublist(end + 1, -1); | ||
7137 | } | ||
7138 | else | ||
7139 | { | ||
7140 | return pref + src; | ||
7141 | } | ||
7142 | } | ||
7143 | // If start is less than or equal to zero, then | ||
7144 | // the new list is simply a prefix. We still need to | ||
7145 | // figure out any necessary surgery to the destination | ||
7146 | // based upon end. Note that if end exceeds the upper | ||
7147 | // bound in this case, the entire destination list | ||
7148 | // is removed. | ||
7149 | else | ||
7150 | { | ||
7151 | if (end + 1 < dest.Length) | ||
7152 | { | ||
7153 | return src + dest.GetSublist(end + 1, -1); | ||
7154 | } | ||
7155 | else | ||
7156 | { | ||
7157 | return src; | ||
7158 | } | ||
7159 | } | ||
7160 | } | ||
7161 | // Finally, if start > end, we strip away a prefix and | ||
7162 | // a suffix, to leave the list that sits <between> ens | ||
7163 | // and start, and then tag on the src list. AT least | ||
7164 | // that's my interpretation. We can get sublist to do | ||
7165 | // this for us. Note that one, or both of the indices | ||
7166 | // might have been negative. | ||
7167 | else | ||
7168 | { | ||
7169 | return dest.GetSublist(end + 1, start - 1) + src; | ||
7170 | } | ||
7171 | } | ||
7172 | |||
7173 | public void llLoadURL(string avatar_id, string message, string url) | ||
7174 | { | ||
7175 | m_host.AddScriptLPS(1); | ||
7176 | UUID avatarId = new UUID(avatar_id); | ||
7177 | m_ScriptEngine.World.SendUrlToUser(avatarId, m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, | ||
7178 | url); | ||
7179 | // ScriptSleep(10000); | ||
7180 | } | ||
7181 | |||
7182 | public void llParcelMediaCommandList(LSL_List commandList) | ||
7183 | { | ||
7184 | //TO DO: Implement the missing commands | ||
7185 | //PARCEL_MEDIA_COMMAND_STOP Stop the media stream and go back to the first frame. | ||
7186 | //PARCEL_MEDIA_COMMAND_PAUSE Pause the media stream (stop playing but stay on current frame). | ||
7187 | //PARCEL_MEDIA_COMMAND_PLAY Start the media stream playing from the current frame and stop when the end is reached. | ||
7188 | //PARCEL_MEDIA_COMMAND_LOOP Start the media stream playing from the current frame. When the end is reached, loop to the beginning and continue. | ||
7189 | //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture. | ||
7190 | //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url. | ||
7191 | //PARCEL_MEDIA_COMMAND_TIME float time Move a media stream to a specific time. | ||
7192 | //PARCEL_MEDIA_COMMAND_AGENT key uuid Applies the media command to the specified agent only. | ||
7193 | //PARCEL_MEDIA_COMMAND_UNLOAD Completely unloads the movie and restores the original texture. | ||
7194 | //PARCEL_MEDIA_COMMAND_AUTO_ALIGN integer boolean Sets the parcel option 'Auto scale content'. | ||
7195 | //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later) | ||
7196 | //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later) | ||
7197 | //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later) | ||
7198 | //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) | ||
7199 | m_host.AddScriptLPS(1); | ||
7200 | for (int i = 0; i < commandList.Data.Length; i++) | ||
7201 | { | ||
7202 | switch ((ParcelMediaCommandEnum)commandList.Data[i]) | ||
7203 | { | ||
7204 | case ParcelMediaCommandEnum.Play: | ||
7205 | List<ScenePresence> scenePresencePlayList = World.GetScenePresences(); | ||
7206 | foreach (ScenePresence agent in scenePresencePlayList) | ||
7207 | { | ||
7208 | if (!agent.IsChildAgent) | ||
7209 | { | ||
7210 | agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Play, 0); | ||
7211 | } | ||
7212 | } | ||
7213 | break; | ||
7214 | case ParcelMediaCommandEnum.Stop: | ||
7215 | List<ScenePresence> scenePresenceStopList = World.GetScenePresences(); | ||
7216 | foreach (ScenePresence agent in scenePresenceStopList) | ||
7217 | { | ||
7218 | if (!agent.IsChildAgent) | ||
7219 | { | ||
7220 | agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Stop, 0); | ||
7221 | } | ||
7222 | } | ||
7223 | break; | ||
7224 | case ParcelMediaCommandEnum.Pause: | ||
7225 | List<ScenePresence> scenePresencePauseList = World.GetScenePresences(); | ||
7226 | foreach (ScenePresence agent in scenePresencePauseList) | ||
7227 | { | ||
7228 | if (!agent.IsChildAgent) | ||
7229 | { | ||
7230 | agent.ControllingClient.SendParcelMediaCommand((uint)(4), ParcelMediaCommandEnum.Pause, 0); | ||
7231 | } | ||
7232 | } | ||
7233 | break; | ||
7234 | |||
7235 | case ParcelMediaCommandEnum.Url: | ||
7236 | if ((i + 1) < commandList.Length) | ||
7237 | { | ||
7238 | if (commandList.Data[i + 1] is string) | ||
7239 | { | ||
7240 | UUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
7241 | |||
7242 | if (landowner == UUID.Zero) | ||
7243 | { | ||
7244 | return; | ||
7245 | } | ||
7246 | |||
7247 | if (landowner != m_host.ObjectOwner) | ||
7248 | { | ||
7249 | return; | ||
7250 | } | ||
7251 | |||
7252 | World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, (string)commandList.GetLSLStringItem(i + 1)); | ||
7253 | |||
7254 | List<ScenePresence> scenePresenceList = World.GetScenePresences(); | ||
7255 | LandData landData = World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); | ||
7256 | //Send an update of the mediaURL to all the clients that are in the parcel | ||
7257 | foreach (ScenePresence agent in scenePresenceList) | ||
7258 | { | ||
7259 | if (!agent.IsChildAgent) | ||
7260 | { | ||
7261 | //Send parcel media update to the client | ||
7262 | agent.ControllingClient.SendParcelMediaUpdate(landData.MediaURL, landData.MediaID, landData.MediaAutoScale, "", landData.Description, 0, 0, 1); | ||
7263 | } | ||
7264 | } | ||
7265 | |||
7266 | } | ||
7267 | i++; | ||
7268 | } | ||
7269 | break; | ||
7270 | default: | ||
7271 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; | ||
7272 | NotImplemented("llParcelMediaCommandList parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType(), commandList.Data[i].ToString()).ToString()); | ||
7273 | break; | ||
7274 | }//end switch | ||
7275 | |||
7276 | } | ||
7277 | // ScriptSleep(2000); | ||
7278 | } | ||
7279 | |||
7280 | public LSL_List llParcelMediaQuery(LSL_List aList) | ||
7281 | { | ||
7282 | m_host.AddScriptLPS(1); | ||
7283 | LSL_List list = new LSL_List(); | ||
7284 | //TO DO: make the implementation for the missing commands | ||
7285 | //PARCEL_MEDIA_COMMAND_TEXTURE key uuid Use this to get or set the parcel's media texture. | ||
7286 | //PARCEL_MEDIA_COMMAND_URL string url Used to get or set the parcel's media url. | ||
7287 | //PARCEL_MEDIA_COMMAND_TYPE string mime_type Use this to get or set the parcel media MIME type (e.g. "text/html"). (1.19.1 RC0 or later) | ||
7288 | //PARCEL_MEDIA_COMMAND_SIZE integer x, integer y Use this to get or set the parcel media pixel resolution. (1.19.1 RC0 or later) | ||
7289 | //PARCEL_MEDIA_COMMAND_DESC string desc Use this to get or set the parcel media description. (1.19.1 RC0 or later) | ||
7290 | //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) | ||
7291 | for (int i = 0; i < aList.Data.Length; i++) | ||
7292 | { | ||
7293 | |||
7294 | if (aList.Data[i] != null) | ||
7295 | { | ||
7296 | switch ((ParcelMediaCommandEnum) aList.Data[i]) | ||
7297 | { | ||
7298 | case ParcelMediaCommandEnum.Url: | ||
7299 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); | ||
7300 | break; | ||
7301 | case ParcelMediaCommandEnum.Desc: | ||
7302 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); | ||
7303 | break; | ||
7304 | case ParcelMediaCommandEnum.Texture: | ||
7305 | list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); | ||
7306 | break; | ||
7307 | default: | ||
7308 | ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; | ||
7309 | NotImplemented("llParcelMediaQuery parameter do not supported yet: " + Enum.Parse(mediaCommandEnum.GetType() , aList.Data[i].ToString()).ToString()); | ||
7310 | break; | ||
7311 | } | ||
7312 | |||
7313 | } | ||
7314 | } | ||
7315 | // ScriptSleep(2000); | ||
7316 | return list; | ||
7317 | } | ||
7318 | |||
7319 | public LSL_Integer llModPow(int a, int b, int c) | ||
7320 | { | ||
7321 | m_host.AddScriptLPS(1); | ||
7322 | Int64 tmp = 0; | ||
7323 | Math.DivRem(Convert.ToInt64(Math.Pow(a, b)), c, out tmp); | ||
7324 | // ScriptSleep(1000); | ||
7325 | return Convert.ToInt32(tmp); | ||
7326 | } | ||
7327 | |||
7328 | public LSL_Integer llGetInventoryType(string name) | ||
7329 | { | ||
7330 | m_host.AddScriptLPS(1); | ||
7331 | foreach (KeyValuePair<UUID, TaskInventoryItem> inv in m_host.TaskInventory) | ||
7332 | { | ||
7333 | if (inv.Value.Name == name) | ||
7334 | { | ||
7335 | return inv.Value.InvType; | ||
7336 | } | ||
7337 | } | ||
7338 | return -1; | ||
7339 | } | ||
7340 | |||
7341 | public void llSetPayPrice(int price, LSL_List quick_pay_buttons) | ||
7342 | { | ||
7343 | m_host.AddScriptLPS(1); | ||
7344 | |||
7345 | if (quick_pay_buttons.Data.Length < 4) | ||
7346 | { | ||
7347 | LSLError("List must have at least 4 elements"); | ||
7348 | return; | ||
7349 | } | ||
7350 | m_host.ParentGroup.RootPart.PayPrice[0]=price; | ||
7351 | |||
7352 | m_host.ParentGroup.RootPart.PayPrice[1]=(LSL_Integer)quick_pay_buttons.Data[0]; | ||
7353 | m_host.ParentGroup.RootPart.PayPrice[2]=(LSL_Integer)quick_pay_buttons.Data[1]; | ||
7354 | m_host.ParentGroup.RootPart.PayPrice[3]=(LSL_Integer)quick_pay_buttons.Data[2]; | ||
7355 | m_host.ParentGroup.RootPart.PayPrice[4]=(LSL_Integer)quick_pay_buttons.Data[3]; | ||
7356 | m_host.ParentGroup.HasGroupChanged = true; | ||
7357 | } | ||
7358 | |||
7359 | public LSL_Vector llGetCameraPos() | ||
7360 | { | ||
7361 | m_host.AddScriptLPS(1); | ||
7362 | UUID invItemID=InventorySelf(); | ||
7363 | if (invItemID == UUID.Zero) | ||
7364 | return new LSL_Vector(); | ||
7365 | if (m_host.TaskInventory[invItemID].PermsGranter == UUID.Zero) | ||
7366 | return new LSL_Vector(); | ||
7367 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_TRACK_CAMERA) == 0) | ||
7368 | { | ||
7369 | ShoutError("No permissions to track the camera"); | ||
7370 | return new LSL_Vector(); | ||
7371 | } | ||
7372 | ScenePresence presence = World.GetScenePresence(m_host.OwnerID); | ||
7373 | if (presence != null) | ||
7374 | { | ||
7375 | LSL_Vector pos = new LSL_Vector(presence.CameraPosition.X, presence.CameraPosition.Y, presence.CameraPosition.Z); | ||
7376 | return pos; | ||
7377 | } | ||
7378 | return new LSL_Vector(); | ||
7379 | } | ||
7380 | |||
7381 | public LSL_Rotation llGetCameraRot() | ||
7382 | { | ||
7383 | m_host.AddScriptLPS(1); | ||
7384 | NotImplemented("llGetCameraRot"); | ||
7385 | return new LSL_Rotation(); | ||
7386 | } | ||
7387 | |||
7388 | public void llSetPrimURL() | ||
7389 | { | ||
7390 | m_host.AddScriptLPS(1); | ||
7391 | NotImplemented("llSetPrimURL"); | ||
7392 | // ScriptSleep(2000); | ||
7393 | } | ||
7394 | |||
7395 | public void llRefreshPrimURL() | ||
7396 | { | ||
7397 | m_host.AddScriptLPS(1); | ||
7398 | NotImplemented("llRefreshPrimURL"); | ||
7399 | // ScriptSleep(20000); | ||
7400 | } | ||
7401 | |||
7402 | public LSL_String llEscapeURL(string url) | ||
7403 | { | ||
7404 | m_host.AddScriptLPS(1); | ||
7405 | try | ||
7406 | { | ||
7407 | return Uri.EscapeUriString(url); | ||
7408 | } | ||
7409 | catch (Exception ex) | ||
7410 | { | ||
7411 | return "llEscapeURL: " + ex.ToString(); | ||
7412 | } | ||
7413 | } | ||
7414 | |||
7415 | public LSL_String llUnescapeURL(string url) | ||
7416 | { | ||
7417 | m_host.AddScriptLPS(1); | ||
7418 | try | ||
7419 | { | ||
7420 | return Uri.UnescapeDataString(url); | ||
7421 | } | ||
7422 | catch (Exception ex) | ||
7423 | { | ||
7424 | return "llUnescapeURL: " + ex.ToString(); | ||
7425 | } | ||
7426 | } | ||
7427 | |||
7428 | public void llMapDestination(string simname, LSL_Vector pos, LSL_Vector look_at) | ||
7429 | { | ||
7430 | m_host.AddScriptLPS(1); | ||
7431 | NotImplemented("llMapDestination"); | ||
7432 | // ScriptSleep(1000); | ||
7433 | } | ||
7434 | |||
7435 | public void llAddToLandBanList(string avatar, double hours) | ||
7436 | { | ||
7437 | m_host.AddScriptLPS(1); | ||
7438 | UUID key; | ||
7439 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7440 | if (land.OwnerID == m_host.OwnerID) | ||
7441 | { | ||
7442 | ParcelManager.ParcelAccessEntry entry = new ParcelManager.ParcelAccessEntry(); | ||
7443 | if (UUID.TryParse(avatar, out key)) | ||
7444 | { | ||
7445 | entry.AgentID = key; | ||
7446 | entry.Flags = ParcelManager.AccessList.Ban; | ||
7447 | entry.Time = DateTime.Now.AddHours(hours); | ||
7448 | land.ParcelAccessList.Add(entry); | ||
7449 | } | ||
7450 | } | ||
7451 | // ScriptSleep(100); | ||
7452 | } | ||
7453 | |||
7454 | public void llRemoveFromLandPassList(string avatar) | ||
7455 | { | ||
7456 | m_host.AddScriptLPS(1); | ||
7457 | UUID key; | ||
7458 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7459 | if (land.OwnerID == m_host.OwnerID) | ||
7460 | { | ||
7461 | if (UUID.TryParse(avatar, out key)) | ||
7462 | { | ||
7463 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7464 | { | ||
7465 | if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Access) | ||
7466 | { | ||
7467 | land.ParcelAccessList.Remove(entry); | ||
7468 | break; | ||
7469 | } | ||
7470 | } | ||
7471 | } | ||
7472 | } | ||
7473 | // ScriptSleep(100); | ||
7474 | } | ||
7475 | |||
7476 | public void llRemoveFromLandBanList(string avatar) | ||
7477 | { | ||
7478 | m_host.AddScriptLPS(1); | ||
7479 | UUID key; | ||
7480 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7481 | if (land.OwnerID == m_host.OwnerID) | ||
7482 | { | ||
7483 | if (UUID.TryParse(avatar, out key)) | ||
7484 | { | ||
7485 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7486 | { | ||
7487 | if (entry.AgentID == key && entry.Flags == ParcelManager.AccessList.Ban) | ||
7488 | { | ||
7489 | land.ParcelAccessList.Remove(entry); | ||
7490 | break; | ||
7491 | } | ||
7492 | } | ||
7493 | } | ||
7494 | } | ||
7495 | // ScriptSleep(100); | ||
7496 | } | ||
7497 | |||
7498 | public void llSetCameraParams(LSL_List rules) | ||
7499 | { | ||
7500 | m_host.AddScriptLPS(1); | ||
7501 | |||
7502 | // our key in the object we are in | ||
7503 | UUID invItemID=InventorySelf(); | ||
7504 | if (invItemID == UUID.Zero) return; | ||
7505 | |||
7506 | // the object we are in | ||
7507 | UUID objectID = m_host.ParentUUID; | ||
7508 | if (objectID == UUID.Zero) return; | ||
7509 | |||
7510 | // we need the permission first, to know which avatar we want to set the camera for | ||
7511 | UUID agentID = m_host.TaskInventory[invItemID].PermsGranter; | ||
7512 | if (agentID == UUID.Zero) return; | ||
7513 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; | ||
7514 | |||
7515 | ScenePresence presence = World.GetScenePresence(agentID); | ||
7516 | |||
7517 | // we are not interested in child-agents | ||
7518 | if (presence.IsChildAgent) return; | ||
7519 | |||
7520 | SortedDictionary<int, float> parameters = new SortedDictionary<int, float>(); | ||
7521 | object[] data = rules.Data; | ||
7522 | for (int i = 0; i < data.Length; ++i) { | ||
7523 | int type = Convert.ToInt32(data[i++].ToString()); | ||
7524 | if (i >= data.Length) break; // odd number of entries => ignore the last | ||
7525 | |||
7526 | // some special cases: Vector parameters are split into 3 float parameters (with type+1, type+2, type+3) | ||
7527 | switch (type) { | ||
7528 | case ScriptBaseClass.CAMERA_FOCUS: | ||
7529 | case ScriptBaseClass.CAMERA_FOCUS_OFFSET: | ||
7530 | case ScriptBaseClass.CAMERA_POSITION: | ||
7531 | LSL_Vector v = (LSL_Vector)data[i]; | ||
7532 | parameters.Add(type + 1, (float)v.x); | ||
7533 | parameters.Add(type + 2, (float)v.y); | ||
7534 | parameters.Add(type + 3, (float)v.z); | ||
7535 | break; | ||
7536 | default: | ||
7537 | // TODO: clean that up as soon as the implicit casts are in | ||
7538 | if (data[i] is LSL_Float) | ||
7539 | parameters.Add(type, (float)((LSL_Float)data[i]).value); | ||
7540 | else if (data[i] is LSL_Integer) | ||
7541 | parameters.Add(type, (float)((LSL_Integer)data[i]).value); | ||
7542 | else parameters.Add(type, Convert.ToSingle(data[i])); | ||
7543 | break; | ||
7544 | } | ||
7545 | } | ||
7546 | if (parameters.Count > 0) presence.ControllingClient.SendSetFollowCamProperties(objectID, parameters); | ||
7547 | } | ||
7548 | |||
7549 | public void llClearCameraParams() | ||
7550 | { | ||
7551 | m_host.AddScriptLPS(1); | ||
7552 | |||
7553 | // our key in the object we are in | ||
7554 | UUID invItemID=InventorySelf(); | ||
7555 | if (invItemID == UUID.Zero) return; | ||
7556 | |||
7557 | // the object we are in | ||
7558 | UUID objectID = m_host.ParentUUID; | ||
7559 | if (objectID == UUID.Zero) return; | ||
7560 | |||
7561 | // we need the permission first, to know which avatar we want to clear the camera for | ||
7562 | UUID agentID = m_host.TaskInventory[invItemID].PermsGranter; | ||
7563 | if (agentID == UUID.Zero) return; | ||
7564 | if ((m_host.TaskInventory[invItemID].PermsMask & ScriptBaseClass.PERMISSION_CONTROL_CAMERA) == 0) return; | ||
7565 | |||
7566 | ScenePresence presence = World.GetScenePresence(agentID); | ||
7567 | |||
7568 | // we are not interested in child-agents | ||
7569 | if (presence.IsChildAgent) return; | ||
7570 | |||
7571 | presence.ControllingClient.SendClearFollowCamProperties(objectID); | ||
7572 | } | ||
7573 | |||
7574 | public LSL_Float llListStatistics(int operation, LSL_List src) | ||
7575 | { | ||
7576 | m_host.AddScriptLPS(1); | ||
7577 | LSL_List nums = LSL_List.ToDoubleList(src); | ||
7578 | switch (operation) | ||
7579 | { | ||
7580 | case ScriptBaseClass.LIST_STAT_RANGE: | ||
7581 | return nums.Range(); | ||
7582 | case ScriptBaseClass.LIST_STAT_MIN: | ||
7583 | return nums.Min(); | ||
7584 | case ScriptBaseClass.LIST_STAT_MAX: | ||
7585 | return nums.Max(); | ||
7586 | case ScriptBaseClass.LIST_STAT_MEAN: | ||
7587 | return nums.Mean(); | ||
7588 | case ScriptBaseClass.LIST_STAT_MEDIAN: | ||
7589 | return nums.Median(); | ||
7590 | case ScriptBaseClass.LIST_STAT_NUM_COUNT: | ||
7591 | return nums.NumericLength(); | ||
7592 | case ScriptBaseClass.LIST_STAT_STD_DEV: | ||
7593 | return nums.StdDev(); | ||
7594 | case ScriptBaseClass.LIST_STAT_SUM: | ||
7595 | return nums.Sum(); | ||
7596 | case ScriptBaseClass.LIST_STAT_SUM_SQUARES: | ||
7597 | return nums.SumSqrs(); | ||
7598 | case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: | ||
7599 | return nums.GeometricMean(); | ||
7600 | case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: | ||
7601 | return nums.HarmonicMean(); | ||
7602 | default: | ||
7603 | return 0.0; | ||
7604 | } | ||
7605 | } | ||
7606 | |||
7607 | public LSL_Integer llGetUnixTime() | ||
7608 | { | ||
7609 | m_host.AddScriptLPS(1); | ||
7610 | return Util.UnixTimeSinceEpoch(); | ||
7611 | } | ||
7612 | |||
7613 | public LSL_Integer llGetParcelFlags(LSL_Vector pos) | ||
7614 | { | ||
7615 | m_host.AddScriptLPS(1); | ||
7616 | return (int)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y).landData.Flags; | ||
7617 | } | ||
7618 | |||
7619 | public LSL_Integer llGetRegionFlags() | ||
7620 | { | ||
7621 | m_host.AddScriptLPS(1); | ||
7622 | IEstateModule estate = World.RequestModuleInterface<IEstateModule>(); | ||
7623 | if (estate == null) | ||
7624 | return 67108864; | ||
7625 | return (int)estate.GetRegionFlags(); | ||
7626 | } | ||
7627 | |||
7628 | public LSL_String llXorBase64StringsCorrect(string str1, string str2) | ||
7629 | { | ||
7630 | m_host.AddScriptLPS(1); | ||
7631 | string ret = String.Empty; | ||
7632 | string src1 = llBase64ToString(str1); | ||
7633 | string src2 = llBase64ToString(str2); | ||
7634 | int c = 0; | ||
7635 | for (int i = 0; i < src1.Length; i++) | ||
7636 | { | ||
7637 | ret += src1[i] ^ src2[c]; | ||
7638 | |||
7639 | c++; | ||
7640 | if (c >= src2.Length) | ||
7641 | c = 0; | ||
7642 | } | ||
7643 | return llStringToBase64(ret); | ||
7644 | } | ||
7645 | |||
7646 | public LSL_String llHTTPRequest(string url, LSL_List parameters, string body) | ||
7647 | { | ||
7648 | // Partial implementation: support for parameter flags needed | ||
7649 | // see http://wiki.secondlife.com/wiki/LlHTTPRequest | ||
7650 | // parameter flags support are implemented in ScriptsHttpRequests.cs | ||
7651 | // in StartHttpRequest | ||
7652 | |||
7653 | m_host.AddScriptLPS(1); | ||
7654 | IHttpRequests httpScriptMod = | ||
7655 | m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>(); | ||
7656 | List<string> param = new List<string>(); | ||
7657 | foreach (object o in parameters.Data) | ||
7658 | { | ||
7659 | param.Add(o.ToString()); | ||
7660 | } | ||
7661 | |||
7662 | Vector3 position = m_host.AbsolutePosition; | ||
7663 | Vector3 velocity = m_host.Velocity; | ||
7664 | Quaternion rotation = m_host.RotationOffset; | ||
7665 | ScenePresence scenePresence = World.GetScenePresence(m_host.ObjectOwner); | ||
7666 | RegionInfo regionInfo = World.RegionInfo; | ||
7667 | |||
7668 | Dictionary<string, string> httpHeaders = new Dictionary<string, string>(); | ||
7669 | |||
7670 | httpHeaders["X-SecondLife-Shard"] = "OpenSim"; | ||
7671 | httpHeaders["X-SecondLife-Object-Name"] = m_host.Name; | ||
7672 | httpHeaders["X-SecondLife-Object-Key"] = m_itemID.ToString(); | ||
7673 | httpHeaders["X-SecondLife-Region"] = string.Format("{0} ({1}, {2})", regionInfo.RegionName, regionInfo.RegionLocX, regionInfo.RegionLocY); | ||
7674 | httpHeaders["X-SecondLife-Local-Position"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", position.X, position.Y, position.Z); | ||
7675 | httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z); | ||
7676 | 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); | ||
7677 | httpHeaders["X-SecondLife-Owner-Name"] = scenePresence == null ? string.Empty : scenePresence.ControllingClient.Name; | ||
7678 | httpHeaders["X-SecondLife-Owner-Key"] = m_host.ObjectOwner.ToString(); | ||
7679 | |||
7680 | UUID reqID = httpScriptMod. | ||
7681 | StartHttpRequest(m_localID, m_itemID, url, param, httpHeaders, body); | ||
7682 | |||
7683 | if (reqID != UUID.Zero) | ||
7684 | return reqID.ToString(); | ||
7685 | else | ||
7686 | return null; | ||
7687 | } | ||
7688 | |||
7689 | public void llResetLandBanList() | ||
7690 | { | ||
7691 | m_host.AddScriptLPS(1); | ||
7692 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7693 | if (land.OwnerID == m_host.OwnerID) | ||
7694 | { | ||
7695 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7696 | { | ||
7697 | if (entry.Flags == ParcelManager.AccessList.Ban) | ||
7698 | { | ||
7699 | land.ParcelAccessList.Remove(entry); | ||
7700 | } | ||
7701 | } | ||
7702 | } | ||
7703 | // ScriptSleep(100); | ||
7704 | } | ||
7705 | |||
7706 | public void llResetLandPassList() | ||
7707 | { | ||
7708 | m_host.AddScriptLPS(1); | ||
7709 | LandData land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).landData; | ||
7710 | if (land.OwnerID == m_host.OwnerID) | ||
7711 | { | ||
7712 | foreach (ParcelManager.ParcelAccessEntry entry in land.ParcelAccessList) | ||
7713 | { | ||
7714 | if (entry.Flags == ParcelManager.AccessList.Access) | ||
7715 | { | ||
7716 | land.ParcelAccessList.Remove(entry); | ||
7717 | } | ||
7718 | } | ||
7719 | } | ||
7720 | // ScriptSleep(100); | ||
7721 | } | ||
7722 | |||
7723 | public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) | ||
7724 | { | ||
7725 | m_host.AddScriptLPS(1); | ||
7726 | |||
7727 | LandData land = World.GetLandData((float)pos.x, (float)pos.y); | ||
7728 | |||
7729 | if (land == null) | ||
7730 | { | ||
7731 | return 0; | ||
7732 | } | ||
7733 | |||
7734 | else | ||
7735 | { | ||
7736 | if (sim_wide == 1) | ||
7737 | { | ||
7738 | if (category == 0) | ||
7739 | { | ||
7740 | return land.SimwidePrims; | ||
7741 | } | ||
7742 | |||
7743 | else | ||
7744 | { | ||
7745 | //public int simwideArea = 0; | ||
7746 | return 0; | ||
7747 | } | ||
7748 | } | ||
7749 | |||
7750 | else | ||
7751 | { | ||
7752 | if (category == 0)//Total Prims | ||
7753 | { | ||
7754 | return 0;//land. | ||
7755 | } | ||
7756 | |||
7757 | else if (category == 1)//Owner Prims | ||
7758 | { | ||
7759 | return land.OwnerPrims; | ||
7760 | } | ||
7761 | |||
7762 | else if (category == 2)//Group Prims | ||
7763 | { | ||
7764 | return land.GroupPrims; | ||
7765 | } | ||
7766 | |||
7767 | else if (category == 3)//Other Prims | ||
7768 | { | ||
7769 | return land.OtherPrims; | ||
7770 | } | ||
7771 | |||
7772 | else if (category == 4)//Selected | ||
7773 | { | ||
7774 | return land.SelectedPrims; | ||
7775 | } | ||
7776 | |||
7777 | else if (category == 5)//Temp | ||
7778 | { | ||
7779 | return 0;//land. | ||
7780 | } | ||
7781 | } | ||
7782 | } | ||
7783 | return 0; | ||
7784 | } | ||
7785 | |||
7786 | public LSL_List llGetParcelPrimOwners(LSL_Vector pos) | ||
7787 | { | ||
7788 | m_host.AddScriptLPS(1); | ||
7789 | LandObject land = (LandObject)World.LandChannel.GetLandObject((float)pos.x, (float)pos.y); | ||
7790 | LSL_List ret = new LSL_List(); | ||
7791 | if (land != null) | ||
7792 | { | ||
7793 | foreach (KeyValuePair<UUID, int> d in land.getLandObjectOwners()) | ||
7794 | { | ||
7795 | ret.Add(d.Key.ToString()); | ||
7796 | ret.Add(d.Value); | ||
7797 | } | ||
7798 | } | ||
7799 | // ScriptSleep(2000); | ||
7800 | return ret; | ||
7801 | } | ||
7802 | |||
7803 | public LSL_Integer llGetObjectPrimCount(string object_id) | ||
7804 | { | ||
7805 | m_host.AddScriptLPS(1); | ||
7806 | SceneObjectPart part = World.GetSceneObjectPart(new UUID(object_id)); | ||
7807 | if (part == null) | ||
7808 | { | ||
7809 | return 0; | ||
7810 | } | ||
7811 | else | ||
7812 | { | ||
7813 | return part.ParentGroup.Children.Count; | ||
7814 | } | ||
7815 | } | ||
7816 | |||
7817 | public LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide) | ||
7818 | { | ||
7819 | m_host.AddScriptLPS(1); | ||
7820 | // Alondria: This currently just is utilizing the normal grid's 0.22 prims/m2 calculation | ||
7821 | // Which probably will be irrelevent in OpenSim.... | ||
7822 | LandData land = World.GetLandData((float)pos.x, (float)pos.y); | ||
7823 | |||
7824 | float bonusfactor = (float)World.RegionInfo.RegionSettings.ObjectBonus; | ||
7825 | |||
7826 | if (land == null) | ||
7827 | { | ||
7828 | return 0; | ||
7829 | } | ||
7830 | |||
7831 | if (sim_wide == 1) | ||
7832 | { | ||
7833 | decimal v = land.SimwideArea * (decimal)(0.22) * (decimal)bonusfactor; | ||
7834 | |||
7835 | return (int)v; | ||
7836 | } | ||
7837 | |||
7838 | else | ||
7839 | { | ||
7840 | decimal v = land.Area * (decimal)(0.22) * (decimal)bonusfactor; | ||
7841 | |||
7842 | return (int)v; | ||
7843 | } | ||
7844 | |||
7845 | } | ||
7846 | |||
7847 | public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) | ||
7848 | { | ||
7849 | m_host.AddScriptLPS(1); | ||
7850 | LandData land = World.GetLandData((float)pos.x, (float)pos.y); | ||
7851 | if (land == null) | ||
7852 | { | ||
7853 | return new LSL_List(0); | ||
7854 | } | ||
7855 | LSL_List ret = new LSL_List(); | ||
7856 | foreach (object o in param.Data) | ||
7857 | { | ||
7858 | switch (o.ToString()) | ||
7859 | { | ||
7860 | case "0": | ||
7861 | ret = ret + new LSL_List(land.Name); | ||
7862 | break; | ||
7863 | case "1": | ||
7864 | ret = ret + new LSL_List(land.Description); | ||
7865 | break; | ||
7866 | case "2": | ||
7867 | ret = ret + new LSL_List(land.OwnerID.ToString()); | ||
7868 | break; | ||
7869 | case "3": | ||
7870 | ret = ret + new LSL_List(land.GroupID.ToString()); | ||
7871 | break; | ||
7872 | case "4": | ||
7873 | ret = ret + new LSL_List(land.Area); | ||
7874 | break; | ||
7875 | default: | ||
7876 | ret = ret + new LSL_List(0); | ||
7877 | break; | ||
7878 | } | ||
7879 | } | ||
7880 | return ret; | ||
7881 | } | ||
7882 | |||
7883 | public void llSetLinkTexture(int linknumber, string texture, int face) | ||
7884 | { | ||
7885 | m_host.AddScriptLPS(1); | ||
7886 | |||
7887 | if (m_host.ParentGroup == null) | ||
7888 | return; | ||
7889 | |||
7890 | SceneObjectPart part = m_host.ParentGroup.GetLinkNumPart(linknumber); | ||
7891 | |||
7892 | if (part == null) | ||
7893 | return; | ||
7894 | |||
7895 | SetTexture(part, texture, face); | ||
7896 | // ScriptSleep(200); | ||
7897 | } | ||
7898 | |||
7899 | public LSL_String llStringTrim(string src, int type) | ||
7900 | { | ||
7901 | m_host.AddScriptLPS(1); | ||
7902 | if (type == (int)ScriptBaseClass.STRING_TRIM_HEAD) { return src.TrimStart(); } | ||
7903 | if (type == (int)ScriptBaseClass.STRING_TRIM_TAIL) { return src.TrimEnd(); } | ||
7904 | if (type == (int)ScriptBaseClass.STRING_TRIM) { return src.Trim(); } | ||
7905 | return src; | ||
7906 | } | ||
7907 | |||
7908 | public LSL_List llGetObjectDetails(string id, LSL_List args) | ||
7909 | { | ||
7910 | m_host.AddScriptLPS(1); | ||
7911 | LSL_List ret = new LSL_List(); | ||
7912 | UUID key = new UUID(); | ||
7913 | if (UUID.TryParse(id, out key)) | ||
7914 | { | ||
7915 | ScenePresence av = World.GetScenePresence(key); | ||
7916 | |||
7917 | if (av != null) | ||
7918 | { | ||
7919 | foreach (object o in args.Data) | ||
7920 | { | ||
7921 | switch (o.ToString()) | ||
7922 | { | ||
7923 | case "1": | ||
7924 | ret.Add(av.Firstname + " " + av.Lastname); | ||
7925 | break; | ||
7926 | case "2": | ||
7927 | ret.Add(""); | ||
7928 | break; | ||
7929 | case "3": | ||
7930 | ret.Add(new LSL_Vector((double)av.AbsolutePosition.X, (double)av.AbsolutePosition.Y, (double)av.AbsolutePosition.Z)); | ||
7931 | break; | ||
7932 | case "4": | ||
7933 | ret.Add(new LSL_Rotation((double)av.Rotation.X, (double)av.Rotation.Y, (double)av.Rotation.Z, (double)av.Rotation.W)); | ||
7934 | break; | ||
7935 | case "5": | ||
7936 | ret.Add(new LSL_Vector(av.Velocity.X, av.Velocity.Y, av.Velocity.Z)); | ||
7937 | break; | ||
7938 | case "6": | ||
7939 | ret.Add(id); | ||
7940 | break; | ||
7941 | case "7": | ||
7942 | ret.Add(UUID.Zero.ToString()); | ||
7943 | break; | ||
7944 | case "8": | ||
7945 | ret.Add(UUID.Zero.ToString()); | ||
7946 | break; | ||
7947 | } | ||
7948 | } | ||
7949 | return ret; | ||
7950 | } | ||
7951 | SceneObjectPart obj = World.GetSceneObjectPart(key); | ||
7952 | if (obj != null) | ||
7953 | { | ||
7954 | foreach (object o in args.Data) | ||
7955 | { | ||
7956 | switch (o.ToString()) | ||
7957 | { | ||
7958 | case "1": | ||
7959 | ret.Add(obj.Name); | ||
7960 | break; | ||
7961 | case "2": | ||
7962 | ret.Add(obj.Description); | ||
7963 | break; | ||
7964 | case "3": | ||
7965 | ret.Add(new LSL_Vector(obj.AbsolutePosition.X, obj.AbsolutePosition.Y, obj.AbsolutePosition.Z)); | ||
7966 | break; | ||
7967 | case "4": | ||
7968 | ret.Add(new LSL_Rotation(obj.RotationOffset.X, obj.RotationOffset.Y, obj.RotationOffset.Z, obj.RotationOffset.W)); | ||
7969 | break; | ||
7970 | case "5": | ||
7971 | ret.Add(new LSL_Vector(obj.Velocity.X, obj.Velocity.Y, obj.Velocity.Z)); | ||
7972 | break; | ||
7973 | case "6": | ||
7974 | ret.Add(obj.OwnerID.ToString()); | ||
7975 | break; | ||
7976 | case "7": | ||
7977 | ret.Add(obj.GroupID.ToString()); | ||
7978 | break; | ||
7979 | case "8": | ||
7980 | ret.Add(obj.CreatorID.ToString()); | ||
7981 | break; | ||
7982 | } | ||
7983 | } | ||
7984 | return ret; | ||
7985 | } | ||
7986 | } | ||
7987 | return new LSL_List(); | ||
7988 | } | ||
7989 | |||
7990 | |||
7991 | internal UUID ScriptByName(string name) | ||
7992 | { | ||
7993 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
7994 | { | ||
7995 | if (item.Type == 10 && item.Name == name) | ||
7996 | return item.ItemID; | ||
7997 | } | ||
7998 | return UUID.Zero; | ||
7999 | } | ||
8000 | |||
8001 | internal void ShoutError(string msg) | ||
8002 | { | ||
8003 | llShout(ScriptBaseClass.DEBUG_CHANNEL, msg); | ||
8004 | } | ||
8005 | |||
8006 | internal void NotImplemented(string command) | ||
8007 | { | ||
8008 | if (throwErrorOnNotImplemented) | ||
8009 | throw new NotImplementedException("Command not implemented: " + command); | ||
8010 | } | ||
8011 | |||
8012 | internal void Deprecated(string command) | ||
8013 | { | ||
8014 | throw new Exception("Command deprecated: " + command); | ||
8015 | } | ||
8016 | |||
8017 | internal void LSLError(string msg) | ||
8018 | { | ||
8019 | throw new Exception("LSL Runtime Error: " + msg); | ||
8020 | } | ||
8021 | |||
8022 | public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); | ||
8023 | private void WithNotecard(UUID assetID, AssetRequestCallback cb) | ||
8024 | { | ||
8025 | World.AssetCache.GetAsset(assetID, delegate(UUID i, AssetBase a) { cb(i, a); }, false); | ||
8026 | } | ||
8027 | |||
8028 | public LSL_String llGetNumberOfNotecardLines(string name) | ||
8029 | { | ||
8030 | m_host.AddScriptLPS(1); | ||
8031 | |||
8032 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
8033 | { | ||
8034 | if (item.Type == 7 && item.Name == name) | ||
8035 | { | ||
8036 | UUID tid = AsyncCommands. | ||
8037 | DataserverPlugin.RegisterRequest(m_localID, | ||
8038 | m_itemID, item.AssetID.ToString()); | ||
8039 | if (NotecardCache.IsCached(item.AssetID)) | ||
8040 | { | ||
8041 | AsyncCommands. | ||
8042 | DataserverPlugin.DataserverReply(item.AssetID.ToString(), | ||
8043 | NotecardCache.GetLines(item.AssetID).ToString()); | ||
8044 | // ScriptSleep(100); | ||
8045 | return tid.ToString(); | ||
8046 | } | ||
8047 | WithNotecard(item.AssetID, delegate (UUID id, AssetBase a) | ||
8048 | { | ||
8049 | System.Text.ASCIIEncoding enc = | ||
8050 | new System.Text.ASCIIEncoding(); | ||
8051 | string data = enc.GetString(a.Data); | ||
8052 | //Console.WriteLine(data); | ||
8053 | NotecardCache.Cache(id, data); | ||
8054 | AsyncCommands. | ||
8055 | DataserverPlugin.DataserverReply(id.ToString(), | ||
8056 | NotecardCache.GetLines(id).ToString()); | ||
8057 | }); | ||
8058 | // ScriptSleep(100); | ||
8059 | return tid.ToString(); | ||
8060 | } | ||
8061 | } | ||
8062 | // if we got to here, we didn't find the notecard the script was asking for | ||
8063 | // => complain loudly, as specified by the LSL docs | ||
8064 | ShoutError("Notecard '" + name + "' could not be found."); | ||
8065 | |||
8066 | // ScriptSleep(100); | ||
8067 | return UUID.Zero.ToString(); | ||
8068 | } | ||
8069 | |||
8070 | public LSL_String llGetNotecardLine(string name, int line) | ||
8071 | { | ||
8072 | m_host.AddScriptLPS(1); | ||
8073 | |||
8074 | foreach (TaskInventoryItem item in m_host.TaskInventory.Values) | ||
8075 | { | ||
8076 | if (item.Type == 7 && item.Name == name) | ||
8077 | { | ||
8078 | UUID tid = AsyncCommands. | ||
8079 | DataserverPlugin.RegisterRequest(m_localID, | ||
8080 | m_itemID, item.AssetID.ToString()); | ||
8081 | |||
8082 | if (NotecardCache.IsCached(item.AssetID)) | ||
8083 | { | ||
8084 | AsyncCommands. | ||
8085 | DataserverPlugin.DataserverReply(item.AssetID.ToString(), | ||
8086 | NotecardCache.GetLine(item.AssetID, line)); | ||
8087 | // ScriptSleep(100); | ||
8088 | return tid.ToString(); | ||
8089 | } | ||
8090 | |||
8091 | WithNotecard(item.AssetID, delegate (UUID id, AssetBase a) | ||
8092 | { | ||
8093 | System.Text.ASCIIEncoding enc = | ||
8094 | new System.Text.ASCIIEncoding(); | ||
8095 | string data = enc.GetString(a.Data); | ||
8096 | //Console.WriteLine(data); | ||
8097 | NotecardCache.Cache(id, data); | ||
8098 | AsyncCommands. | ||
8099 | DataserverPlugin.DataserverReply(id.ToString(), | ||
8100 | NotecardCache.GetLine(id, line)); | ||
8101 | }); | ||
8102 | |||
8103 | // ScriptSleep(100); | ||
8104 | return tid.ToString(); | ||
8105 | } | ||
8106 | } | ||
8107 | |||
8108 | // if we got to here, we didn't find the notecard the script was asking for | ||
8109 | // => complain loudly, as specified by the LSL docs | ||
8110 | ShoutError("Notecard '" + name + "' could not be found."); | ||
8111 | |||
8112 | // ScriptSleep(100); | ||
8113 | return UUID.Zero.ToString(); | ||
8114 | } | ||
8115 | |||
8116 | } | ||
8117 | |||
8118 | public class NotecardCache | ||
8119 | { | ||
8120 | private class Notecard | ||
8121 | { | ||
8122 | public string[] text; | ||
8123 | public DateTime lastRef; | ||
8124 | } | ||
8125 | |||
8126 | private static Dictionary<UUID, Notecard> m_Notecards = | ||
8127 | new Dictionary<UUID, Notecard>(); | ||
8128 | |||
8129 | public static void Cache(UUID assetID, string text) | ||
8130 | { | ||
8131 | CacheCheck(); | ||
8132 | |||
8133 | lock (m_Notecards) | ||
8134 | { | ||
8135 | if (m_Notecards.ContainsKey(assetID)) | ||
8136 | return; | ||
8137 | |||
8138 | Notecard nc = new Notecard(); | ||
8139 | nc.lastRef = DateTime.Now; | ||
8140 | nc.text = ParseText(text.Replace("\r", "").Split('\n')); | ||
8141 | m_Notecards[assetID] = nc; | ||
8142 | } | ||
8143 | } | ||
8144 | |||
8145 | private static string[] ParseText(string[] input) | ||
8146 | { | ||
8147 | int idx = 0; | ||
8148 | int level = 0; | ||
8149 | List<string> output = new List<string>(); | ||
8150 | string[] words; | ||
8151 | |||
8152 | while (idx < input.Length) | ||
8153 | { | ||
8154 | if (input[idx] == "{") | ||
8155 | { | ||
8156 | level++; | ||
8157 | idx++; | ||
8158 | continue; | ||
8159 | } | ||
8160 | |||
8161 | if (input[idx]== "}") | ||
8162 | { | ||
8163 | level--; | ||
8164 | idx++; | ||
8165 | continue; | ||
8166 | } | ||
8167 | |||
8168 | switch (level) | ||
8169 | { | ||
8170 | case 0: | ||
8171 | words = input[idx].Split(' '); // Linden text ver | ||
8172 | // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) | ||
8173 | if (words.Length < 3) | ||
8174 | return new String[0]; | ||
8175 | |||
8176 | int version = int.Parse(words[3]); | ||
8177 | if (version != 2) | ||
8178 | return new String[0]; | ||
8179 | break; | ||
8180 | case 1: | ||
8181 | words = input[idx].Split(' '); | ||
8182 | if (words[0] == "LLEmbeddedItems") | ||
8183 | break; | ||
8184 | if (words[0] == "Text") | ||
8185 | { | ||
8186 | int len = int.Parse(words[2]); | ||
8187 | idx++; | ||
8188 | |||
8189 | int count = -1; | ||
8190 | |||
8191 | while (count < len) | ||
8192 | { | ||
8193 | // int l = input[idx].Length; | ||
8194 | string ln = input[idx]; | ||
8195 | |||
8196 | int need = len-count-1; | ||
8197 | if (ln.Length > need) | ||
8198 | ln = ln.Substring(0, need); | ||
8199 | |||
8200 | output.Add(ln); | ||
8201 | count += ln.Length + 1; | ||
8202 | idx++; | ||
8203 | } | ||
8204 | |||
8205 | return output.ToArray(); | ||
8206 | } | ||
8207 | break; | ||
8208 | case 2: | ||
8209 | words = input[idx].Split(' '); // count | ||
8210 | if (words[0] == "count") | ||
8211 | { | ||
8212 | int c = int.Parse(words[1]); | ||
8213 | if (c > 0) | ||
8214 | return new String[0]; | ||
8215 | break; | ||
8216 | } | ||
8217 | break; | ||
8218 | } | ||
8219 | idx++; | ||
8220 | } | ||
8221 | return output.ToArray(); | ||
8222 | } | ||
8223 | |||
8224 | public static bool IsCached(UUID assetID) | ||
8225 | { | ||
8226 | lock (m_Notecards) | ||
8227 | { | ||
8228 | return m_Notecards.ContainsKey(assetID); | ||
8229 | } | ||
8230 | } | ||
8231 | |||
8232 | public static int GetLines(UUID assetID) | ||
8233 | { | ||
8234 | if (!IsCached(assetID)) | ||
8235 | return -1; | ||
8236 | |||
8237 | lock (m_Notecards) | ||
8238 | { | ||
8239 | m_Notecards[assetID].lastRef = DateTime.Now; | ||
8240 | return m_Notecards[assetID].text.Length; | ||
8241 | } | ||
8242 | } | ||
8243 | |||
8244 | public static string GetLine(UUID assetID, int line) | ||
8245 | { | ||
8246 | if (line < 0) | ||
8247 | return ""; | ||
8248 | |||
8249 | string data; | ||
8250 | |||
8251 | if (!IsCached(assetID)) | ||
8252 | return ""; | ||
8253 | |||
8254 | lock (m_Notecards) | ||
8255 | { | ||
8256 | m_Notecards[assetID].lastRef = DateTime.Now; | ||
8257 | |||
8258 | if (line >= m_Notecards[assetID].text.Length) | ||
8259 | return "\n\n\n"; | ||
8260 | |||
8261 | data = m_Notecards[assetID].text[line]; | ||
8262 | if (data.Length > 255) | ||
8263 | data = data.Substring(0, 255); | ||
8264 | |||
8265 | return data; | ||
8266 | } | ||
8267 | } | ||
8268 | |||
8269 | public static void CacheCheck() | ||
8270 | { | ||
8271 | foreach (UUID key in new List<UUID>(m_Notecards.Keys)) | ||
8272 | { | ||
8273 | Notecard nc = m_Notecards[key]; | ||
8274 | if (nc.lastRef.AddSeconds(30) < DateTime.Now) | ||
8275 | m_Notecards.Remove(key); | ||
8276 | } | ||
8277 | } | ||
8278 | } | ||
8279 | } | ||
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index ffde7ac..b54bc04 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs | |||
@@ -100,7 +100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
100 | [Serializable] | 100 | [Serializable] |
101 | public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi | 101 | public class OSSL_Api : MarshalByRefObject, IOSSL_Api, IScriptApi |
102 | { | 102 | { |
103 | internal IScriptEngine m_ScriptEngine; | 103 | internal IEventReceiver m_ScriptEngine; |
104 | internal SceneObjectPart m_host; | 104 | internal SceneObjectPart m_host; |
105 | internal uint m_localID; | 105 | internal uint m_localID; |
106 | internal UUID m_itemID; | 106 | internal UUID m_itemID; |
@@ -110,7 +110,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api | |||
110 | internal float m_ScriptDistanceFactor = 1.0f; | 110 | internal float m_ScriptDistanceFactor = 1.0f; |
111 | internal Dictionary<string, List<UUID> > m_FunctionPerms = new Dictionary<string, List<UUID> >(); | 111 | internal Dictionary<string, List<UUID> > m_FunctionPerms = new Dictionary<string, List<UUID> >(); |
112 | 112 | ||
113 | public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) | 113 | public void Initialize(IEventReceiver ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) |
114 | { | 114 | { |
115 | m_ScriptEngine = ScriptEngine; | 115 | m_ScriptEngine = ScriptEngine; |
116 | m_host = host; | 116 | m_host = host; |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 9dd4a45..b2d6d3a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs | |||
@@ -25,6 +25,7 @@ | |||
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 | using System.Collections; | 27 | using System.Collections; |
28 | using OpenSim.Region.ScriptEngine.Interfaces; | ||
28 | namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces | 29 | namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces |
29 | { | 30 | { |
30 | public interface IOSSL_Api | 31 | public interface IOSSL_Api |
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index 6e6d169..c8d60af 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs | |||
@@ -443,6 +443,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
443 | new DetectParams[0])); | 443 | new DetectParams[0])); |
444 | PostEvent(new EventParams("state_entry", new Object[0], | 444 | PostEvent(new EventParams("state_entry", new Object[0], |
445 | new DetectParams[0])); | 445 | new DetectParams[0])); |
446 | |||
447 | throw new EventAbortException(); | ||
446 | } | 448 | } |
447 | 449 | ||
448 | public void PostEvent(EventParams data) | 450 | public void PostEvent(EventParams data) |
@@ -733,6 +735,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance | |||
733 | m_SaveState = true; | 735 | m_SaveState = true; |
734 | PostEvent(new EventParams("state_entry", | 736 | PostEvent(new EventParams("state_entry", |
735 | new Object[0], new DetectParams[0])); | 737 | new Object[0], new DetectParams[0])); |
738 | throw new EventAbortException(); | ||
736 | } | 739 | } |
737 | } | 740 | } |
738 | 741 | ||