From 08bd16285d3b9e2be8f76db17ac7cd7a861ae817 Mon Sep 17 00:00:00 2001 From: Justin Clark-Casey (justincc) Date: Wed, 7 Sep 2011 23:55:41 +0100 Subject: When invoking any of the OSSL teleport functions, do it on a separate thread rather than the script thread. This is to prevent the aborting of attachment script threads on teleport from aborting the one actually doing the teleport. This allows OSSL teleport functions to work when invoked on scripts in attachments (and huds, I assume) --- .../Shared/Api/Implementation/OSSL_Api.cs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 3ddd79b..e1c837e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -703,9 +703,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api == World.LandChannel.GetLandObject( presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) { - World.RequestTeleportLocation(presence.ControllingClient, regionName, - new Vector3((float)position.x, (float)position.y, (float)position.z), - new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); + // We will launch the teleport on a new thread so that when the script threads are terminated + // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. + Util.FireAndForget( + o => World.RequestTeleportLocation(presence.ControllingClient, regionName, + new Vector3((float)position.x, (float)position.y, (float)position.z), + new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); ScriptSleep(5000); } @@ -741,9 +744,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api == World.LandChannel.GetLandObject( presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) { - World.RequestTeleportLocation(presence.ControllingClient, regionHandle, - new Vector3((float)position.x, (float)position.y, (float)position.z), - new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); + // We will launch the teleport on a new thread so that when the script threads are terminated + // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. + Util.FireAndForget( + o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, + new Vector3((float)position.x, (float)position.y, (float)position.z), + new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); + ScriptSleep(5000); } } -- cgit v1.1 From 28961dd1cfc21a90510faa33af6d3c1c6f8bc0af Mon Sep 17 00:00:00 2001 From: Micheil Merlin Date: Sun, 4 Sep 2011 12:21:29 -0500 Subject: llSetPrimitiveParams Prim type params precision errors --- .../Shared/Api/Implementation/LSL_Api.cs | 76 ++++++++++++++++------ 1 file changed, 57 insertions(+), 19 deletions(-) (limited to 'OpenSim/Region/ScriptEngine/Shared/Api/Implementation') diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 88e884d..cf8517d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6570,6 +6570,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) { + float tempFloat; // Use in float expressions below to avoid byte cast precision issues. ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); if (holeshape != (int)ScriptBaseClass.PRIM_HOLE_DEFAULT && @@ -6651,8 +6652,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { twist.y = 1.0f; } - shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); - shapeBlock.PathTwist = (sbyte)(100 * twist.y); + // A fairly large precision error occurs for some calculations, + // if a float or double is directly cast to a byte or sbyte + // variable, in both .Net and Mono. In .Net, coding + // "(sbyte)(float)(some expression)" corrects the precision + // errors. But this does not work for Mono. This longer coding + // form of creating a tempoary float variable from the + // expression first, then casting that variable to a byte or + // sbyte, works for both .Net and Mono. These types of + // assignments occur in SetPrimtiveBlockShapeParams and + // SetPrimitiveShapeParams in support of llSetPrimitiveParams. + tempFloat = (float)(100.0d * twist.x); + shapeBlock.PathTwistBegin = (sbyte)tempFloat; + tempFloat = (float)(100.0d * twist.y); + shapeBlock.PathTwist = (sbyte)tempFloat; shapeBlock.ObjectLocalID = part.LocalId; @@ -6663,6 +6676,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Prim type box, cylinder and prism. protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector taper_b, LSL_Vector topshear, byte profileshape, byte pathcurve) { + float tempFloat; // Use in float expressions below to avoid byte cast precision issues. ObjectShapePacket.ObjectDataBlock shapeBlock; shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); @@ -6683,8 +6697,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { taper_b.y = 2f; } - shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); - shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); + tempFloat = (float)(100.0d * (2.0d - taper_b.x)); + shapeBlock.PathScaleX = (byte)tempFloat; + tempFloat = (float)(100.0d * (2.0d - taper_b.y)); + shapeBlock.PathScaleY = (byte)tempFloat; if (topshear.x < -0.5f) { topshear.x = -0.5f; @@ -6701,8 +6717,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { topshear.y = 0.5f; } - shapeBlock.PathShearX = (byte)(100 * topshear.x); - shapeBlock.PathShearY = (byte)(100 * topshear.y); + tempFloat = (float)(100.0d * topshear.x); + shapeBlock.PathShearX = (byte)tempFloat; + tempFloat = (float)(100.0d * topshear.y); + shapeBlock.PathShearY = (byte)tempFloat; part.Shape.SculptEntry = false; part.UpdateShape(shapeBlock); @@ -6752,6 +6770,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Prim type torus, tube and ring. protected void SetPrimitiveShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, LSL_Vector holesize, LSL_Vector topshear, LSL_Vector profilecut, LSL_Vector taper_a, float revolutions, float radiusoffset, float skew, byte profileshape, byte pathcurve) { + float tempFloat; // Use in float expressions below to avoid byte cast precision issues. ObjectShapePacket.ObjectDataBlock shapeBlock; shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); @@ -6776,8 +6795,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { holesize.y = 0.5f; } - shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); - shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); + tempFloat = (float)(100.0d * (2.0d - holesize.x)); + shapeBlock.PathScaleX = (byte)tempFloat; + tempFloat = (float)(100.0d * (2.0d - holesize.y)); + shapeBlock.PathScaleY = (byte)tempFloat; if (topshear.x < -0.5f) { topshear.x = -0.5f; @@ -6794,8 +6815,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { topshear.y = 0.5f; } - shapeBlock.PathShearX = (byte)(100 * topshear.x); - shapeBlock.PathShearY = (byte)(100 * topshear.y); + tempFloat = (float)(100.0d * topshear.x); + shapeBlock.PathShearX = (byte)tempFloat; + tempFloat = (float)(100.0d * topshear.y); + shapeBlock.PathShearY = (byte)tempFloat; if (profilecut.x < 0f) { profilecut.x = 0f; @@ -6839,8 +6862,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { taper_a.y = 1f; } - shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); - shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); + tempFloat = (float)(100.0d * taper_a.x); + shapeBlock.PathTaperX = (sbyte)tempFloat; + tempFloat = (float)(100.0d * taper_a.y); + shapeBlock.PathTaperY = (sbyte)tempFloat; if (revolutions < 1f) { revolutions = 1f; @@ -6849,7 +6874,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { revolutions = 4f; } - shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); + tempFloat = 66.66667f * (revolutions - 1.0f); + shapeBlock.PathRevolutions = (byte)tempFloat; // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 if (radiusoffset < 0f) { @@ -6859,7 +6885,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { radiusoffset = 1f; } - shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); + tempFloat = 100.0f * radiusoffset; + shapeBlock.PathRadiusOffset = (sbyte)tempFloat; if (skew < -0.95f) { skew = -0.95f; @@ -6868,7 +6895,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { skew = 0.95f; } - shapeBlock.PathSkew = (sbyte)(100 * skew); + tempFloat = 100.0f * skew; + shapeBlock.PathSkew = (sbyte)tempFloat; part.Shape.SculptEntry = false; part.UpdateShape(shapeBlock); @@ -7681,10 +7709,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); // float revolutions - res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned - // byte is being used to represent the entire - // range of floating-point values from 1.0 - // through 4.0 (which is how SL does it). + res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d); + // Slightly inaccurate, because an unsigned byte is being used to represent + // the entire range of floating-point values from 1.0 through 4.0 (which is how + // SL does it). + // + // Using these formulas to store and retrieve PathRevolutions, it is not + // possible to use all values between 1.00 and 4.00. For instance, you can't + // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you + // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them + // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar + // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11. + // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value + // such as 1.10. So, SL must store and retreive the actual user input rather + // than only storing the encoded value. // float radiusoffset res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); -- cgit v1.1