aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ScriptEngine
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ScriptEngine')
-rw-r--r--OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs53
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs149
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs69
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs29
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs6
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs2
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs142
19 files changed, 355 insertions, 141 deletions
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index b04f6b6..2f5b526 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -59,6 +59,18 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
59 public interface IScriptInstance 59 public interface IScriptInstance
60 { 60 {
61 /// <summary> 61 /// <summary>
62 /// Debug level for this script instance.
63 /// </summary>
64 /// <remarks>
65 /// Level == 0, no extra data is logged.
66 /// Level >= 1, state changes are logged.
67 /// Level >= 2, event firing is logged.
68 /// <value>
69 /// The debug level.
70 /// </value>
71 int DebugLevel { get; set; }
72
73 /// <summary>
62 /// Is the script currently running? 74 /// Is the script currently running?
63 /// </summary> 75 /// </summary>
64 bool Running { get; set; } 76 bool Running { get; set; }
@@ -114,6 +126,16 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
114 UUID AssetID { get; } 126 UUID AssetID { get; }
115 Queue EventQueue { get; } 127 Queue EventQueue { get; }
116 128
129 /// <summary>
130 /// Number of events queued for processing.
131 /// </summary>
132 long EventsQueued { get; }
133
134 /// <summary>
135 /// Number of events processed by this script instance.
136 /// </summary>
137 long EventsProcessed { get; }
138
117 void ClearQueue(); 139 void ClearQueue();
118 int StartParam { get; set; } 140 int StartParam { get; set; }
119 141
@@ -125,7 +147,13 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
125 /// <summary> 147 /// <summary>
126 /// Stop the script instance. 148 /// Stop the script instance.
127 /// </summary> 149 /// </summary>
150 /// <remarks>
151 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
152 /// there is a danger that it will self-abort and not complete the reset.
153 /// </remarks>
128 /// <param name="timeout"></param> 154 /// <param name="timeout"></param>
155 /// How many milliseconds we will wait for an existing script event to finish before
156 /// forcibly aborting that event.
129 /// <returns>true if the script was successfully stopped, false otherwise</returns> 157 /// <returns>true if the script was successfully stopped, false otherwise</returns>
130 bool Stop(int timeout); 158 bool Stop(int timeout);
131 159
@@ -147,8 +175,31 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
147 object EventProcessor(); 175 object EventProcessor();
148 176
149 int EventTime(); 177 int EventTime();
150 void ResetScript(); 178
179 /// <summary>
180 /// Reset the script.
181 /// </summary>
182 /// <remarks>
183 /// This must not be called by a thread that is in the process of handling an event for this script. Otherwise
184 /// there is a danger that it will self-abort and not complete the reset. Such a thread must call
185 /// ApiResetScript() instead.
186 /// </remarks>
187 /// <param name='timeout'>
188 /// How many milliseconds we will wait for an existing script event to finish before
189 /// forcibly aborting that event prior to script reset.
190 /// </param>
191 void ResetScript(int timeout);
192
193 /// <summary>
194 /// Reset the script.
195 /// </summary>
196 /// <remarks>
197 /// This must not be called by any thread other than the one executing the scripts current event. This is
198 /// because there is no wait or abort logic if another thread is in the middle of processing a script event.
199 /// Such an external thread should use ResetScript() instead.
200 /// </remarks>
151 void ApiResetScript(); 201 void ApiResetScript();
202
152 Dictionary<string, object> GetVars(); 203 Dictionary<string, object> GetVars();
153 void SetVars(Dictionary<string, object> vars); 204 void SetVars(Dictionary<string, object> vars);
154 DetectParams GetDetectParams(int idx); 205 DetectParams GetDetectParams(int idx);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 7ff30ca..aa389ba 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -100,6 +100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
100 protected float m_ScriptDelayFactor = 1.0f; 100 protected float m_ScriptDelayFactor = 1.0f;
101 protected float m_ScriptDistanceFactor = 1.0f; 101 protected float m_ScriptDistanceFactor = 1.0f;
102 protected float m_MinTimerInterval = 0.5f; 102 protected float m_MinTimerInterval = 0.5f;
103 protected float m_recoilScaleFactor = 0.0f;
103 104
104 protected DateTime m_timer = DateTime.Now; 105 protected DateTime m_timer = DateTime.Now;
105 protected bool m_waitingForScriptAnswer = false; 106 protected bool m_waitingForScriptAnswer = false;
@@ -187,6 +188,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
187 // there's an smtp config, so load in the snooze time. 188 // there's an smtp config, so load in the snooze time.
188 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME); 189 EMAIL_PAUSE_TIME = SMTPConfig.GetInt("email_pause_time", EMAIL_PAUSE_TIME);
189 } 190 }
191 // Rezzing an object with a velocity can create recoil. This feature seems to have been
192 // removed from recent versions of SL. The code computes recoil (vel*mass) and scales
193 // it by this factor. May be zero to turn off recoil all together.
194 m_recoilScaleFactor = m_ScriptEngine.Config.GetFloat("RecoilScaleFactor", m_recoilScaleFactor);
190 } 195 }
191 196
192 public override Object InitializeLifetimeService() 197 public override Object InitializeLifetimeService()
@@ -1483,19 +1488,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1483 return 0; 1488 return 0;
1484 1489
1485 case ScriptBaseClass.STATUS_ROTATE_X: 1490 case ScriptBaseClass.STATUS_ROTATE_X:
1486 if (m_host.GetAxisRotation(2) == 2) 1491 // if (m_host.GetAxisRotation(2) != 0)
1492 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_X) != 0)
1487 return 1; 1493 return 1;
1488 else 1494 else
1489 return 0; 1495 return 0;
1490 1496
1491 case ScriptBaseClass.STATUS_ROTATE_Y: 1497 case ScriptBaseClass.STATUS_ROTATE_Y:
1492 if (m_host.GetAxisRotation(4) == 4) 1498 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Y) != 0)
1493 return 1; 1499 return 1;
1494 else 1500 else
1495 return 0; 1501 return 0;
1496 1502
1497 case ScriptBaseClass.STATUS_ROTATE_Z: 1503 case ScriptBaseClass.STATUS_ROTATE_Z:
1498 if (m_host.GetAxisRotation(8) == 8) 1504 if (m_host.GetAxisRotation((int)SceneObjectGroup.axisSelect.STATUS_ROTATE_Z) != 0)
1499 return 1; 1505 return 1;
1500 else 1506 else
1501 return 0; 1507 return 0;
@@ -3107,11 +3113,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3107 3113
3108 PhysicsActor pa = new_group.RootPart.PhysActor; 3114 PhysicsActor pa = new_group.RootPart.PhysActor;
3109 3115
3116 //Recoil.
3110 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) 3117 if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero)
3111 { 3118 {
3112 float groupmass = new_group.GetMass(); 3119 float groupmass = new_group.GetMass();
3113 vel *= -groupmass; 3120 Vector3 recoil = -vel * groupmass * m_recoilScaleFactor;
3114 llApplyImpulse(vel, 0); 3121 if (recoil != Vector3.Zero)
3122 {
3123 llApplyImpulse(recoil, 0);
3124 }
3115 } 3125 }
3116 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) 3126 // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay)
3117 return; 3127 return;
@@ -3288,7 +3298,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3288 /// <summary> 3298 /// <summary>
3289 /// Attach the object containing this script to the avatar that owns it. 3299 /// Attach the object containing this script to the avatar that owns it.
3290 /// </summary> 3300 /// </summary>
3291 /// <param name='attachment'>The attachment point (e.g. ATTACH_CHEST)</param> 3301 /// <param name='attachmentPoint'>
3302 /// The attachment point (e.g. <see cref="OpenSim.Region.ScriptEngine.Shared.ScriptBase.ScriptBaseClass.ATTACH_CHEST">ATTACH_CHEST</see>)
3303 /// </param>
3292 /// <returns>true if the attach suceeded, false if it did not</returns> 3304 /// <returns>true if the attach suceeded, false if it did not</returns>
3293 public bool AttachToAvatar(int attachmentPoint) 3305 public bool AttachToAvatar(int attachmentPoint)
3294 { 3306 {
@@ -3719,21 +3731,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3719 } 3731 }
3720 else 3732 else
3721 { 3733 {
3722 bool sitting = false; 3734 if (m_host.ParentGroup.GetSittingAvatars().Contains(agentID))
3723 if (m_host.SitTargetAvatar == agentID)
3724 {
3725 sitting = true;
3726 }
3727 else
3728 {
3729 foreach (SceneObjectPart p in m_host.ParentGroup.Parts)
3730 {
3731 if (p.SitTargetAvatar == agentID)
3732 sitting = true;
3733 }
3734 }
3735
3736 if (sitting)
3737 { 3735 {
3738 // When agent is sitting, certain permissions are implicit if requested from sitting agent 3736 // When agent is sitting, certain permissions are implicit if requested from sitting agent
3739 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION | 3737 implicitPerms = ScriptBaseClass.PERMISSION_TRIGGER_ANIMATION |
@@ -3775,7 +3773,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
3775 INPCModule npcModule = World.RequestModuleInterface<INPCModule>(); 3773 INPCModule npcModule = World.RequestModuleInterface<INPCModule>();
3776 if (npcModule != null && npcModule.IsNPC(agentID, World)) 3774 if (npcModule != null && npcModule.IsNPC(agentID, World))
3777 { 3775 {
3778 if (agentID == m_host.ParentGroup.OwnerID || npcModule.GetOwner(agentID) == m_host.ParentGroup.OwnerID) 3776 if (npcModule.CheckPermissions(agentID, m_host.OwnerID))
3779 { 3777 {
3780 lock (m_host.TaskInventory) 3778 lock (m_host.TaskInventory)
3781 { 3779 {
@@ -4150,62 +4148,56 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
4150 public LSL_String llGetLinkName(int linknum) 4148 public LSL_String llGetLinkName(int linknum)
4151 { 4149 {
4152 m_host.AddScriptLPS(1); 4150 m_host.AddScriptLPS(1);
4153 // simplest case, this prims link number
4154 if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS)
4155 return m_host.Name;
4156 4151
4157 // parse for sitting avatare-names 4152 if (linknum < 0)
4158 List<String> nametable = new List<String>();
4159 World.ForEachRootScenePresence(delegate(ScenePresence presence)
4160 { 4153 {
4161 SceneObjectPart sitPart = presence.ParentPart; 4154 if (linknum == ScriptBaseClass.LINK_THIS)
4162 if (sitPart != null && m_host.ParentGroup.ContainsPart(sitPart.LocalId))
4163 nametable.Add(presence.ControllingClient.Name);
4164 });
4165
4166 int totalprims = m_host.ParentGroup.PrimCount + nametable.Count;
4167 if (totalprims > m_host.ParentGroup.PrimCount)
4168 {
4169 // sitting Avatar-Name with negativ linknum / SinglePrim
4170 if (linknum < 0 && m_host.ParentGroup.PrimCount == 1 && nametable.Count == 1)
4171 return nametable[0];
4172 // Prim-Name / SinglePrim Sitting Avatar
4173 if (linknum == 1 && m_host.ParentGroup.PrimCount == 1 && nametable.Count == 1)
4174 return m_host.Name; 4155 return m_host.Name;
4175 // LinkNumber > of Real PrimSet = AvatarName 4156 else
4176 if (linknum > m_host.ParentGroup.PrimCount && linknum <= totalprims) 4157 return ScriptBaseClass.NULL_KEY;
4177 return nametable[totalprims - linknum];
4178 } 4158 }
4179 4159
4180 // Single prim 4160 int actualPrimCount = m_host.ParentGroup.PrimCount;
4181 if (m_host.LinkNum == 0) 4161 List<UUID> sittingAvatarIds = m_host.ParentGroup.GetSittingAvatars();
4162 int adjustedPrimCount = actualPrimCount + sittingAvatarIds.Count;
4163
4164 // Special case for a single prim. In this case the linknum is zero. However, this will not match a single
4165 // prim that has any avatars sat upon it (in which case the root prim is link 1).
4166 if (linknum == 0)
4182 { 4167 {
4183 if (linknum == 0 || linknum == ScriptBaseClass.LINK_ROOT) 4168 if (actualPrimCount == 1 && sittingAvatarIds.Count == 0)
4184 return m_host.Name; 4169 return m_host.Name;
4185 else
4186 return UUID.Zero.ToString();
4187 }
4188 4170
4189 // Link set 4171 return ScriptBaseClass.NULL_KEY;
4190 SceneObjectPart part = null; 4172 }
4191 if (m_host.LinkNum == 1) // this is the Root prim 4173 // Special case to handle a single prim with sitting avatars. GetLinkPart() would only match zero but
4174 // here we must match 1 (ScriptBaseClass.LINK_ROOT).
4175 else if (linknum == 1 && actualPrimCount == 1)
4192 { 4176 {
4193 if (linknum < 0) 4177 if (sittingAvatarIds.Count > 0)
4194 part = m_host.ParentGroup.GetLinkNumPart(2); 4178 return m_host.ParentGroup.RootPart.Name;
4195 else 4179 else
4196 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4180 return ScriptBaseClass.NULL_KEY;
4197 } 4181 }
4198 else // this is a child prim 4182 else if (linknum <= adjustedPrimCount)
4199 { 4183 {
4200 if (linknum < 2) 4184 if (linknum <= actualPrimCount)
4201 part = m_host.ParentGroup.GetLinkNumPart(1); 4185 {
4186 return m_host.ParentGroup.GetLinkNumPart(linknum).Name;
4187 }
4202 else 4188 else
4203 part = m_host.ParentGroup.GetLinkNumPart(linknum); 4189 {
4190 ScenePresence sp = World.GetScenePresence(sittingAvatarIds[linknum - actualPrimCount - 1]);
4191 if (sp != null)
4192 return sp.Name;
4193 else
4194 return ScriptBaseClass.NULL_KEY;
4195 }
4204 } 4196 }
4205 if (part != null)
4206 return part.Name;
4207 else 4197 else
4208 return UUID.Zero.ToString(); 4198 {
4199 return ScriptBaseClass.NULL_KEY;
4200 }
4209 } 4201 }
4210 4202
4211 public LSL_Integer llGetInventoryNumber(int type) 4203 public LSL_Integer llGetInventoryNumber(int type)
@@ -5818,9 +5810,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5818 } 5810 }
5819 5811
5820 /// <summary> 5812 /// <summary>
5821 /// Insert the list identified by <src> into the 5813 /// Insert the list identified by <paramref name="src"/> into the
5822 /// list designated by <dest> such that the first 5814 /// list designated by <paramref name="dest"/> such that the first
5823 /// new element has the index specified by <index> 5815 /// new element has the index specified by <paramref name="index"/>
5824 /// </summary> 5816 /// </summary>
5825 5817
5826 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index) 5818 public LSL_List llListInsertList(LSL_List dest, LSL_List src, int index)
@@ -6653,6 +6645,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6653 ps.BurstSpeedMax = 1.0f; 6645 ps.BurstSpeedMax = 1.0f;
6654 ps.BurstRate = 0.1f; 6646 ps.BurstRate = 0.1f;
6655 ps.PartMaxAge = 10.0f; 6647 ps.PartMaxAge = 10.0f;
6648 ps.BurstPartCount = 1;
6656 return ps; 6649 return ps;
6657 } 6650 }
6658 6651
@@ -6674,10 +6667,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
6674 SetParticleSystem(m_host, rules); 6667 SetParticleSystem(m_host, rules);
6675 } 6668 }
6676 6669
6677 private void SetParticleSystem(SceneObjectPart part, LSL_List rules) 6670 private void SetParticleSystem(SceneObjectPart part, LSL_List rules)
6678 { 6671 {
6679
6680
6681 if (rules.Length == 0) 6672 if (rules.Length == 0)
6682 { 6673 {
6683 part.RemoveParticleSystem(); 6674 part.RemoveParticleSystem();
@@ -7334,6 +7325,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7334 public void llCloseRemoteDataChannel(string channel) 7325 public void llCloseRemoteDataChannel(string channel)
7335 { 7326 {
7336 m_host.AddScriptLPS(1); 7327 m_host.AddScriptLPS(1);
7328
7329 IXmlRpcRouter xmlRpcRouter = m_ScriptEngine.World.RequestModuleInterface<IXmlRpcRouter>();
7330 if (xmlRpcRouter != null)
7331 {
7332 xmlRpcRouter.UnRegisterReceiver(channel, m_item.ItemID);
7333 }
7334
7337 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>(); 7335 IXMLRPC xmlrpcMod = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
7338 xmlrpcMod.CloseXMLRPCChannel((UUID)channel); 7336 xmlrpcMod.CloseXMLRPCChannel((UUID)channel);
7339 ScriptSleep(1000); 7337 ScriptSleep(1000);
@@ -13215,7 +13213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13215 /// Get a notecard line. 13213 /// Get a notecard line.
13216 /// </summary> 13214 /// </summary>
13217 /// <param name="assetID"></param> 13215 /// <param name="assetID"></param>
13218 /// <param name="line">Lines start at index 0</param> 13216 /// <param name="lineNumber">Lines start at index 0</param>
13219 /// <returns></returns> 13217 /// <returns></returns>
13220 public static string GetLine(UUID assetID, int lineNumber) 13218 public static string GetLine(UUID assetID, int lineNumber)
13221 { 13219 {
@@ -13244,9 +13242,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
13244 /// Get a notecard line. 13242 /// Get a notecard line.
13245 /// </summary> 13243 /// </summary>
13246 /// <param name="assetID"></param> 13244 /// <param name="assetID"></param>
13247 /// <param name="line">Lines start at index 0</param> 13245 /// <param name="lineNumber">Lines start at index 0</param>
13248 /// <param name="maxLength">Maximum length of the returned line. Longer lines will be truncated</para> 13246 /// <param name="maxLength">
13249 /// <returns></returns> 13247 /// Maximum length of the returned line.
13248 /// </param>
13249 /// <returns>
13250 /// If the line length is longer than <paramref name="maxLength"/>,
13251 /// the return string will be truncated.
13252 /// </returns>
13250 public static string GetLine(UUID assetID, int lineNumber, int maxLength) 13253 public static string GetLine(UUID assetID, int lineNumber, int maxLength)
13251 { 13254 {
13252 string line = GetLine(assetID, lineNumber); 13255 string line = GetLine(assetID, lineNumber);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 51c8c7e..637d83a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1214,12 +1214,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1214 sunHour += 24.0; 1214 sunHour += 24.0;
1215 1215
1216 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun; 1216 World.RegionInfo.RegionSettings.UseEstateSun = useEstateSun;
1217 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30 1217 World.RegionInfo.RegionSettings.SunPosition = sunHour + 6; // LL Region Sun Hour is 6 to 30
1218 World.RegionInfo.RegionSettings.FixedSun = sunFixed; 1218 World.RegionInfo.RegionSettings.FixedSun = sunFixed;
1219 World.RegionInfo.RegionSettings.Save(); 1219 World.RegionInfo.RegionSettings.Save();
1220 1220
1221 World.EventManager.TriggerEstateToolsSunUpdate( 1221 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1222 World.RegionInfo.RegionHandle, sunFixed, useEstateSun, (float)sunHour);
1223 } 1222 }
1224 1223
1225 /// <summary> 1224 /// <summary>
@@ -1244,8 +1243,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1244 World.RegionInfo.EstateSettings.FixedSun = sunFixed; 1243 World.RegionInfo.EstateSettings.FixedSun = sunFixed;
1245 World.RegionInfo.EstateSettings.Save(); 1244 World.RegionInfo.EstateSettings.Save();
1246 1245
1247 World.EventManager.TriggerEstateToolsSunUpdate( 1246 World.EventManager.TriggerEstateToolsSunUpdate(World.RegionInfo.RegionHandle);
1248 World.RegionInfo.RegionHandle, sunFixed, World.RegionInfo.RegionSettings.UseEstateSun, (float)sunHour);
1249 } 1247 }
1250 1248
1251 /// <summary> 1249 /// <summary>
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
index 7763619..77e087c 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CSCodeGeneratorTest.cs
@@ -39,7 +39,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
39 /// The generated C# code is compared against the expected C# code. 39 /// The generated C# code is compared against the expected C# code.
40 /// </summary> 40 /// </summary>
41 [TestFixture] 41 [TestFixture]
42 public class CSCodeGeneratorTest 42 public class CSCodeGeneratorTest : OpenSimTestCase
43 { 43 {
44 [Test] 44 [Test]
45 public void TestDefaultState() 45 public void TestDefaultState()
diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
index 1fa6954..05a8756 100644
--- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Tests/CompilerTest.cs
@@ -41,7 +41,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools.Tests
41 /// the LSL source. 41 /// the LSL source.
42 /// </summary> 42 /// </summary>
43 [TestFixture] 43 [TestFixture]
44 public class CompilerTest 44 public class CompilerTest : OpenSimTestCase
45 { 45 {
46 private string m_testDir; 46 private string m_testDir;
47 private CSharpCodeProvider m_CSCodeProvider; 47 private CSharpCodeProvider m_CSCodeProvider;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 771db0c..ff4d130 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -94,6 +94,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
94 private UUID m_CurrentStateHash; 94 private UUID m_CurrentStateHash;
95 private UUID m_RegionID; 95 private UUID m_RegionID;
96 96
97 public int DebugLevel { get; set; }
98
97 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; } 99 public Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> LineMap { get; set; }
98 100
99 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>(); 101 private Dictionary<string,IScriptApi> m_Apis = new Dictionary<string,IScriptApi>();
@@ -174,6 +176,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
174 176
175 public Queue EventQueue { get; private set; } 177 public Queue EventQueue { get; private set; }
176 178
179 public long EventsQueued
180 {
181 get
182 {
183 lock (EventQueue)
184 return EventQueue.Count;
185 }
186 }
187
188 public long EventsProcessed { get; private set; }
189
177 public int StartParam { get; set; } 190 public int StartParam { get; set; }
178 191
179 public TaskInventoryItem ScriptTask { get; private set; } 192 public TaskInventoryItem ScriptTask { get; private set; }
@@ -538,9 +551,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
538 // forcibly abort the work item (this aborts the underlying thread). 551 // forcibly abort the work item (this aborts the underlying thread).
539 if (!m_InSelfDelete) 552 if (!m_InSelfDelete)
540 { 553 {
541// m_log.ErrorFormat( 554 m_log.DebugFormat(
542// "[SCRIPT INSTANCE]: Aborting script {0} {1} in prim {2} {3} {4} {5}", 555 "[SCRIPT INSTANCE]: Aborting unstopped script {0} {1} in prim {2}, localID {3}, timeout was {4} ms",
543// ScriptName, ItemID, PrimName, ObjectID, m_InSelfDelete, DateTime.Now.Ticks); 556 ScriptName, ItemID, PrimName, LocalID, timeout);
544 557
545 workItem.Abort(); 558 workItem.Abort();
546 } 559 }
@@ -696,19 +709,41 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
696 { 709 {
697 710
698// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this); 711// m_log.DebugFormat("[XEngine]: Processing event {0} for {1}", data.EventName, this);
712 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
713
714 if (DebugLevel >= 2)
715 m_log.DebugFormat(
716 "[SCRIPT INSTANCE]: Processing event {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
717 data.EventName,
718 ScriptName,
719 part.Name,
720 part.LocalId,
721 part.ParentGroup.Name,
722 part.ParentGroup.UUID,
723 part.AbsolutePosition,
724 part.ParentGroup.Scene.Name);
699 725
700 m_DetectParams = data.DetectParams; 726 m_DetectParams = data.DetectParams;
701 727
702 if (data.EventName == "state") // Hardcoded state change 728 if (data.EventName == "state") // Hardcoded state change
703 { 729 {
704 // m_log.DebugFormat("[Script] Script {0}.{1} state set to {2}",
705 // PrimName, ScriptName, data.Params[0].ToString());
706 State = data.Params[0].ToString(); 730 State = data.Params[0].ToString();
731
732 if (DebugLevel >= 1)
733 m_log.DebugFormat(
734 "[SCRIPT INSTANCE]: Changing state to {0} for {1}/{2}({3})/{4}({5}) @ {6}/{7}",
735 State,
736 ScriptName,
737 part.Name,
738 part.LocalId,
739 part.ParentGroup.Name,
740 part.ParentGroup.UUID,
741 part.AbsolutePosition,
742 part.ParentGroup.Scene.Name);
743
707 AsyncCommandManager.RemoveScript(Engine, 744 AsyncCommandManager.RemoveScript(Engine,
708 LocalID, ItemID); 745 LocalID, ItemID);
709 746
710 SceneObjectPart part = Engine.World.GetSceneObjectPart(
711 LocalID);
712 if (part != null) 747 if (part != null)
713 { 748 {
714 part.SetScriptEvents(ItemID, 749 part.SetScriptEvents(ItemID,
@@ -720,8 +755,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
720 if (Engine.World.PipeEventsForScript(LocalID) || 755 if (Engine.World.PipeEventsForScript(LocalID) ||
721 data.EventName == "control") // Don't freeze avies! 756 data.EventName == "control") // Don't freeze avies!
722 { 757 {
723 SceneObjectPart part = Engine.World.GetSceneObjectPart(
724 LocalID);
725 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}", 758 // m_log.DebugFormat("[Script] Delivered event {2} in state {3} to {0}.{1}",
726 // PrimName, ScriptName, data.EventName, State); 759 // PrimName, ScriptName, data.EventName, State);
727 760
@@ -776,6 +809,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
776 ChatTypeEnum.DebugChannel, 2147483647, 809 ChatTypeEnum.DebugChannel, 2147483647,
777 part.AbsolutePosition, 810 part.AbsolutePosition,
778 part.Name, part.UUID, false); 811 part.Name, part.UUID, false);
812
813
814 m_log.DebugFormat(
815 "[SCRIPT INSTANCE]: Runtime error in script {0}, part {1} {2} at {3} in {4}, displayed error {5}, actual exception {6}",
816 ScriptName,
817 PrimName,
818 part.UUID,
819 part.AbsolutePosition,
820 part.ParentGroup.Scene.Name,
821 text.Replace("\n", "\\n"),
822 e.InnerException);
779 } 823 }
780 catch (Exception) 824 catch (Exception)
781 { 825 {
@@ -810,6 +854,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
810 // script engine to run the next event. 854 // script engine to run the next event.
811 lock (EventQueue) 855 lock (EventQueue)
812 { 856 {
857 EventsProcessed++;
858
813 if (EventQueue.Count > 0 && Running && !ShuttingDown) 859 if (EventQueue.Count > 0 && Running && !ShuttingDown)
814 { 860 {
815 m_CurrentWorkItem = Engine.QueueEventHandler(this); 861 m_CurrentWorkItem = Engine.QueueEventHandler(this);
@@ -834,7 +880,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
834 return (DateTime.Now - m_EventStart).Seconds; 880 return (DateTime.Now - m_EventStart).Seconds;
835 } 881 }
836 882
837 public void ResetScript() 883 public void ResetScript(int timeout)
838 { 884 {
839 if (m_Script == null) 885 if (m_Script == null)
840 return; 886 return;
@@ -844,7 +890,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
844 RemoveState(); 890 RemoveState();
845 ReleaseControls(); 891 ReleaseControls();
846 892
847 Stop(0); 893 Stop(timeout);
848 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID); 894 SceneObjectPart part = Engine.World.GetSceneObjectPart(LocalID);
849 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0; 895 part.Inventory.GetInventoryItem(ItemID).PermsMask = 0;
850 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero; 896 part.Inventory.GetInventoryItem(ItemID).PermsGranter = UUID.Zero;
@@ -1015,7 +1061,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
1015 "({0}): {1}", scriptLine - 1, 1061 "({0}): {1}", scriptLine - 1,
1016 e.InnerException.Message); 1062 e.InnerException.Message);
1017 1063
1018 System.Console.WriteLine(e.ToString()+"\n");
1019 return message; 1064 return message;
1020 } 1065 }
1021 } 1066 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
index c9c4753..2e61fb8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs
@@ -633,19 +633,44 @@ namespace OpenSim.Region.ScriptEngine.Shared
633 633
634 public LSL_Types.Vector3 GetVector3Item(int itemIndex) 634 public LSL_Types.Vector3 GetVector3Item(int itemIndex)
635 { 635 {
636 if(m_data[itemIndex] is LSL_Types.Vector3) 636 if (m_data[itemIndex] is LSL_Types.Vector3)
637 {
637 return (LSL_Types.Vector3)m_data[itemIndex]; 638 return (LSL_Types.Vector3)m_data[itemIndex];
639 }
640 else if(m_data[itemIndex] is OpenMetaverse.Vector3)
641 {
642 return new LSL_Types.Vector3(
643 (OpenMetaverse.Vector3)m_data[itemIndex]);
644 }
638 else 645 else
646 {
639 throw new InvalidCastException(string.Format( 647 throw new InvalidCastException(string.Format(
640 "{0} expected but {1} given", 648 "{0} expected but {1} given",
641 typeof(LSL_Types.Vector3).Name, 649 typeof(LSL_Types.Vector3).Name,
642 m_data[itemIndex] != null ? 650 m_data[itemIndex] != null ?
643 m_data[itemIndex].GetType().Name : "null")); 651 m_data[itemIndex].GetType().Name : "null"));
652 }
644 } 653 }
645 654
646 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) 655 public LSL_Types.Quaternion GetQuaternionItem(int itemIndex)
647 { 656 {
648 return (LSL_Types.Quaternion)m_data[itemIndex]; 657 if (m_data[itemIndex] is LSL_Types.Quaternion)
658 {
659 return (LSL_Types.Quaternion)m_data[itemIndex];
660 }
661 else if(m_data[itemIndex] is OpenMetaverse.Quaternion)
662 {
663 return new LSL_Types.Quaternion(
664 (OpenMetaverse.Quaternion)m_data[itemIndex]);
665 }
666 else
667 {
668 throw new InvalidCastException(string.Format(
669 "{0} expected but {1} given",
670 typeof(LSL_Types.Quaternion).Name,
671 m_data[itemIndex] != null ?
672 m_data[itemIndex].GetType().Name : "null"));
673 }
649 } 674 }
650 675
651 public LSL_Types.key GetKeyItem(int itemIndex) 676 public LSL_Types.key GetKeyItem(int itemIndex)
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
index c73e22f..cb7291a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs
@@ -51,14 +51,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for inventory functions in LSL 51 /// Tests for inventory functions in LSL
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class LSL_ApiInventoryTests 54 public class LSL_ApiInventoryTests : OpenSimTestCase
55 { 55 {
56 protected Scene m_scene; 56 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
58 58
59 [SetUp] 59 [SetUp]
60 public void SetUp() 60 public override void SetUp()
61 { 61 {
62 base.SetUp();
63
62 IConfigSource initConfigSource = new IniConfigSource(); 64 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 65 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 66 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
index 2565ae7..d9b17d7 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiLinkingTests.cs
@@ -56,14 +56,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests. 56 /// OpenSim.Region.Framework.Scenes.Tests.SceneObjectLinkingTests.
57 /// </remarks> 57 /// </remarks>
58 [TestFixture] 58 [TestFixture]
59 public class LSL_ApiLinkingTests 59 public class LSL_ApiLinkingTests : OpenSimTestCase
60 { 60 {
61 protected Scene m_scene; 61 protected Scene m_scene;
62 protected XEngine.XEngine m_engine; 62 protected XEngine.XEngine m_engine;
63 63
64 [SetUp] 64 [SetUp]
65 public void SetUp() 65 public override void SetUp()
66 { 66 {
67 base.SetUp();
68
67 IConfigSource initConfigSource = new IniConfigSource(); 69 IConfigSource initConfigSource = new IniConfigSource();
68 IConfig config = initConfigSource.AddConfig("XEngine"); 70 IConfig config = initConfigSource.AddConfig("XEngine");
69 config.Set("Enabled", "true"); 71 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
index dd23be8..98017d8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs
@@ -46,13 +46,15 @@ using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString;
46namespace OpenSim.Region.ScriptEngine.Shared.Tests 46namespace OpenSim.Region.ScriptEngine.Shared.Tests
47{ 47{
48 [TestFixture] 48 [TestFixture]
49 public class LSL_ApiListTests 49 public class LSL_ApiListTests : OpenSimTestCase
50 { 50 {
51 private LSL_Api m_lslApi; 51 private LSL_Api m_lslApi;
52 52
53 [SetUp] 53 [SetUp]
54 public void SetUp() 54 public override void SetUp()
55 { 55 {
56 base.SetUp();
57
56 IConfigSource initConfigSource = new IniConfigSource(); 58 IConfigSource initConfigSource = new IniConfigSource();
57 IConfig config = initConfigSource.AddConfig("XEngine"); 59 IConfig config = initConfigSource.AddConfig("XEngine");
58 config.Set("Enabled", "true"); 60 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
index 3ed2562..c8c7f82 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLFloat.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLFloat 36 public class LSL_TypesTestLSLFloat : OpenSimTestCase
37 { 37 {
38 // Used for testing equality of two floats. 38 // Used for testing equality of two floats.
39 private double _lowPrecisionTolerance = 0.000001; 39 private double _lowPrecisionTolerance = 0.000001;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
index 8d1169a..c664108 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLInteger.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLInteger 36 public class LSL_TypesTestLSLInteger : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, int> m_doubleIntSet; 38 private Dictionary<double, int> m_doubleIntSet;
39 private Dictionary<string, int> m_stringIntSet; 39 private Dictionary<string, int> m_stringIntSet;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
index c4ca1a8..8550f2d 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestLSLString.cs
@@ -33,7 +33,7 @@ using OpenSim.Region.ScriptEngine.Shared;
33namespace OpenSim.Region.ScriptEngine.Shared.Tests 33namespace OpenSim.Region.ScriptEngine.Shared.Tests
34{ 34{
35 [TestFixture] 35 [TestFixture]
36 public class LSL_TypesTestLSLString 36 public class LSL_TypesTestLSLString : OpenSimTestCase
37 { 37 {
38 private Dictionary<double, string> m_doubleStringSet; 38 private Dictionary<double, string> m_doubleStringSet;
39 39
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
index b81225f..71b88bc 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestList.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests the LSL_Types.list class. 36 /// Tests the LSL_Types.list class.
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestList 39 public class LSL_TypesTestList : OpenSimTestCase
40 { 40 {
41 /// <summary> 41 /// <summary>
42 /// Tests concatenating a string to a list. 42 /// Tests concatenating a string to a list.
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
index ebf8001..0c838af 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_TypesTestVector3.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
36 /// Tests for Vector3 36 /// Tests for Vector3
37 /// </summary> 37 /// </summary>
38 [TestFixture] 38 [TestFixture]
39 public class LSL_TypesTestVector3 39 public class LSL_TypesTestVector3 : OpenSimTestCase
40 { 40 {
41 [Test] 41 [Test]
42 public void TestDotProduct() 42 public void TestDotProduct()
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
index c401794..1381d2b 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs
@@ -51,14 +51,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
51 /// Tests for OSSL_Api 51 /// Tests for OSSL_Api
52 /// </summary> 52 /// </summary>
53 [TestFixture] 53 [TestFixture]
54 public class OSSL_ApiAppearanceTest 54 public class OSSL_ApiAppearanceTest : OpenSimTestCase
55 { 55 {
56 protected Scene m_scene; 56 protected Scene m_scene;
57 protected XEngine.XEngine m_engine; 57 protected XEngine.XEngine m_engine;
58 58
59 [SetUp] 59 [SetUp]
60 public void SetUp() 60 public override void SetUp()
61 { 61 {
62 base.SetUp();
63
62 IConfigSource initConfigSource = new IniConfigSource(); 64 IConfigSource initConfigSource = new IniConfigSource();
63 IConfig config = initConfigSource.AddConfig("XEngine"); 65 IConfig config = initConfigSource.AddConfig("XEngine");
64 config.Set("Enabled", "true"); 66 config.Set("Enabled", "true");
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
index b49bcc2..d6c82f1 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs
@@ -127,12 +127,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
127 OSSL_Api osslApi = new OSSL_Api(); 127 OSSL_Api osslApi = new OSSL_Api();
128 osslApi.Initialize(m_engine, so.RootPart, null); 128 osslApi.Initialize(m_engine, so.RootPart, null);
129 129
130 string npcRaw;
131 bool gotExpectedException = false; 130 bool gotExpectedException = false;
132 try 131 try
133 { 132 {
134 npcRaw 133 osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
135 = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name");
136 } 134 }
137 catch (ScriptException) 135 catch (ScriptException)
138 { 136 {
diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
index f331658..5abfe9a 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests
44 /// XEngine tests. 44 /// XEngine tests.
45 /// </summary> 45 /// </summary>
46 [TestFixture] 46 [TestFixture]
47 public class XEngineTest 47 public class XEngineTest : OpenSimTestCase
48 { 48 {
49 private TestScene m_scene; 49 private TestScene m_scene;
50 private XEngine m_xEngine; 50 private XEngine m_xEngine;
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9f05666..05dd7ab 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -31,6 +31,7 @@ using System.Collections.Generic;
31using System.Diagnostics; //for [DebuggerNonUserCode] 31using System.Diagnostics; //for [DebuggerNonUserCode]
32using System.Globalization; 32using System.Globalization;
33using System.IO; 33using System.IO;
34using System.Linq;
34using System.Reflection; 35using System.Reflection;
35using System.Security; 36using System.Security;
36using System.Security.Policy; 37using System.Security.Policy;
@@ -107,6 +108,24 @@ namespace OpenSim.Region.ScriptEngine.XEngine
107 private IXmlRpcRouter m_XmlRpcRouter; 108 private IXmlRpcRouter m_XmlRpcRouter;
108 private int m_EventLimit; 109 private int m_EventLimit;
109 private bool m_KillTimedOutScripts; 110 private bool m_KillTimedOutScripts;
111
112 /// <summary>
113 /// Number of milliseconds we will wait for a script event to complete on script stop before we forcibly abort
114 /// its thread.
115 /// </summary>
116 /// <remarks>
117 /// It appears that if a script thread is aborted whilst it is holding ReaderWriterLockSlim (possibly the write
118 /// lock) then the lock is not properly released. This causes mono 2.6, 2.10 and possibly
119 /// later to crash, sometimes with symptoms such as a leap to 100% script usage and a vm thead dump showing
120 /// all threads waiting on release of ReaderWriterLockSlim write thread which none of the threads listed
121 /// actually hold.
122 ///
123 /// Pausing for event completion reduces the risk of this happening. However, it may be that aborting threads
124 /// is not a mono issue per se but rather a risky activity in itself in an AppDomain that is not immediately
125 /// shutting down.
126 /// </remarks>
127 private int m_WaitForEventCompletionOnScriptStop = 1000;
128
110 private string m_ScriptEnginesPath = null; 129 private string m_ScriptEnginesPath = null;
111 130
112 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>(); 131 private ExpiringCache<UUID, bool> m_runFlags = new ExpiringCache<UUID, bool>();
@@ -316,6 +335,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
316 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30); 335 m_EventLimit = m_ScriptConfig.GetInt("EventLimit", 30);
317 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false); 336 m_KillTimedOutScripts = m_ScriptConfig.GetBoolean("KillTimedOutScripts", false);
318 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000; 337 m_SaveTime = m_ScriptConfig.GetInt("SaveInterval", 120) * 1000;
338 m_WaitForEventCompletionOnScriptStop
339 = m_ScriptConfig.GetInt("WaitForEventCompletionOnScriptStop", m_WaitForEventCompletionOnScriptStop);
340
319 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines"); 341 m_ScriptEnginesPath = m_ScriptConfig.GetString("ScriptEnginesPath", "ScriptEngines");
320 342
321 m_Prio = ThreadPriority.BelowNormal; 343 m_Prio = ThreadPriority.BelowNormal;
@@ -371,7 +393,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
371 393
372 MainConsole.Instance.Commands.AddCommand( 394 MainConsole.Instance.Commands.AddCommand(
373 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information", 395 "Scripts", false, "scripts show", "scripts show [<script-item-uuid>]", "Show script information",
374 "Show information on all scripts known to the script engine." 396 "Show information on all scripts known to the script engine.\n"
375 + "If a <script-item-uuid> is given then only information on that script will be shown.", 397 + "If a <script-item-uuid> is given then only information on that script will be shown.",
376 HandleShowScripts); 398 HandleShowScripts);
377 399
@@ -390,22 +412,30 @@ namespace OpenSim.Region.ScriptEngine.XEngine
390 MainConsole.Instance.Commands.AddCommand( 412 MainConsole.Instance.Commands.AddCommand(
391 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts", 413 "Scripts", false, "scripts resume", "scripts resume [<script-item-uuid>]", "Resumes all suspended scripts",
392 "Resumes all currently suspended scripts.\n" 414 "Resumes all currently suspended scripts.\n"
393 + "Resumed scripts will process all events accumulated whilst suspended." 415 + "Resumed scripts will process all events accumulated whilst suspended.\n"
394 + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.", 416 + "If a <script-item-uuid> is given then only that script will be resumed. Otherwise, all suitable scripts are resumed.",
395 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript)); 417 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleResumeScript));
396 418
397 MainConsole.Instance.Commands.AddCommand( 419 MainConsole.Instance.Commands.AddCommand(
398 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts", 420 "Scripts", false, "scripts stop", "scripts stop [<script-item-uuid>]", "Stops all running scripts",
399 "Stops all running scripts." 421 "Stops all running scripts.\n"
400 + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.", 422 + "If a <script-item-uuid> is given then only that script will be stopped. Otherwise, all suitable scripts are stopped.",
401 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript)); 423 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStopScript));
402 424
403 MainConsole.Instance.Commands.AddCommand( 425 MainConsole.Instance.Commands.AddCommand(
404 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts", 426 "Scripts", false, "scripts start", "scripts start [<script-item-uuid>]", "Starts all stopped scripts",
405 "Starts all stopped scripts." 427 "Starts all stopped scripts.\n"
406 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.", 428 + "If a <script-item-uuid> is given then only that script will be started. Otherwise, all suitable scripts are started.",
407 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); 429 (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript));
408 430
431 MainConsole.Instance.Commands.AddCommand(
432 "Scripts", false, "debug script log", "debug scripts log <item-id> <log-level>", "Extra debug logging for a script",
433 "Activates or deactivates extra debug logging for the given script.\n"
434 + "Level == 0, deactivate extra debug logging.\n"
435 + "Level >= 1, log state changes.\n"
436 + "Level >= 2, log event invocations.\n",
437 HandleDebugScriptLogCommand);
438
409// MainConsole.Instance.Commands.AddCommand( 439// MainConsole.Instance.Commands.AddCommand(
410// "Debug", false, "debug xengine", "debug xengine [<level>]", 440// "Debug", false, "debug xengine", "debug xengine [<level>]",
411// "Turn on detailed xengine debugging.", 441// "Turn on detailed xengine debugging.",
@@ -414,6 +444,41 @@ namespace OpenSim.Region.ScriptEngine.XEngine
414// HandleDebugLevelCommand); 444// HandleDebugLevelCommand);
415 } 445 }
416 446
447 private void HandleDebugScriptLogCommand(string module, string[] args)
448 {
449 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
450 return;
451
452 if (args.Length != 5)
453 {
454 MainConsole.Instance.Output("Usage: debug script log <item-id> <log-level>");
455 return;
456 }
457
458 UUID itemId;
459
460 if (!ConsoleUtil.TryParseConsoleUuid(MainConsole.Instance, args[3], out itemId))
461 return;
462
463 int newLevel;
464
465 if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[4], out newLevel))
466 return;
467
468 IScriptInstance si;
469
470 lock (m_Scripts)
471 {
472 // XXX: We can't give the user feedback on a bad item id because this may apply to a different script
473 // engine
474 if (!m_Scripts.TryGetValue(itemId, out si))
475 return;
476 }
477
478 si.DebugLevel = newLevel;
479 MainConsole.Instance.OutputFormat("Set debug level of {0} {1} to {2}", si.ScriptName, si.ItemID, newLevel);
480 }
481
417 /// <summary> 482 /// <summary>
418 /// Change debug level 483 /// Change debug level
419 /// </summary> 484 /// </summary>
@@ -445,9 +510,21 @@ namespace OpenSim.Region.ScriptEngine.XEngine
445 /// </summary> 510 /// </summary>
446 /// <param name="cmdparams"></param> 511 /// <param name="cmdparams"></param>
447 /// <param name="instance"></param> 512 /// <param name="instance"></param>
448 /// <returns>true if we're okay to proceed, false if not.</returns> 513 /// <param name="comparer">Basis on which to sort output. Can be null if no sort needs to take place</param>
449 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action) 514 private void HandleScriptsAction(string[] cmdparams, Action<IScriptInstance> action)
450 { 515 {
516 HandleScriptsAction<object>(cmdparams, action, null);
517 }
518
519 /// <summary>
520 /// Parse the raw item id into a script instance from the command params if it's present.
521 /// </summary>
522 /// <param name="cmdparams"></param>
523 /// <param name="instance"></param>
524 /// <param name="keySelector">Basis on which to sort output. Can be null if no sort needs to take place</param>
525 private void HandleScriptsAction<TKey>(
526 string[] cmdparams, Action<IScriptInstance> action, Func<IScriptInstance, TKey> keySelector)
527 {
451 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) 528 if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene))
452 return; 529 return;
453 530
@@ -458,7 +535,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
458 535
459 if (cmdparams.Length == 2) 536 if (cmdparams.Length == 2)
460 { 537 {
461 foreach (IScriptInstance instance in m_Scripts.Values) 538 IEnumerable<IScriptInstance> scripts = m_Scripts.Values;
539
540 if (keySelector != null)
541 scripts = scripts.OrderBy<IScriptInstance, TKey>(keySelector);
542
543 foreach (IScriptInstance instance in scripts)
462 action(instance); 544 action(instance);
463 545
464 return; 546 return;
@@ -468,7 +550,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
468 550
469 if (!UUID.TryParse(rawItemId, out itemId)) 551 if (!UUID.TryParse(rawItemId, out itemId))
470 { 552 {
471 MainConsole.Instance.OutputFormat("Error - {0} is not a valid UUID", rawItemId); 553 MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid UUID", rawItemId);
472 return; 554 return;
473 } 555 }
474 556
@@ -505,9 +587,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine
505 StringBuilder sb = new StringBuilder(); 587 StringBuilder sb = new StringBuilder();
506 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); 588 sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName);
507 589
590 long scriptsLoaded, eventsQueued = 0, eventsProcessed = 0;
591
508 lock (m_Scripts) 592 lock (m_Scripts)
509 sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); 593 {
594 scriptsLoaded = m_Scripts.Count;
595
596 foreach (IScriptInstance si in m_Scripts.Values)
597 {
598 eventsQueued += si.EventsQueued;
599 eventsProcessed += si.EventsProcessed;
600 }
601 }
510 602
603 sb.AppendFormat("Scripts loaded : {0}\n", scriptsLoaded);
511 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); 604 sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count);
512 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); 605 sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count);
513 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads); 606 sb.AppendFormat("Max threads : {0}\n", m_ThreadPool.MaxThreads);
@@ -516,6 +609,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine
516 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); 609 sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads);
517 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); 610 sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks);
518// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); 611// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count);
612 sb.AppendFormat("Events queued : {0}\n", eventsQueued);
613 sb.AppendFormat("Events processed : {0}\n", eventsProcessed);
519 614
520 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this); 615 SensorRepeat sr = AsyncCommandManager.GetSensorRepeatPlugin(this);
521 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0); 616 sb.AppendFormat("Sensors : {0}\n", sr != null ? sr.SensorsCount : 0);
@@ -546,7 +641,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
546 } 641 }
547 } 642 }
548 643
549 HandleScriptsAction(cmdparams, HandleShowScript); 644 HandleScriptsAction<long>(cmdparams, HandleShowScript, si => si.EventsProcessed);
550 } 645 }
551 646
552 private void HandleShowScript(IScriptInstance instance) 647 private void HandleShowScript(IScriptInstance instance)
@@ -576,11 +671,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
576 671
577 sb.AppendFormat("Script name : {0}\n", instance.ScriptName); 672 sb.AppendFormat("Script name : {0}\n", instance.ScriptName);
578 sb.AppendFormat("Status : {0}\n", status); 673 sb.AppendFormat("Status : {0}\n", status);
579 674 sb.AppendFormat("Queued events : {0}\n", instance.EventsQueued);
580 lock (eq) 675 sb.AppendFormat("Processed events : {0}\n", instance.EventsProcessed);
581 sb.AppendFormat("Queued events : {0}\n", eq.Count);
582
583 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); 676 sb.AppendFormat("Item UUID : {0}\n", instance.ItemID);
677 sb.AppendFormat("Asset UUID : {0}\n", instance.AssetID);
584 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); 678 sb.AppendFormat("Containing part name: {0}\n", instance.PrimName);
585 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); 679 sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID);
586 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); 680 sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition);
@@ -1089,8 +1183,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1089 1183
1090 string assembly = ""; 1184 string assembly = "";
1091 1185
1092 CultureInfo USCulture = new CultureInfo("en-US"); 1186 Culture.SetCurrentCulture();
1093 Thread.CurrentThread.CurrentCulture = USCulture;
1094 1187
1095 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap; 1188 Dictionary<KeyValuePair<int, int>, KeyValuePair<int, int>> linemap;
1096 1189
@@ -1347,9 +1440,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1347 lockScriptsForWrite(false); 1440 lockScriptsForWrite(false);
1348 instance.ClearQueue(); 1441 instance.ClearQueue();
1349 1442
1350 // Give the script some time to finish processing its last event. Simply aborting the script thread can 1443 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1351 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1352 instance.Stop(1000);
1353 1444
1354// bool objectRemoved = false; 1445// bool objectRemoved = false;
1355 1446
@@ -1485,6 +1576,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1485 startInfo.StartSuspended = true; 1576 startInfo.StartSuspended = true;
1486 1577
1487 m_ThreadPool = new SmartThreadPool(startInfo); 1578 m_ThreadPool = new SmartThreadPool(startInfo);
1579 m_ThreadPool.Name = "XEngine";
1488 } 1580 }
1489 1581
1490 // 1582 //
@@ -1504,8 +1596,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1504 /// <returns></returns> 1596 /// <returns></returns>
1505 private object ProcessEventHandler(object parms) 1597 private object ProcessEventHandler(object parms)
1506 { 1598 {
1507 CultureInfo USCulture = new CultureInfo("en-US"); 1599 Culture.SetCurrentCulture();
1508 Thread.CurrentThread.CurrentCulture = USCulture;
1509 1600
1510 IScriptInstance instance = (ScriptInstance) parms; 1601 IScriptInstance instance = (ScriptInstance) parms;
1511 1602
@@ -1693,7 +1784,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1693 { 1784 {
1694 IScriptInstance instance = GetInstance(itemID); 1785 IScriptInstance instance = GetInstance(itemID);
1695 if (instance != null) 1786 if (instance != null)
1696 instance.ResetScript(); 1787 instance.ResetScript(m_WaitForEventCompletionOnScriptStop);
1697 } 1788 }
1698 1789
1699 public void StartScript(UUID itemID) 1790 public void StartScript(UUID itemID)
@@ -1708,16 +1799,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine
1708 public void StopScript(UUID itemID) 1799 public void StopScript(UUID itemID)
1709 { 1800 {
1710 IScriptInstance instance = GetInstance(itemID); 1801 IScriptInstance instance = GetInstance(itemID);
1802
1711 if (instance != null) 1803 if (instance != null)
1712 { 1804 instance.Stop(m_WaitForEventCompletionOnScriptStop);
1713 // Give the script some time to finish processing its last event. Simply aborting the script thread can
1714 // cause issues on mono 2.6, 2.10 and possibly later where locks are not released properly on abort.
1715 instance.Stop(1000);
1716 }
1717 else 1805 else
1718 {
1719 m_runFlags.AddOrUpdate(itemID, false, 240); 1806 m_runFlags.AddOrUpdate(itemID, false, 240);
1720 }
1721 } 1807 }
1722 1808
1723 public DetectParams GetDetectParams(UUID itemID, int idx) 1809 public DetectParams GetDetectParams(UUID itemID, int idx)